- add options sub-menu to title screen: bgm, sfx, fullscreen, and exit
- hide UI when gamepad is in use, enable when mouse is in use - indicate selected UI button using hue rotation animation - support for gamepad hat - support for disconnecting and reconnecting gamepads - sanitize collected data in WASM build and write files per session - add function for finding the closest UI button in a given direction - bug fix: prevent character from moving when level loads or play is resumed from the pause menu - bug fix: cancel character walking sfx when paused
This commit is contained in:
parent
ba53c72b01
commit
290e23b5da
|
@ -15,7 +15,7 @@ ext/
|
|||
local/
|
||||
src/__pycache__/
|
||||
storage/
|
||||
Play_History.json
|
||||
*Play_History.json
|
||||
press.html
|
||||
feed
|
||||
test.html
|
||||
|
|
8
Makefile
8
Makefile
|
@ -116,8 +116,8 @@ $(addsuffix /Input.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Input.cpp Inpu
|
|||
Delegate.hpp) | $(BUILD_DIRS)
|
||||
$(CXX) $(CXXFLAGS) $< -c -o $@
|
||||
|
||||
$(addsuffix /Configuration.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Configuration.cpp Configuration.hpp Node.hpp Animation.hpp \
|
||||
Log.hpp extension.hpp) | $(BUILD_DIRS)
|
||||
$(addsuffix /Configuration.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Configuration.cpp Configuration.hpp Animation.hpp Log.hpp \
|
||||
extension.hpp) | $(BUILD_DIRS)
|
||||
$(CXX) $(CXXFLAGS) $< -c -o $@
|
||||
|
||||
$(addsuffix /Delegate.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Delegate.cpp Delegate.hpp Node.hpp Game.hpp Input.hpp) \
|
||||
|
@ -265,7 +265,7 @@ cakefoot.js : CXXFLAGS = $(CFLAGS) --std=c++17
|
|||
cakefoot.js : $(addprefix $(WASM_BUILD_DIR)/, SDL2_rotozoom.o SDL2_gfxPrimitives.o $(SB_O_FILES) $(SRC_O_FILES)) \
|
||||
$(EMSCRIPTEN_GAME_CONFIGS)
|
||||
$(CXX) $(filter-out $(EMSCRIPTEN_GAME_CONFIGS), $^) $(CXXFLAGS) $(EMSCRIPTEN_LFLAGS) $(EMSCRIPTEN_PRELOADS) \
|
||||
--pre-js "src/pre_js_foam.js" -o $(WASM_BUILD_DIR)/$@
|
||||
--pre-js "src/pre_js_collect.js" -o $(WASM_BUILD_DIR)/$@
|
||||
|
||||
cakefoot_debug.html : CC = $(EMSCRIPTENHOME)/emcc
|
||||
cakefoot_debug.html : CXX = $(EMSCRIPTENHOME)/em++
|
||||
|
@ -505,7 +505,7 @@ press :
|
|||
###################
|
||||
|
||||
all : Cakefoot-linux.x64 Cakefoot-linux_debug.x64 cakefoot.js cakefoot_debug.html cakefoot_coolmath.js Cakefoot-win32.exe \
|
||||
Cakefoot-win64.exe Cakefoot-win32-ARCADE_ONLY.exe Cakefoot-win32-DEMO.exe press
|
||||
Cakefoot-win64.exe Cakefoot-win32-ARCADE_ONLY.exe Cakefoot-win32-DEMO.exe press Cakefoot.app Ubuntu-18
|
||||
|
||||
#########################
|
||||
# Clean up object files #
|
||||
|
|
15
README.md
15
README.md
|
@ -54,6 +54,21 @@ The code is open source under the zlib license. The images and sound effects are
|
|||
|
||||
See [LICENSE.txt](LICENSE.txt) for details.
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
1.0.4
|
||||
|
||||
- add options sub-menu to title screen: bgm, sfx, fullscreen, and exit
|
||||
- hide UI when gamepad is in use, enable when mouse is in use
|
||||
- indicate selected UI button using hue rotation animation
|
||||
- support for gamepad hat
|
||||
- support for disconnecting and reconnecting gamepads
|
||||
- sanitize collected data in WASM build and write files per session
|
||||
- add function for finding the closest UI button in a given direction
|
||||
- bug fix: prevent character from moving when level loads or play is resumed from the pause menu
|
||||
- bug fix: cancel character walking sfx when paused
|
||||
|
||||
Contact
|
||||
=======
|
||||
|
||||
|
|
41
config.json
41
config.json
|
@ -28,7 +28,7 @@
|
|||
"hitbox": false,
|
||||
"use play button": false,
|
||||
"arcade only": false,
|
||||
"use arcade prompt": true,
|
||||
"use arcade prompt": false,
|
||||
"game over text": "GAME OVER",
|
||||
"game over display time": 2.5,
|
||||
"game over foreground": [255.0, 255.0, 255.0, 255.0],
|
||||
|
@ -54,7 +54,7 @@
|
|||
"scoreboard translation": [-0.4, 0.835],
|
||||
"scoreboard scale": [1.35, 0.14],
|
||||
"scoreboard wrap": 3000,
|
||||
"qr display": true,
|
||||
"qr display": false,
|
||||
"qr background display": true,
|
||||
"qr background texture": "resource/qr_background.png",
|
||||
"qr texture": "resource/qr.png",
|
||||
|
@ -95,7 +95,9 @@
|
|||
"arcade warning color": [0.5, 0.0, 0.0, 1.0],
|
||||
"auto save translation": [-1.45, -0.65],
|
||||
"auto save scale": [0.325, 0.15],
|
||||
"social media click": false
|
||||
"social media click": false,
|
||||
"highlight saturation": 1.0,
|
||||
"highlight value": 0.5
|
||||
},
|
||||
|
||||
"shader":
|
||||
|
@ -116,7 +118,7 @@
|
|||
{
|
||||
"screenshot directory": "local/screenshots",
|
||||
"video directory": "local/video",
|
||||
"enabled": true,
|
||||
"enabled": false,
|
||||
"write mp4": true,
|
||||
"video frame length": 0.016666666,
|
||||
"max video memory": 2000,
|
||||
|
@ -129,7 +131,8 @@
|
|||
"any key ignore commands": ["left", "right", "up", "down", "pause"],
|
||||
"gamepad pause button index": 9,
|
||||
"gamepad axis cooldown": 0.2,
|
||||
"gamepad reset button index": 8
|
||||
"gamepad reset button index": 8,
|
||||
"gamepad home button index": 10
|
||||
},
|
||||
|
||||
"keys":
|
||||
|
@ -267,16 +270,16 @@
|
|||
"text dimensions": [275.0, 50.0],
|
||||
"text scale": 0.71,
|
||||
"text foreground": [200.0, 200.0, 200.0, 255.0],
|
||||
"text background": [60.0, 60.0, 60.0, 190.0],
|
||||
"text background": [60.0, 60.0, 60.0, 255.0],
|
||||
"start text": "✶✶ PLAY ✶✶",
|
||||
"start translation": [0.0, -0.4],
|
||||
"start alt texture": "resource/press_button_to_start.png",
|
||||
"start alt translation": [0.0, -0.5],
|
||||
"start alt scale": [0.5787, 0.91],
|
||||
"resume text": "RESUME",
|
||||
"resume translation": [0.0, 0.25],
|
||||
"resume translation": [0.0, 0.35],
|
||||
"reset text": "SAVE & EXIT",
|
||||
"reset translation": [0.0, -0.25],
|
||||
"reset translation": [0.0, -0.025],
|
||||
"level decrement translation": [-0.67, -0.71],
|
||||
"level decrement text": "◀",
|
||||
"level decrement dimensions": [40.0, 40.0],
|
||||
|
@ -336,7 +339,22 @@
|
|||
"fullscreen texture": "resource/fullscreen.png",
|
||||
"fullscreen translation": [-1.45, -0.85],
|
||||
"fullscreen scale": 0.07,
|
||||
"fullscreen scale ratio": 0.75
|
||||
"fullscreen scale ratio": 0.75,
|
||||
"fullscreen text text": "FULLSCREEN",
|
||||
"fullscreen text translation home": [0.0, -0.69],
|
||||
"fullscreen text translation pause": [0.0, -0.29],
|
||||
"fullscreen text dimensions": [850.0, 40.0],
|
||||
"fullscreen text scale": 0.71,
|
||||
"bgm text on": "BGM ON",
|
||||
"bgm text off": "BGM OFF",
|
||||
"bgm translation home": [0.0, -0.77],
|
||||
"bgm translation pause": [0.0, -0.38],
|
||||
"sfx text on": "SFX ON",
|
||||
"sfx text off": "SFX OFF",
|
||||
"sfx translation home": [0.0, -0.85],
|
||||
"sfx translation pause": [0.0, -0.47],
|
||||
"exit text": "EXIT GAME",
|
||||
"exit translation": [0.0, -0.93]
|
||||
},
|
||||
|
||||
"world": [
|
||||
|
@ -387,6 +405,9 @@
|
|||
"level addition advanced": 30.0,
|
||||
"bank bonus": 5.0,
|
||||
"advanced": 14
|
||||
},
|
||||
{
|
||||
"name": "OPTIONS"
|
||||
}
|
||||
],
|
||||
|
||||
|
@ -456,7 +477,7 @@
|
|||
|
||||
"demo":
|
||||
{
|
||||
"active": true,
|
||||
"active": false,
|
||||
"idle timeout": 30.0,
|
||||
"countdown display timeout": 10.0,
|
||||
"countdown message": "IDLE RESET IN ",
|
||||
|
|
|
@ -252,7 +252,7 @@
|
|||
var ticker_content = [
|
||||
"Use ☝️, 🖱️, ⌨️ or 🎮 to play",
|
||||
"🗓️ Releasing on <a href='https://store.steampowered.com/app/2869020/Cakefoot/' target='_blank'>Steam</a>, " +
|
||||
"<a href='https://ohsqueezy.itch.io/cakefoot' target='new'>itch.io</a>, Android & " +
|
||||
"<a href='https://ohsqueezy.itch.io/cakefoot' target='new'>itch.io</a> & " +
|
||||
"<a href='https://coolmathgames.com' target='_blank'>Coolmath</a> May 10th",
|
||||
"<a href='https://youtu.be/xn-iNcUlIpo' target='_blank'>Watch the trailer</a> ▶️ and " +
|
||||
"<a href='https://store.steampowered.com/app/2869020/Cakefoot/'>wishlist on Steam</a>",
|
||||
|
|
2
lib/sb
2
lib/sb
|
@ -1 +1 @@
|
|||
Subproject commit 8498dfa00472431a6dd8a2ec588f0792a9e435dc
|
||||
Subproject commit a9665c7e3799636940c21c97d2e5ade7fcce6e5e
|
633
src/Cakefoot.cpp
633
src/Cakefoot.cpp
File diff suppressed because it is too large
Load Diff
|
@ -236,7 +236,11 @@ private:
|
|||
{"name 3 decrement", sb::Pad<>()},
|
||||
{"fullscreen", sb::Pad<>()},
|
||||
{"diskmem", sb::Pad<>()},
|
||||
{"azuria sky", sb::Pad<>()}
|
||||
{"azuria sky", sb::Pad<>()},
|
||||
{"fullscreen text", sb::Pad<>()},
|
||||
{"bgm", sb::Pad<>()},
|
||||
{"sfx", sb::Pad<>()},
|
||||
{"exit", sb::Pad<>()}
|
||||
};
|
||||
std::map<std::string, std::shared_ptr<TTF_Font>> fonts {
|
||||
{"medium", font(configuration()("font", "medium", "path").get<std::string>(), configuration()("font", "medium", "size"))},
|
||||
|
@ -277,7 +281,7 @@ private:
|
|||
std::string name_entry;
|
||||
sb::Text scoreboard {fonts.at("large")}, thanks {fonts.at("medium")};
|
||||
std::vector<Flame> ending_coins;
|
||||
sb::Color rotating_hue {128, 0, 0, 0};
|
||||
sb::Color rotating_hue;
|
||||
std::vector<sb::Text> ending_messages;
|
||||
std::optional<std::string> selected;
|
||||
std::shared_ptr<SDL_GameController> controller = nullptr;
|
||||
|
@ -369,7 +373,8 @@ private:
|
|||
int distance() const;
|
||||
|
||||
/*!
|
||||
* @return The time limit of the current run. Combines the challenge mode's initial limit with added time for completed levels and checkpoints.
|
||||
* @return The time limit of the current run. Combines the challenge mode's initial limit with added time for completed levels and
|
||||
* checkpoints.
|
||||
*/
|
||||
float limit() const;
|
||||
|
||||
|
@ -411,14 +416,14 @@ private:
|
|||
|
||||
inline bool skip_resume_quest()
|
||||
{
|
||||
return configuration()("challenge", challenge_index, "name") == "RESUME QUEST" && configuration()("progress", "quest level") == 1 &&
|
||||
configuration()("progress", "quest checkpoint") == 0.0f;
|
||||
return configuration()("challenge", challenge_index, "name") == "RESUME QUEST" &&
|
||||
configuration()("progress", "quest level") == 1 && configuration()("progress", "quest checkpoint") == 0.0f;
|
||||
}
|
||||
|
||||
inline bool skip_resume_arcade()
|
||||
{
|
||||
return configuration()("challenge", challenge_index, "name") == "RESUME ARCADE" && configuration()("progress", "arcade level") == 1 &&
|
||||
configuration()("progress", "arcade checkpoint") == 0.0f;
|
||||
return configuration()("challenge", challenge_index, "name") == "RESUME ARCADE" &&
|
||||
configuration()("progress", "arcade level") == 1 && configuration()("progress", "arcade checkpoint") == 0.0f;
|
||||
}
|
||||
|
||||
inline bool skip_level_select()
|
||||
|
@ -515,6 +520,30 @@ private:
|
|||
*/
|
||||
void refresh_scoreboard();
|
||||
|
||||
/*!
|
||||
* Return the name of the button closest to a given button in Cakefoot::buttons in the specified direction ("up", "right", "down",
|
||||
* or "left").
|
||||
*
|
||||
* @param subject The button to base the search on
|
||||
* @param direction One of either "up", "right", "down", or "left"
|
||||
* @param pool Buttons to search through. If omitted, all buttons will be searched.
|
||||
* @return The nearest button in the specified direction or the subject if none is found
|
||||
*/
|
||||
std::string nearest_button(const std::string& subject, const std::string& direction,
|
||||
const std::map<std::string, sb::Pad<>>& pool) const;
|
||||
|
||||
/*!
|
||||
* @overload nearest_button(const std::string&, const std::string&, const std::map<std::string, sb::Pad<>>&)
|
||||
*/
|
||||
std::string nearest_button(const std::string& subject, const std::string& direction,
|
||||
const std::vector<std::string>& names) const;
|
||||
|
||||
/*!
|
||||
* @overload nearest_button(const std::string&, const std::string&, const std::map<std::string, sb::Pad<>>&)
|
||||
*
|
||||
* Searches every Cakefoot::button
|
||||
*/
|
||||
std::string nearest_button(const std::string& subject, const std::string& direction) const;
|
||||
public:
|
||||
|
||||
/*!
|
||||
|
|
|
@ -14,7 +14,8 @@ void Character::profile(const std::string& name)
|
|||
|
||||
/* Reload the texture */
|
||||
_sprite.clear_textures();
|
||||
nlohmann::json frames = configuration("progress", "jackpot") == 777 ? configuration("character", "jackpot frames") : profile().at("animation frames");
|
||||
nlohmann::json frames = configuration("progress", "jackpot") == 777 ? configuration("character", "jackpot frames") :
|
||||
profile().at("animation frames");
|
||||
for (const std::string path : frames)
|
||||
{
|
||||
_sprite.texture(path, GL_LINEAR);
|
||||
|
@ -95,6 +96,12 @@ bool Character::resting() const
|
|||
return _resting;
|
||||
}
|
||||
|
||||
bool Character::resting(bool state)
|
||||
{
|
||||
_resting = state;
|
||||
return _resting;
|
||||
}
|
||||
|
||||
float Character::relative(const Curve& curve) const
|
||||
{
|
||||
return float(next_point_index) / curve.length();
|
||||
|
@ -118,12 +125,14 @@ void Character::update(const Curve& curve, const sb::Timer& timer, bool muted, s
|
|||
_resting = false;
|
||||
|
||||
/* Apply delta time to the speed increase. */
|
||||
speed += timer.delta(profile()["speed increment"].get<float>()) + glm::abs(speed) * profile()["increment mod"].get<float>();
|
||||
speed += timer.delta(profile()["speed increment"].get<float>()) +
|
||||
glm::abs(speed) * profile()["increment mod"].get<float>();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Apply delta time to the speed decrease. */
|
||||
speed -= timer.delta(profile()["speed decrement"].get<float>()) + glm::abs(speed) * profile()["decrement mod"].get<float>();
|
||||
speed -= timer.delta(profile()["speed decrement"].get<float>()) +
|
||||
glm::abs(speed) * profile()["decrement mod"].get<float>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,12 @@ public:
|
|||
*/
|
||||
bool resting() const;
|
||||
|
||||
/*!
|
||||
* @param state resting state
|
||||
* @return resting state
|
||||
*/
|
||||
bool resting(bool state);
|
||||
|
||||
/*!
|
||||
* @return character's relative position on the given curve
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"recording":
|
||||
{
|
||||
"enabled": true
|
||||
},
|
||||
|
||||
"log":
|
||||
{
|
||||
"enabled": true
|
||||
}
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
/* _ _
|
||||
* c/a`k-e'f`o^o~t-, | a single-button action game | by @ooofoam
|
||||
* / _< | wow a living cake the sweet | play online: https://foam.ooo/cakefoot
|
||||
* > `~_/ | taste of victory | open source: https://open.shampoo.ooo/shampoo/cakefoot
|
||||
/* _ _
|
||||
* / `-' `-^~~-, | cakefoot presented by dank.game
|
||||
* \__ _ _< |
|
||||
* `v ) `~_/ | source code and license at https://open.shampoo.ooo/shampoo/cakefoot
|
||||
*
|
||||
* Custom modifications to Emscripten's Module object and other JavaScript to be included in the WASM build specific to the FOAM site.
|
||||
* @file pre_js_collect.js
|
||||
*
|
||||
* Addition to Emscripten's Module object to be included in WASM builds that will collect user play data.
|
||||
*/
|
||||
|
||||
/* Collect user play data when running on the FOAM site */
|
||||
function collectData()
|
||||
{
|
||||
/* Open the database Emscripten's IDBFS library created. */
|
|
@ -4,8 +4,9 @@
|
|||
session_start();
|
||||
|
||||
/* The log of play history is stored in JSON format in a file in the same directory as this script. If this file doesn't exist yet, it
|
||||
* will be created at write time. */
|
||||
$history_path = "Play_History.json";
|
||||
* will be created at write time. Each session ID is written to its own file to avoid race conditions between multiple sessions
|
||||
* sharing a single file. */
|
||||
$history_path = session_id() . "-Play_History.json";
|
||||
|
||||
/* Read JSON data from the history path. If the file doesn't exist, is not in JSON format, or any other exception occurs, just set the
|
||||
* history to an empty array. */
|
||||
|
@ -18,11 +19,15 @@ catch (Exception $e)
|
|||
$history = array();
|
||||
}
|
||||
|
||||
/* JSON data containing the user's play history is passed as a POST request from JavaScript */
|
||||
$submitted_user_log = array(session_id() => json_decode(file_get_contents("php://input"), true)["progress"]);
|
||||
/* JSON data containing the user's play history is passed as a POST request from JavaScript in pre_js_dank.js. Remove HTML and PHP
|
||||
* special characters and limit length of input to 2048 characters to protect against injections. */
|
||||
$submitted_user_log = array(session_id() => json_decode(file_get_contents("php://input", false, null, 0, 2048), true)["progress"]);
|
||||
|
||||
/* Merge the passed play history into the history array, overwriting any existing data at the current session ID, or adding a new section
|
||||
* to the array if the session ID doesn't exist as a key in the array yet. Write the array to the history path. */
|
||||
/* Add a timestamp to the log */
|
||||
$submitted_user_log["timestamp"] = date("Y-m-d H:i:s");
|
||||
|
||||
/* Merge the passed play history into the history array, overwriting any existing data at the current session ID, or adding a new
|
||||
* section to the array if the session ID doesn't exist as a key in the array yet. Write the array to the history path. */
|
||||
file_put_contents(
|
||||
$history_path,
|
||||
json_encode(
|
||||
|
|
Loading…
Reference in New Issue