Skip to content

Commit

Permalink
Add Rust to descriptions, include game list in metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbarry authored Aug 5, 2024
2 parents 44bc8dc + 7641cd3 commit d7b743d
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 44 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
# AlexGames

A collection of simple Lua games, and a web engine for playing them including an English dictionary (for word puzzles), websocket multiplayer, state sharing via URL, and auto saving with undo/redo. You can also upload your own games and play in the public web version.
A collection of simple Lua and Rust games, and an API for playing them including an English dictionary (for word puzzles), websocket multiplayer, state sharing via URL, and auto saving with undo/redo. You can also upload your own Lua games and play in the public web version.

Try the web version here: https://alexbarry.github.io/AlexGames

[<img src="https://fdroid.gitlab.io/artwork/badge/get-it-on.png"
alt="Get it on F-Droid"
height="80">](https://f-droid.org/packages/net.alexbarry.alexgames/)

## Brief technical overview

High level:
* Simple API for handling input/output defined in [`game_api.h`](src/game_api/game_api.h). e.g. "draw rectangle", "handle touch", "send/receive multiplayer message".
* Wrappers to this API for [Lua](src/lua_api/lua_api.c), [Rust](src/rust_games/rust_game_api.rs). (C/C++ can call the API directly).
* Games are written for this API in [Lua](src/lua_scripts/games) and [Rust](src/rust_games). (See the "history browser" (described below) for an example of implementing the game API in C++).
* The API is implemented by the following platforms:
* web (HTML/JS/WASM): ([C wrapper](src/emscripten/emscripten_api.c), [JS callbacks](src/html/js/alexgames_wasm_api.js), [JS Game APIs](src/html/js/alexgames_wasm_wrapper.js)),
* [wxWidgets](src/ui_wxWidgets/wx_main.cpp), and
* Android bundles the web version for offline play, and _(experimental)_ Android supports the native AlexGames API, no browser or WebView required: ([C wrapper](src/android/app/src/main/cpp/alex_games_android_jni.cpp), [Java JNI Interface](src/android/app/src/main/java/net/alexbarry/alexgames/AlexGamesJni.java), [Android canvas writes](src/android/app/src/main/java/net/alexbarry/alexgames/graphics/AlexGamesCanvas.java)).

The web version is polished and fairly robust. The wxWidgets and Android native versions serve more as proof of concepts for now, demonstrating how relatively easy it is to bring up a new platform that supports all the games. But they are lacking some functionality.

Some other cool features:
* [History Browser](src/cpp_libs/history_browse_ui/history_browse_ui.cpp) allows you to view previously saved game states, including a preview. The history browser code itself implements the same API as the games, so it should be easy to support it on a new platform. The history browser code also uses the games' code to render previews, meaning it runs them as games within itself, which is also implementing the game interface.
* [Saved State database](src/cpp_libs/saved_state_db) to keep the API simple, the only persistent state is writing to key value pairs (based on HTML local storage). The "saved state database" is a C++ wrapper to allow games to simply call `save_state` with a `uint8_t` array every time there is a state change, and the saved state database keeps track of the move ID. It also handles distinguishing between game sessions, and supports undo/redo and loading initial state on game start (e.g. browser refresh).
* _(Experimental)_ [Android web games server](src/android/app/src/main/java/net/alexbarry/alexgames/server): this isn't often a useful feature, but if you had a WiFi network with no public internet access, and IP isolation isn't enforced, you could use a phone with the AlexGames Android app to host the simple static HTTP and websocket server. This would allow you to play games with your friends on your local network, without relying on the public internet.

## How to build

### Using docker
Expand Down Expand Up @@ -60,3 +78,6 @@ See BUILD.md. I find this much more convenient for incremental builds.

* Email: `alexbarry.dev2 [ at ] gmail.com`.
* Matrix: [`#alexgames:matrix.org`](https://matrix.to/#/#alexgames:matrix.org)
* Github: https://github.com/alexbarry/AlexGames
* Discord: https://discord.gg/rhy8SuHPYU
* Lemmy: [`!alexgames@lemmy.ca`](https://lemmyverse.link/c/alexgames@lemmy.ca)
20 changes: 19 additions & 1 deletion metadata/en-US/full_description.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
A collection of simple Lua games, and a web engine for playing them including an English dictionary (for word puzzles), websocket multiplayer, state sharing via URL, and auto saving with undo/redo. You can also upload your own games and play them.
A collection of simple Lua and Rust games, and a web engine for playing them including an English dictionary (for word puzzles), websocket multiplayer, state sharing via URL, and auto saving with undo/redo. You can also upload your own games and play them.

Some games incude:
* Solitaire
* "Word Mastermind": Guess 5 letter words, finding out if you guessed the right letter, or the right letter in the right position.
* chess
* "Crossword Letters": Try to make as many words as you can with the letters provided, with a crossword as a hint.
* "Gem Match": Swap gems to make lines of three or more of the same kind.
* Go/Weiqi/Baduk
* Reversi
* Checkers/Draughts
* "Endless Runner": Tap the screen or press space bar to propel yourself upwards, dodging the endless oncoming obstacles.
* Minesweeper
* Fluid Mix: Rearrange the stacks where you can only move stacks onto empty stacks or stacks of the same colour, until each stack has only a single colour.
* Backgammon
* Cribbage
* "Spider Swing": swing from point to point, being careful not to lose too much height or speed.
* "Thrust": Race your space ship around the track, trying to control your momentum.
* Gomoku/Wuziqi/Omok: Place stones on a Go board, trying to be the first to create a line of 5.

The android app bundles the web version for offline play. (For network multiplayer, try the web version at https://alexbarry.github.io/AlexGames).

Expand Down
2 changes: 1 addition & 1 deletion metadata/en-US/short_description.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Play simple Lua games, host web games server
Play simple Lua/Rust games, host web games server
34 changes: 9 additions & 25 deletions src/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html manifest="cache.manifest">
<head>
<meta charset="utf-8"/>
<meta name="description" content="Collection of simple Lua games that can be played in your browser. Includes solitaire, word games, chess, go, checkers. Supports local or websocket multiplayer."/>
<meta name="description" content="Collection of simple Lua and Rust games that can be played in your browser. Includes solitaire, word games, chess, go, checkers. Supports local or websocket multiplayer."/>
<meta name="keywords" content="games, simple, board games, lua, multiplayer, solitaire, chess, go, checkers"/>
<meta name="author" content="Alex Barry"/>
<!-- setting maximum-scale=1 to prevent auto zooming in on input fields in safari mobile.
Expand Down Expand Up @@ -244,38 +244,20 @@ <h2 id="subtitle" class="subtitle">Choose a game</h2>


<div id="game_button_row" class="button_row">
<!-- TODO these buttons should be instantiated from Lua, they are game dependent.
I am just putting them here for now to see how it looks in pure JS before
making it more complicated -->
<!--
<button style="flex:1">Undo</button>
<button style="flex:1">Redo</button>
<button style="flex:2">Pass</button>
-->
<!-- Buttons are added here from the game API -->
</div>

<!-- TODO this popup should also be instantiated from Lua, or at least hidden by default
but Lua decides when to show it and what content to populate it with.
Maybe for now it is okay to define a "choice popup" that shows a message
like this with a header, some text, and some number of buttons. -->
<div id="popup" class="popup game_popup" style="display:none">
<!--
<h2>Choose piece colour</h2>
<p>Black moves first.</p>
<p>The other player has not yet chosen.</p>
<p>The other player has chosen <em>white</em>.</p>
<button>Black</button>
<button>White</button>
-->
<!-- This popup is populated and set visible by the game API -->
</div>

<div class="overlay" style="display:none"></div>

</div>

</div>


<!-- This is made visible when the user presses the "Options" button -->
<div id="options_popup" class="popup meta_popup options_popup" style="display:none">
<button id="btn_close_options" class="close_button">X</button>
<div class="popup_content_wrapper">
Expand All @@ -301,6 +283,7 @@ <h3>Main</h3>
</div>

<h3>Game options</h3>
<!-- These options are populated by the game API -->
<div id="game_options">
<div id="game_options_none_placeholder">
<p>This game has not defined any options. <span class="dev_note not_supported">(For developers: call the <code>add_game_option</code> API to add options here. This is useful for less commonly used options like starting a new game.)</span></p>
Expand Down Expand Up @@ -617,13 +600,13 @@ <h2 class="game_title">Conway's Game of Life</h2>
<div class="popup_content_wrapper">
<h2 class="title">About AlexGames</h2>

<p>AlexGames is a platform for simple games written in Lua or C/C++, currently supporting HTML (the page you are currently visiting), and experimental implementations in Android, and Windows/MacOS/Linux (using wxWidgets). The idea is that someone can throw together the "fun parts" of a game in a few hundred lines of Lua or C++, and then the boilerplate to get it running on their platform of choice should be already taken care of. Adding support for a new platform should be relatively easy.</p>
<p>AlexGames is a platform for simple games written in Lua, Rust, or C/C++, currently supporting HTML (the page you are currently visiting), and experimental implementations in Android, and Windows/MacOS/Linux (using wxWidgets). The idea is that someone can throw together the "fun parts" of a game in a few hundred lines of Lua, Rust, or C++, and then the boilerplate to get it running on their platform of choice should be already taken care of. Adding support for a new platform should be relatively easy.</p>

<p>For further convenience (both for game developers and game players), you can develop and/or play your own game just by uploading a bundle of Lua code to the browser client. If you want to put together a simple game, but don't want to bother building this project, you shouldn't need to: just download <a href="example_game_apidemo.zip">the example Lua game zip</a>, consult the <a href="game_api_doc.html" target="_blank">Lua API reference</a>, and then you can modify the existing example Lua code or write your own, and then zip your files. Then you can upload that zip file into the web client, or send it to a friend.</p>
<p>For further convenience (both for game developers and game players), you can develop and/or play your own Lua game just by uploading a bundle of Lua code to the browser client. If you want to put together a simple game, but don't want to bother building this project, you shouldn't need to: just download <a href="example_game_apidemo.zip">the example Lua game zip</a>, consult the <a href="game_api_doc.html" target="_blank">Lua API reference</a>, and then you can modify the existing example Lua code or write your own, and then zip your files. Then you can upload that zip file into the web client, or send it to a friend.</p>

<p>It also supports some helpful features like a built in English dictionary (for word puzzle games), sharing state via URL, and saving state and browsing previously saved states. Previews of saved states are generated using the same code the programmer wrote to render the game itself. The logic for handling this is included as a library to the game platform itself: very little extra code should be needed for game developers or developers of new "clients" (more on what a "client" is below).</p>

<p>One of the goals is for the API to be very convenient both for game developers, and for developers of new "clients". In this context a "client" is a platform that the game is built for: there is a client for browsers, developed in HTML/JS/WASM, a native Android client, and a wxWidgets client that allows for playing games natively on Windows, MacOS, and Linux.</p>
<p>One of the goals is for the API to be very convenient both for game developers, and for developers of new "platforms". In this context a "platform" is a device that the game is built for: there is a platform for browsers, developed in HTML/JS/WASM, a native Android platform, and a wxWidgets platform that allows for playing games natively on Windows, MacOS, and Linux.</p>

<p>Created by <a href="https://github.com/alexbarry">Alex Barry</a>. You are encouraged to submit comments, bug reports, feature requests, or say hi at:</p>

Expand All @@ -642,6 +625,7 @@ <h2 class="title">About AlexGames</h2>
<li><a href="https://lua.org"><img alt="Lua Logo" src="img/credits/Lua-Logo_128x128.png" width="48" height="48"/></a> A lightweight scripting language that integrates very nicely with C</li>
<li><a href="https://cmake.org">CMake</a>: cross platform build system</li>
<li><a href="https://emscripten.org">Emscripten</a>: compile C/C++ to WebAssembly</li>
<li><a href="https://www.rust-lang.org/">Rust (Language)</a>: a much nicer alternative to C++ which still integrates nicely with C++ and has great support for WebAssembly.</li>
</ul>
<!-- The others don't explicitly say to include their logo, so I'm not sure if I should. -->
<p>See more in the <a href="licenses.html" target="_blank">licenses page</a>.</p>
Expand Down
31 changes: 31 additions & 0 deletions src/html/licenses.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ <h2 id="subtitle" class="subtitle">Licenses</h2>
<li><strong>AlexGames</strong> (<a href="#alexgames-license">license</a>): see the license for this project below.</li>
<li><strong>Lua</strong> (<a href="#lua-license">license</a>) (<a href="https://lua.org">web site</a>): A wonderful scripting language whose interpreter compiles into about 400 kB of WASM.</li>
<li><strong>Emscripten</strong> (<a href="#emscripten-license">license</a>) (<a href="https://emscripten.org">web site</a>): Compiles C/C++ code into webassembly (WASM). This is invaluable to this project both for compiling my own C/C++ code, but also the Lua interpreter. It also packages my Lua files in a convenient filesystem-like way, and makes it easy for me to upload zip bundles of Lua files to the browser.</li>
<li><strong>Rust (Language)</strong> (<a href="#rust-lang-license">license</a>) (<a href="https://www.rust-lang.org/policies/licenses">web site</a>): Another option used for writing games to use this API with. It is a much nicer alternative to C++, still integrates nicely with C++, and has great support for WebAssembly.</li>
<li><strong>libzip</strong> (<a href="#libzip-license">license</a>) (<a href="https://libzip.org">web site</a>): Handles unzipping user uploaded bundles of Lua scripts, to allow users to play their own games without having to build this project.</li>
<li><strong>zlib</strong> (<a href="#zlib-license">license</a>) (<a href="https://zlib.net">web site</a>): Dependency of libzip.</li>
<li>Python <strong>websockets</strong> library: (<a href="#websockets-license">license</a>) (<a href="https://github.com/python-websockets/websockets">web site</a>): Used for websocket multiplayer server.
Expand Down Expand Up @@ -860,6 +861,36 @@ <h3 id="emscripten-license">Emscripten</h3>
flag will run closure compiler from third_party/).
</pre>

<h2 id="rust-lang-license">Rust</h2>

<a href="https://github.com/rust-lang/rust/blob/master/LICENSE-MIT">Rust github license MIT</a>

<pre>
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</pre>

<h2 id="libzip-license">libzip</h2>

<a href="https://libzip.org/license/">libzip.org/license/</a>
Expand Down
12 changes: 0 additions & 12 deletions src/rust_games/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,10 @@ edition = "2021"
[dependencies]
libc = "0.2.155"
rand = "0.8"
#web-sys = { version = "0.3.69", features = ["console"] }
#wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
#serde-binary = "0.5"
bincode = "1.3.3"

#[dependencies.web-sys]
#version = "0.3"
#features = [ "console" ]



[lib]
name = "alexgames_rust"
path = "rust_game_handler.rs"
#crate-type = ["cdylib"]
#crate-type = ["staticlib"]
#crate-type = ["staticlib", "cdylib"]
crate-type = ["staticlib"]
12 changes: 8 additions & 4 deletions src/rust_games/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
## AlexGames Rust games

This is how I've been building (from project root):
See [gem match](gem_match) and [reversi](reversi) for an example of how to implement a game.

(cd src/rust_games/ && cargo build --target=wasm32-unknown-emscripten) && build/wasm/build.sh -- -j32
Your game should implement `AlexGamesApi` (defined in [`rust_game_api.rs`](rust_game_api.rs)), and it can call the `*const CCallbacksPtr` it is passed to draw on the game canvas, initialize UI elements, send multiplayer messages, etc.

I think what I'm doing is mostly okay, once I figure out how to convert the generic
GameState trait into the reversi state.
When adding a new game, two changes need to be made to [`rust_game_handler.rs`](rust_game_handler.rs):
* `get_rust_game_init_func`: need to match the `game_id` (string, e.g. `"reversi"` or `"gem_match`) to your game's implementation of `pub fn init(callbacks: *const rust_game_api::CCallbacksPtr) -> Box<dyn AlexGamesApi>`.
* `handle_void_ptr_to_trait_ref`: need to match the `game_id` string to the right cast of the `*mut AlexGamesHandle` field `api` to your game struct, which should implement the `AlexGamesApi` trait.

The `handle_void_ptr_to_trait_ref` step for each game could maybe be removed in the future by passing a struct of function pointers to C instead, or something like that. I think in C++ each object's vtable is referenced in a generic place on the object, but in Rust it seems to work differently, and you need to cast to your struct first before you can call the struct functions, even if all the structs implement the `AlexGamesApi` trait.

0 comments on commit d7b743d

Please sign in to comment.