mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-10 00:51:34 +11:00
add amplitude
This commit is contained in:
parent
3ec9bd2610
commit
e78a6624ff
14
examples/amplitude/.cargo/config.toml
Normal file
14
examples/amplitude/.cargo/config.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[unstable]
|
||||||
|
build-std = ["core", "alloc"]
|
||||||
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "thumbv4t-none-eabi"
|
||||||
|
|
||||||
|
[target.thumbv4t-none-eabi]
|
||||||
|
rustflags = ["-Clink-arg=-Tgba.ld", "-Ctarget-cpu=arm7tdmi"]
|
||||||
|
runner = "mgba-qt"
|
||||||
|
|
||||||
|
[target.armv4t-none-eabi]
|
||||||
|
rustflags = ["-Clink-arg=-Tgba.ld", "-Ctarget-cpu=arm7tdmi"]
|
||||||
|
runner = "mgba-qt"
|
407
examples/amplitude/Cargo.lock
generated
Normal file
407
examples/amplitude/Cargo.lock
generated
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler32"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "agb"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"agb_fixnum",
|
||||||
|
"agb_hashmap",
|
||||||
|
"agb_image_converter",
|
||||||
|
"agb_macros",
|
||||||
|
"agb_sound_converter",
|
||||||
|
"bare-metal",
|
||||||
|
"bitflags 2.1.0",
|
||||||
|
"modular-bitfield",
|
||||||
|
"rustc-hash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "agb_fixnum"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"agb_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "agb_hashmap"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"rustc-hash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "agb_image_converter"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"asefile",
|
||||||
|
"fontdue",
|
||||||
|
"image",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "agb_macros"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "agb_sound_converter"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"hound",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ahash"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "amplitude"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"agb",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "asefile"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"byteorder",
|
||||||
|
"flate2",
|
||||||
|
"image",
|
||||||
|
"log",
|
||||||
|
"nohash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bare-metal"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c70beb79cbb5ce9c4f8e20849978f34225931f665bb49efa6982875a4d5facb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deflate"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide 0.6.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fontdue"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0793f5137567643cf65ea42043a538804ff0fbf288649e2141442b602d81f9bc"
|
||||||
|
dependencies = [
|
||||||
|
"hashbrown",
|
||||||
|
"ttf-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
|
||||||
|
dependencies = [
|
||||||
|
"ahash",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hound"
|
||||||
|
version = "3.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.23.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "modular-bitfield"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
|
||||||
|
dependencies = [
|
||||||
|
"modular-bitfield-impl",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "modular-bitfield-impl"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nohash"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0f889fb66f7acdf83442c35775764b51fed3c606ab9cee51500dbde2cf528ca"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.16.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"crc32fast",
|
||||||
|
"deflate",
|
||||||
|
"miniz_oxide 0.3.7",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ttf-parser"
|
||||||
|
version = "0.15.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
20
examples/amplitude/Cargo.toml
Normal file
20
examples/amplitude/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
[package]
|
||||||
|
name = "amplitude"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = [""]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
agb = { version = "0.14.0", path = "../../agb" }
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 2
|
||||||
|
debug = true
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
panic = "abort"
|
||||||
|
lto = true
|
||||||
|
debug = true
|
||||||
|
codegen-units = 1
|
72
examples/amplitude/README.md
Normal file
72
examples/amplitude/README.md
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
# AGBRS template
|
||||||
|
|
||||||
|
## A basic template example for agb projects
|
||||||
|
|
||||||
|
This makes getting started with a new project for the Game Boy Advance in rust really simple, by providing
|
||||||
|
all the boiler plate files for you.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
You will need the following installed in order to build and run this project:
|
||||||
|
|
||||||
|
* A recent version of `rustup`. See the [rust website](https://www.rust-lang.org/tools/install) for instructions for your operating system
|
||||||
|
* `arm-none-eabi-binutils` for assembling and linking
|
||||||
|
* Windows: [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads).
|
||||||
|
Make sure you select "Add path to environment variable" during the install
|
||||||
|
* Debian and derivatives (e.g. Ubuntu, raspberry pi OS, linux mint): `sudo apt install binutils-arm-none-eabi`
|
||||||
|
* Arch linux and derivatives: `sudo pacman -S arm-none-eabi-binutils`
|
||||||
|
|
||||||
|
You will also want to install an emulator. The best support in agb is with [mgba](https://mgba.io), with
|
||||||
|
`println!` support via `agb::println!` but any emulator should work. You'll get the best experience if
|
||||||
|
`mgba-qt` is in your `PATH`.
|
||||||
|
|
||||||
|
If you want to run your game on real hardware, you will also need to install `agb-gbafix` which you can do after installing
|
||||||
|
rust with the following: `cargo install agb-gbafix`. This is not required if you are only running your game in an emulator.
|
||||||
|
|
||||||
|
### Running in an emulator
|
||||||
|
|
||||||
|
Once you have the prerequisites installed, you should be able to build using
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo build
|
||||||
|
```
|
||||||
|
|
||||||
|
or in release mode (recommended for the final version to ship to players)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting file will be in `target/thumbv4t-none-eabi/debug/<your game>` or `target/thumbv4t-none-eabi/release/<your game>` depending on
|
||||||
|
whether you did a release or debug build.
|
||||||
|
|
||||||
|
If you have `mgba-qt` in your path, you will be able to run your game with
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
or in release mode
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo run --release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Starting development
|
||||||
|
|
||||||
|
You can find the documentation for agb [here](https://docs.rs/agb/latest/agb/).
|
||||||
|
|
||||||
|
You may also want to change the package name and version in `Cargo.toml` before you start.
|
||||||
|
|
||||||
|
## Shipping a .gba file for real hardware
|
||||||
|
|
||||||
|
To make a game run on real hardware, you will need to convert the built file into a file suitable for
|
||||||
|
running on the real thing.
|
||||||
|
|
||||||
|
First build the binary in release mode using the instructions above, then do the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
agb-gbafix target/thumbv4t-none-eabi/release/<your game> -o <your game>.gba
|
||||||
|
```
|
117
examples/amplitude/gba.ld
Normal file
117
examples/amplitude/gba.ld
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
|
||||||
|
ENTRY(__start)
|
||||||
|
EXTERN(__RUST_INTERRUPT_HANDLER)
|
||||||
|
|
||||||
|
EXTERN(__agbabi_memset)
|
||||||
|
EXTERN(__agbabi_memcpy)
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ewram (w!x) : ORIGIN = 0x02000000, LENGTH = 256K
|
||||||
|
iwram (w!x) : ORIGIN = 0x03000000, LENGTH = 32K
|
||||||
|
rom (rx) : ORIGIN = 0x08000000, LENGTH = 32M
|
||||||
|
}
|
||||||
|
|
||||||
|
__text_start = ORIGIN(rom);
|
||||||
|
|
||||||
|
INPUT (agb.a)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = __text_start;
|
||||||
|
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.crt0));
|
||||||
|
*(.crt0 .crt0*);
|
||||||
|
*(.text .text*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > rom
|
||||||
|
__text_end = .;
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > rom
|
||||||
|
|
||||||
|
__iwram_rom_start = .;
|
||||||
|
.iwram : {
|
||||||
|
__iwram_data_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
*(.iwram .iwram.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
*(.text_iwram .text_iwram.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
__iwram_data_end = ABSOLUTE(.);
|
||||||
|
} > iwram AT>rom
|
||||||
|
|
||||||
|
. = __iwram_rom_start + (__iwram_data_end - __iwram_data_start);
|
||||||
|
|
||||||
|
__ewram_rom_start = .;
|
||||||
|
.ewram : {
|
||||||
|
__ewram_data_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
*(.ewram .ewram.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
*(.data .data.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
__ewram_data_end = ABSOLUTE(.);
|
||||||
|
} > ewram AT>rom
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss .bss.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
__iwram_end = ABSOLUTE(.);
|
||||||
|
} > iwram
|
||||||
|
|
||||||
|
__iwram_rom_length_bytes = __iwram_data_end - __iwram_data_start;
|
||||||
|
__iwram_rom_length_halfwords = (__iwram_rom_length_bytes + 1) / 2;
|
||||||
|
|
||||||
|
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
|
||||||
|
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
|
||||||
|
|
||||||
|
.shstrtab : {
|
||||||
|
*(.shstrtab)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* debugging sections */
|
||||||
|
/* Stabs */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
|
||||||
|
/* discard anything not already mentioned */
|
||||||
|
/DISCARD/ : { *(*) }
|
||||||
|
}
|
115
examples/amplitude/gba_mb.ld
Normal file
115
examples/amplitude/gba_mb.ld
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
|
||||||
|
ENTRY(__start)
|
||||||
|
EXTERN(__RUST_INTERRUPT_HANDLER)
|
||||||
|
|
||||||
|
EXTERN(__agbabi_memset)
|
||||||
|
EXTERN(__agbabi_memcpy)
|
||||||
|
|
||||||
|
MEMORY {
|
||||||
|
ewram (w!x) : ORIGIN = 0x02000000, LENGTH = 256K
|
||||||
|
iwram (w!x) : ORIGIN = 0x03000000, LENGTH = 32K
|
||||||
|
}
|
||||||
|
|
||||||
|
__text_start = ORIGIN(ewram);
|
||||||
|
|
||||||
|
INPUT (agb.a)
|
||||||
|
|
||||||
|
SECTIONS {
|
||||||
|
. = __text_start;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.crt0));
|
||||||
|
*(.crt0 .crt0*);
|
||||||
|
*(.text .text*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > rom
|
||||||
|
__text_end = .;
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > ewram
|
||||||
|
|
||||||
|
__iwram_rom_start = .;
|
||||||
|
.iwram : {
|
||||||
|
__iwram_data_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
*(.iwram .iwram.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
*(.text_iwram .text_iwram.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
__iwram_data_end = ABSOLUTE(.);
|
||||||
|
} > iwram AT>ewram
|
||||||
|
|
||||||
|
. = __iwram_rom_start + (__iwram_data_end - __iwram_data_start);
|
||||||
|
|
||||||
|
__ewram_rom_start = .;
|
||||||
|
.ewram : {
|
||||||
|
__ewram_data_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
*(.ewram .ewram.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
*(.data .data.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
__ewram_data_end = ABSOLUTE(.);
|
||||||
|
} > ewram AT>ewram
|
||||||
|
|
||||||
|
.bss : {
|
||||||
|
*(.bss .bss.*);
|
||||||
|
. = ALIGN(4);
|
||||||
|
__iwram_end = ABSOLUTE(.);
|
||||||
|
} > iwram
|
||||||
|
|
||||||
|
__iwram_rom_length_bytes = __iwram_data_end - __iwram_data_start;
|
||||||
|
__iwram_rom_length_halfwords = (__iwram_rom_length_bytes + 1) / 2;
|
||||||
|
|
||||||
|
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
|
||||||
|
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
|
||||||
|
|
||||||
|
.shstrtab : {
|
||||||
|
*(.shstrtab)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* debugging sections */
|
||||||
|
/* Stabs */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
|
||||||
|
/* discard anything not already mentioned */
|
||||||
|
/DISCARD/ : { *(*) }
|
||||||
|
}
|
BIN
examples/amplitude/gfx/circles.aseprite
Normal file
BIN
examples/amplitude/gfx/circles.aseprite
Normal file
Binary file not shown.
BIN
examples/amplitude/gfx/numbers.aseprite
Normal file
BIN
examples/amplitude/gfx/numbers.aseprite
Normal file
Binary file not shown.
BIN
examples/amplitude/gfx/saw.aseprite
Normal file
BIN
examples/amplitude/gfx/saw.aseprite
Normal file
Binary file not shown.
3
examples/amplitude/rust-toolchain.toml
Normal file
3
examples/amplitude/rust-toolchain.toml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
|
components = ["rust-src", "clippy", "rustfmt"]
|
373
examples/amplitude/src/lib.rs
Normal file
373
examples/amplitude/src/lib.rs
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![cfg_attr(test, feature(custom_test_frameworks))]
|
||||||
|
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
||||||
|
#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use agb::{
|
||||||
|
display::{
|
||||||
|
self,
|
||||||
|
affine::{self, AffineMatrix},
|
||||||
|
object::{
|
||||||
|
AffineMatrixInstance, AffineMode, Graphics, OamIterator, ObjectUnmanaged, Sprite,
|
||||||
|
SpriteLoader, SpriteVram, Tag, TagMap,
|
||||||
|
},
|
||||||
|
palette16::Palette16,
|
||||||
|
},
|
||||||
|
fixnum::{num, Num, Vector2D},
|
||||||
|
include_aseprite,
|
||||||
|
input::{Button, ButtonController},
|
||||||
|
rng,
|
||||||
|
};
|
||||||
|
use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
|
||||||
|
|
||||||
|
type Number = Num<i32, 8>;
|
||||||
|
|
||||||
|
struct Saw {
|
||||||
|
object: ObjectUnmanaged,
|
||||||
|
position: Vector2D<Number>,
|
||||||
|
angle: Number,
|
||||||
|
rotation_speed: Number,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Colour {
|
||||||
|
Red,
|
||||||
|
Blue,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Circle {
|
||||||
|
colour: Colour,
|
||||||
|
position: Vector2D<Number>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct SpriteCache {
|
||||||
|
saw: SpriteVram,
|
||||||
|
blue: SpriteVram,
|
||||||
|
red: SpriteVram,
|
||||||
|
numbers: Box<[SpriteVram]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum DrawDirection {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_number(
|
||||||
|
mut number: u32,
|
||||||
|
position: Vector2D<i32>,
|
||||||
|
oam: &mut OamIterator,
|
||||||
|
direction: DrawDirection,
|
||||||
|
sprite_cache: &SpriteCache,
|
||||||
|
) {
|
||||||
|
let mut digits = Vec::new();
|
||||||
|
if number == 0 {
|
||||||
|
digits.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
while number != 0 {
|
||||||
|
digits.push(number % 10);
|
||||||
|
number /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut current_position = if direction == DrawDirection::Right {
|
||||||
|
position + (4 * (digits.len() - 1) as i32, 0).into()
|
||||||
|
} else {
|
||||||
|
position
|
||||||
|
};
|
||||||
|
|
||||||
|
for digit in digits {
|
||||||
|
let mut obj = ObjectUnmanaged::new(sprite_cache.numbers[digit as usize].clone());
|
||||||
|
obj.show().set_position(current_position);
|
||||||
|
|
||||||
|
if let Some(slot) = oam.next() {
|
||||||
|
slot.set(&obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_position -= (4, 0).into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpriteCache {
|
||||||
|
fn new(loader: &mut SpriteLoader) -> Self {
|
||||||
|
const SPRITES: &Graphics = include_aseprite!(
|
||||||
|
"gfx/circles.aseprite",
|
||||||
|
"gfx/saw.aseprite",
|
||||||
|
"gfx/numbers.aseprite"
|
||||||
|
);
|
||||||
|
|
||||||
|
const NUMBERS: &Tag = SPRITES.tags().get("numbers");
|
||||||
|
const BLUE_CIRCLE: &Sprite = SPRITES.tags().get("Blue").sprite(0);
|
||||||
|
const RED_CIRCLE: &Sprite = SPRITES.tags().get("Red").sprite(0);
|
||||||
|
const SAW: &Sprite = SPRITES.tags().get("Saw").sprite(0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
saw: loader.get_vram_sprite(SAW),
|
||||||
|
blue: loader.get_vram_sprite(BLUE_CIRCLE),
|
||||||
|
red: loader.get_vram_sprite(RED_CIRCLE),
|
||||||
|
numbers: (0..10)
|
||||||
|
.map(|x| NUMBERS.sprite(x))
|
||||||
|
.map(|x| loader.get_vram_sprite(x))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_boxed_slice(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Game {
|
||||||
|
settings: FinalisedSettings,
|
||||||
|
circles: VecDeque<Circle>,
|
||||||
|
saws: VecDeque<Saw>,
|
||||||
|
head_position: Vector2D<Number>,
|
||||||
|
phase_time: Number,
|
||||||
|
input: ButtonController,
|
||||||
|
energy: Number,
|
||||||
|
frame_since_last_saw: i32,
|
||||||
|
alive_frames: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum GameState {
|
||||||
|
Continue,
|
||||||
|
Loss(u32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
fn from_settings(settings: Settings) -> Self {
|
||||||
|
let finalised = settings.to_finalised_settings();
|
||||||
|
|
||||||
|
let mut circles = VecDeque::with_capacity(finalised.number_of_circles);
|
||||||
|
for idx in 0..finalised.number_of_circles {
|
||||||
|
circles.push_back(Circle {
|
||||||
|
colour: Colour::Red,
|
||||||
|
position: Vector2D::new(
|
||||||
|
finalised.speed * idx as i32 - 4,
|
||||||
|
settings.head_start_position.y,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Game {
|
||||||
|
energy: 100.into(),
|
||||||
|
input: agb::input::ButtonController::new(),
|
||||||
|
settings: finalised,
|
||||||
|
circles,
|
||||||
|
saws: VecDeque::new(),
|
||||||
|
head_position: settings.head_start_position,
|
||||||
|
phase_time: 0.into(),
|
||||||
|
frame_since_last_saw: 0,
|
||||||
|
alive_frames: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn frame(&mut self, sprite_cache: &SpriteCache) -> GameState {
|
||||||
|
self.input.update();
|
||||||
|
|
||||||
|
let (height, colour) = if self.input.is_pressed(Button::A) {
|
||||||
|
(self.settings.wave_height_ability, Colour::Blue)
|
||||||
|
} else {
|
||||||
|
(self.settings.wave_height_normal, Colour::Red)
|
||||||
|
};
|
||||||
|
|
||||||
|
let next_phase_time = self.phase_time + self.settings.phase_speed;
|
||||||
|
|
||||||
|
let this_frame_y_delta = next_phase_time.cos() - self.phase_time.cos();
|
||||||
|
self.phase_time = next_phase_time % num!(1.);
|
||||||
|
let this_frame_y_delta = this_frame_y_delta * height;
|
||||||
|
self.head_position.y += this_frame_y_delta;
|
||||||
|
|
||||||
|
// update circles
|
||||||
|
for circle in self.circles.iter_mut() {
|
||||||
|
circle.position.x -= self.settings.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.circles.pop_front();
|
||||||
|
|
||||||
|
// generate circle
|
||||||
|
let circle = Circle {
|
||||||
|
colour,
|
||||||
|
position: self.head_position,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.circles.push_back(circle);
|
||||||
|
|
||||||
|
// update saws + check for death
|
||||||
|
let mut saw_has_hit_head = false;
|
||||||
|
let mut number_of_saws_to_pop = 0;
|
||||||
|
for (idx, saw) in self.saws.iter_mut().enumerate() {
|
||||||
|
saw.position.x -= self.settings.speed;
|
||||||
|
if saw.position.x < (-32).into() {
|
||||||
|
number_of_saws_to_pop = idx + 1;
|
||||||
|
}
|
||||||
|
saw.angle += saw.rotation_speed;
|
||||||
|
|
||||||
|
let angle_affine_matrix = AffineMatrix::from_rotation(saw.angle);
|
||||||
|
|
||||||
|
saw.object.set_affine_matrix(AffineMatrixInstance::new(
|
||||||
|
angle_affine_matrix.to_object_wrapping(),
|
||||||
|
));
|
||||||
|
saw.object.show_affine(AffineMode::Affine);
|
||||||
|
|
||||||
|
saw.object
|
||||||
|
.set_position(saw.position.floor() - (16, 16).into());
|
||||||
|
|
||||||
|
if (saw.position - self.head_position).magnitude_squared()
|
||||||
|
< ((16 + 4) * (16 + 4)).into()
|
||||||
|
{
|
||||||
|
saw_has_hit_head = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destroy saws
|
||||||
|
for _ in 0..number_of_saws_to_pop {
|
||||||
|
self.saws.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create saw
|
||||||
|
self.frame_since_last_saw -= 1;
|
||||||
|
if self.frame_since_last_saw <= 0 {
|
||||||
|
self.frame_since_last_saw = self.settings.frames_between_saws;
|
||||||
|
let mut rotation_direction = rng::gen().signum();
|
||||||
|
if rotation_direction == 0 {
|
||||||
|
rotation_direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rotation_magnitude =
|
||||||
|
Number::from_raw(rng::gen().abs() % (1 << 8)) % num!(0.02) + num!(0.005);
|
||||||
|
|
||||||
|
let rotation_speed = rotation_magnitude * rotation_direction;
|
||||||
|
let saw = Saw {
|
||||||
|
object: ObjectUnmanaged::new(sprite_cache.saw.clone()),
|
||||||
|
position: (300, rng::gen().rem_euclid(display::HEIGHT)).into(),
|
||||||
|
angle: 0.into(),
|
||||||
|
rotation_speed,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.saws.push_back(saw);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.alive_frames += 1;
|
||||||
|
|
||||||
|
let out_of_bounds_death = self.head_position.y.floor() < -4
|
||||||
|
|| (self.head_position.y + 1).floor() > display::HEIGHT + 4;
|
||||||
|
|
||||||
|
if saw_has_hit_head || out_of_bounds_death {
|
||||||
|
GameState::Loss(self.alive_frames)
|
||||||
|
} else {
|
||||||
|
GameState::Continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&self, oam: &mut OamIterator, sprite_cache: &SpriteCache) {
|
||||||
|
for saw in self.saws.iter() {
|
||||||
|
if let Some(slot) = oam.next() {
|
||||||
|
slot.set(&saw.object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for circle in self.circles.iter() {
|
||||||
|
if let Some(slot) = oam.next() {
|
||||||
|
let mut object = ObjectUnmanaged::new(match circle.colour {
|
||||||
|
Colour::Red => sprite_cache.red.clone(),
|
||||||
|
Colour::Blue => sprite_cache.blue.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
object
|
||||||
|
.show()
|
||||||
|
.set_position(circle.position.floor() - (4, 4).into());
|
||||||
|
|
||||||
|
slot.set(&object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Settings {
|
||||||
|
phase_speed: Number,
|
||||||
|
frames_between_saws: i32,
|
||||||
|
speed: Number,
|
||||||
|
head_start_position: Vector2D<Number>,
|
||||||
|
wave_height_normal: Number,
|
||||||
|
wave_height_ability: Number,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
fn to_finalised_settings(&self) -> FinalisedSettings {
|
||||||
|
FinalisedSettings {
|
||||||
|
number_of_circles: ((self.head_start_position.x + 4) / self.speed + 1)
|
||||||
|
.floor()
|
||||||
|
.try_into()
|
||||||
|
.expect("number should be positive"),
|
||||||
|
speed: self.speed,
|
||||||
|
phase_speed: self.phase_speed,
|
||||||
|
frames_between_saws: self.frames_between_saws,
|
||||||
|
wave_height_ability: self.wave_height_ability,
|
||||||
|
wave_height_normal: self.wave_height_normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FinalisedSettings {
|
||||||
|
wave_height_normal: Number,
|
||||||
|
wave_height_ability: Number,
|
||||||
|
phase_speed: Number,
|
||||||
|
frames_between_saws: i32,
|
||||||
|
speed: Number,
|
||||||
|
number_of_circles: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main(mut gba: agb::Gba) -> ! {
|
||||||
|
let (mut unmanaged, mut sprites) = gba.display.object.get_unmanaged();
|
||||||
|
let sprite_cache = SpriteCache::new(&mut sprites);
|
||||||
|
|
||||||
|
let (_background, mut vram) = gba.display.video.tiled0();
|
||||||
|
|
||||||
|
vram.set_background_palettes(&[Palette16::new([u16::MAX; 16])]);
|
||||||
|
|
||||||
|
let vblank = agb::interrupt::VBlank::get();
|
||||||
|
|
||||||
|
let mut max_score = 0;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut game = Game::from_settings(Settings {
|
||||||
|
phase_speed: num!(0.02),
|
||||||
|
frames_between_saws: 60,
|
||||||
|
speed: num!(1.),
|
||||||
|
head_start_position: (40, 100).into(),
|
||||||
|
wave_height_normal: 20.into(),
|
||||||
|
wave_height_ability: 5.into(),
|
||||||
|
});
|
||||||
|
loop {
|
||||||
|
let state = game.frame(&sprite_cache);
|
||||||
|
if game.alive_frames > max_score {
|
||||||
|
max_score = game.alive_frames;
|
||||||
|
}
|
||||||
|
vblank.wait_for_vblank();
|
||||||
|
let oam_frame = &mut unmanaged.iter();
|
||||||
|
draw_number(
|
||||||
|
max_score,
|
||||||
|
(display::WIDTH - 4, 1).into(),
|
||||||
|
oam_frame,
|
||||||
|
DrawDirection::Left,
|
||||||
|
&sprite_cache,
|
||||||
|
);
|
||||||
|
draw_number(
|
||||||
|
game.alive_frames,
|
||||||
|
(1, 1).into(),
|
||||||
|
oam_frame,
|
||||||
|
DrawDirection::Right,
|
||||||
|
&sprite_cache,
|
||||||
|
);
|
||||||
|
game.render(oam_frame, &sprite_cache);
|
||||||
|
|
||||||
|
if let GameState::Loss(score) = state {
|
||||||
|
for _ in 0..30 {
|
||||||
|
vblank.wait_for_vblank();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
examples/amplitude/src/main.rs
Normal file
10
examples/amplitude/src/main.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
#![cfg_attr(test, feature(custom_test_frameworks))]
|
||||||
|
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
|
||||||
|
#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
|
||||||
|
|
||||||
|
#[agb::entry]
|
||||||
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
|
amplitude::main(gba)
|
||||||
|
}
|
Loading…
Reference in a new issue