From 8fb7919854f2e635de3059d35d4f9e051e4f6798 Mon Sep 17 00:00:00 2001 From: Brandon Date: Tue, 5 Sep 2017 00:45:32 -0700 Subject: [PATCH] Add missing replay files. Introduce line marker graphics, homemade GOAL sign --- romfs/graphics/game/line_markers.png | Bin 0 -> 427 bytes romfs/graphics/menu/windowskin.png | Bin 5737 -> 6560 bytes source/replay_helpers.cpp | 82 +++++++++++++++++++++++++++ source/replay_helpers.hpp | 68 ++++++++++++++++++++++ source/scenes/game_scene.cpp | 24 ++++++++ source/scenes/game_scene.hpp | 9 +++ source/scenes/score_scene.cpp | 7 +++ source/scenes/score_scene.hpp | 1 + 8 files changed, 191 insertions(+) create mode 100644 romfs/graphics/game/line_markers.png create mode 100644 source/replay_helpers.cpp create mode 100644 source/replay_helpers.hpp diff --git a/romfs/graphics/game/line_markers.png b/romfs/graphics/game/line_markers.png new file mode 100644 index 0000000000000000000000000000000000000000..8cfefc266e6fe2f0dd745adb770d1d85e98fc7d1 GIT binary patch literal 427 zcmeAS@N?(olHy`uVBq!ia0vp^8bGYT!3HD~)>;8c2DT(`cNY+YA*$#v^HdO>_ z%)r1c48n{Iv*t(u1=&kHeO=ifahT|;+&tGo0?a`;9QiNSdyBe zP@Y+mq2TW68xY>eC(gjYDD3It7!q;#ZI~lpivmwd$NDGSd)oEin5XlvV-s8w5N>g! z#f9s|mXbFIB+_4fTPT^t*Uchh$tKUBceb7BTYA;I;;OXoN3vhuT)lVp&A5VD2iD!2 z`YZSR@fVd{A-mR>tb4LOHRwfWBSYvlZifHfUAL}=Wf`z8KfP#+NQ-F&i+hp$q}7vu zS!D;5tzCO_$5NGRDZE)CU**4YUGT}~oAC8fVcOXz-Jqtb2Ws0qAEh+ZCKk zqWOQd&)6ID(or|^Q9@C+keT^QM@`OmXWoTW2^?5C+h-a3`L*w^HtQd__>FZJ+fFBT TlZN}iFl6v_^>bP0l+XkKv6QKi literal 0 HcmV?d00001 diff --git a/romfs/graphics/menu/windowskin.png b/romfs/graphics/menu/windowskin.png index 7f2a4a07c562255e394793cc5c4694cf862c8d50..f2220dd88442202aee772332b26fa31739037264 100644 GIT binary patch delta 6540 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 B&8PqX diff --git a/source/replay_helpers.cpp b/source/replay_helpers.cpp new file mode 100644 index 0000000..250bce2 --- /dev/null +++ b/source/replay_helpers.cpp @@ -0,0 +1,82 @@ +#include "replay_helpers.hpp" +#include +#include "recorder.hpp" + +u32 ReplayInputDataSource::trigger() const +{ + if (index >= data.size()) return 0; + return data[index].trigger; +} + +u32 ReplayInputDataSource::held() const +{ + if (index >= data.size()) return 0; + return data[index].held; +} + +void ReplayInputDataSource::update() +{ + if (index >= data.size()) return; + frame++; + if (frame - start > data[index].frames) + { + start += data[index].frames; + index++; + } +} + +bool load_replay(const std::string& filename, ReplayInfo& info) +{ + std::ifstream file(filename.c_str(), std::ios::binary); + return load_replay(file, info); +} + +bool load_replay(std::istream& file, ReplayInfo& info) +{ + char magic[4]; + + file.read(magic, 4); + if (memcmp(magic, "BBB", 4) != 0) + return false; + + char major = file.get(); + char minor = file.get(); + + if (major != RECORDER_MAJOR_VERSION) + return false; + if (minor != RECORDER_MINOR_VERSION) + return false; + + info.rows = file.get(); + info.columns = file.get(); + info.type = file.get(); + info.difficulty = file.get(); + info.level = file.get(); + + std::vector initial; + unsigned int size = info.rows * info.columns; + initial.reserve(size); + for (unsigned int i = 0; i < size; i++) + initial.push_back(static_cast(file.get())); + + file.read(reinterpret_cast(&size), sizeof(size)); + std::vector next; + next.reserve(size); + for (unsigned int i = 0; i < size; i++) + next.push_back(static_cast(file.get())); + + info.source.reset(new ReplayPanelSource(info.rows, info.columns, initial, next)); + + file.read(reinterpret_cast(&size), sizeof(size)); + std::vector items; + for (unsigned int i = 0; i < size; i++) + { + ReplayInputItem move; + file.read(reinterpret_cast(&move), sizeof(move)); + items.emplace_back(move); + } + + info.input.reset(new ReplayInputDataSource(items)); + + return true; +} diff --git a/source/replay_helpers.hpp b/source/replay_helpers.hpp new file mode 100644 index 0000000..0214ff0 --- /dev/null +++ b/source/replay_helpers.hpp @@ -0,0 +1,68 @@ +#ifndef REPLAY_HELPERS_HPP +#define REPLAY_HELPERS_HPP + +#include +#include +#include +#include + +#include + +#include "panel_source.hpp" + +struct ReplayInputItem +{ + u32 trigger; + u32 held; + u32 frames; +}; + +class ReplayPanelSource : public PanelSource +{ +public: + ReplayPanelSource(int rows, int columns, const std::vector& start, const std::vector next_set) : + PanelSource(rows, columns), initial(start), next(next_set), index(0) {} + ~ReplayPanelSource() {} + std::vector board() override {return initial;} + Panel::Type panel() override + { + if (index >= next.size()) return Panel::EMPTY; + return next[index++]; + } +private: + std::vector initial; + std::vector next; + unsigned int index; +}; + +class ReplayInputDataSource : public InputDataSourceInterface +{ +public: + ReplayInputDataSource(const std::vector& items) : data(items), index(0) {} + ~ReplayInputDataSource() {} + u32 trigger() const override; + u32 held() const override; + void update() override; +private: + std::vector data; + unsigned int index; + unsigned int start; + unsigned int frame; + +}; + +struct ReplayInfo +{ + std::unique_ptr source; + std::unique_ptr input; + char rows; + char columns; + char type; + char difficulty; + char level; +}; + +bool load_replay(const std::string& filename, ReplayInfo& info); +bool load_replay(std::istream& file, ReplayInfo& info); + +#endif diff --git a/source/scenes/game_scene.cpp b/source/scenes/game_scene.cpp index 2029877..e2ee905 100644 --- a/source/scenes/game_scene.cpp +++ b/source/scenes/game_scene.cpp @@ -88,6 +88,7 @@ void GameScene::init_sprites() selector.create("romfs:/graphics/game/selector.png"); border.create("romfs:/graphics/borders/red.png"); debug.create("romfs:/graphics/game/debug_text.png"); + line_markers.create("romfs:/graphics/game/line_markers.png"); frames.reset(); } @@ -340,6 +341,29 @@ void GameScene::draw_board() border.draw(startx, starty); } +void GameScene::draw_line_marker(int line, LineMarker type) +{ + int bottom_line = table->get_lines(); + int top_line = bottom_line - table->height(); + + if (!(line >= top_line && line <= bottom_line)) + return; + + int offset_line = top_line - line; + int column_underlined = frame % table->width(); + + int startx = (BOTTOM_SCREEN_WIDTH - border.width()) / 2 + 9 + 4; + int starty = BOTTOM_SCREEN_HEIGHT - border.height() + 9; + const int panel_size = PANEL_SIZE; + int offset = table->get_rise(); + + int x = startx + table->width() * panel_size + 6; + int y = starty + (offset_line + 1) * panel_size - offset; + + line_markers.draw(x, y, 0, type * 16, 40, 16); +} + + void GameScene::draw_debug_top() { extern Font* default_font; diff --git a/source/scenes/game_scene.hpp b/source/scenes/game_scene.hpp index 660de7a..167419c 100644 --- a/source/scenes/game_scene.hpp +++ b/source/scenes/game_scene.hpp @@ -31,6 +31,13 @@ enum TimingMode MOVES = 2, }; +/// Represents the type of line marker to draw +enum LineMarker +{ + CLEAR = 0, + GOAL = 1, +}; + /// TODO clean up this class and provide a much clearer interface to write other modes. class GameScene : public Scene2D { @@ -105,6 +112,7 @@ class GameScene : public Scene2D void draw_selector(); void draw_board(); void draw_panels(); + void draw_line_marker(int line, LineMarker type); virtual void draw_debug_bottom(); // Configuration @@ -118,6 +126,7 @@ class GameScene : public Scene2D Texture selector; Texture border; Texture debug; + Texture line_markers; // Core game stuff std::unique_ptr table; diff --git a/source/scenes/score_scene.cpp b/source/scenes/score_scene.cpp index 137f66c..2389935 100644 --- a/source/scenes/score_scene.cpp +++ b/source/scenes/score_scene.cpp @@ -121,6 +121,13 @@ void ScoreScene::draw_game_top() info.draw(); } +void ScoreScene::draw_game_bottom() +{ + GameScene::draw_game_bottom(); + if (config.time_mode == LINES) + draw_line_marker(config.value, GOAL); +} + void ScoreScene::draw_gameover_top() { game_over.draw(); diff --git a/source/scenes/score_scene.hpp b/source/scenes/score_scene.hpp index ce6ca9b..5c13013 100644 --- a/source/scenes/score_scene.hpp +++ b/source/scenes/score_scene.hpp @@ -23,6 +23,7 @@ class ScoreScene : public GameScene void update_on_gameover() override; void draw_game_top() override; + void draw_game_bottom() override; void draw_gameover_top() override; private: ScoreInfoWindow info;