- rebuild emscripten build when levels.json changes

- add precision to enemy angles to account for accumulating drift
- add challenge coin parameters to wave enemy
- fix flame mirror drift by resetting position each cycle
- fix fish angle desync by using time since init to calculate angle
This commit is contained in:
ohsqueezy 2023-09-12 03:02:54 +00:00
parent bd36c762eb
commit 712c6cf3ea
8 changed files with 92 additions and 56 deletions

View File

@ -110,28 +110,27 @@ Cakefoot-linux.x86_64 : $(LINUX_OBJ)
EMSCRIPTENHOME = $(HOME)/ext/software/emsdk/upstream/emscripten
EMSCRIPTEN_CFLAGS = -O0 -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 \
--no-heap-copy -I $(SB_LIB_DIR) -I $(SB_SRC_DIR) \
# -fsanitize=undefined -fsanitize=address --pre-js emscripten_asan_options.js
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 -s ALLOW_MEMORY_GROWTH=1 \
# -fsanitize=undefined -fsanitize=address
EMSCRIPTEN_PRELOADS = --preload-file "BPmono.ttf"@/ --preload-file "config.json"@/ --preload-file "config_wasm.json"@/ --preload-file "resource/"@/"resource/" \
--preload-file "src/shaders/"@/"src/shaders/"
EMSCRIPTEN_GAME_CONFIGS = config.json config_wasm.json resource/levels.json
cakefoot.js : CC = $(EMSCRIPTENHOME)/emcc
cakefoot.js : CXX = $(EMSCRIPTENHOME)/em++
cakefoot.js : CFLAGS = $(EMSCRIPTEN_CFLAGS)
cakefoot.js : CXXFLAGS = $(CFLAGS) --std=c++17
cakefoot.js : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES) config.json config_wasm.json
cakefoot.js : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES) $(EMSCRIPTEN_GAME_CONFIGS)
$(CREATE_FONT_SYMLINK)
$(CXX) $(filter-out $(wildcard *.json), $^) $(CXXFLAGS) $(EMSCRIPTEN_LFLAGS) $(EMSCRIPTEN_PRELOADS) -o cakefoot.js
$(CXX) $(filter-out $(EMSCRIPTEN_GAME_CONFIG), $^) $(CXXFLAGS) $(EMSCRIPTEN_LFLAGS) $(EMSCRIPTEN_PRELOADS) -o cakefoot.js
cakefoot_debug.html : CC = $(EMSCRIPTENHOME)/emcc
cakefoot_debug.html : CXX = $(EMSCRIPTENHOME)/em++
cakefoot_debug.html : CFLAGS = $(EMSCRIPTEN_CFLAGS) -g2
cakefoot_debug.html : CXXFLAGS = $(CFLAGS) --std=c++17
cakefoot_debug.html : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES) config.json config_wasm.json
cakefoot_debug.html : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) $(SB_O_FILES) $(SRC_O_FILES) $(EMSCRIPTEN_GAME_CONFIG)
$(CREATE_FONT_SYMLINK)
$(CXX) $(filter-out $(wildcard *.json), $^) $(CXXFLAGS) $(EMSCRIPTEN_LFLAGS) $(EMSCRIPTEN_PRELOADS) --memoryprofiler --cpuprofiler -o cakefoot_debug.html
$(CXX) $(filter-out $(EMSCRIPTEN_GAME_CONFIGS), $^) $(EMSCRIPTEN_LFLAGS) $(EMSCRIPTEN_PRELOADS) --memoryprofiler --cpuprofiler -o cakefoot_debug.html
#################
# Android build #

View File

@ -112,7 +112,7 @@
},
{
"start": 11,
"color": [0.151, 0.23, 0.12, 1.0]
"color": [0.151, 0.2, 0.12, 1.0]
},
{
"start": 17,

2
lib/sb

@ -1 +1 @@
Subproject commit fb76e08707a4fc5d80250a6d259f4b7fb36a94a8
Subproject commit 4c3235c2ffd35ebcfaacca3cd0c417826c363e74

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 B

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -147,12 +147,12 @@
"enemies": [
["fish", 0.25, -0.2, 100, 0.0],
["fish", 0.75, 0.2, 100, 0.0],
["flame", [-1.77, -0.75, 0], 0.25, 1.57, -1],
["flame", [-1.18, -0.75, 0], 0.25, 1.57, -1],
["flame", [-0.59, -0.75, 0], 0.25, 1.57, -1],
["flame", [0, -0.75, 0], 0.25, 1.57, -1],
["flame", [0.59, -0.75, 0], 0.25, 1.57, -1],
["flame", [1.18, -0.75, 0], 0.25, 1.57, -1],
["flame", [-1.77, -0.75, 0], 0.25, 1.5707963267948966, -1],
["flame", [-1.18, -0.75, 0], 0.25, 1.5707963267948966, -1],
["flame", [-0.59, -0.75, 0], 0.25, 1.5707963267948966, -1],
["flame", [0, -0.75, 0], 0.25, 1.5707963267948966, -1],
["flame", [0.59, -0.75, 0], 0.25, 1.5707963267948966, -1],
["flame", [1.18, -0.75, 0], 0.25, 1.5707963267948966, -1],
["slicer", 0.97, 6, 75, 0.09, 4.712]
]
},
@ -232,16 +232,16 @@
["slicer", 0.5, 13.5, 200],
["slicer", 0.5, 11.5, 200],
["slicer", 0.5, 8, 200],
["flame", [-1.77, 0.8, 0], 0.25, 4.71, -1],
["flame", [-1.18, 0.8, 0], 0.25, 4.71, -1],
["flame", [-0.59, 0.8, 0], 0.25, 4.71, -1],
["flame", [0, 0.8, 0], 0.25, 4.71, -1],
["flame", [-1.77, 0.8, 0], 0.25, 4.71238898038469, -1],
["flame", [-1.18, 0.8, 0], 0.25, 4.71238898038469, -1],
["flame", [-0.59, 0.8, 0], 0.25, 4.71238898038469, -1],
["flame", [0, 0.8, 0], 0.25, 4.71238898038469, -1],
["flame", [0.59, 0.8, 0], 0.25, 4.71, -1],
["flame", [1.18, 0.8, 0], 0.25, 4.71, -1],
["flame", [-1.1, 1.0, 0], 0.25, 3.14, -1],
["flame", [-1.1, 0.5, 0], 0.25, 3.14, -1],
["flame", [-1.1, 0, 0], 0.25, 3.14, -1],
["flame", [-1.1, -0.5, 0], 0.25, 3.14, -1],
["flame", [-1.1, 1.0, 0], 0.25, 3.141592653589793, -1],
["flame", [-1.1, 0.5, 0], 0.25, 3.141592653589793, -1],
["flame", [-1.1, 0, 0], 0.25, 3.141592653589793, -1],
["flame", [-1.1, -0.5, 0], 0.25, 3.141592653589793, -1],
["flame", [1.1, 1.0, 0], 0.25, 0, -1],
["flame", [1.1, 0.5, 0], 0.25, 0, -1],
["flame", [1.1, 0, 0], 0.25, 0, -1],
@ -574,7 +574,7 @@
["wave", 0.0, 7, 0.08, 0.3, 0.79, [0.95, 1.15]],
["wave", 0.0, 7, 0.08, 0.3, 0.56, [1.25, 1.45]],
["wave", 0.0, 7, 0.08, 0.3, 0.79, [1.55, 1.75]],
["wave", 0.15, 7, 0.08, -0.35, -0.8]
["wave", 0.15, 7, 0.08, -0.35, -0.8, [-1.77, 1.77], -1.0, 8, 0.08, 0.15]
],
"checkpoints": [
{
@ -774,15 +774,15 @@
["fish", 0.84, 0.045, 180.0, 4.398],
["fish", 0.84, 0.045, 180.0, 5.655],
["flame", [0.9875, 0.975, 0.0], 0.15, 3.14, 2.3],
["flame", [0.9875, 0.875, 0.0], 0.15, 3.14, 2.3],
["flame", [0.9875, 0.975, 0.0], 0.15, 3.141592653589793, 2.3],
["flame", [0.9875, 0.875, 0.0], 0.15, 3.141592653589793, 2.3],
["flame", [0.8175, 0.59, 0.0], 0.15, 1.57, 2.3],
["flame", [1.17, 0.59, 0.0], 0.15, -1.57, 2.3],
["flame", [0.8175, 0.59, 0.0], 0.15, 1.5707963267948966, 2.3],
["flame", [1.17, 0.59, 0.0], 0.15, -1.5707963267948966, 2.3],
["flame", [1.15, 0.2, 0.0], 0.15, -1.57, 2.3],
["flame", [1.15, 0.2, 0.0], 0.15, -1.5707963267948966, 2.3],
["flame", [0.9875, -0.075, 0.0], 0.15, 3.14, 2.3],
["flame", [0.9875, -0.075, 0.0], 0.15, 3.141592653589793, 2.3],
["fish", 0.952, 0.015, 80.0, 0.0],
["fish", 0.952, 0.015, 80.0, 1.257],
@ -893,34 +893,34 @@
["flame", [1.115, 0.42, 0.0], 0.125, 0, 1],
["slicer", 0.476, 6.0, 72.5],
["flame", [1.225, 0.77, 0.0], 0.125, 1.57, 3.8],
["flame", [1.225, 0.77, 0.0], 0.125, 1.5707963267948966, 3.8],
["flame", [-1.53, 0.21, 0.0], 0.125, 0, 1],
["flame", [-1.48, 0.21, 0.0], 0.125, 0, 1],
["fish", 0.72, 0.04, 30.0, 0.0],
["fish", 0.72, 0.05, 50.0, 0.0],
["fish", 0.72, 0.06, 70.0, 0.0],
["fish", 0.72, 0.07, 90.0, 0.0],
["fish", 0.72, 0.08, 110.0, 0.0],
["fish", 0.72, 0.09, 130.0, 0.0],
["fish", 0.72, 0.10, 150.0, 0.0],
["fish", 0.72, 0.11, 170.0, 0.0],
["fish", 0.72, 0.03769911184307752, 30.0, 0.0],
["fish", 0.72, 0.05026548245743669, 50.0, 0.0],
["fish", 0.72, 0.06283185307179587, 70.0, 0.0],
["fish", 0.72, 0.07539822368615504, 90.0, 0.0],
["fish", 0.72, 0.0879645943005142, 110.0, 0.0],
["fish", 0.72, 0.10053096491487339, 130.0, 0.0],
["fish", 0.72, 0.11309733552923255, 150.0, 0.0],
["fish", 0.72, 0.12566370614359174, 170.0, 0.0],
["flame", [-0.06, 0.21, 0.0], 0.125, 0, 1],
["flame", [-0.01, 0.21, 0.0], 0.125, 0, 1],
["flame", [0.04, 0.21, 0.0], 0.125, 0, 1],
["slicer", 0.787, 4.0, 65],
["flame", [0.05, -0.1, 0.0], 0.1, 1.57, 4.3],
["flame", [0.35, -0.1, 0.0], 0.1, 1.57, 4.3],
["flame", [0.65, -0.1, 0.0], 0.1, 1.57, 4.3],
["flame", [0.05, -0.35, 0.0], 0.1, 1.57, 4.3],
["flame", [0.35, -0.35, 0.0], 0.1, 1.57, 4.3],
["flame", [0.65, -0.35, 0.0], 0.1, 1.57, 4.3],
["flame", [0.05, -0.6, 0.0], 0.1, 1.57, 4.3],
["flame", [0.35, -0.6, 0.0], 0.1, 1.57, 4.3],
["flame", [0.65, -0.6, 0.0], 0.1, 1.57, 4.3],
["flame", [0.05, -0.1, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.35, -0.1, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.65, -0.1, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.05, -0.35, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.35, -0.35, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.65, -0.35, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.05, -0.6, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.35, -0.6, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [0.65, -0.6, 0.0], 0.1, 1.5707963267948966, 4.3],
["flame", [1.41, 0.21, 0.0], 0.125, 0, 1],
["flame", [1.46, 0.21, 0.0], 0.125, 0, 1],

View File

@ -263,7 +263,11 @@ void Cakefoot::load_level(int index)
sb::Box field {-curve().aspect, -1.0f, 2.0f * curve().aspect, 2.0f};
/* Reset enemies list to empty. Open configuration for the current level. Repopulate list of enemies one by one using the list of enemies in the
* configuration. For each enemy, add a challenge coin if the config specifies the coin parameters. */
* configuration. For each enemy, add a challenge coin if the config specifies the coin parameters.
*
* Values read from the config are in some cases converted from old 25fps hard-coded per-frame values to per-second values, and hard-coded
* 864px by 486px pixel space to relative NDC space.
*/
this->enemies.clear();
if (configuration()("levels", index).contains("enemies"))
{
@ -344,7 +348,7 @@ void Cakefoot::load_level(int index)
float x = field.left() + shift * margin.x / 2.0f;
while (x < field.right())
{
std::shared_ptr<Flame> flame = std::make_shared<Flame>(field, glm::vec3{x, y, 0.0f}, 0.41152263f, 25.0f * glm::quarter_pi<float>());
std::shared_ptr<Flame> flame = std::make_shared<Flame>(field, glm::vec3{x, y, 0.0f}, 0.41152263f, glm::quarter_pi<float>());
/* Add a challenge coin */
if (++count == 15)
@ -379,10 +383,14 @@ void Cakefoot::load_level(int index)
range = enemy[6].get<glm::vec2>();
}
float x = range.x;
while (x < range.y)
for (std::size_t count = 0; x < range.y; ++count)
{
y = amplitude * glm::sin(period * x) + shift;
std::shared_ptr<Flame> flame = std::make_shared<Flame>(field, glm::vec3{x, y, 0.0f}, speed, 3.0f * glm::half_pi<float>(), mirror);
if (enemy.size() > 8 && enemy[8].get<std::size_t>() == count)
{
flame->coin(coin, enemy[9].get<float>(), enemy[10].get<float>());
}
this->enemies.push_back(flame);
x += step;
}

View File

@ -180,8 +180,19 @@ void Fish::coin(const sb::Sprite& sprite, float radius, float angle)
void Fish::update(const sb::Timer& timer)
{
angle += timer.delta(speed);
glm::vec3 position = center() + glm::vec3{sb::angle_to_vector(angle + offset, radius), 0.0f};
/* On the first update, record the timestamp of the timer, so the difference between subsequent timestamps and the first timestamp can
* be used to measure the angle position of the fish. Do this instead of adding to the angle position every frame to avoid letting
* floating point addition error accumulate differently among fish with different speeds. */
if (!first_update_time.has_value())
{
first_update_time = timer.elapsed();
}
/* The angle position is the seconds since the first update multiplied by radians per second plus the fish's given angle offset. */
angle = (timer.elapsed() - *first_update_time) * speed + offset;
/* Place the fish an amount away from its center using the angle and radius to get the vector. */
glm::vec3 position = center() + glm::vec3{sb::angle_to_vector(angle, radius), 0.0f};
/* Update challenge coin position */
if (_coin.has_value() && !coin_taken() && !coin_collected)
@ -425,6 +436,10 @@ void Projector::release()
Flame::Flame(const sb::Box field, const glm::vec3& position, float speed, float angle, float mirror_interval) :
field(field), position(position), speed(speed), angle(angle)
{
/* Save initial values */
initial_angle = angle;
initial_position = position;
/* Initialize object size and position */
glm::vec2 size {12.0f / 486.0f};
sprite.texture("resource/flame/flame-1.png");
@ -475,7 +490,19 @@ void Flame::draw(GLuint transformation_uniform, const glm::mat4 view, const glm:
void Flame::mirror()
{
angle += glm::pi<float>();
/* Reset the flame position and angle at the end of a cycle so overflow in time and movement don't begin to accumulate and desync the mirror cycle. */
if (mirrored)
{
angle = initial_angle;
position = initial_position;
}
else
{
angle += glm::pi<float>();
}
/* Indicate whether flame is moving away from its original position or toward it. */
mirrored = !mirrored;
}
bool Flame::collide_coin(sb::Box box, const glm::vec3& clip_lower, const glm::vec3& clip_upper) const

View File

@ -52,7 +52,7 @@ public:
virtual void collect_coin();
/*!
* @param timer timer updated every frame to be used for delta time
* @param timer timer that has been updating every unpaused frame to be used to measure distance to move this frame
*/
virtual void update(const sb::Timer& timer) = 0;
@ -170,6 +170,7 @@ private:
std::reference_wrapper<const Curve> curve;
float relative = 0.0f, speed = 0.0f, radius = 0.0f, angle = 0.0f, offset = 0.0f, coin_angle = 0.0f, coin_radius = 0.0f;
sb::Sprite sprite;
std::optional<float> first_update_time;
/*!
* @return vertex in world coordinates the fish is rotating around, always lies on the curve
@ -368,10 +369,11 @@ class Flame : public Enemy
private:
const sb::Box field;
glm::vec3 position = glm::vec3{0.0f};
float speed = 0.0f, angle = 0.0f, coin_angle = 0.0f, coin_radius = 0.0f;
glm::vec3 position = glm::vec3{0.0f}, initial_position = glm::vec3{0.0f};
float speed = 0.0f, angle = 0.0f, coin_angle = 0.0f, coin_radius = 0.0f, initial_angle = 0.0f;
sb::Sprite sprite;
sb::Animation animation_mirror = sb::Animation(std::bind(&Flame::mirror, this));
bool mirrored = false;
/*!
* Rotate direction 180 degrees.