208 lines
6.2 KiB
C++
208 lines
6.2 KiB
C++
/* >> Cakefoot << */
|
|
|
|
#pragma once
|
|
|
|
/* Needed for functions in glm/gtx/ */
|
|
#define GLM_ENABLE_EXPERIMENTAL
|
|
|
|
/* Standard library includes */
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <functional>
|
|
#include <malloc.h>
|
|
|
|
/* Include Game.hpp before any other SDL-related headers because it defines SDL_MAIN_HANDLED */
|
|
#include "Game.hpp"
|
|
|
|
/* SPACEBOX external libraries included in source package */
|
|
#include "sdl2-gfx/SDL2_gfxPrimitives.h"
|
|
#include "json/json.hpp"
|
|
#include "glm/glm.hpp"
|
|
#include "glm/gtx/matrix_decompose.hpp"
|
|
#include "glm/gtc/matrix_access.hpp"
|
|
|
|
/* SPACEBOX classes and functions */
|
|
#include "Color.hpp"
|
|
#include "extension.hpp"
|
|
#include "filesystem.hpp"
|
|
#include "Animation.hpp"
|
|
#include "Texture.hpp"
|
|
#include "GLObject.hpp"
|
|
#include "Log.hpp"
|
|
#include "Attributes.hpp"
|
|
#include "VBO.hpp"
|
|
#include "Model.hpp"
|
|
#include "Box.hpp"
|
|
#include "Switch.hpp"
|
|
#include "Selection.hpp"
|
|
#include "math.hpp"
|
|
#include "Configuration.hpp"
|
|
#include "Timer.hpp"
|
|
#include "Text.hpp"
|
|
#include "Segment.hpp"
|
|
#include "Input.hpp"
|
|
|
|
/* Project classes */
|
|
#include "Character.hpp"
|
|
#include "Sprite.hpp"
|
|
#include "Pad.hpp"
|
|
#include "Curve.hpp"
|
|
#include "Enemy.hpp"
|
|
|
|
/*!
|
|
* The main game object. There is currently only support for one of these to exist at a time.
|
|
*
|
|
* Note: the conversion for pixel distance from the original 864x468 coordinate system to this program's NDC coordinate system is
|
|
*
|
|
* f(distance) = distance / 486.0 * 2
|
|
*
|
|
* Note: the conversion for pixel speed values from the original Python version's per-frame, fixed 25fps, 864x468 coordinate system to
|
|
* this program's per-second, adjustable framerate, NDC coordinate system is below. This gives the speed in amount of NDC to travel per
|
|
* second. For non-pixel values, just multiply by 25.
|
|
*
|
|
* f(speed) = speed / 486.0 * 25 * 2
|
|
*/
|
|
class Cakefoot : public sb::Game
|
|
{
|
|
|
|
private:
|
|
|
|
/* Convention for calling parent class in a consistent way across classes */
|
|
typedef sb::Game super;
|
|
|
|
/* Static members */
|
|
inline static std::string reset_command_name = "reset";
|
|
const inline static std::string progress_file_path = "storage/cakefoot_progress.json";
|
|
|
|
/* Member vars */
|
|
std::shared_ptr<SDL_Cursor> poke, grab;
|
|
int previous_frames_per_second = 0, curve_index = 0, curve_byte_count = 0, level_index = 0, level_select_index = 1, profile_index = 0;
|
|
std::map<std::string, GLuint> uniform;
|
|
GLuint shader_program;
|
|
glm::mat4 view {1.0f}, projection {1.0f};
|
|
sb::VAO vao;
|
|
sb::VBO vbo;
|
|
std::map<std::string, sb::Pad<>> button = {
|
|
{"start", sb::Pad<>()},
|
|
{"resume", sb::Pad<>()},
|
|
{"reset", sb::Pad<>()},
|
|
{"level increment", sb::Pad<>()},
|
|
{"level decrement", sb::Pad<>()},
|
|
{"pause", sb::Pad<>()},
|
|
{"profile increment", sb::Pad<>()},
|
|
{"profile decrement", sb::Pad<>()},
|
|
{"volume", sb::Pad<>()}
|
|
};
|
|
std::map<std::string, sb::Text> label = {
|
|
{"fps", sb::Text(font())},
|
|
{"clock", sb::Text(font())},
|
|
{"level", sb::Text(font())},
|
|
{"level select", sb::Text(font())},
|
|
{"profile", sb::Text(font())}
|
|
};
|
|
sb::Sprite playing_field, checkpoint_on, checkpoint_off, coin {"resource/coin/coin-0.png", glm::vec2{12.0f / 486.0f}};
|
|
sb::Timer on_timer, run_timer, unpaused_timer;
|
|
glm::vec3 camera_position {0.0f, 0.0f, 2.0f}, subject_position {0.0f, 0.0f, 0.0f};
|
|
float zoom = 0.0f;
|
|
glm::vec2 rotation = {0.0f, 0.0f};
|
|
std::vector<Curve> curves;
|
|
std::vector<std::shared_ptr<Enemy>> enemies;
|
|
glm::vec4 world_color {0.2f, 0.2f, 0.2f, 1.0f};
|
|
std::map<std::string, std::shared_ptr<TTF_Font>> fonts;
|
|
std::map<std::string, sb::audio::Chunk> audio;
|
|
Character character {_configuration, audio};
|
|
|
|
/*!
|
|
* Load sound effects and music into objects that can be used by the SDL mixer library. Use chunk objects for background music instead of
|
|
* music objects so background music tracks can fade into each other.
|
|
*/
|
|
void load_audio();
|
|
|
|
/*!
|
|
* Open configuration and load curve data into the object.
|
|
*/
|
|
void load_curves();
|
|
|
|
/*!
|
|
* Create GL context via super class and load vertices, UV data, and shaders.
|
|
*/
|
|
void load_gl_context();
|
|
|
|
/*!
|
|
* Create button objects and assign them to the entries in the button map. This can be re-run to apply changes made in the configuration or
|
|
* to refresh label content.
|
|
*/
|
|
void set_up_buttons();
|
|
|
|
/*!
|
|
* Style the HUD elements based on the configuration settings. This can be re-run to apply changes made in the configuration.
|
|
*/
|
|
void set_up_hud();
|
|
|
|
/*!
|
|
* Generate, bind, and fill a vertex buffer object with the game's vertex data.
|
|
*/
|
|
void load_vbo();
|
|
|
|
/*!
|
|
* @return the currently active curve
|
|
*/
|
|
Curve& curve();
|
|
|
|
/*!
|
|
* Change the level to the given index. Load enemies, update the curve index.
|
|
*
|
|
* @param index index of the level to load
|
|
*/
|
|
void load_level(int index);
|
|
|
|
/*!
|
|
* Save the JSON in the `progress` field of Game::configuration to storage at Cakefoot::progress_file_path.
|
|
*
|
|
* For PC builds, the folder `storage/` will be created in the current working directory if it doesn't exist already. The user must have
|
|
* permission to create folders in the directory. The file `progress.json` will also be created if necessary.
|
|
*
|
|
* For web builds, Emscripten is used to abstract this function so that writing to a browser's Indexed DB is done automatically. The folder
|
|
* `storage/` must have been mounted already using Emscripten's FS module.
|
|
*/
|
|
void write_progress();
|
|
|
|
public:
|
|
|
|
/*!
|
|
* Initialize a Cakefoot instance
|
|
*/
|
|
Cakefoot();
|
|
|
|
/*!
|
|
* Respond to command events
|
|
*/
|
|
void respond(SDL_Event&);
|
|
|
|
/*!
|
|
* Start timers, enable auto refresh, and run the super class's run function, which starts the game's update loop.
|
|
*
|
|
* @see Game::run()
|
|
*/
|
|
void run();
|
|
|
|
/*!
|
|
* Update parameters and draw the screen.
|
|
*
|
|
* @param timestamp seconds since the start of the program
|
|
*/
|
|
void update(float timestamp);
|
|
|
|
};
|
|
|
|
/*!
|
|
* Create a Cakewalk instance and launch its mainloop.
|
|
*
|
|
* @return Always returns 0
|
|
*/
|
|
int main();
|