From 39ae1fbdb91ec7458d7f5a7c3ce98b9a1bcc9169 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 17 Jan 2023 17:45:41 +0900 Subject: [PATCH] Work on game, currently is usable, WIP anims --- CMakeLists.txt | 3 + src/3d/anim_concurrent.cc | 4 +- src/3d/anim_concurrent.h | 5 +- src/3d/anim_model_attack.cc | 17 +-- src/3d/anim_model_attack.h | 7 +- src/3d/anim_model_grow.cc | 4 +- src/3d/anim_model_grow.h | 4 +- src/3d/anim_model_shrink.cc | 4 +- src/3d/anim_model_shrink.h | 4 +- src/3d/anim_model_still.cc | 19 ++++ src/3d/anim_model_still.h | 22 ++++ src/3d/anim_sequence.cc | 4 +- src/3d/anim_sequence.h | 5 +- src/3d/anims.cc | 28 +++++ src/3d/anims.h | 14 ++- src/3d_renderer.cc | 221 ++++++++++++++++++++++++++++++++---- src/3d_renderer.h | 13 ++- src/basic_renderer.cc | 2 +- src/basic_renderer.h | 4 +- src/constants.h | 2 +- src/game_renderer.h | 2 +- src/helpers.cc | 36 ++++++ src/helpers.h | 2 + src/main.cc | 4 +- wasm_build/Makefile | 7 +- wasm_build/client.js | 10 +- wasm_build/logic.js | 8 ++ 27 files changed, 387 insertions(+), 68 deletions(-) create mode 100644 src/3d/anim_model_still.cc create mode 100644 src/3d/anim_model_still.h create mode 100644 src/3d/anims.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cae423..96c93ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,11 +25,13 @@ set(RPSDuelNative_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/a3f.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/a3f_conv.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/qm.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anims.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_concurrent.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_sequence.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_shrink.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_grow.cc" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_attack.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_still.cc" ) set(RPSDuelNative_HEADERS @@ -48,6 +50,7 @@ set(RPSDuelNative_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_shrink.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_grow.h" "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_attack.h" + "${CMAKE_CURRENT_SOURCE_DIR}/src/3d/anim_model_still.h" ) add_executable(RPSDuelNative ${RPSDuelNative_SOURCES}) diff --git a/src/3d/anim_concurrent.cc b/src/3d/anim_concurrent.cc index 5dc66f1..3d9c5d8 100644 --- a/src/3d/anim_concurrent.cc +++ b/src/3d/anim_concurrent.cc @@ -4,8 +4,6 @@ AnimConcurrent::AnimConcurrent(Model *model) : Anims(model) {} AnimConcurrent::~AnimConcurrent() {} -bool AnimConcurrent::is_done() { return anims.empty(); } - void AnimConcurrent::do_update(float dt) { for (auto iter = anims.begin(); iter != anims.end();) { (*iter)->do_update(dt); @@ -26,3 +24,5 @@ void AnimConcurrent::do_draw() { void AnimConcurrent::push_anim(UPtr &&p) { anims.emplace_back(std::forward(p)); } + +bool AnimConcurrent::is_done_impl() { return anims.empty(); } diff --git a/src/3d/anim_concurrent.h b/src/3d/anim_concurrent.h index a773187..a103faa 100644 --- a/src/3d/anim_concurrent.h +++ b/src/3d/anim_concurrent.h @@ -11,13 +11,14 @@ class AnimConcurrent : public Anims { AnimConcurrent(Model *model); ~AnimConcurrent() override; - bool is_done() override; - void do_update(float dt) override; void do_draw() override; void push_anim(UPtr &&p); + protected: + bool is_done_impl() override; + private: std::list anims; }; diff --git a/src/3d/anim_model_attack.cc b/src/3d/anim_model_attack.cc index 64e98f8..950cddf 100644 --- a/src/3d/anim_model_attack.cc +++ b/src/3d/anim_model_attack.cc @@ -8,17 +8,16 @@ #include "../helpers.h" #include "a3f_conv.h" -AnimModelAttack::AnimModelAttack(Model *model, A3F pos) +AnimModelAttack::AnimModelAttack(Model *model, A3F pos, bool is_p1) : Anims(model), pos(pos), offset{0.0F, 0.0F, 0.0F}, timer(MODEL_ATTACK_TIME_0), - state(0) {} + state(0), + is_p1(is_p1) {} AnimModelAttack::~AnimModelAttack() {} -bool AnimModelAttack::is_done() { return state == 3; } - void AnimModelAttack::do_update(float dt) { timer -= dt; if (timer <= 0.0F) { @@ -43,14 +42,16 @@ void AnimModelAttack::do_update(float dt) { 1.0F - timer / MODEL_ATTACK_TIME_0); break; case 1: - offset.at(0) = Helpers::lerp(MODEL_ATTACK_0_X, MODEL_ATTACK_1_X, + offset.at(0) = Helpers::lerp(MODEL_ATTACK_0_X, + MODEL_ATTACK_1_X * (is_p1 ? 1.0F : -1.0F), 1.0F - timer / MODEL_ATTACK_TIME_1); offset.at(1) = Helpers::lerp(MODEL_ATTACK_0_Y, MODEL_ATTACK_1_Y, 1.0F - timer / MODEL_ATTACK_TIME_1); break; case 2: - offset.at(0) = Helpers::lerp(MODEL_ATTACK_1_X, MODEL_ATTACK_2_X, - 1.0F - timer / MODEL_ATTACK_TIME_2); + offset.at(0) = + Helpers::lerp(MODEL_ATTACK_1_X * (is_p1 ? 1.0F : -1.0F), + MODEL_ATTACK_2_X, 1.0F - timer / MODEL_ATTACK_TIME_2); offset.at(1) = Helpers::lerp(MODEL_ATTACK_1_Y, MODEL_ATTACK_2_Y, 1.0F - timer / MODEL_ATTACK_TIME_2); break; @@ -64,3 +65,5 @@ void AnimModelAttack::do_update(float dt) { void AnimModelAttack::do_draw() { DrawModel(*model, A3FToRV3(pos + offset), 1.0F, WHITE); } + +bool AnimModelAttack::is_done_impl() { return state == 3; } diff --git a/src/3d/anim_model_attack.h b/src/3d/anim_model_attack.h index 2b77fa3..c07e8ce 100644 --- a/src/3d/anim_model_attack.h +++ b/src/3d/anim_model_attack.h @@ -6,15 +6,15 @@ class AnimModelAttack : public Anims { public: - AnimModelAttack(Model *model, A3F pos); + AnimModelAttack(Model *model, A3F pos, bool is_p1); ~AnimModelAttack() override; - bool is_done() override; - void do_update(float dt) override; void do_draw() override; private: + bool is_done_impl() override; + A3F pos; A3F offset; float timer; @@ -25,6 +25,7 @@ class AnimModelAttack : public Anims { * 3 - done */ int state; + bool is_p1; }; #endif diff --git a/src/3d/anim_model_grow.cc b/src/3d/anim_model_grow.cc index 78e776d..f06fb79 100644 --- a/src/3d/anim_model_grow.cc +++ b/src/3d/anim_model_grow.cc @@ -12,11 +12,11 @@ AnimModelGrow::AnimModelGrow(Model *model, A3F pos) AnimModelGrow::~AnimModelGrow() {} -bool AnimModelGrow::is_done() { return timer <= 0.0F; } - void AnimModelGrow::do_update(float dt) { timer -= dt; } void AnimModelGrow::do_draw() { DrawModel(*model, A3FToRV3(pos), timer >= 0.0F ? (1.0F - timer / MODEL_GROW_TIME) : 1.0F, WHITE); } + +bool AnimModelGrow::is_done_impl() { return timer <= 0.0F; } diff --git a/src/3d/anim_model_grow.h b/src/3d/anim_model_grow.h index bd97b28..f881e4f 100644 --- a/src/3d/anim_model_grow.h +++ b/src/3d/anim_model_grow.h @@ -9,12 +9,12 @@ class AnimModelGrow : public Anims { AnimModelGrow(Model *model, A3F pos); ~AnimModelGrow() override; - bool is_done() override; - void do_update(float dt) override; void do_draw() override; private: + bool is_done_impl() override; + A3F pos; float timer; }; diff --git a/src/3d/anim_model_shrink.cc b/src/3d/anim_model_shrink.cc index 49270cd..5924b82 100644 --- a/src/3d/anim_model_shrink.cc +++ b/src/3d/anim_model_shrink.cc @@ -12,11 +12,11 @@ AnimModelShrink::AnimModelShrink(Model *model, A3F pos) AnimModelShrink::~AnimModelShrink() {} -bool AnimModelShrink::is_done() { return timer <= 0.0F; } - void AnimModelShrink::do_update(float dt) { timer -= dt; } void AnimModelShrink::do_draw() { DrawModel(*model, A3FToRV3(pos), timer >= 0.0F ? (timer / MODEL_SHRINK_TIME) : 0.0F, WHITE); } + +bool AnimModelShrink::is_done_impl() { return timer <= 0.0F; } diff --git a/src/3d/anim_model_shrink.h b/src/3d/anim_model_shrink.h index 39c1a39..4af0e7d 100644 --- a/src/3d/anim_model_shrink.h +++ b/src/3d/anim_model_shrink.h @@ -9,12 +9,12 @@ class AnimModelShrink : public Anims { AnimModelShrink(Model *model, A3F pos); ~AnimModelShrink() override; - bool is_done() override; - void do_update(float dt) override; void do_draw() override; private: + bool is_done_impl() override; + A3F pos; float timer; }; diff --git a/src/3d/anim_model_still.cc b/src/3d/anim_model_still.cc new file mode 100644 index 0000000..87f9d37 --- /dev/null +++ b/src/3d/anim_model_still.cc @@ -0,0 +1,19 @@ +#include "anim_model_still.h" + +#include "a3f_conv.h" + +// third party includes +#include + +AnimModelStill::AnimModelStill(Model *model, A3F pos, float time) + : Anims(model), pos(pos), timer(time) {} + +AnimModelStill::~AnimModelStill() {} + +void AnimModelStill::do_update(float dt) { timer -= dt; } + +void AnimModelStill::do_draw() { + DrawModel(*model, A3FToRV3(pos), 1.0F, WHITE); +} + +bool AnimModelStill::is_done_impl() { return timer <= 0.0F; } diff --git a/src/3d/anim_model_still.h b/src/3d/anim_model_still.h new file mode 100644 index 0000000..b59505f --- /dev/null +++ b/src/3d/anim_model_still.h @@ -0,0 +1,22 @@ +#ifndef ROCK_PAPER_SCISSORS_DUEL_3D_ANIM_MODEL_STILL_H_ +#define ROCK_PAPER_SCISSORS_DUEL_3D_ANIM_MODEL_STILL_H_ + +#include "a3f.h" +#include "anims.h" + +class AnimModelStill : public Anims { + public: + AnimModelStill(Model *model, A3F pos, float time); + ~AnimModelStill() override; + + void do_update(float dt) override; + void do_draw() override; + + private: + bool is_done_impl() override; + + A3F pos; + float timer; +}; + +#endif diff --git a/src/3d/anim_sequence.cc b/src/3d/anim_sequence.cc index 81d0c90..6695475 100644 --- a/src/3d/anim_sequence.cc +++ b/src/3d/anim_sequence.cc @@ -4,8 +4,6 @@ AnimSequence::AnimSequence(Model *model) : Anims(model) {} AnimSequence::~AnimSequence() {} -bool AnimSequence::is_done() { return anims.empty(); } - void AnimSequence::do_update(float dt) { if (!anims.empty()) { anims.front()->do_update(dt); @@ -24,3 +22,5 @@ void AnimSequence::do_draw() { void AnimSequence::push_anim(UPtr &&p) { anims.emplace_back(std::forward(p)); } + +bool AnimSequence::is_done_impl() { return anims.empty(); } diff --git a/src/3d/anim_sequence.h b/src/3d/anim_sequence.h index d08d615..f359196 100644 --- a/src/3d/anim_sequence.h +++ b/src/3d/anim_sequence.h @@ -11,13 +11,14 @@ class AnimSequence : public Anims { AnimSequence(Model *model); ~AnimSequence() override; - bool is_done() override; - void do_update(float dt) override; void do_draw() override; void push_anim(UPtr &&p); + protected: + bool is_done_impl() override; + private: std::list anims; }; diff --git a/src/3d/anims.cc b/src/3d/anims.cc new file mode 100644 index 0000000..57d765d --- /dev/null +++ b/src/3d/anims.cc @@ -0,0 +1,28 @@ +#include "anims.h" + +Anims::Anims(Model *model) + : model(model), + userdata(nullptr), + function_ptr(nullptr), + is_done_finished(false) {} + +bool Anims::is_done() { + if (is_done_finished) { + return true; + } + bool result = is_done_impl(); + if (result) { + if (function_ptr) { + function_ptr(userdata); + } + is_done_finished = true; + } + return result; +} + +void Anims::reset_is_done() { is_done_finished = false; } + +void Anims::set_end_callback(Anims::FP fp, void *ud) { + userdata = ud; + function_ptr = fp; +} diff --git a/src/3d/anims.h b/src/3d/anims.h index 1411fed..d24efc0 100644 --- a/src/3d/anims.h +++ b/src/3d/anims.h @@ -12,16 +12,26 @@ class Anims { using UPtr = std::unique_ptr; using SPtr = std::shared_ptr; - Anims(Model *model) : model(model) {} + using FP = void (*)(void *); + + Anims(Model *model); virtual ~Anims() {} - virtual bool is_done() = 0; + bool is_done(); + void reset_is_done(); virtual void do_update(float dt) = 0; virtual void do_draw() = 0; + void set_end_callback(FP function_ptr, void *ud); + protected: + virtual bool is_done_impl() = 0; + Model *model; + void *userdata; + FP function_ptr; + bool is_done_finished; }; #endif diff --git a/src/3d_renderer.cc b/src/3d_renderer.cc index 037907c..beebd4f 100644 --- a/src/3d_renderer.cc +++ b/src/3d_renderer.cc @@ -8,14 +8,22 @@ // third party includes #include +#include + // local includes #include "3d/a3f_conv.h" +#include "3d/anim_concurrent.h" +#include "3d/anim_model_attack.h" +#include "3d/anim_model_grow.h" +#include "3d/anim_model_shrink.h" +#include "3d/anim_model_still.h" #include "constants.h" #include "ems.h" #include "helpers.h" Renderer3D::Renderer3D() : qms{}, + anims(nullptr), root_pos{0.0F, 0.0F, 0.0F}, overview_timer(OVERVIEW_TIMER_MAX), button_color_timer(BUTTON_COLOR_TIME), @@ -71,6 +79,7 @@ Renderer3D::Renderer3D() flags.set(1); flags.set(4); flags.set(5); + flags.set(14); qms.at(0).set_model(&qm_model); qms.at(0).set_pos({-1.0F, 0.0F, 0.0F}); @@ -106,7 +115,7 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo, char second_first, char second_second, char second_third, bool first_ready, bool second_ready, int pos, int matchup_idx, - bool gameover) { + bool gameover, bool matchup_started) { if (std::strcmp(playerOne, currentPlayer) == 0) { flags.set(2); flags.reset(3); @@ -120,6 +129,7 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo, flags.set(9, first_ready); flags.set(10, second_ready); + flags.set(13, matchup_started); flags.set(12); @@ -127,18 +137,34 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo, std::cout << "got pos: " << pos << std::endl; std::cout << "got matchup_idx: " << matchup_idx << std::endl; std::cout << "camera.target.x: " << camera.target.x << std::endl; + std::cout << "matchup started: " << (matchup_started ? "true" : "false") + << std::endl; + std::cout << "p1 is " << (first_ready ? "ready" : "NOT ready") << "\np2 is " + << (second_ready ? "ready" : "NOT ready") << std::endl; } - received_pos = pos; + if (!flags.test(13)) { + received_pos = pos; + } + if (received_matchup_idx != matchup_idx) { + flags.reset(7); + } received_matchup_idx = matchup_idx; if (second_first != '?') { - opponent_choices.at(0) = second_first; - opponent_choices.at(1) = second_second; - opponent_choices.at(2) = second_third; + if (flags.test(2)) { + opponent_choices.at(0) = second_first; + opponent_choices.at(1) = second_second; + opponent_choices.at(2) = second_third; + } else { + opponent_choices.at(0) = first_first; + opponent_choices.at(1) = first_second; + opponent_choices.at(2) = first_third; + } } - if (flags.test(11) && first_first == '?' && second_first == '?') { + if (flags.test(11) && first_first == '?' && second_first == '?' && + flags.test(15) && !flags.test(13)) { choices.at(0) = '?'; choices.at(1) = '?'; choices.at(2) = '?'; @@ -148,8 +174,20 @@ void Renderer3D::update_state(const char *playerOne, const char *playerTwo, flags.reset(11); flags.reset(8); flags.reset(0); + flags.reset(15); + flags.set(14); overview_timer = OVERVIEW_TIMER_MAX; set_random_overview(); + qms.at(0).set_pos_x(received_pos * 2.0F - 1.0F); + qms.at(1).set_pos_x(received_pos * 2.0F + 1.0F); + camera.target.x = received_pos * 2.0F; + if (flags.test(2)) { + std::cerr << "RESET STATE for next round" << std::endl; + } + } + + if (flags.test(2)) { + std::cout << flags.to_string().substr(64 - 16) << std::endl; } } @@ -296,27 +334,160 @@ void Renderer3D::update_impl() { button_color_timer += BUTTON_COLOR_TIME; } + if (flags.test(8) && flags.test(9) && flags.test(10) && !flags.test(11)) { + char buf[6] = {(char)choices.at(0), 0, (char)choices.at(1), 0, + (char)choices.at(2), 0}; + flags.set(11); + flags.set(0); + call_js_set_choices(&buf[0], &buf[2], &buf[4]); + call_js_request_update(); + } + if (flags.test(12)) { - if (flags.test(8) && flags.test(11)) { - call_js_set_ready(); - call_js_request_update(); - } else if (flags.test(8) && flags.test(9) && flags.test(10) && - !flags.test(11)) { - char buf[6] = {(char)choices.at(0), 0, (char)choices.at(1), 0, - (char)choices.at(2), 0}; - call_js_set_choices(&buf[0], &buf[2], &buf[4]); - flags.set(11); - flags.set(0); + if (flags.test(11) && !flags.test(7) && flags.test(13) && anims.is_done()) { + flags.set(7); + flags.reset(14); + flags.set(15); + + anims.reset_is_done(); + + auto newAnim = std::make_unique(nullptr); + newAnim->push_anim(std::make_unique( + &qm_model, A3F{received_pos * 2.0F - 1.0F, 0.0F, 0.0F})); + newAnim->push_anim(std::make_unique( + &qm_model, A3F{received_pos * 2.0F + 1.0F, 0.0F, 0.0F})); + anims.push_anim(std::move(newAnim)); + + newAnim = std::make_unique(nullptr); + Model *p1_model = &qm_model; + Model *p2_model = &qm_model; + switch (choices.at(received_matchup_idx)) { + case 'r': + if (flags.test(2)) { + p1_model = &rock_model; + } else { + p2_model = &rock_model; + } + break; + case 'p': + if (flags.test(2)) { + p1_model = &paper_model; + } else { + p2_model = &paper_model; + } + break; + case 's': + if (flags.test(2)) { + p1_model = &scissors_model; + } else { + p2_model = &scissors_model; + } + break; + } + switch (opponent_choices.at(received_matchup_idx)) { + case 'r': + if (flags.test(2)) { + p2_model = &rock_model; + } else { + p1_model = &rock_model; + } + break; + case 'p': + if (flags.test(2)) { + p2_model = &paper_model; + } else { + p1_model = &paper_model; + } + break; + case 's': + if (flags.test(2)) { + p2_model = &scissors_model; + } else { + p1_model = &scissors_model; + } + break; + } + newAnim->push_anim(std::make_unique( + p1_model, A3F{received_pos * 2.0F - 1.0F, 0.0F, 0.0F})); + newAnim->push_anim(std::make_unique( + p2_model, A3F{received_pos * 2.0F + 1.0F, 0.0F, 0.0F})); + anims.push_anim(std::move(newAnim)); + + newAnim = std::make_unique(nullptr); + + const int result = Helpers::a_vs_b( + flags.test(2) ? choices.at(received_matchup_idx) + : opponent_choices.at(received_matchup_idx), + flags.test(2) ? opponent_choices.at(received_matchup_idx) + : choices.at(received_matchup_idx)); + + switch (result) { + case -1: + newAnim->push_anim(std::make_unique( + p1_model, A3F{received_pos * 2.0F - 1.0F, 0.0F, 0.0F}, + MODEL_ATTACK_TIME_0 + MODEL_ATTACK_TIME_1 + MODEL_ATTACK_TIME_2)); + newAnim->push_anim(std::make_unique( + p2_model, A3F{received_pos * 2.0F + 1.0F, 0.0F, 0.0F}, false)); + break; + case 1: + newAnim->push_anim(std::make_unique( + p1_model, A3F{received_pos * 2.0F - 1.0F, 0.0F, 0.0F}, true)); + newAnim->push_anim(std::make_unique( + p2_model, A3F{received_pos * 2.0F + 1.0F, 0.0F, 0.0F}, + MODEL_ATTACK_TIME_0 + MODEL_ATTACK_TIME_1 + MODEL_ATTACK_TIME_2)); + break; + case 0: + default: + break; + } + + if (result != 0) { + anims.push_anim(std::move(newAnim)); + } + + newAnim = std::make_unique(nullptr); + newAnim->push_anim(std::make_unique( + p1_model, A3F{received_pos * 2.0F - 1.0F, 0.0F, 0.0F})); + newAnim->push_anim(std::make_unique( + p2_model, A3F{received_pos * 2.0F + 1.0F, 0.0F, 0.0F})); + + using DataT = std::tuple; + DataT *data = new DataT{&flags, &received_pos, result}; + newAnim->set_end_callback( + [](void *ud) { + auto *d = (std::tuple *)(ud); + std::get<0>(*d)->set(14); + *std::get<1>(*d) += std::get<2>(*d); + delete d; + }, + data); + + anims.push_anim(std::move(newAnim)); + + newAnim = std::make_unique(nullptr); + newAnim->push_anim(std::make_unique( + &qm_model, A3F{(result + received_pos) * 2.0F - 1.0F, 0.0F, 0.0F})); + newAnim->push_anim(std::make_unique( + &qm_model, A3F{(result + received_pos) * 2.0F + 1.0F, 0.0F, 0.0F})); + + anims.push_anim(std::move(newAnim)); } } flags.reset(12); - qms.at(0).get_pos().at(0) += - ((received_pos * 2.0F - 1.0F) - qms.at(0).get_pos().at(0)) / 50.0F; - qms.at(1).get_pos().at(0) += - ((received_pos * 2.0F + 1.0F) - qms.at(1).get_pos().at(0)) / 50.0F; - camera.target.x += (received_pos * 2.0F - camera.target.x) / 50.0F; + if (flags.test(8) && flags.test(11) && flags.test(7) && anims.is_done()) { + flags.set(14); + call_js_set_ready(); + call_js_request_update(); + } + + if (flags.test(14)) { + float offset = received_pos * 2.0F - camera.target.x; + camera.target.x += offset / 4.0F; + } + + anims.do_update(dt); } void Renderer3D::draw_impl() { @@ -325,8 +496,12 @@ void Renderer3D::draw_impl() { BeginMode3D(camera); DrawModel(skybox_model, root_pos, 1.0F, WHITE); DrawModel(platform_model, root_pos, 1.0F, WHITE); - for (auto &obj : qms) { - obj.draw(); + if (flags.test(0)) { + anims.do_draw(); + } else { + for (auto &obj : qms) { + obj.draw(); + } } EndMode3D(); diff --git a/src/3d_renderer.h b/src/3d_renderer.h index 9a57250..c3e9625 100644 --- a/src/3d_renderer.h +++ b/src/3d_renderer.h @@ -12,6 +12,8 @@ #include // local includes +#include "3d/anim_sequence.h" +#include "3d/anims.h" #include "3d/qm.h" class Renderer3D : public GameRenderer { @@ -23,8 +25,8 @@ class Renderer3D : public GameRenderer { const char *currentPlayer, char first_first, char first_second, char first_third, char second_first, char second_second, char second_third, bool first_ready, - bool second_ready, int pos, int matchup_idx, - bool gameover) override; + bool second_ready, int pos, int matchup_idx, bool gameover, + bool matchup_started) override; void do_update() override; @@ -55,6 +57,8 @@ class Renderer3D : public GameRenderer { Model paper_model; Model scissors_model; + AnimSequence anims; + Vector3 root_pos; /* @@ -73,12 +77,15 @@ class Renderer3D : public GameRenderer { * 101 - UNUSED * 110 - UNUSED * 111 - UNUSED - * 7 - UNUSED + * 7 - anims set for current matchup * 8 - choices locked * 9 - p1 ready * 10 - p2 ready * 11 - choices submitted * 12 - update received + * 13 - matchup started + * 14 - do update camera target/pos + * 15 - anims was set for matchup */ std::bitset<64> flags; diff --git a/src/basic_renderer.cc b/src/basic_renderer.cc index 5d02b7a..d2e5395 100644 --- a/src/basic_renderer.cc +++ b/src/basic_renderer.cc @@ -39,7 +39,7 @@ void BasicRenderer::update_state(const char *playerOne, const char *playerTwo, char second_first, char second_second, char second_third, bool first_ready, bool second_ready, int pos, int matchup_idx, - bool gameover) { + bool gameover, bool matchup_started) { // TODO DEBUG // if (std::strcmp(playerOne, currentPlayer) == 0) { // std::clog << "update_state:\n" diff --git a/src/basic_renderer.h b/src/basic_renderer.h index 0765910..31d182e 100644 --- a/src/basic_renderer.h +++ b/src/basic_renderer.h @@ -21,8 +21,8 @@ class BasicRenderer : public GameRenderer { const char *currentPlayer, char first_first, char first_second, char first_third, char second_first, char second_second, char second_third, bool first_ready, - bool second_ready, int pos, int matchup_idx, - bool gameover) override; + bool second_ready, int pos, int matchup_idx, bool gameover, + bool matchup_started) override; void do_update() override; diff --git a/src/constants.h b/src/constants.h index 9093d9a..ff91e9d 100644 --- a/src/constants.h +++ b/src/constants.h @@ -85,7 +85,7 @@ constexpr float MODEL_ATTACK_TIME_1 = 0.3F; constexpr float MODEL_ATTACK_TIME_2 = 0.4F; constexpr float MODEL_ATTACK_0_X = 0.0F; constexpr float MODEL_ATTACK_0_Y = 2.0F; -constexpr float MODEL_ATTACK_1_X = -1.0F; +constexpr float MODEL_ATTACK_1_X = 1.0F; constexpr float MODEL_ATTACK_1_Y = 0.2F; constexpr float MODEL_ATTACK_2_X = 0.0F; constexpr float MODEL_ATTACK_2_Y = 0.0F; diff --git a/src/game_renderer.h b/src/game_renderer.h index 1cee95e..385fea8 100644 --- a/src/game_renderer.h +++ b/src/game_renderer.h @@ -12,7 +12,7 @@ class GameRenderer { char second_first, char second_second, char second_third, bool first_ready, bool second_ready, int pos, int matchup_idx, - bool gameover) = 0; + bool gameover, bool matchup_started) = 0; virtual void do_update() = 0; diff --git a/src/helpers.cc b/src/helpers.cc index 9fd7bf3..a19ad11 100644 --- a/src/helpers.cc +++ b/src/helpers.cc @@ -98,3 +98,39 @@ void Helpers::overview_orbit(Vector3 *out, float value, bool is_opposite, out->y = OVERVIEW_ORBIT_Y; out->z = -(value * value - 1.0F) * OVERVIEW_ORBIT_RADIUS; } + +int Helpers::a_vs_b(char a, char b) { + if (a == 'r') { + if (b == 'r') { + return 0; + } else if (b == 'p') { + return -1; + } else if (b == 's') { + return 1; + } else { + return 0; + } + } else if (a == 'p') { + if (b == 'r') { + return 1; + } else if (b == 'p') { + return 0; + } else if (b == 's') { + return -1; + } else { + return 0; + } + } else if (a == 's') { + if (b == 'r') { + return -1; + } else if (b == 'p') { + return 1; + } else if (b == 's') { + return 0; + } else { + return 0; + } + } else { + return 0; + } +} diff --git a/src/helpers.h b/src/helpers.h index c66b1d8..b342a15 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -26,6 +26,8 @@ extern void overview_zoom_out_c(Vector3 *out, float value, bool is_opposite, extern void overview_orbit(Vector3 *out, float value, bool is_opposite, float offset_x); +extern int a_vs_b(char a, char b); + } // namespace Helpers #endif diff --git a/src/main.cc b/src/main.cc index 4a58602..c40917a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -30,12 +30,12 @@ int EMSCRIPTEN_KEEPALIVE game_visual_update( const char *playerOne, const char *playerTwo, const char *currentPlayer, char first_first, char first_second, char first_third, char second_first, char second_second, char second_third, bool first_ready, bool second_ready, - int pos, int matchup_idx, bool gameover) { + int pos, int matchup_idx, bool gameover, bool matchup_started) { ((GameRenderer *)global_game_ptr) ->update_state(playerOne, playerTwo, currentPlayer, first_first, first_second, first_third, second_first, second_second, second_third, first_ready, second_ready, pos, matchup_idx, - gameover); + gameover, matchup_started); return 0; } diff --git a/wasm_build/Makefile b/wasm_build/Makefile index 2196f31..bb1e1ed 100644 --- a/wasm_build/Makefile +++ b/wasm_build/Makefile @@ -15,11 +15,13 @@ SOURCES = \ ../src/3d/a3f.cc \ ../src/3d/a3f_conv.cc \ ../src/3d/qm.cc \ + ../src/3d/anims.cc \ ../src/3d/anim_concurrent.cc \ ../src/3d/anim_sequence.cc \ ../src/3d/anim_model_shrink.cc \ ../src/3d/anim_model_grow.cc \ - ../src/3d/anim_model_attack.cc + ../src/3d/anim_model_attack.cc \ + ../src/3d/anim_model_still.cc HEADERS = \ ../src/constants.h \ @@ -37,7 +39,8 @@ HEADERS = \ ../src/3d/anim_sequence.h \ ../src/3d/anim_model_shrink.h \ ../src/3d/anim_model_grow.h \ - ../src/3d/anim_model_attack.h + ../src/3d/anim_model_attack.h \ + ../src/3d/anim_model_still.h CXX = source ${HOME}/git/emsdk/emsdk_env.sh && em++ diff --git a/wasm_build/client.js b/wasm_build/client.js index 726fa60..e48f78a 100644 --- a/wasm_build/client.js +++ b/wasm_build/client.js @@ -1,6 +1,6 @@ Rune.initClient({ visualUpdate: ({ newGame, yourPlayerId}) => { - const { player1, player2, first_choices, second_choices, ready, pos, matchup_idx, gameover } = newGame; + const { player1, player2, first_choices, second_choices, ready, pos, matchup_idx, gameover, matchup_started } = newGame; function is_choices_filled(choices) { for (let i = 0; i < 3; ++i) { @@ -18,7 +18,7 @@ Rune.initClient({ 'number', 'number', 'number', 'number', 'number', 'number', 'boolean', 'boolean', - 'number', 'number', 'boolean'], + 'number', 'number', 'boolean', 'boolean'], [player1, player2, yourPlayerId === undefined ? 'undefined' : yourPlayerId, first_choices[0].charCodeAt(0), @@ -28,7 +28,7 @@ Rune.initClient({ second_choices[1].charCodeAt(0), second_choices[2].charCodeAt(0), ready[0], ready[1], - pos, matchup_idx, gameover]); + pos, matchup_idx, gameover, matchup_started]); } else { Module.ccall('game_visual_update', 'number', @@ -36,7 +36,7 @@ Rune.initClient({ 'number', 'number', 'number', 'number', 'number', 'number', 'boolean', 'boolean', - 'number', 'number', 'boolean'], + 'number', 'number', 'boolean', 'boolean'], [player1, player2, yourPlayerId === undefined ? 'undefined' : yourPlayerId, '?'.charCodeAt(0), @@ -46,7 +46,7 @@ Rune.initClient({ '?'.charCodeAt(0), '?'.charCodeAt(0), ready[0], ready[1], - pos, matchup_idx, gameover]); + pos, matchup_idx, gameover, matchup_started]); } }, }); diff --git a/wasm_build/logic.js b/wasm_build/logic.js index b3ddf58..8e821d6 100644 --- a/wasm_build/logic.js +++ b/wasm_build/logic.js @@ -10,6 +10,7 @@ Rune.initLogic({ pos: 0, matchup_idx: 0, gameover: false, + matchup_started: false, }), actions: { set_choices: ({first, second, third}, { game, playerId }) => { @@ -81,6 +82,12 @@ Rune.initLogic({ } // Both sides are ready, iterate through matchups + if (!game.matchup_started) { + game.matchup_started = true; + game.ready[0] = false; + game.ready[1] = false; + return; + } // check if first won the matchup if ((game.first_choices[game.matchup_idx] === 'r' @@ -121,6 +128,7 @@ Rune.initLogic({ } game.matchup_idx = 0; } + game.matchup_started = false; } }, }, -- 2.49.0