added jackpot, ending screen messages, title screen idle animation, play button flash
This commit is contained in:
parent
0121b33cbe
commit
ec6165214b
83
config.json
83
config.json
|
@ -34,14 +34,14 @@
|
|||
"game over background": [0.0, 0.0, 0.0, 255.0],
|
||||
"game over translation": [0.0, 0.0],
|
||||
"game over scale": [0.25, 0.05],
|
||||
"arcade rank scale": [0.4, 0.1],
|
||||
"arcade rank scale": [0.5, 0.15],
|
||||
"arcade rank dimensions": [300.0, 80.0],
|
||||
"arcade rank translation": [-1.2, 0.5],
|
||||
"arcade distance scale": [0.4, 0.1],
|
||||
"arcade rank translation": [0.3, 0.6],
|
||||
"arcade distance scale": [0.3, 0.075],
|
||||
"arcade distance dimensions": [300.0, 80.0],
|
||||
"arcade distance translation": [0.0, 0.5],
|
||||
"arcade time remaining scale": [0.4, 0.1],
|
||||
"arcade time remaining translation": [1.2, 0.5],
|
||||
"arcade distance translation": [1.1, 0.675],
|
||||
"arcade time remaining scale": [0.3, 0.075],
|
||||
"arcade time remaining translation": [1.1, 0.525],
|
||||
"scoreboard foreground": [155.0, 155.0, 155.0, 255.0],
|
||||
"scoreboard background": [0.0, 0.0, 0.0, 0.0],
|
||||
"scoreboard translation": [-0.38, 0.845],
|
||||
|
@ -52,11 +52,12 @@
|
|||
"qr translation": [1.49, -0.7],
|
||||
"qr scale": [0.205, 0.225],
|
||||
"end screen timeout": 40.0,
|
||||
"end screen timeout": 10040.0,
|
||||
"enemy sprite scale": 0.024691358,
|
||||
"quest best text": "BEST ",
|
||||
"quest best scale": [0.31, 0.04],
|
||||
"quest best text": "★ ",
|
||||
"quest best scale": [0.25, 0.04],
|
||||
"quest best translation": [-1.42, 0.92],
|
||||
"quest best dimensions": [160.0, 19.0],
|
||||
"quest best dimensions": [160.0, 24.0],
|
||||
"quest best foreground": [255.0, 255.0, 255.0, 255.0],
|
||||
"quest best background": [0.0, 0.0, 0.0, 60.0],
|
||||
"hue shift": 10.0,
|
||||
|
@ -111,15 +112,30 @@
|
|||
|
||||
"font":
|
||||
{
|
||||
"text":
|
||||
"medium":
|
||||
{
|
||||
"path": "BPmono.ttf",
|
||||
"path": "resource/BPmono.ttf",
|
||||
"size": 24
|
||||
},
|
||||
"small text":
|
||||
"small":
|
||||
{
|
||||
"path": "BPmono.ttf",
|
||||
"path": "resource/BPmono.ttf",
|
||||
"size": 14
|
||||
},
|
||||
"large":
|
||||
{
|
||||
"path": "resource/BPmono.ttf",
|
||||
"size": 72
|
||||
},
|
||||
"glyph":
|
||||
{
|
||||
"path": "resource/DejaVuSans.ttf",
|
||||
"size": 24
|
||||
},
|
||||
"glyph large":
|
||||
{
|
||||
"path": "resource/DejaVuSans.ttf",
|
||||
"size": 44
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -183,7 +199,14 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"hitbox": 0.7
|
||||
"hitbox": 0.7,
|
||||
"idle speed": 0.001,
|
||||
"jackpot frames": [
|
||||
"resource/gold/cake1.png",
|
||||
"resource/gold/cake2.png",
|
||||
"resource/gold/cake3.png",
|
||||
"resource/gold/cake4.png"
|
||||
]
|
||||
},
|
||||
|
||||
"button":
|
||||
|
@ -195,7 +218,7 @@
|
|||
"text scale": 0.71,
|
||||
"text foreground": [200.0, 200.0, 200.0, 255.0],
|
||||
"text background": [60.0, 60.0, 60.0, 190.0],
|
||||
"start text": "PLAY",
|
||||
"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],
|
||||
|
@ -248,16 +271,16 @@
|
|||
{
|
||||
"arrow dimensions": [80.0, 40.0],
|
||||
"arrow scale": [0.3, 0.15],
|
||||
"arrow increment y": -0.25,
|
||||
"arrow decrement y": -0.76,
|
||||
"character 1 x": -0.4,
|
||||
"character 2 x": 0.0,
|
||||
"character 3 x": 0.4,
|
||||
"arrow increment y": 0.85,
|
||||
"arrow decrement y": 0.32,
|
||||
"character 1 x": -1.2,
|
||||
"character 2 x": -0.9,
|
||||
"character 3 x": -0.6,
|
||||
"arrow increment texture": "resource/up_arrow.png",
|
||||
"arrow decrement texture": "resource/down_arrow.png",
|
||||
"character dimensions": [60.0, 80.0],
|
||||
"character scale": [0.2, 0.15],
|
||||
"character y": -0.5
|
||||
"character y": 0.6
|
||||
},
|
||||
"fullscreen texture": "resource/fullscreen.png",
|
||||
"fullscreen translation": [-1.45, -0.85],
|
||||
|
@ -350,7 +373,8 @@
|
|||
"main": 1.0,
|
||||
"menu": 1.0,
|
||||
"take": 0.5,
|
||||
"checkpoint": 0.5
|
||||
"checkpoint": 0.5,
|
||||
"bong": 0.5
|
||||
},
|
||||
"fade": 2.0
|
||||
},
|
||||
|
@ -358,6 +382,19 @@
|
|||
"ending":
|
||||
{
|
||||
"coin range": [-0.5, 0.5],
|
||||
"coin y": 0.07
|
||||
"coin y": 0.07,
|
||||
"messages y": -0.3,
|
||||
"messages margin": -0.075,
|
||||
"messages step": -0.125,
|
||||
"messages dimensions": [500.0, 48.0],
|
||||
"messages scale": [0.9, 0.08],
|
||||
"messages foreground": [255.0, 255.0, 255.0, 255.0],
|
||||
"end text": "THE END",
|
||||
"unlock mirror": "✩ UNLOCKED MIRROR MODE ✩",
|
||||
"unlock warped": "✩ UNLOCKED WARPED MODE ✩",
|
||||
"unlock beef": "✩ UNLOCKED BEEF CAKE ✩",
|
||||
"unlock buffalo": "✩ UNLOCKED BUFFALO BEEF CAKE ✩",
|
||||
"unlock jackpot": "✩ UNLOCKED GOLDEN CAKE ✩",
|
||||
"new best": "✩ NEW BEST TIME ✩"
|
||||
}
|
||||
}
|
||||
|
|
2
lib/sb
2
lib/sb
|
@ -1 +1 @@
|
|||
Subproject commit fb68938889ce200fc8623a5608d3c7adb58a9b34
|
||||
Subproject commit c7fb948e3970eeaccb143225ab10bc84689bd09f
|
|
@ -0,0 +1,97 @@
|
|||
Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
|
||||
Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below)
|
||||
|
||||
Bitstream Vera Fonts Copyright
|
||||
———————————————
|
||||
|
||||
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
|
||||
a trademark of Bitstream, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of the fonts accompanying this license (“Fonts”) and associated
|
||||
documentation files (the “Font Software”), to reproduce and distribute the
|
||||
Font Software, including without limitation the rights to use, copy, merge,
|
||||
publish, distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice shall
|
||||
be included in all copies of one or more of the Font Software typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in particular
|
||||
the designs of glyphs or characters in the Fonts may be modified and
|
||||
additional glyphs or characters may be added to the Fonts, only if the fonts
|
||||
are renamed to names not containing either the words “Bitstream” or the word
|
||||
“Vera”.
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts or Font
|
||||
Software that has been modified and is distributed under the “Bitstream
|
||||
Vera” names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but no
|
||||
copy of one or more of the Font Software typefaces may be sold by itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
|
||||
TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
|
||||
FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
|
||||
ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
||||
THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
|
||||
FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Gnome, the Gnome
|
||||
Foundation, and Bitstream Inc., shall not be used in advertising or
|
||||
otherwise to promote the sale, use or other dealings in this Font Software
|
||||
without prior written authorization from the Gnome Foundation or Bitstream
|
||||
Inc., respectively. For further information, contact: fonts at gnome dot
|
||||
org.
|
||||
|
||||
Arev Fonts Copyright
|
||||
———————————————
|
||||
|
||||
Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the fonts accompanying this license (“Fonts”) and
|
||||
associated documentation files (the “Font Software”), to reproduce
|
||||
and distribute the modifications to the Bitstream Vera Font Software,
|
||||
including without limitation the rights to use, copy, merge, publish,
|
||||
distribute, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice
|
||||
shall be included in all copies of one or more of the Font Software
|
||||
typefaces.
|
||||
|
||||
The Font Software may be modified, altered, or added to, and in
|
||||
particular the designs of glyphs or characters in the Fonts may be
|
||||
modified and additional glyphs or characters may be added to the
|
||||
Fonts, only if the fonts are renamed to names not containing either
|
||||
the words “Tavmjong Bah” or the word “Arev”.
|
||||
|
||||
This License becomes null and void to the extent applicable to Fonts
|
||||
or Font Software that has been modified and is distributed under the
|
||||
“Tavmjong Bah Arev” names.
|
||||
|
||||
The Font Software may be sold as part of a larger software package but
|
||||
no copy of one or more of the Font Software typefaces may be sold by
|
||||
itself.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||
TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Tavmjong Bah shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other
|
||||
dealings in this Font Software without prior written authorization
|
||||
from Tavmjong Bah. For further information, contact: tavmjong @ free
|
||||
. fr.
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
122
src/Cakefoot.cpp
122
src/Cakefoot.cpp
|
@ -53,7 +53,8 @@ Cakefoot::Cakefoot()
|
|||
{"arcade max distance", 0},
|
||||
{"arcade time", 0.0f},
|
||||
{"arcade coin", false},
|
||||
{"arcade bank", 0}
|
||||
{"arcade bank", 0},
|
||||
{"jackpot", 0}
|
||||
};
|
||||
|
||||
/* Overwrite progress data with saved data if it is available */
|
||||
|
@ -131,26 +132,6 @@ Cakefoot::Cakefoot()
|
|||
/* Set the character to use the profile stored to progress */
|
||||
character.profile(configuration()("character", "profile", profile_index, "name"));
|
||||
|
||||
/* Try to load fonts. Default to the game object's font if the font doesn't load. */
|
||||
for (auto [name, font_config] : configuration()("font").items())
|
||||
{
|
||||
fonts[name] = {TTF_OpenFont(font_config["path"].get<std::string>().c_str(), font_config["size"]), TTF_CloseFont};
|
||||
std::ostringstream message;
|
||||
if (fonts[name].get() == nullptr)
|
||||
{
|
||||
message << "Could not load " << font_config["path"] << ". Using framework's font instead.";
|
||||
sb::Log::log(message, sb::Log::ERR);
|
||||
|
||||
/* Default to framework's font */
|
||||
fonts[name] = font();
|
||||
}
|
||||
else
|
||||
{
|
||||
message << "Loaded " << font_config["path"];
|
||||
sb::Log::log(message);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up checkpoint on and off sprites */
|
||||
checkpoint_on = sb::Sprite {"resource/checkpoint/on.png", glm::vec2(12.0f / 486.0f)};
|
||||
checkpoint_off = sb::Sprite {"resource/checkpoint/off.png", glm::vec2(12.0f / 486.0f)};
|
||||
|
@ -328,7 +309,7 @@ void Cakefoot::set_up_buttons()
|
|||
"challenge decrement", "view increment", "view decrement"
|
||||
})
|
||||
{
|
||||
sb::Text text {fonts.at("text")};
|
||||
sb::Text text {name == "start" ? fonts.at("glyph") : fonts.at("medium")};
|
||||
float scale;
|
||||
glm::vec2 dimensions;
|
||||
if (name == "start" || name == "resume" || name == "reset")
|
||||
|
@ -655,7 +636,7 @@ void Cakefoot::set_up_buttons()
|
|||
for (const std::string& character_index : {"1", "2", "3"})
|
||||
{
|
||||
glm::vec2 character_dimensions {configuration()("button", "name", "character dimensions")};
|
||||
sb::Text character {large_font, "", configuration()("display", "clock hud foreground").get<glm::vec4>(),
|
||||
sb::Text character {fonts.at("large"), "", configuration()("display", "clock hud foreground").get<glm::vec4>(),
|
||||
configuration()("display", "clock hud background").get<glm::vec4>(), character_dimensions};
|
||||
character.content(name_entry[std::stoi(character_index) - 1]);
|
||||
button.at("name " + character_index) = sb::Pad<>{
|
||||
|
@ -761,7 +742,7 @@ void Cakefoot::set_up_hud()
|
|||
glm::vec3 clock_scale, clock_translation;
|
||||
if (static_cast<std::size_t>(level_index) == _configuration("levels").size() - 1)
|
||||
{
|
||||
label.at("clock").font(large_font);
|
||||
label.at("clock").font(fonts.at("large"));
|
||||
if (arcade())
|
||||
{
|
||||
/* Arcade results size */
|
||||
|
@ -1065,8 +1046,8 @@ void Cakefoot::load_level(int index)
|
|||
}
|
||||
}
|
||||
|
||||
/* If the level is the end screen, reset the player's current level to the beginning and load ending screen coin list. Otherwise, if the level is not
|
||||
* the title screen, save it as the current level in the player's progress. Also save the newly assigned current level in the level select index. */
|
||||
/* If the level is the end screen, reset the player's current level to the beginning and load ending screen coin list. Unlock any new difficulty
|
||||
* or view. Set a list of messages to be displayed on the end screen. */
|
||||
if (end_screen())
|
||||
{
|
||||
/* Load ending coins */
|
||||
|
@ -1082,6 +1063,44 @@ void Cakefoot::load_level(int index)
|
|||
ending_coins.push_back(coin);
|
||||
}
|
||||
|
||||
/* Clear list of ending messages */
|
||||
ending_messages.clear();
|
||||
|
||||
/* Show the end for any run that beats all the levels */
|
||||
if (quest() || (arcade() && configuration()("progress", "arcade level") >= configuration()("levels").size() - 2))
|
||||
{
|
||||
sb::Text message {fonts.at("glyph large"), configuration()("ending", "end text"), configuration()("ending", "messages foreground").get<glm::vec4>()};
|
||||
message.dimensions(configuration()("ending", "messages dimensions"));
|
||||
ending_messages.push_back(message);
|
||||
}
|
||||
|
||||
/* Unlocks for getting all coins */
|
||||
if (bank() >= max_bank())
|
||||
{
|
||||
if (configuration()("progress", "max view").get<int>() < 1)
|
||||
{
|
||||
configuration()["progress"]["max view"] = 1;
|
||||
sb::Text message {fonts.at("glyph"), configuration()("ending", "unlock mirror"), configuration()("ending", "messages foreground").get<glm::vec4>()};
|
||||
message.dimensions(configuration()("ending", "messages dimensions"));
|
||||
ending_messages.push_back(message);
|
||||
}
|
||||
if (configuration()("progress", "max view").get<int>() < 2 && profile_index >= 1)
|
||||
{
|
||||
configuration()["progress"]["max view"] = 2;
|
||||
sb::Text message {fonts.at("glyph"), configuration()("ending", "unlock warped"), configuration()("ending", "messages foreground").get<glm::vec4>()};
|
||||
message.dimensions(configuration()("ending", "messages dimensions"));
|
||||
ending_messages.push_back(message);
|
||||
}
|
||||
if (configuration()("progress", "jackpot") != 777 && profile_index == 2)
|
||||
{
|
||||
configuration()["progress"]["jackpot"] = 777;
|
||||
character.profile(configuration()("character", "profile", profile_index, "name"));
|
||||
sb::Text message {fonts.at("glyph"), configuration()("ending", "unlock jackpot"), configuration()("ending", "messages foreground").get<glm::vec4>()};
|
||||
message.dimensions(configuration()("ending", "messages dimensions"));
|
||||
ending_messages.push_back(message);
|
||||
}
|
||||
}
|
||||
|
||||
configuration()["progress"]["current level"] = 1;
|
||||
|
||||
/* Update save progress */
|
||||
|
@ -1112,6 +1131,15 @@ void Cakefoot::load_level(int index)
|
|||
{
|
||||
if (profile_index < static_cast<int>(configuration()("character", "profile").size()) - 1)
|
||||
{
|
||||
if (profile_index == configuration()("progress", "max level"))
|
||||
{
|
||||
sb::Text message {fonts.at("glyph")};
|
||||
message.foreground(configuration()("ending", "messages foreground").get<glm::vec4>());
|
||||
profile_index == 1 ? message.content(configuration()("ending", "unlock beef")) : message.content(configuration()("ending", "unlock buffalo"));
|
||||
message.dimensions(configuration()("ending", "messages dimensions"));
|
||||
ending_messages.push_back(message);
|
||||
}
|
||||
|
||||
configuration()["progress"]["max difficulty"] = ++profile_index;
|
||||
configuration()["progress"]["max level"] = 1;
|
||||
character.profile(configuration()("character", "profile", profile_index, "name"));
|
||||
|
@ -1122,12 +1150,18 @@ void Cakefoot::load_level(int index)
|
|||
{
|
||||
configuration()["progress"]["quest best"] = run_timer.elapsed();
|
||||
label.at("quest best").content(configuration()("display", "quest best text").get<std::string>() + " " + format_clock(run_timer.elapsed()));
|
||||
sb::Text message {fonts.at("glyph"), configuration()("ending", "new best"), configuration()("ending", "messages foreground").get<glm::vec4>()};
|
||||
message.dimensions(configuration()("ending", "messages dimensions"));
|
||||
ending_messages.push_back(message);
|
||||
}
|
||||
}
|
||||
|
||||
write_progress();
|
||||
level_select_index = 1;
|
||||
}
|
||||
|
||||
/* Otherwise, if the level is not the title screen, save it as the current level in the player's progress. Also save the newly assigned current level
|
||||
* in the level select index. */
|
||||
else if (index > 0)
|
||||
{
|
||||
/* Unlock the level if it is a newly reached level */
|
||||
|
@ -1926,7 +1960,8 @@ void Cakefoot::update(float timestamp)
|
|||
{
|
||||
/* Update character, along the curve, using the timer to determine movement since last frame, and update enemies. Check for collison
|
||||
* as enemies are updated. */
|
||||
character.update(curve(), unpaused_timer, !button.at("volume").pressed());
|
||||
character.update(curve(), unpaused_timer, !button.at("volume").pressed(),
|
||||
level_index ? std::nullopt : std::optional<float>(configuration()("character", "idle speed").get<float>()));
|
||||
if (character.at_end(curve()))
|
||||
{
|
||||
/* On the end level, save the score and name entry. */
|
||||
|
@ -1939,9 +1974,9 @@ void Cakefoot::update(float timestamp)
|
|||
/* Collect any previously taken coins */
|
||||
collect_coin();
|
||||
|
||||
/* Load next level, or reload current level if in level select mode */
|
||||
/* Load next level, or reload current level if in level select mode or on title screen */
|
||||
audio.at("teleport").play();
|
||||
load_level(level_select() ? level_index : level_index + 1);
|
||||
load_level(level_select() || level_index == 0 ? level_index : level_index + 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2139,7 +2174,13 @@ void Cakefoot::update(float timestamp)
|
|||
glm::mat4 label_transformation {0.0f};
|
||||
if (level_index == 0)
|
||||
{
|
||||
/* Flash play button */
|
||||
glUniform4fv(uniform.at("color addition"), 1, &rotating_hue.normal()[0]);
|
||||
button.at("start").draw(uniform["mvp"], view, projection, uniform["texture enabled"]);
|
||||
if (!flash_animation.playing())
|
||||
{
|
||||
glUniform4fv(uniform.at("color addition"), 1, &glm::vec4(0)[0]);
|
||||
}
|
||||
|
||||
/* Disable spinners in arcade-only mode */
|
||||
if (!configuration()("display", "arcade only"))
|
||||
|
@ -2273,6 +2314,29 @@ void Cakefoot::update(float timestamp)
|
|||
qr_code.draw(uniform.at("mvp"), view, projection, uniform.at("texture enabled"));
|
||||
}
|
||||
|
||||
/* Draw end screen messages */
|
||||
if (static_cast<std::size_t>(level_index) == configuration()("levels").size() - 1)
|
||||
{
|
||||
float y = configuration()("ending", "messages y").get<float>();
|
||||
for (std::size_t message_ii = 0; message_ii < ending_messages.size(); message_ii++)
|
||||
{
|
||||
sb::Text& message = ending_messages[message_ii];
|
||||
message.untransform();
|
||||
message.translate({0.0f, y, 0.0f});
|
||||
message.scale(configuration()("ending", "messages scale"));
|
||||
message.texture(0).bind();
|
||||
label_transformation = projection * view * message.transformation();
|
||||
glUniformMatrix4fv(uniform["mvp"], 1, GL_FALSE, &label_transformation[0][0]);
|
||||
message.enable();
|
||||
glDrawArrays(GL_TRIANGLES, 0, message.attributes("position")->count());
|
||||
if (message_ii == 0)
|
||||
{
|
||||
y += configuration()("ending", "messages margin").get<float>();
|
||||
}
|
||||
y += configuration()("ending", "messages step").get<float>();
|
||||
}
|
||||
}
|
||||
|
||||
/* Update FPS indicator display to the current FPS count and draw. */
|
||||
if (configuration()["display"]["fps"])
|
||||
{
|
||||
|
|
|
@ -224,8 +224,13 @@ private:
|
|||
{"name 3 decrement", sb::Pad<>()},
|
||||
{"fullscreen", sb::Pad<>()}
|
||||
};
|
||||
std::shared_ptr<TTF_Font> large_font {font(configuration()("display", "default font path").get<std::string>(), 72)},
|
||||
small_font {font(configuration()("display", "default font path").get<std::string>(), 12)};
|
||||
std::map<std::string, std::shared_ptr<TTF_Font>> fonts {
|
||||
{"medium", font(configuration()("font", "medium", "path").get<std::string>(), configuration()("font", "medium", "size"))},
|
||||
{"small", font(configuration()("font", "small", "path").get<std::string>(), configuration()("font", "small", "size"))},
|
||||
{"large", font(configuration()("font", "large", "path").get<std::string>(), configuration()("font", "large", "size"))},
|
||||
{"glyph", font(configuration()("font", "glyph", "path").get<std::string>(), configuration()("font", "glyph", "size"))},
|
||||
{"glyph large", font(configuration()("font", "glyph large", "path").get<std::string>(), configuration()("font", "glyph large", "size"))}
|
||||
};
|
||||
std::map<std::string, sb::Text> label = {
|
||||
{"fps", sb::Text(font())},
|
||||
{"clock", sb::Text(font())},
|
||||
|
@ -235,9 +240,9 @@ private:
|
|||
{"challenge", sb::Text(font())},
|
||||
{"view", sb::Text(font())},
|
||||
{"game over", sb::Text(font())},
|
||||
{"arcade rank", sb::Text(large_font)},
|
||||
{"arcade distance", sb::Text(large_font)},
|
||||
{"quest best", sb::Text(font())}
|
||||
{"arcade rank", sb::Text(fonts.at("large"))},
|
||||
{"arcade distance", sb::Text(fonts.at("large"))},
|
||||
{"quest best", sb::Text(fonts.at("glyph"))}
|
||||
};
|
||||
sb::Sprite playing_field, checkpoint_on, checkpoint_off, coin {"resource/coin/coin-0.png", glm::vec2{12.0f / 486.0f}}, qr_code;
|
||||
sb::Timer on_timer, run_timer, unpaused_timer;
|
||||
|
@ -247,16 +252,16 @@ private:
|
|||
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};
|
||||
bool use_play_button = false, coin_collected = false;
|
||||
ArcadeScores arcade_scores;
|
||||
ArcadeScores::Score arcade_score;
|
||||
std::string name_entry = "AAA";
|
||||
sb::Text scoreboard {large_font};
|
||||
sb::Text scoreboard {fonts.at("large")};
|
||||
std::vector<Flame> ending_coins;
|
||||
sb::Color rotating_hue {128, 0, 0, 0};
|
||||
std::vector<sb::Text> ending_messages;
|
||||
|
||||
/*!
|
||||
* Load sound effects and music into objects that can be used by the SDL mixer library. Use chunk objects for background music instead of
|
||||
|
|
|
@ -14,7 +14,8 @@ void Character::profile(const std::string& name)
|
|||
|
||||
/* Reload the texture */
|
||||
_sprite.clear_textures();
|
||||
for (const std::string& path : 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);
|
||||
}
|
||||
|
@ -99,22 +100,31 @@ float Character::relative(const Curve& curve) const
|
|||
return float(next_point_index) / curve.length();
|
||||
}
|
||||
|
||||
void Character::update(const Curve& curve, const sb::Timer& timer, bool muted)
|
||||
void Character::update(const Curve& curve, const sb::Timer& timer, bool muted, std::optional<float> constant_speed)
|
||||
{
|
||||
if (timer.frame() > 0.0f)
|
||||
{
|
||||
/* Adjust speed based on acceleration state and character profile. */
|
||||
if (accelerating)
|
||||
if (constant_speed.has_value())
|
||||
{
|
||||
/* Override physics */
|
||||
speed = constant_speed.value();
|
||||
_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>();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Apply delta time to the speed decrease. */
|
||||
speed -= timer.delta(profile()["speed decrement"].get<float>()) + glm::abs(speed) * profile()["decrement mod"].get<float>();
|
||||
/* Adjust speed based on acceleration state and character profile. */
|
||||
if (accelerating)
|
||||
{
|
||||
_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>();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Apply delta time to the speed decrease. */
|
||||
speed -= timer.delta(profile()["speed decrement"].get<float>()) + glm::abs(speed) * profile()["decrement mod"].get<float>();
|
||||
}
|
||||
}
|
||||
|
||||
/* Clamp speed, applying delta time to the limits */
|
||||
|
@ -124,44 +134,47 @@ void Character::update(const Curve& curve, const sb::Timer& timer, bool muted)
|
|||
|
||||
/* Calculate volume based on speed relative to max speed */
|
||||
int volume;
|
||||
if (speed >= 0.0f)
|
||||
if (!constant_speed.has_value())
|
||||
{
|
||||
/* Only play walking forward effect. */
|
||||
audio.at("reverse").stop();
|
||||
if (!audio.at("walk").playing())
|
||||
{
|
||||
audio.at("walk").play(0.0f, walk_channel);
|
||||
}
|
||||
|
||||
if (!muted)
|
||||
{
|
||||
/* Get louder closer to max speed using an exponential scale */
|
||||
volume = std::round(std::pow(speed / max_speed, 3.0f) * static_cast<float>(MIX_MAX_VOLUME));
|
||||
audio.at("walk").channel_volume(volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
audio.at("walk").stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only play walking backward effect. */
|
||||
audio.at("walk").stop();
|
||||
if (!audio.at("reverse").playing())
|
||||
{
|
||||
audio.at("reverse").play(0.0f, reverse_channel);
|
||||
}
|
||||
|
||||
if (!muted)
|
||||
{
|
||||
/* Get louder closer to min speed using an exponential scale */
|
||||
volume = std::round(std::pow(speed / min_speed, 3.0f) * static_cast<float>(MIX_MAX_VOLUME));
|
||||
audio.at("reverse").channel_volume(volume);
|
||||
}
|
||||
else
|
||||
if (speed >= 0.0f)
|
||||
{
|
||||
/* Only play walking forward effect. */
|
||||
audio.at("reverse").stop();
|
||||
if (!audio.at("walk").playing())
|
||||
{
|
||||
audio.at("walk").play(0.0f, walk_channel);
|
||||
}
|
||||
|
||||
if (!muted)
|
||||
{
|
||||
/* Get louder closer to max speed using an exponential scale */
|
||||
volume = std::round(std::pow(speed / max_speed, 3.0f) * static_cast<float>(MIX_MAX_VOLUME));
|
||||
audio.at("walk").channel_volume(volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
audio.at("walk").stop();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only play walking backward effect. */
|
||||
audio.at("walk").stop();
|
||||
if (!audio.at("reverse").playing())
|
||||
{
|
||||
audio.at("reverse").play(0.0f, reverse_channel);
|
||||
}
|
||||
|
||||
if (!muted)
|
||||
{
|
||||
/* Get louder closer to min speed using an exponential scale */
|
||||
volume = std::round(std::pow(speed / min_speed, 3.0f) * static_cast<float>(MIX_MAX_VOLUME));
|
||||
audio.at("reverse").channel_volume(volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
audio.at("reverse").stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,16 +190,24 @@ void Character::update(const Curve& curve, const sb::Timer& timer, bool muted)
|
|||
if (speed > 0.0f)
|
||||
{
|
||||
if (speed == max_speed)
|
||||
{
|
||||
walk.frame_length(0.095f);
|
||||
}
|
||||
else if (speed > max_speed * 0.9f)
|
||||
{
|
||||
walk.frame_length(0.1f);
|
||||
}
|
||||
else if (speed > max_speed / 2)
|
||||
else if (speed > max_speed * 0.75f)
|
||||
{
|
||||
walk.frame_length(0.07f);
|
||||
walk.frame_length(0.125f);
|
||||
}
|
||||
else if (speed > max_speed * 0.5)
|
||||
{
|
||||
walk.frame_length(0.15f);
|
||||
}
|
||||
else
|
||||
{
|
||||
walk.frame_length(0.04f);
|
||||
walk.frame_length(0.175f);
|
||||
}
|
||||
_sprite.texture_increment(1);
|
||||
}
|
||||
|
@ -196,13 +217,17 @@ void Character::update(const Curve& curve, const sb::Timer& timer, bool muted)
|
|||
{
|
||||
walk.frame_length(0.1f);
|
||||
}
|
||||
else if (speed < max_speed / 2)
|
||||
else if (speed < max_speed * 0.75f)
|
||||
{
|
||||
walk.frame_length(0.07f);
|
||||
walk.frame_length(0.125f);
|
||||
}
|
||||
else if (speed < max_speed * 0.5f)
|
||||
{
|
||||
walk.frame_length(0.15f);
|
||||
}
|
||||
else
|
||||
{
|
||||
walk.frame_length(0.04f);
|
||||
walk.frame_length(0.175f);
|
||||
}
|
||||
_sprite.texture_increment(-1);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
* 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`
|
||||
* @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);
|
||||
|
||||
|
@ -146,11 +146,12 @@ public:
|
|||
/*!
|
||||
* 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 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);
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue