Further improvements

This commit is contained in:
Gwilym Inzani 2023-02-25 22:29:06 +00:00
parent d3b38d9e94
commit 12e9433b8d
3 changed files with 45 additions and 57 deletions

View file

@ -1,25 +1,23 @@
# Learn agb part I - pong
# Learn agb part I: Pong
In this section, we'll make a simple pong style game for the Game Boy Advance using `agb`.
You will learn:
In this section, you'll learn how to make a simple pong-style game for the Game Boy Advance using agb.
By following the steps in this section below, you'll gain an understanding of:
* How to use tiled graphics modes.
* How to import graphics using `agb`.
* What Game Boy Advance sprites are and how to put them on the screen.
* How to detect button input and react to it.
* How to add a static background.
* How to make a dynamic background for a score display.
* How to add music to your game.
* How to add sound effects to your game.
* What Game Boy Advance sprites are, how to create them, and how to display them on the screen.
* How to detect button input and use it to control game objects.
* How to add a static background to your game.
* How to make a dynamic background to display scores.
* How to add music and sound effects to your game.
With this knowledge, you'll be well equipped to start making your own games!
With this knowledge, you'll be well equipped to start making your own games for the GBA!
## Getting started
To start, create a new repository based on the [agb template](https://github.com/agbrs/template).
We'll call this `pong`.
To get started, create a new repository based on the [agb template](https://github.com/agbrs/template) and name it `pong`.
Then replace the `name` field in `Cargo.toml` with `pong`, to end up with something similar to:
Next, update the `name` field in `Cargo.toml` to `pong` like so:
```toml
[package]
@ -31,4 +29,4 @@ edition = "2021"
# ...
```
You are now ready to get started learning about how `agb` works.
Now, you're ready to dive and and start learning about `agb`!

View file

@ -4,14 +4,17 @@ In this section, we'll cover the importance of the Gba struct and how it gets cr
# The importance of the Gba struct
Almost all interaction with the Game Boy Advance's hardware goes through the [Gba singleton struct](https://docs.rs/agb/latest/agb/struct.Gba.html).
You should not create the Gba struct yourself, instead having it be passed into your main function.
The [Gba singleton struct](https://docs.rs/agb/latest/agb/struct.Gba.html) is a crucial part of agb game development.
It is used for almost all interactions with the Game Boy Advance's hardware, such as graphics rendering, timer access and audio playback.
The Gba struct is used to take advantage of rust's borrow checker, and lean on it to ensure that access to the Game Boy Advance hardware is done 'sensibly'.
You won't have to worry about 2 bits of your code modifying data in the wrong way!
You should not create the Gba struct yourself. Instead, it is passed to your main function as an owned reference.
This allows rust's borrow checker to ensure that access to the Game Boy Advance hardware is done in a safe and sensible manner, preventing two bits of your code from modifying data in the wrong way.
# How all agb games start
To use the Gba struct in your agb game, you'll need to create a function (normally called `main`) which takes an owned reference to the Gba instance.
The recommended way to do this is by using the `#[agb::entry]` attribute macro provided by the `agb` crate.
Replace the content of the `main` function with the following:
```rust,ignore
@ -23,15 +26,14 @@ loop {} // infinite loop for now
# }
```
and ignore warnings for now.
This creates an infinite loop and allows you to start building your game.
# Running your pong game
Although there isn't much to see at the moment (just a black screen), you can start the game by using `cargo run` or whatever worked for you in the introduction.
At this point, your game won't do much except display a black screen. To run your game, use the `cargo run` command as before.
# What we did
# What we covered
This was a very simple but incredibly important part of any game using `agb`.
All interactions with the hardware are gated via the Gba struct, which you never create yourself.
You are now ready to learn about display modes and how to start getting things onto the screen!
In this section, we covered the importance of the Gba struct in agb game development.
By using the Gba struct as a gatekeeper for all hardware interactions, you can ensure that your code is safe and efficient.
You are now ready to learn about sprites and start getting things onto the screen!

View file

@ -1,56 +1,44 @@
# Sprites
In this section, we'll put the sprites needed for our pong game onto the screen.
We'll cover what sprites are in the Game Boy Advance, and how to get them to show up on screen.
We'll briefly cover vblank and by the end of this section, you'll have a ball bouncing around the screen!
In this section, we'll cover what sprites are in the Game Boy Advance and how to put them on the screen in our pong game.
We'll briefly cover vblank, and by the end of this section, you'll have a ball bouncing around the screen!
# Why do we need sprites in the first place?
# Why do we need sprites?
The Game Boy Advance has a 240x160px screen, with 15-bit RGB colour support.
In order to manually set the colour for each pixel in the screen, you would need to update a total of 38,400 pixels per frame, or 2,304,000 pixels per second at 60 fps.
With a 16MHz processor, that means you would need to be able to calculate 1 pixel every 8 clock cycles, which is pretty much impossible.
You could get clever with how you update these pixels, but using the tools provided by the Game Boy Advance to put pixels on the screen, you'll have a much easier time.
The Game Boy Advance has a 240x160px screen with 15-bit RGB color support. Setting the color for each pixel manually would require updating 38,400 pixels per frame, or 2,304,000 pixels per second at 60 fps.
With a 16 MHz processor, this means calculating 1 pixel every 8 clock cycles, which is pretty much impossible.
he Game Boy Advance provides two ways to easily put pixels on the screen: tiles and sprites.
So there are 2 ways that the Game Boy Advance allows you to get these pixels on screen much more easily.
Tiles and sprites.
Tiles are 8x8 pixels in size and can be placed in a grid on the screen.
You can also scroll the whole tile layer to arbitrary positions, but the tiles will remain in this 8x8 pixel grid.
We'll cover tiles in more detail later.
The other way you can draw things on screen is using sprites, which we'll cover in more detail in this section.
Sprites are the other way to draw things on the screen, which we'll cover in this section.
The Game Boy Advance supports 256 hardware sprites, with different sizes ranging from square 8x8 to more exotic sizes like 8x32 pixels.
In our pong game, all the sprites will be 16x16 pixels to make things simpler.
# Sprites on the Game Boy Advance
Sprites are stored in a special area of video memory called the 'Object Attribute Memory' (OAM).
OAM has space for the 'attributes' of the sprites, such as their location, whether or not they are visible, and which tile to use, but it does not store the actual pixel data.
The pixel data is stored in video RAM (VRAM).
This split allows multiple sprites to refer to the same tiles in VRAM, which saves space and allows for more objects on screen than would be possible by repeating them.
The Game Boy Advance supports 256 hardware sprites.
These can be in one of many sizes, ranging from square 8x8 to more exotic sizes like 8x32 pixels.
For our pong game, all the sprites will be 16x16 pixels to make things a bit simpler.
Since RAM is in short supply and expensive, the tile data is stored as indexed palette data.
Instead of storing the full color data for each pixel in the tile, the Game Boy Advance stores a 'palette' of colors, and the tiles that make up the sprites are stored as indexes to the palette.
Each sprite can use a maximum of 16 colors out of the total sprite palette of 256 colors.
Sprites are stored in the Game Boy Advance in a special area of video memory called the 'Object Attribute Memory' (OAM).
This has space for the 'attributes' of the sprites (things like whether or not they are visible, the location, which tile to use etc) but it does not store the actual pixel data.
The pixel data is stored in a video RAM (VRAM).
Because of this split, it is possible to have multiple sprites refer to the same tiles in video RAM which saves space and allows for more objects on screen at once then repeating them would otherwise allow.
Since RAM is in short supply, and at the time was quite expensive, the tile data is stored as indexed palette data.
So rather than storing the full colour data for each pixel in the tile, the Game Boy Advance instead stores a 'palette' of colours and the tiles which make up the sprites are stored as indexes to the palette.
You don't need to worry about this though, because `agb` handles it for you, but it is important to keep in mind that each sprite can use a maximum of 16 colours out of the total sprite palette of 256 colours.
There are technically 2 types of sprite, regular and affine sprites.
There are technically two types of sprites: regular and affine sprites.
For now, we will only be dealing with regular sprites.
# Import the sprite
Firstly, you're going to need to import the sprites into your project.
`agb` has great support for the [aseprite](https://www.aseprite.org/) sprite editor which can be bought for $20 or you can compile it yourself for free.
`agb` has excellent support for the [aseprite](https://www.aseprite.org/) sprite editor which can be bought for $20 or you can compile it yourself for free.
Aseprite files can be natively imported by `agb` for use on the Game Boy Advance.
Here is the sprite sheet we will use as a png, but you should [download the aseprite file](sprites.aseprite) and place it in `gfx/sprites.aseprite`.
![pong sprites](sprites.png)
This contains 5 `16x16px` sprites.
The first is the end cap for the paddle.
The second is the centre part of the paddle, which could potentially be repeated a few times.
The third until the fifth is the ball, with various squashed states.
The aseprite file defines tags for these sprites, being "Paddle End", "Paddle Mid", and "Ball".
This contains 5 `16x16px` sprites: the end cap for the paddle, the center part of the paddle, which could potentially be repeated a few times, and the ball with various squashed states.
The aseprite file defines tags for these sprites: "Paddle End," "Paddle Mid," and "Ball."
```rust
use agb::{