···11-# AGBRS template
22-33-## A basic template example for agb projects
44-55-This makes getting started with a new project for the Game Boy Advance in rust really simple, by providing
66-all the boiler plate files for you.
77-88-## Building
99-1010-### Prerequisites
1111-1212-You will need the following installed in order to build and run this project:
1313-1414-- A recent version of `rustup`. See the [rust website](https://www.rust-lang.org/tools/install) for instructions for your operating system
1515-1616-You will also want to install an emulator. The best support in agb is with [mgba](https://mgba.io), with
1717-`println!` support via `agb::println!` but any emulator should work. You'll get the best experience if
1818-`mgba-qt` is in your `PATH`.
11+# Pumpkin Head The Game
1922020-If you want to run your game on real hardware, you will also need to install `agb-gbafix` which you can do after installing
2121-rust with the following: `cargo install agb-gbafix`. This is not required if you are only running your game in an emulator.
33+They said it couldn't be done. But now you can play the exciting Pumpkin Head game play.
2242323-### Running in an emulator
55+Okay it's just really a demo of my [rpg.actor](https://rpg.actor) sprite walking around in a GBA game built with [agbrs](https://agbrs.dev/)
2462525-Once you have the prerequisites installed, you should be able to build using
77+Post showing it [here](https://bsky.app/profile/pds.dad/post/3mkgkpk2vi22x)
2682727-```sh
2828-cargo build
2929-```
3093131-or in release mode (recommended for the final version to ship to players)
3232-3333-```sh
3434-cargo build --release
3535-```
3636-3737-The resulting file will be in `target/thumbv4t-none-eabi/debug/<your game>` or `target/thumbv4t-none-eabi/release/<your game>` depending on
3838-whether you did a release or debug build.
3939-4040-If you have `mgba-qt` in your path, you will be able to run your game with
4141-4242-```sh
4343-cargo run
4444-```
4545-4646-or in release mode
4747-4848-```sh
4949-cargo run --release
5050-```
5151-5252-## Starting development
5353-5454-You can find the documentation for agb [here](https://docs.rs/agb/latest/agb/), or follow the tutorial in [the book](https://agbrs.dev/book/).
5555-5656-You may also want to change the package name and version in `Cargo.toml` before you start.
5757-5858-## Shipping a .gba file for real hardware
5959-6060-To make a game run on real hardware, you will need to convert the built file into a file suitable for
6161-running on the real thing.
6262-6363-First build the binary in release mode using the instructions above, then do the following:
6464-6565-```sh
6666-agb-gbafix target/thumbv4t-none-eabi/release/<your game> -o <your game>.gba
6767-```
1010+If you're wanting to learn to build your own GBA with rust or to run this, best to start with [The agb book](https://agbrs.dev/book/introduction/introduction.html).
gfx/pumpkin_head.aseprite
This is a binary file and will not be displayed.
+105-12
src/main.rs
···11-// Games made using `agb` are no_std which means you don't have access to the standard
22-// rust library. This is because the game boy advance doesn't have an operating
33-// system, so most of the content of the standard library doesn't apply.
41#![no_std]
55-// `agb` defines its own `main` function, so you must declare your game's main function
66-// using the #[agb::entry] proc macro. Failing to do so will cause failure in linking
77-// which won't be a particularly clear error message.
82#![no_main]
99-// This is required to allow writing tests
103#![cfg_attr(test, feature(custom_test_frameworks))]
114#![cfg_attr(test, reexport_test_harness_main = "test_main")]
125#![cfg_attr(test, test_runner(agb::test_runner::test_runner))]
1361414-// By default no_std crates don't get alloc, so you won't be able to use things like Vec
1515-// until you declare the extern crate. `agb` provides an allocator so it will all work
167extern crate alloc;
1781818-// The main function must take 1 arguments and never returns, and must be marked with
1919-// the #[agb::entry] macro.
99+use agb::{
1010+ display::{
1111+ HEIGHT, WIDTH,
1212+ object::{Object, Sprite, Tag},
1313+ },
1414+ fixnum::{Num, Vector2D, num, vec2},
1515+ include_aseprite,
1616+ input::ButtonController,
1717+};
1818+1919+include_aseprite!(mod sprites, "gfx/pumpkin_head.aseprite");
2020+use sprites::{FORWARD, LEFT, REVERSE, RIGHT};
2121+2222+type Number = Num<i32, 8>;
2323+2424+#[derive(Clone, Copy)]
2525+enum Facing {
2626+ Forward,
2727+ Reverse,
2828+ Left,
2929+ Right,
3030+}
3131+3232+impl Facing {
3333+ fn tag(self) -> &'static Tag {
3434+ match self {
3535+ Facing::Forward => &FORWARD,
3636+ Facing::Reverse => &REVERSE,
3737+ Facing::Left => &LEFT,
3838+ Facing::Right => &RIGHT,
3939+ }
4040+ }
4141+}
4242+4343+const SPEED: Number = num!(0.75);
4444+const SPRITE_SIZE: i32 = 32;
4545+const FRAMES_PER_STEP: usize = 8;
4646+2047#[agb::entry]
2148fn main(gba: agb::Gba) -> ! {
2222- agb::no_game(gba);
4949+ run(gba);
5050+}
5151+5252+fn run(mut gba: agb::Gba) -> ! {
5353+ let mut gfx = gba.graphics.get();
5454+ let mut input = ButtonController::new();
5555+5656+ let mut position: Vector2D<Number> = vec2(
5757+ Number::new((WIDTH - SPRITE_SIZE) / 2),
5858+ Number::new((HEIGHT - SPRITE_SIZE) / 2),
5959+ );
6060+ let mut facing = Facing::Forward;
6161+ let mut walk_frames: usize = 0;
6262+6363+ let max_x = Number::new(WIDTH - SPRITE_SIZE);
6464+ let max_y = Number::new(HEIGHT - SPRITE_SIZE);
6565+6666+ loop {
6767+ input.update();
6868+6969+ let dx = input.x_tri() as i32;
7070+ let dy = input.y_tri() as i32;
7171+ let moving = dx != 0 || dy != 0;
7272+7373+ if moving {
7474+ facing = if dy < 0 {
7575+ Facing::Reverse
7676+ } else if dy > 0 {
7777+ Facing::Forward
7878+ } else if dx < 0 {
7979+ Facing::Left
8080+ } else {
8181+ Facing::Right
8282+ };
8383+8484+ position.x += SPEED * dx;
8585+ position.y += SPEED * dy;
8686+8787+ if position.x < num!(0.0) {
8888+ position.x = num!(0.0);
8989+ }
9090+ if position.y < num!(0.0) {
9191+ position.y = num!(0.0);
9292+ }
9393+ if position.x > max_x {
9494+ position.x = max_x;
9595+ }
9696+ if position.y > max_y {
9797+ position.y = max_y;
9898+ }
9999+100100+ walk_frames = walk_frames.wrapping_add(1);
101101+ }
102102+103103+ let tag = facing.tag();
104104+ let sprite: &'static Sprite = if moving {
105105+ tag.animation_sprite(walk_frames / FRAMES_PER_STEP)
106106+ } else {
107107+ tag.sprite(0)
108108+ };
109109+110110+ let mut frame = gfx.frame();
111111+ Object::new(sprite)
112112+ .set_pos(position.floor())
113113+ .show(&mut frame);
114114+ frame.commit();
115115+ }
23116}