diff --git a/.scripts/README.md b/.scripts/README.md new file mode 100644 index 0000000..6655906 --- /dev/null +++ b/.scripts/README.md @@ -0,0 +1,13 @@ +About generate-stats.sh +This is an automated script that can automatically accomplish three things. +1. Counts lines in .cpp and .h files. + +2. Counts the total number of commits and remote branches. + +3. Counts contributors and generates a contributor list plus a headcount. + +All of these are written to stats/ + +About test-menu.cpp + +this is a small testing tool in the development stage. It enables testers to pull a single game repository from GitHub using the local terminal and compile it into a startup script according to the configuration command in a fixed path, making it one-click executable. At the same time, it supports viewing and modifying the config.cfg of the game. \ No newline at end of file diff --git a/Progress Report/Progress Report.md b/Progress Report/Progress Report.md new file mode 100644 index 0000000..a5a81a9 --- /dev/null +++ b/Progress Report/Progress Report.md @@ -0,0 +1,49 @@ +# Arcade Machine — First Progress Report + +**First of all, well done.** + +This should be the first progress report for the arcade machine. Given the project’s risk of discontinuity and the development difficulties that such discontinuity brings, I am writing this document and sincerely recommend that every future development team come back here to write your summary at the end of each semester. + +This semester, we spent a great deal of time accepting the fact of this project’s discontinuity and putting in effort to understand and improve it. Although I believe we did not accomplish much, and I personally feel I did not work hard enough, I still want to provide whatever help I can for future developers. So next I will introduce everything I know and understand, and I hope your development goes smoothly. + +## What is the arcade machine? + +The arcade machine is an entertainment machine developed by Deakin students and placed across Deakin campuses. As of September 25, 2025, the status is: the units currently on campus can only play three games (about one quarter of what’s in the arcade-games Git repository). Various settings and buttons are missing, so the machine functions only as a device for playing games, and the player experience is not ideal. That said, given the pandemic context, the previous developers building this from zero to one was already a remarkable achievement. + +## How is the arcade machine going? + +In fact, the arcade machine consists of two Git repositories—“arcade machine” and “arcade games.” At present, its situation may not be ideal. Based on the arcade machine and arcade games code, we set up two test rigs (one on RPi 5, one on RPi 3B). However, the version running on the real arcade machine differs completely from the version built from the repositories. I do not currently know why there is such a large discrepancy, nor do I know the exact source code base used to build the real machine. Therefore, I cannot tell you with certainty whether the code and logic are the same between the two. + +Based on certain facts (the three games that run on the real arcade are a subset of the arcade-games repository; a previous developer told me that, due to image copyright considerations, they did not use the version from the repo), I can only offer my personal judgment: the code environment on the real machine should be broadly similar to what’s in the repositories, but perhaps due to build issues or other reasons, only three games from arcade-games are present there. + +## What did our team do this semester? + +- Contributed three games to arcade-games: + - a tower defense game (SDL2 engine), + - a 2D RPG (Unity engine), and + - Tetris. +- Wrote explanatory documentation in many places across both the machine and games repositories. +- Prepared two test rigs: one RPi 5 and one RPi 3B. +- Authored this progress report. + +I am ashamed that our team did not do enough, so I wrote this report to provide help until the very last moment. + +## Points to note for the arcade machine + +For now, there are not many special caveats. You can find answers to most questions in the explanatory documents I placed throughout the repositories. The machine repository itself is already relatively complete and does not have any particularly unusual pitfalls. + +One thing worth mentioning is the arcade games side. The repository’s automatic CI will automatically pull the latest updates from games, compile them, and put everything into a compiled games folder. This seems like a great design that would allow automatic updates of games on the arcade machine. However, in the arcade machine’s game-pulling logic, it first looks for the execution path in config, then looks for builds, and if it still cannot find anything, it fails. As a result, the compiled games folder is not actually used in this process. I ultimately did not fully understand the purpose of this design; perhaps it serves as a ready-to-use backup repository of pre-compiled games. + +Another important matter: while developing the machine test rigs, we encountered version incompatibilities with the SplashKit framework. The SplashKit used by developers three years ago is quite different from today’s. Using the latest version leads to compatibility issues. I did not dare to undertake a full repository refactor lightly, so in the test environment I used a SplashKit version prior to 2022.8.21 to fully reproduce the earlier arcade environment. + +## Closing + +I sincerely hope this document helps future developers. When you try to do more for the arcade, getting your hands on the test rigs and the repository documents—together with this report and the notes scattered across the repos—should improve your development experience. I’m sorry I couldn’t do more for you. If you would like to know more details about our development at the time, feel free to email me; I will do my best to help: 903157209hy@gmail.com. + +Wishing you happy times with the arcade machine! + +--- + +September 25, 2025 +Haoyu Liu +Arcade Machine 2025 T3 Development Team diff --git a/about the test machine/ArcadeMachine_Pi3_Replication_Checklist.md b/about the test machine/ArcadeMachine_Pi3_Replication_Checklist.md new file mode 100644 index 0000000..0ecb895 --- /dev/null +++ b/about the test machine/ArcadeMachine_Pi3_Replication_Checklist.md @@ -0,0 +1,352 @@ +# Arcade Machine — Raspberry Pi 3 Replication Checklist (Pi3 Test Machine) + +Below is a checklist of the steps we took to reproduce the current state on a Raspberry Pi, plus unfinished parts and suggestions for improvement. Follow these steps to replicate the environment and get the ArcadeMachine UI running. + +--- + +## Replication Target (Current State) + +On **Raspberry Pi OS** (kernel **6.1**, **g++ 10**), we built only the **SplashKitBackend** static library from the `splashkit-core` branch from early **2022**. + +We used a **shim dynamic library** to package the Backend into the `libSplashKit.so` expected by the legacy project (exporting legacy API names like `open_database` / `run_sql` / `query_success`). + +We also wrote a **header compatibility layer** (`sk-compat`) to map the `splashkit.h` included in the legacy project to the new Backend header/namespace, forwarding commonly used functions and macros so we can compile the **ArcadeMachine** main program and start the UI. + +Running **ArcadeMachine** successfully enters the interface; audio and some games still need adaptation (see **Unfinished & Suggestions**). + +--- + +## 1) Environmental Requirements + +- **Device:** Raspberry Pi (armv7) +- **OS:** Raspberry Pi OS (desktop, capable of running X11) +- **Compiler:** g++ 10.2 (Raspbian) + +**Directory layout** (match this to reduce path differences): + +```text +/opt/arcade/ + arcade-machine/ # Main program + arcade-games/ # Game collections + sk-compat/ # Compatibility headers + sk-shim/ # Dynamic library wrapper +/opt/splashkit-core/ # 2022 version core repository +``` + +--- + +## 2) Get the Repositories + +```bash +# 1) splashkit-core (reverted to around 2022-08) +sudo mkdir -p /opt && sudo chown -R "$USER":"$USER" /opt +git clone https://github.com/ZGT23/splashkit-core.git /opt/splashkit-core +cd /opt/splashkit-core + +# Make sure you're in the 2022-08 commit (we used commit 2e75c14) +git show -s --date=short --pretty='commit %h %ad %s' + +# 2) arcade-machine (your own fork) +git clone https://github.com//arcade-machine.git /opt/arcade/arcade-machine + +# 3) arcade-games (your own fork) +git clone https://github.com//arcade-games.git /opt/arcade/arcade-games +``` + +--- + +## 3) Build the “legacy” SplashKitBackend (backend only) + +```bash +cd /opt/splashkit-core +rm -rf build +cmake -S projects/cmake -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j "$(nproc)" --target SplashKitBackend +sudo cmake --install build +sudo ldconfig +``` + +When completed, you should have: + +``` +/usr/local/lib/libSplashKitBackend.a +/usr/local/include/SplashKitBackend/*.h +``` + +We chose **not** to directly generate the official `libSplashKit.so`, but instead used the shim in the next step to export the legacy API symbols. This is the path we validated on the Pi. + +--- + +## 4) Build the shim dynamic library +_Pack the Backend static library into `libSplashKit.so` and export legacy symbols._ + +```bash +mkdir -p /opt/arcade/sk-shim && cd /opt/arcade/sk-shim + +# CMakeLists.txt +cat > CMakeLists.txt << 'EOF' +cmake_minimum_required(VERSION 3.13) +project(SKShim CXX) + +add_library(SplashKit SHARED empty.cpp) +target_include_directories(SplashKit PRIVATE /usr/local/include/SplashKitBackend) + +# Pack the entire Backend static library to ensure symbols are exported +target_link_libraries(SplashKit PRIVATE -Wl,--whole-archive /usr/local/lib/libSplashKitBackend.a -Wl,--no-whole-archive) +EOF + +# An empty source file +echo "extern \"C\" void __skshim_keep(){}" > empty.cpp + +# Build & Install +cmake -S . -B build -DCMAKE_BUILD_TYPE=Release +cmake --build build -j "$(nproc)" +sudo install -m 755 build/libSplashKit.so /usr/local/lib/libSplashKit.so +sudo ldconfig + +# Verify that legacy database-related symbols are exported (example) +nm -D /usr/local/lib/libSplashKit.so | grep -E 'open_database|run_sql|query_success|has_row|query_column_for_' | head +``` + +You should see exported symbols (mostly namespace-qualified symbol names, sufficient for linking). + +--- + +## 5) Install the header compatibility layer (`sk-compat`) +_Resolves inclusion and call discrepancies in legacy code._ + +We adapted `splashkit.h` to forward to the Backend headers and provided shims for a few legacy functions/macros to avoid overload ambiguity (do **not** `using namespace splashkit_lib;` to prevent duplicate-name conflicts). Place this file at `/opt/arcade/sk-compat/include/splashkit.h`: + +```cpp +#pragma once + +// Only include the Backend header, avoid using-directives to reduce ambiguity +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// -- Type short names: Export commonly used types to the global scope -- // +using splashkit_lib::sprite; +using splashkit_lib::bitmap; +using splashkit_lib::point_2d; +using splashkit_lib::rectangle; +using splashkit_lib::vector_2d; +using splashkit_lib::color; +using splashkit_lib::key_code; + +// -- Color macros maintain historical conventions -- // +#define COLOR_BLACK (splashkit_lib::color_black()) +#define COLOR_WHITE (splashkit_lib::color_white()) + +// -- "Unambiguous forwarding" of commonly used functions -- // +inline void refresh_screen() { splashkit_lib::refresh_screen(); } +inline void refresh_screen(unsigned int /*fps*/) { splashkit_lib::refresh_screen(); } + +inline void draw_text(const std::string &t, const color &c, const std::string &font, int sz, double x, double y) { + splashkit_lib::draw_text(t, c, font, sz, x, y); +} +inline void clear_screen(const color &c) { splashkit_lib::clear_screen(c); } +inline void process_events() { splashkit_lib::process_events(); } +inline bool quit_requested() { return splashkit_lib::quit_requested(); } +inline bool key_down(key_code k){ return splashkit_lib::key_down(k); } +inline bool key_typed(key_code k){ return splashkit_lib::key_typed(k); } + +inline void play_music(const std::string &name){ splashkit_lib::play_music(name); } +inline void stop_music(){ splashkit_lib::stop_music(); } +inline bool music_playing(){ return splashkit_lib::music_playing(); } + +inline void write_line(const std::string &s){ splashkit_lib::write_line(s); } + +// Old resource pack API mapping +inline void load_resource_bundle(const std::string &name, const std::string &path){ + splashkit_lib::load_resource_bundle(name, path); +} +inline void free_resource_bundle(const std::string &name){ + splashkit_lib::free_resource_bundle(name); +} + +// sprites / camera commonly used +using splashkit_lib::sprite_center_point; +using splashkit_lib::sprite_position; +using splashkit_lib::sprite_set_position; +using splashkit_lib::sprite_set_dx; +using splashkit_lib::sprite_set_dy; +using splashkit_lib::create_sprite; +using splashkit_lib::bitmap_named; +using splashkit_lib::music_named; +using splashkit_lib::draw_bitmap; +using splashkit_lib::update_animation; +using splashkit_lib::animation_ended; + +using splashkit_lib::screen_width; +using splashkit_lib::screen_height; +using splashkit_lib::to_screen; +using splashkit_lib::to_screen_x; +using splashkit_lib::to_screen_y; +using splashkit_lib::point_on_screen; +using splashkit_lib::rect_on_screen; +using splashkit_lib::camera_x; +using splashkit_lib::camera_y; +using splashkit_lib::move_camera_to; +using splashkit_lib::set_camera_x; +using splashkit_lib::set_camera_y; + +// window related +using splashkit_lib::open_window; +using splashkit_lib::hide_mouse; +using splashkit_lib::window_toggle_border; +using splashkit_lib::window_toggle_fullscreen; +using splashkit_lib::window_is_fullscreen; +``` + +> **Notes** +> +> - We wrap the “ambiguous” functions with `inline` and avoid broad `using` to reduce naming conflicts. +> - The `refresh_screen(unsigned int)` overload is key: it swallows old calls like `refresh_screen(60)` and forwards to the parameterless version, avoiding the “overload ambiguity” compile error. +> - If more functions/enums are missing, add similar inline forwarders here. + +--- + +## 6) Compile ArcadeMachine + +```bash +cd /opt/arcade/arcade-machine +make clean 2>/dev/null || true + +# Key: Include sk-compat headers and link against libSplashKit.so +make \ + CPPFLAGS="-I/opt/arcade/sk-compat/include -I/usr/local/include/SplashKitBackend" \ + CXXFLAGS="-Iinclude -I/opt/arcade/sk-compat/include -I/usr/local/include/SplashKitBackend" \ + LDFLAGS="-lstdc++fs -lSplashKit" +``` + +Successful compilation should produce `./ArcadeMachine` and: + +```bash +ldd ./ArcadeMachine | grep SplashKit +# Should show: /usr/local/lib/libSplashKit.so +``` + +--- + +## 7) Run ArcadeMachine (runtime environment) + +Run inside a **graphical desktop session** (not pure SSH): + +```bash +cd /opt/arcade/arcade-machine + +# If the audio device is missing, use the "silent driver" to avoid errors. +export SDL_AUDIODRIVER=dummy +./ArcadeMachine +``` + +**Common symptoms & fixes** + +- **Font/Audio warnings:** Ignore when using the dummy audio driver. Ensure `resources/fonts/*.ttf` exist and are included in the resource bundle. +- **Menu freeze on first entry:** Likely due to `arcade-games` cloning/indexing or missing resources—clone `/opt/arcade/arcade-games` beforehand and confirm resources are in place. + +--- + +## 8) Compile and run a C++ game (example: _BelowTheSurface_) + +This repository may not ship with a Makefile (in our version). You can compile quickly with one command: + +```bash +cd /opt/arcade/arcade-games/games/BelowTheSurface + +# Single-file example (program.cpp with include/ ) +g++ -std=gnu++14 \ + -I include \ + -I /opt/arcade/sk-compat/include \ + -I /usr/local/include/SplashKitBackend \ + program.cpp \ + -lSplashKit -lstdc++fs -O3 \ + -o below_the_surface + +# Run (dummy audio still recommended) +export SDL_AUDIODRIVER=dummy +./below_the_surface +``` + +If there are multiple `.cpp` files, append them to the command, or create a minimal Makefile with the same include path and `-lSplashKit` link. + +--- + +## 9) Targeted fixes we applied + +- **`refresh_screen(60)` overload ambiguity:** Provided `inline void refresh_screen(unsigned int)` in `sk-compat/splashkit.h`. +- **Missing `sprite_center_point` / `music_playing` symbols:** Resolved via `using` or inline forwarders to `splashkit_lib::...` in `sk-compat`. Add more as needed. +- **Database symbols missing at link:** Pack `libSplashKitBackend.a` via shim `libSplashKit.so` to satisfy old-style symbols. +- **No audio device:** `export SDL_AUDIODRIVER=dummy` to avoid “Attempting to load music when audio is closed”. + +--- + +## 10) Unfinished & Constructive Suggestions + +### A. Uniform `sk-compat` mapping +Systematically review the legacy API and provide items one by one in `sk-compat/splashkit.h`: + +- `write_line` / `delay` / timers family +- Overloads for bundles (e.g., `string_view`) +- Keep exports focused on **types & constants**; use **inline forwarders** for functions to avoid conflicts +- Consider a separate repo/subdir for `sk-compat` and include it in build-product testing + +### B. Provide a common Makefile template for `arcade-games` + +Place a minimal `Makefile` in each game directory so ArcadeMachine can run `make -C ` before launching (avoids a blank screen): + +```make +CXX := g++ +CXXFLAGS := -std=gnu++14 -O3 -I include -I /opt/arcade/sk-compat/include -I /usr/local/include/SplashKitBackend +LDFLAGS := -lSplashKit -lstdc++fs + +SRC := $(wildcard *.cpp src/*.cpp) +BIN := game + +all: $(BIN) + +$(BIN): $(SRC) +\t$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS) + +clean: +\trm -f $(BIN) +``` + +### C. Robustness of resource bundles + +- Verify resource files exist **before** launching a game; show a clear UI prompt if missing instead of a blank screen. +- On silent devices, failures in `play_music`/`load_sound_effect` should warn but **not** interrupt the process. + +### D. Window/Display environment detection + +We encountered: `displayIndex must be in the range 0 - -1` — happens when there is **no desktop session** or `DISPLAY` is unset. Detect `SDL_VIDEODRIVER` / `DISPLAY` at launch and provide a helpful prompt in SSH environments (or fallback to dummy video). + +### E. Script the shim build + +Automate the three-step CMake build (`scripts/build-shim.sh`) for one-click install to lower entry barriers. + +### F. CI verification + +Set up a minimal GitHub Action (for ARM via cross/runner) to run header and link checks to avoid future breakages after system upgrades. + +--- + +_This Markdown was adapted directly from the original operation manual for the Pi3 test machine to preserve readability while making it easy to follow and copy-paste commands._ diff --git a/include/AboutScreen.h b/include/AboutScreen.h index 806c79d..979dfc9 100644 --- a/include/AboutScreen.h +++ b/include/AboutScreen.h @@ -45,4 +45,5 @@ class AboutScreen { void main(); }; -#endif \ No newline at end of file +#endif + diff --git a/include/about.md b/include/about.md new file mode 100644 index 0000000..81bdf5e --- /dev/null +++ b/include/about.md @@ -0,0 +1,123 @@ +1.AboutScreen.h +The developer contribution list page will scroll through the contribution information of developers and obtain information from the data collected by the previous statistics script. + +2.ArcadeMachine.h +The master control type of the entire "arcade front-end program" - organizing the startup animation, main menu, game list, option menu, button clicks, sounds and layout all together. + +3.Audio.h +The music player plays the main menu music by default upon startup. It can switch songs and adjust the volume, ensuring that games/menus have a unified music management interface. + +4.Button.h +The parent class of all buttons provides the basic attributes and behaviors for the buttons. + +5.ButtonNode.h +Button nodes are used to form a bidirectional circular linked list of a bunch of buttons. This enables the menu cursor to move in a loop between buttons, just like in a real arcade machine. You can push in one direction without going all the way, making there no sense of boundaries. + +6.cell.h +The grid cell, as the smallest drawing unit in the machine, supports storing four types: EMPTY,BMP,SPT(Animation Sprite), and BTN. It also supports functions such as center alignment, how large this cell should occupy (merging other base cells), etc. A very important drawing unit. + +7.ConfigData.h +A very important header file is the "Data model manual" for each game. It is through this that the menu system knows which games are available and how to start them. Including: All metadata of each game. + +Basic information: m_id + + m_repo + + m_language + + m_folder + +Display information: m_image + + m_title + + m_genre + + m_rating + + m_author + + m_description + +Executable file path + + The executable path of Win + + The executable path of Linux + + The executable path of MacOS + +It can open the config.txt of each game, read this information from it (here we have to mention config.txt, which is the information that every game uploader must provide), and then convert this information from text information into object attributes for the convenience of using it for config later. + +8.Configuration.h +Global configuration constants, uniformly managing environment-related parameters such as "resolution, path separator, CPU architecture, operating system type, and executable file extension". + +9.Database.h +The database encapsulation for arcade menu/statistics provides common operation methods such as table creation, addition, deletion, modification, query, and printing, making it convenient for direct invocation elsewhere. + +10.GameData.h +To record each round encapsulation, wrote in the database a is fixed: gameData, it exists fields: gamaName, startTime, endTime, rating, highScore. It will even provide aggregated statistics: average score, total duration, highest score, etc. + +11.GameScreenButton.h +The specific implementation class on the game selection menu completes the implementation of button images, drawing, click behavior, etc. In the menu interface, each game/option will be displayed with a GameScreenButton. + +12.GridLayout.h +This actually forms a linkage with the previous grid header file. The two work together to achieve a very good drawing effect. It can divide the entire screen into x rows and y columns. Each cell is a grid, managing the drawing content of each cell, drawing uniformly, automatically calculating scaling, position, etc. based on the cell size, and finally drawing all of them. And it provides the functions of cleaning the screen and releasing memory. + +13.Helper.h +This is a very important toolbox, involving the reading of game directories, etc. + +(1) There is a function called string getFoldName(string entryPath), which uses the path of the passed game file (usually the config.txt of a certain game) to take the directory where it is located as the "game folder name" Facilitate the subsequent reading of resources by ConfigData. + +(2) vectorgetConfigFiles(string dir) recursively traverses the folder, collects all config.txt files, and returns a list of paths. + +(3) vector ConfigDataList() +Call getConfigFiles(string dir), specify the path for it ("./games/games"), scan it once, then read each config.txt in, convert it into a ConfigData object, and fill it in: + folder + id + The fields parsed from the configuration file +Regarding the specified path ("./games/games"), it is necessary to mention the special directory of the game repository. For the storage of games, a special format must be met. It must be written as config.txt and then uniformly placed in the "games" folder. Only in this way can vector ConfigDataList() correctly find the game and load the relevant configuration. That's why it is hard-coded here. + +(4)void resetScreen(GridLayout grid) +A demonstration tool for drawing grids for testing. + +(5) void gridLayoutExample() +Open a 600x800 window without loading appContainer.png. Create a 5x5 grid and conduct several layout experiments. + +14.Menu.h +The desktop of the arcade machine. + +15.MenuButton.h +The button class of the menu interface inherits from the previous Button. + +16.Option.h +The "Settings/Options Menu" of the arcade machine, the Settings interface. + +17.OptionButton.h +A dedicated button for the Settings menu. + +18.Process.h +Start an external process (basically a game) on Linux/ Raspberry PI and check if it is still running. +1.spawnProcess(std::string directory,std::string fileName) +Generate a new process +Parameters: The first one is placed in the directory where the running file is located, and the second one is placed in the file name of the running program. +Return value: pid_t(ID of the new process). +2.processRunning(pid_t processId) +Check if the process is alive and return T/F. + +Why is this file necessary? Because the arcade machine needs to continuously listen to whether the application is still running, if the program is not running, it needs to exit and return to the main menu. + +19.Rating.h +Scoring component. + +20.Selector.h +Cursor selector component. + +21.Splashscreen.h +The opening animation component plays the logo and provides an opening animation. + +22.Table.h +The description of a table in the Database provides a blueprint for the tables in the previous database. + +23.Tip.h +The screen prompts the implementation of bubbles/small pop-up Windows, which will automatically disappear after a few seconds. \ No newline at end of file diff --git a/resources/about.md b/resources/about.md new file mode 100644 index 0000000..466bd82 --- /dev/null +++ b/resources/about.md @@ -0,0 +1 @@ +The resource file stored when the machine starts running. Provide resources for rendering, playback, etc. It is worth mentioning bundles, which can integrate different versions of resources to meet various needs. Among them, resources.txt is a related integration. \ No newline at end of file diff --git a/scripts.tar.gz b/scripts.tar.gz new file mode 100644 index 0000000..9685a4a Binary files /dev/null and b/scripts.tar.gz differ diff --git a/src/about.md b/src/about.md new file mode 100644 index 0000000..59e09f0 --- /dev/null +++ b/src/about.md @@ -0,0 +1 @@ +Here is the specific implementation file of the previous header file. What they are doing is the same as the purpose of the header file, so the implementation details will not be delved into. \ No newline at end of file diff --git a/stats/about.md b/stats/about.md new file mode 100644 index 0000000..bd3be17 --- /dev/null +++ b/stats/about.md @@ -0,0 +1 @@ +Previously, generate-stats.sh generated the target folder of the file, counted the number of cpp lines, contributors, commits, etc. \ No newline at end of file