integrate ads API on coolmath builds, add loading message

This commit is contained in:
ohsqueezy 2023-12-27 19:21:56 -08:00
parent 63336a3126
commit 9fa8051b06
11 changed files with 189 additions and 35 deletions

View File

@ -138,7 +138,7 @@ $(addsuffix /Attributes.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Attribute
$(addsuffix /Model.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Model.cpp Model.hpp extension.hpp Attributes.hpp Texture.hpp Carousel.hpp) | $(BUILD_DIRS)
$(CXX) $(CXXFLAGS) $< -c -o $@
$(addsuffix /Text.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Text.cpp Text.hpp Model.hpp Color.hpp Log.hpp) | $(BUILD_DIRS)
$(addsuffix /Text.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Text.cpp Text.hpp Model.hpp Color.hpp Log.hpp Texture.hpp) | $(BUILD_DIRS)
$(CXX) $(CXXFLAGS) $< -c -o $@
$(addsuffix /Color.o, $(BUILD_DIRS)): $(addprefix $(SB_SRC_DIR)/, Color.cpp Color.hpp) | $(BUILD_DIRS)
@ -199,8 +199,8 @@ Cakefoot-linux_debug.x86_64 : $(LINUX_DEBUG_OBJ)
EMSCRIPTENHOME = $(HOME)/ext/software/emsdk/upstream/emscripten
EMSCRIPTEN_CFLAGS = -Oz -Wall -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORMATS="['png', 'jpg']" -s USE_SDL_TTF=2 -s USE_SDL_MIXER=2 \
-I $(SB_LIB_DIR) -I $(SB_SRC_DIR)
EMSCRIPTEN_LFLAGS = -s MIN_WEBGL_VERSION=2 -s EXPORTED_FUNCTIONS="['_main', '_malloc']" -s LLD_REPORT_UNDEFINED -s NO_DISABLE_EXCEPTION_CATCHING \
-s FULL_ES3=1 -lidbfs.js -s ALLOW_MEMORY_GROWTH=1
EMSCRIPTEN_LFLAGS = -s MIN_WEBGL_VERSION=2 -s EXPORTED_FUNCTIONS="['_main', '_malloc', '_pause_for_ads', '_unpause_for_ads']" -s LLD_REPORT_UNDEFINED \
-s NO_DISABLE_EXCEPTION_CATCHING -s FULL_ES3=1 -lidbfs.js -s ALLOW_MEMORY_GROWTH=1
EMSCRIPTEN_PRELOADS = --preload-file "config.json" --preload-file "resource/" --preload-file "src/shaders/" --preload-file "src/config_wasm.json" \
--pre-js "src/pre_js.js"
EMSCRIPTEN_GAME_CONFIGS = config.json src/config_wasm.json resource/levels.json
@ -230,6 +230,9 @@ cakefoot_coolmath.js : $(addprefix $(WASM_COOLMATH_BUILD_DIR)/, SDL2_rotozoom.o
$(CXX) $(filter-out $(EMSCRIPTEN_GAME_CONFIGS), $^) $(CXXFLAGS) $(EMSCRIPTEN_LFLAGS) -D__COOLMATH__ $(EMSCRIPTEN_PRELOADS) \
--preload-file "src/config_coolmath.json" -o $(WASM_COOLMATH_BUILD_DIR)/$@
cp src/index_coolmath.html $(WASM_COOLMATH_BUILD_DIR)/index.html
cd $(WASM_COOLMATH_BUILD_DIR) && \
zip -r Cakefoot_coolmath.zip cakefoot_coolmath.data cakefoot_coolmath.js cakefoot_coolmath.wasm index.html && \
rm cakefoot_coolmath.data cakefoot_coolmath.js cakefoot_coolmath.wasm index.html && cd -
#################
# Android build #

View File

@ -70,10 +70,19 @@
padding: 0% 1%;
margin-top: 8px;
}
p#loading
{
font-size: 72px;
}
</style>
</head>
<body>
<p id="loading">
Loading...
</p>
<!-- Emscripten's module object will update this canvas with WebGL content. -->
<canvas id="canvas"></canvas>

2
lib/sb

@ -1 +1 @@
Subproject commit 11c8abcc5441db15dbdcbb9cce8c42fc37803607
Subproject commit 1fff973b46684277e34c2a78ab857fa4766ca5e5

View File

@ -140,8 +140,8 @@ Cakefoot::Cakefoot(std::initializer_list<std::string> configuration_merge) : Gam
character.profile(configuration()("character", "profile", profile_index, "name"));
/* 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)};
checkpoint_on = sb::Sprite {"resource/checkpoint/on.png", glm::vec2(12.0f / 486.0f), GL_LINEAR};
checkpoint_off = sb::Sprite {"resource/checkpoint/off.png", glm::vec2(12.0f / 486.0f), GL_LINEAR};
/* Set hitbox */
character.box_size(configuration()("character", "hitbox").get<float>());
@ -439,6 +439,10 @@ void Cakefoot::set_up_buttons()
challenge_index = 3;
configuration()["progress"]["current challenge"] = challenge_index;
}
#if defined(__COOLMATH__)
/* Coolmath API */
EM_ASM( if (parent.cmgGameEvent !== undefined) { console.log("cmgGameEvent start"); parent.cmgGameEvent("start"); } );
#endif
load_level(level_select_index);
});
button.at("resume").on_state_change([&](bool state){
@ -1366,6 +1370,21 @@ void Cakefoot::load_level(int index)
/* Flash the screen at the start of a level */
flash_animation.play_once(configuration()("display", "flash length"));
#if defined(__COOLMATH__)
/* Send a game event to the Coolmath API if it's a regular level. */
if (index > 0 && static_cast<std::size_t>(index) < configuration()("levels").size() - 1)
{
EM_ASM(
{
if (parent.cmgGameEvent !== undefined)
{
console.log("cmgGameEvent start " + $0);
parent.cmgGameEvent("start", $0);
}
}, index);
}
#endif
}
void Cakefoot::write_progress() const
@ -2082,6 +2101,55 @@ void Cakefoot::respond(SDL_Event& event)
}
}
else if (sb::Delegate::compare(event, "pause for ads"))
{
/* Store current volume to be restored when returning from ads by looking at the state of the button. */
if (button.at("volume").pressed())
{
pre_ad_volume = 1.0f;
}
else
{
pre_ad_volume = 0.0f;
}
std::ostringstream message;
message << "Pre-ad volume registered as " << pre_ad_volume.value();
sb::Log::log(message);
/* Mute without changing the state of the button to avoid losing the original state if this event is fired twice in a row. */
Mix_Volume(-1, 0);
if (level_index > 0 && static_cast<std::size_t>(level_index) <= configuration()("levels").size() - 2)
{
/* Pause game */
unpaused_timer.off();
run_timer.off();
}
}
else if (sb::Delegate::compare(event, "unpause for ads"))
{
/* Restore volume to the volume of the mixer before the ads started */
std::ostringstream message;
if (pre_ad_volume.has_value())
{
Mix_Volume(-1, sb::audio::convert_volume(pre_ad_volume.value()));
message << "Restoring volume to " << pre_ad_volume.value();
}
else
{
message << "Not restoring volume because pre-ad value was not registered";
}
sb::Log::log(message);
if (level_index > 0 && static_cast<std::size_t>(level_index) <= configuration()("levels").size() - 2)
{
/* Unpause game */
unpaused_timer.on();
run_timer.on();
}
}
else if (sb::Delegate::compare(event, "reconfig"))
{
load_curves();
@ -2353,6 +2421,14 @@ void Cakefoot::update(float timestamp)
/* 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 == 0 ? level_index : level_index + 1);
#if defined(__COOLMATH__)
/* Trigger an ad when a level is beaten */
if (level_index > 0 && static_cast<std::size_t>(level_index) < configuration()("levels").size() - 1)
{
EM_ASM(cmgAdBreak());
}
#endif
}
}
else
@ -2380,9 +2456,7 @@ void Cakefoot::update(float timestamp)
configuration()["progress"]["quest checkpoint"] = character.checkpoint();
}
write_progress();
}
}
}
} } }
/* Collide with enemies and challenge coins */
bool enemy_collision = false;
@ -2398,8 +2472,7 @@ void Cakefoot::update(float timestamp)
{
audio.at("take").play();
enemy->take_coin();
}
}
} }
/* Collide with ending screen coins */
if (end_screen())
@ -2433,9 +2506,7 @@ void Cakefoot::update(float timestamp)
/* Record a death */
configuration()["progress"]["deaths"].get_ref<nlohmann::json::number_integer_t&>()++;
write_progress();
}
}
}
} } }
/* Plane position vertices will be used for everything before the curve */
sb::Plane::position->bind("vertex_position", shader_program);
@ -2729,8 +2800,7 @@ void Cakefoot::update(float timestamp)
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"])
@ -2800,6 +2870,21 @@ EM_BOOL respond_to_gamepad_connected(int event_type, const EmscriptenGamepadEven
game->open_game_controller();
return true;
}
extern "C"
{
void pause_for_ads()
{
sb::Delegate::post("pause for ads", false);
}
void unpause_for_ads()
{
sb::Delegate::post("unpause for ads", false);
}
}
#endif
int main()

View File

@ -244,7 +244,7 @@ private:
{"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, qr_code_bg, social;
sb::Sprite playing_field, checkpoint_on, checkpoint_off, coin {"resource/coin/coin-0.png", glm::vec2{12.0f / 486.0f}, GL_LINEAR}, qr_code, qr_code_bg, social;
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;
@ -264,6 +264,7 @@ private:
std::vector<sb::Text> ending_messages;
std::optional<std::string> selected;
std::shared_ptr<SDL_GameController> controller = nullptr;
std::optional<float> pre_ad_volume = std::nullopt;
/*!
* Load sound effects and music into objects that can be used by the SDL mixer library. Use chunk objects for background music instead of
@ -547,6 +548,24 @@ EM_BOOL respond_to_visibility_change(int event_type, const EmscriptenVisibilityC
* @return True to indicate that the event was consumed by the handler
*/
EM_BOOL respond_to_gamepad_connected(int event_type, const EmscriptenGamepadEvent* gamepad_event, void* user_data);
extern "C"
{
/*!
* Custom pause event for use with ad APIs that posts a "pause for ads" event using sb::Delegate::post(const std::string&, bool). This function will
* be exported for use in the JavaScript code in* a web build and is not available in other types of builds.
*/
void pause_for_ads();
/*!
* Custom pause event for use with ad APIs that posts a "unpause for ads" event using sb::Delegate::post(const std::string&, bool). This function will
* be exported for use in the JavaScript code in a web build and is not available in other types of builds.
*/
void unpause_for_ads();
}
#endif
/*!

View File

@ -15,9 +15,9 @@ 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");
for (const std::string& path : frames)
for (const std::string path : frames)
{
_sprite.texture(path);
_sprite.texture(path, GL_LINEAR);
}
_sprite.scale(size);
}

View File

@ -66,8 +66,8 @@ void Enemy::draw(GLuint transformation_uniform, const glm::mat4& view, const glm
Slicer::Slicer(const Curve& curve, float relative, float speed, float stray) : curve(curve), relative(relative), speed(speed), stray(stray)
{
position = start();
sprite.texture("resource/slicer/slicer-1.png");
sprite.texture("resource/slicer/slicer-2.png");
sprite.texture("resource/slicer/slicer-1.png", GL_LINEAR);
sprite.texture("resource/slicer/slicer-2.png", GL_LINEAR);
sprite.frames.frame_length(0.5f);
sprite.frames.play();
@ -171,8 +171,8 @@ bool Slicer::collide_coin(sb::Box box, const glm::vec3& clip_lower, const glm::v
Fish::Fish(const Curve& curve, float relative, float speed, float radius, float offset) :
curve(curve), relative(relative), speed(speed), radius(radius), offset(offset)
{
sprite.texture("resource/fish/fish-1.png");
sprite.texture("resource/fish/fish-2.png");
sprite.texture("resource/fish/fish-1.png", GL_LINEAR);
sprite.texture("resource/fish/fish-2.png", GL_LINEAR);
sprite.frames.frame_length(0.3f);
sprite.frames.play();
@ -257,10 +257,10 @@ Projectile::Projectile(const glm::vec3& position, const glm::vec3& target, float
angle = sb::angle_between(position, target);
/* Initialize sprite */
sprite.texture("resource/projectile/projectile-1.png");
sprite.texture("resource/projectile/projectile-2.png");
sprite.texture("resource/projectile/projectile-3.png");
sprite.texture("resource/projectile/projectile-4.png");
sprite.texture("resource/projectile/projectile-1.png", GL_LINEAR);
sprite.texture("resource/projectile/projectile-2.png", GL_LINEAR);
sprite.texture("resource/projectile/projectile-3.png", GL_LINEAR);
sprite.texture("resource/projectile/projectile-4.png", GL_LINEAR);
sprite.frames.frame_length(0.05f);
sprite.frames.play();
@ -324,11 +324,11 @@ bool Projectile::coinified() const
}
Projector::Projector(const Character& character, const glm::vec3& position, float speed, float rate, float release_delay) :
character(character), position(position), speed(speed), rate(rate), release_delay(release_delay)
character(character), position(position), speed(speed), release_delay(release_delay)
{
animation_charge.frame_length(rate);
sprite.texture("resource/projector/projector-1.png");
sprite.texture("resource/projector/projector-2.png");
sprite.texture("resource/projector/projector-1.png", GL_LINEAR);
sprite.texture("resource/projector/projector-2.png", GL_LINEAR);
/* Set size and position of objects */
glm::vec2 size {12.0f / 486.0f};
@ -474,12 +474,12 @@ Flame::Flame(const sb::Box& field, const glm::vec3& position, float speed, float
/* Set up animation */
if (!camo)
{
sprite.texture("resource/flame/flame-1.png");
sprite.texture("resource/flame/flame-2.png");
sprite.texture("resource/flame/flame-1.png", GL_LINEAR);
sprite.texture("resource/flame/flame-2.png", GL_LINEAR);
}
else
{
sprite.texture("resource/coin/coin-0.png");
sprite.texture("resource/coin/coin-0.png", GL_LINEAR);
}
sprite.frames.frame_length(0.3f);
sprite.frames.play();

View File

@ -286,7 +286,7 @@ private:
const Character& character;
glm::vec3 position = glm::vec3{0.0f};
float speed = 0.0f, rate = 0.0f;
float speed = 0.0f;
float release_delay;
sb::Animation animation_charge = sb::Animation(std::bind(&Projector::charge, this)),
animation_release = sb::Animation(std::bind(&Projector::release, this));

View File

@ -1,6 +1,17 @@
{
"display":
{
"title": "cakefoot🍰👣 Play it now at CoolmathGames.com"
"dimensions": [800, 450],
"title": "cakefoot🍰👣 Play it now at CoolmathGames.com",
"fullscreen enabled": false
},
"keys":
{
"reset": [],
"skip forward": [],
"skip backward": [],
"memory": [],
"coords": []
}
}

View File

@ -21,14 +21,40 @@
aspect-ratio: 16 / 9;
}
p#loading
{
font-size: 16px;
background: #000;
color: #fff;
}
</style>
</head>
<body>
<p id="loading">
Loading...
</p>
<!-- Emscripten's module object will update this canvas with WebGL content. -->
<canvas id="canvas"></canvas>
<!-- This file is built by Emscripten when compiling the program -->
<script src="cakefoot_coolmath.js"></script>
<!-- Coolmath API requirements -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<script type="text/javascript" src="https://www.coolmathgames.com/sites/default/files/cmg-ads.js"></script>
<!-- Coolmath API custom events. Pause/unpause the game for ads -->
<script>
document.addEventListener("adBreakStart", () => {
console.log("AdBreak Started")
_pause_for_ads();
});
document.addEventListener("adBreakComplete", () => {
console.log("adBreak Complete")
_unpause_for_ads();
});
</script>
</body>
</html>

View File

@ -26,6 +26,7 @@ Module.onRuntimeInitialized = function()
}
else
{
document.getElementById("loading").remove();
_main();
}
});