💾 Archived View for devlog.thermokar.st › 2022-12-04.gmi captured on 2023-01-29 at 02:16:12. Gemini links have been rewritten to link to archived content

View Raw

More Information

➡️ Next capture (2023-03-20)

-=-=-=-=-=-=-

2022-12-04

single-button gba rom

4:25p

before i forget: advent of code has been going pretty well so far, i'm doing it in rust again this year.

okay, bootstrapping a simple one-button test rom in agb. step 1, scaffold.

agb template

git clone https://github.com/agbrs/template single-button-agb
cd single-button-agb
cargo run

4:35p

agb is designed to integrate with aseprite, so i better get that set up. i've used it before but i don't think i own a licensed copy of it.

4:45p

i just picked up aseprite on itch.io and spent a few minutes getting re-acquainted.

so my plan is to show a single sprite on the screen, and pressing the a button will cause the sprite to toggle. im not sure if it is a moment toggle, or if its only toggled while being held down.

mkdir gfx
# set up two-frame aseprite with distinctly different images
#   and unique tag names

in the gba src:

const FACES: &Graphics = include_aseprite!("gfx/face.aseprite");
const HAPPY_FACE: &Tag = FACES.tags().get("Happy Face");
const SAD_FACE: &Tag = FACES.tags().get("Sad Face");

5:45p

i have a simple demo working, i want to clean this up and then see about adding a sound effect when toggling the sprite.

7:00p

i had a bit of a break for the last 45 mins, but came back and was able to use the agb built-in sound synthesis to play back a really terrible sounding sound clip.

#![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))]

use agb::{
    display::object::{Graphics, Tag},
    include_aseprite,
    input::{Button, ButtonController},
    sound,
};

const FACES: &Graphics = include_aseprite!("gfx/face.aseprite");
const HAPPY_FACE: &Tag = FACES.tags().get("Happy Face");
const SAD_FACE: &Tag = FACES.tags().get("Sad Face");

const WIDTH: i32 = agb::display::WIDTH - 16;
const HEIGHT: i32 = agb::display::HEIGHT - 16;

struct Face {
    is_happy: bool,
    x: i32,
    y: i32,
    vel_x: i32,
    vel_y: i32,
}

impl Face {
    fn new() -> Face {
        Face {
            is_happy: false,
            x: 55,
            y: 55,
            vel_x: 1,
            vel_y: 1,
        }
    }

    fn tick(&mut self) -> () {
        self.x = (self.x + self.vel_x).clamp(0, WIDTH);
        self.y = (self.y + self.vel_y).clamp(0, HEIGHT);

        if self.x == 0 || self.x == WIDTH {
            self.vel_x = -self.vel_x;
        }

        if self.y == 0 || self.y == HEIGHT {
            self.vel_y = -self.vel_y;
        }
    }
}

#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
    gba.sound.enable();
    let object_controller = gba.display.object.get();
    let mut input = ButtonController::new();

    let mut face_data = Face::new();

    let sad_face_sprite = SAD_FACE.sprite(0);
    let happy_face_sprite = HAPPY_FACE.sprite(0);

    let mut face_obj = object_controller.object_sprite(sad_face_sprite);

    loop {
        input.update();

        if input.is_just_pressed(Button::A) {
            let face_sprite = match face_data.is_happy {
                true => sad_face_sprite,
                false => happy_face_sprite,
            };
            let sprite = object_controller.sprite(face_sprite);
            face_obj.set_sprite(sprite);
            face_data.is_happy = !face_data.is_happy;
            gba.sound.noise().play_sound(
                Some(0),
                &sound::dmg::EnvelopeSettings::default(),
                7,
                false,
                1,
            );
        }

        face_data.tick();

        face_obj.set_x(face_data.x as u16).set_y(face_data.y as u16);

        agb::display::busy_wait_for_vblank();
        object_controller.commit();
    }
}

7:15p

uploaded to the gameSH and everything is great!

10:15p

two things to look into:

the chicken example

gba.ninja

Home

© 2022 Matthew Ryan Dillon