cakefoot/src/Character.hpp

170 lines
6.1 KiB
C++

#pragma once
#include <vector>
#include <algorithm>
#include <map>
#include "json/json.hpp"
#include "SDL_mixer.h"
#include "Configuration.hpp"
#include "Switch.hpp"
#include "Selection.hpp"
#include "Sprite.hpp"
#include "Curve.hpp"
#include "Segment.hpp"
#include "Audio.hpp"
class Character
{
private:
/* Convert pixel size to NDC size. */
inline static const glm::vec2 size {20.0f / 486.0f};
/* Keep references to the global configuration and audio data */
const Configuration& configuration;
std::map<std::string, sb::audio::Chunk>& audio;
/* Set at runtime based on the configuration */
sb::Sprite _sprite;
std::string _profile;
/* Physics, movement, and collision */
float speed {0.0f}, _checkpoint {0.0f};
int next_point_index {0};
Box _box {{0.0f, 0.0f}, 2.0f * this->size};
bool _resting = true;
/* Walking forward, backward, and not walking animation timer */
sb::Animation walk;
/*!
* A JSON object containing the fields: name, speed increment, speed decrement, max speed, increment mod, decrement mod, and
* animation frames.
*
* This will use the profile name set by Character::profile(const std::string&) to get the associated profile in
* Character::configuration at `character -> profile`.
*
* @return JSON containing the currently selected profile name along with physics and texture values
*/
const nlohmann::json& profile() const;
public:
/* Two SDL mixer channels reserved for walk sound effects */
inline static const int walk_channel = 0;
inline static const int reverse_channel = 1;
/* Create an object which can be switched on and off to move and stop the character. */
sb::Switch<> accelerating = false;
/* Where the character is located in NDC. */
glm::vec3 position;
/*!
* @param configuration reference to the global configuration which is expected to contain profile entries for character physics
*/
Character(const Configuration& configuration, std::map<std::string, sb::audio::Chunk>& audio);
/*!
* Change the character's physics and texture by specifying a profile name. The name refers to a JSON profile stored in an array of
* profiles in `Character::configuration` at `character -> profile`. The JSON for each profile is expected to contain the following
* fields: name, speed increment, speed decrement, max speed, increment mod, decrement mod, and animation frames.
*
* The character will refer to the given profile when accessing the profile in other calls. No physics values are directly modified
* by this function. This is done so external changes to the configuration can be registered automatically during runtime.
*
* However, the texture will be directly modified because re-reading the texture every frame is too slow. To automate re-reading the
* texture, insert a hook into the game's update loop that runs this function every time a configuration modification is detected.
*
* @param name String in the name field of the chosen profile in the list of profiles at `character -> profile`
*/
void profile(const std::string& name);
/*!
* Set the size of the hit box as a percentage of the sprite's size.
*
* @param size percentage of sprite size
*/
void box_size(float size);
/*!
* Load the graphics into the GPU. This is only necessary to run if the object was constructed before the GL context was loaded.
*/
void load();
/*!
* @return reference to the box object enclosing the character in world space
*/
const Box& box() const;
/*!
* @return reference to the character's sprite object for accessing the character's graphics
*/
const sb::Sprite& sprite() const;
/*!
* @param curve the curve to reset the beginning position to
*/
void beginning(const Curve& curve);
/*!
* @return relative point on the curve where the character should spawn
*/
float checkpoint() const;
/*!
* Update the spawn point.
*
* @param checkpoint relative point on the curve where the character should spawn
*/
void checkpoint(float checkpoint);
/*!
* Place character at checkpoint position on the curve.
*
* @param curve curve to spawn on
*/
void spawn(const Curve& curve);
/*!
* @param curve curve to check against
* @return `true` if the character is at the end of the curve, `false` otherwise
*/
bool at_end(const Curve& curve) const;
/*!
* @return True if the character has just respawned or the level just began
*/
bool resting() const;
/*!
* @return character's relative position on the given curve
*/
float relative(const Curve& curve) const;
/*!
* Check acceleration state and adjust speed. Move character toward the next point on the curve.
*
* @param curve the curve to update against
* @param timer a timer object that is updated once per frame, so that it provides delta time for movement
* @param muted flag for preventing the walk sound effect output
* @param constant_speed override acceleration processing and set the movement to a constant speed
*/
void update(const Curve& curve, const sb::Timer& timer, bool muted = false, std::optional<float> constant_speed = std::nullopt);
/*!
* Perform GL drawing operations using the character's sprite object.
*
* @param curve curve which determines how to wrap the character's position to the curve's space
* @param transformation_uniform transformation uniform location in the shader program
* @param view view transformation matrix
* @param projection projection transformation matrix
* @param texture_flag_uniform uniform location in the shader program of the boolean that turns texture drawing on or off
*/
void draw(const Curve& curve, GLuint transformation_uniform, const glm::mat4& view, const glm::mat4& projection,
GLuint texture_flag_uniform);
};