cakefoot/src/Character.hpp

201 lines
7.2 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 sb::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 sb::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;
/*!
* Spawn the character at the beginning of the given curve.
*
* @param curve The curve to reset the beginning position to
* @param continue_acceleration If Character::acceleration is true, allow it to continue when respawned
*/
void beginning(const Curve& curve, bool continue_acceleration = false);
/*!
* @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. Acceleration is cancelled unless `continue_acceleration` is
* set.
*
* @param curve Curve to spawn on
* @param continue_acceleration If Character::accelerating is set, do not unset it
*/
void spawn(const Curve& curve, bool continue_acceleration = false);
/*!
* @param curve Curve to check against
*
* @return True if the character is at the beginning of the curve, false otherwise
*/
bool at_beginning(const Curve& curve) const;
/*!
* @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;
/*!
* @param state resting state
* @return resting state
*/
bool resting(bool state);
/*!
* @return character's relative position on the given curve
*/
float relative(const Curve& curve) const;
/*!
* @return Character object's current speed
*/
float speed() 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 ndc Coordinates of the character in NDC space
* @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, const glm::vec3& ndc, 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);
};