feat: MVP for 2d_sprites.gba
This commit is contained in:
parent
35044acfa7
commit
babbda0d43
|
@ -4,3 +4,4 @@ zig-cache/
|
||||||
**/*.s
|
**/*.s
|
||||||
**/*.asm
|
**/*.asm
|
||||||
**/*.bin
|
**/*.bin
|
||||||
|
**/*.sav
|
|
@ -11,8 +11,83 @@ const SquareSpriteTuple = std.meta.Tuple(&[_]type{ Rainbow, Bebe16, Bebe32, Bebe
|
||||||
// TODO: ZigGBA should support spaces in the ROM Title IIRC
|
// TODO: ZigGBA should support spaces in the ROM Title IIRC
|
||||||
export var gameHeader linksection(".gbaheader") = GBA.Header.setup("2DSPRITE", "PAOD", "00", 0);
|
export var gameHeader linksection(".gbaheader") = GBA.Header.setup("2DSPRITE", "PAOD", "00", 0);
|
||||||
|
|
||||||
// 16x16 4BPP Sprite depicting
|
// To-do List:
|
||||||
// denpa artist Nanahira's pet rabbit: Bebe-chan
|
// TODO: 8BPP variants?
|
||||||
|
// TODO: Tall Sprites
|
||||||
|
// TODO: Wide Sprites
|
||||||
|
// TODO: 8x8 Bebe-chan
|
||||||
|
|
||||||
|
const square_sprites = initSquareSpriteTuple();
|
||||||
|
|
||||||
|
fn initSquareSpriteTuple() SquareSpriteTuple {
|
||||||
|
return .{ Rainbow{}, Bebe16{}, Bebe32{}, Bebe64{} };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() noreturn {
|
||||||
|
LCD.setupDisplayControl(.{
|
||||||
|
.mode = .Mode0, // No Affine BGs
|
||||||
|
.objectLayer = .Show, // Enable Sprites
|
||||||
|
.objVramCharacterMapping = .TwoDimension, // 2D Sprite Mapping
|
||||||
|
});
|
||||||
|
|
||||||
|
OAM.init();
|
||||||
|
|
||||||
|
square_sprites[0].load(); // Copy Mapping to VRAM and Palette to PALRAM
|
||||||
|
|
||||||
|
var sprite: *OAM.Attribute = OAM.allocate();
|
||||||
|
sprite.paletteMode = square_sprites[0].paletteMode();
|
||||||
|
sprite.palette = 0;
|
||||||
|
sprite.tileIndex = 0;
|
||||||
|
sprite.setSize(square_sprites[0].size());
|
||||||
|
|
||||||
|
var x: i32 = 96;
|
||||||
|
var y: i32 = 32;
|
||||||
|
|
||||||
|
var i: i32 = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
LCD.naiveVSync();
|
||||||
|
Input.readInput();
|
||||||
|
|
||||||
|
const shoulder = Input.getShoulderJustPressed();
|
||||||
|
if (shoulder != 0) {
|
||||||
|
i = (i + shoulder) & 0b11;
|
||||||
|
|
||||||
|
// Index must be comptime known unfortunately
|
||||||
|
// so we need this ugly switch statement
|
||||||
|
switch (i) {
|
||||||
|
0 => {
|
||||||
|
square_sprites[0].load();
|
||||||
|
sprite.setSize(square_sprites[0].size());
|
||||||
|
},
|
||||||
|
1 => {
|
||||||
|
square_sprites[1].load();
|
||||||
|
sprite.setSize(square_sprites[1].size());
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
square_sprites[2].load();
|
||||||
|
sprite.setSize(square_sprites[2].size());
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
square_sprites[3].load();
|
||||||
|
sprite.setSize(square_sprites[3].size());
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x += Input.getHorizontal() * 2;
|
||||||
|
y += Input.getVertical() * 2;
|
||||||
|
|
||||||
|
sprite.setPosition(x, y);
|
||||||
|
|
||||||
|
OAM.update(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 16x16 4bpp Sprite
|
||||||
|
/// Denpa vocalist Nanahira's pet rabbit: Bebe-chan
|
||||||
|
// Ad: If you're weeb enough, check out Denpasongs
|
||||||
const Bebe16 = struct {
|
const Bebe16 = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -34,6 +109,7 @@ const Bebe16 = struct {
|
||||||
fn size(_: Self) OAM.ObjectSize {
|
fn size(_: Self) OAM.ObjectSize {
|
||||||
return .Size16x16;
|
return .Size16x16;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load(_: Self) void {
|
fn load(_: Self) void {
|
||||||
// In Memory, Tile Map is laid out like: 1 2
|
// In Memory, Tile Map is laid out like: 1 2
|
||||||
// 3 4
|
// 3 4
|
||||||
|
@ -48,7 +124,8 @@ const Bebe16 = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bebe-chan but bigger
|
/// 32x32 Bebe-chan
|
||||||
|
/// Same art as Bebe16, but scaled up
|
||||||
const Bebe32 = struct {
|
const Bebe32 = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -102,7 +179,8 @@ const Bebe32 = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// The Biggest Bebe-chan yet
|
/// 64x64 Bebe-chan
|
||||||
|
/// Same art as Bebe16, just scaled up
|
||||||
const Bebe64 = struct {
|
const Bebe64 = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -214,9 +292,7 @@ const Bebe64 = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 8x8 4bpp Sprite depicting a Rainbow
|
/// 8x8 4bpp Sprite depicting a Rainbow-like gradient 'cause I can't draw
|
||||||
// (it's more of a gradiant, I don't know english, whatever.)
|
|
||||||
// source: Laziness? I can't draw, especially within the confines of 8x8 pixels
|
|
||||||
const Rainbow = struct {
|
const Rainbow = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -228,15 +304,15 @@ const Rainbow = struct {
|
||||||
0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
|
0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline fn paletteMode(_: Self) GBA.PaletteMode {
|
fn paletteMode(_: Self) GBA.PaletteMode {
|
||||||
return .Color16;
|
return .Color16;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn size(_: Self) OAM.ObjectSize {
|
fn size(_: Self) OAM.ObjectSize {
|
||||||
return .Size8x8;
|
return .Size8x8;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn load(_: Self) void {
|
fn load(_: Self) void {
|
||||||
// 8x8 Sprites don't differ in any meaningful way between 1D and 2D mapping
|
// 8x8 Sprites don't differ in any meaningful way between 1D and 2D mapping
|
||||||
|
|
||||||
// Copy Tile Mapping
|
// Copy Tile Mapping
|
||||||
|
@ -246,71 +322,3 @@ const Rainbow = struct {
|
||||||
GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32));
|
GBA.memcpy32(GBA.OBJ_PALETTE_RAM, &Self.pal, Self.pal.len * @sizeOf(u32));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const square_sprites = withoutThisMethodZigComplains();
|
|
||||||
|
|
||||||
fn withoutThisMethodZigComplains() SquareSpriteTuple {
|
|
||||||
return .{ Rainbow{}, Bebe16{}, Bebe32{}, Bebe64{} };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() noreturn {
|
|
||||||
LCD.setupDisplayControl(.{
|
|
||||||
.mode = .Mode0, // No Affine BGs
|
|
||||||
.objectLayer = .Show, // Enable Sprites
|
|
||||||
.objVramCharacterMapping = .TwoDimension, // 2D Sprite Mapping
|
|
||||||
});
|
|
||||||
|
|
||||||
OAM.init();
|
|
||||||
|
|
||||||
square_sprites[0].load(); // Copy Mapping to VRAM and Palette to PALRAM
|
|
||||||
|
|
||||||
var sprite: *OAM.Attribute = OAM.allocate();
|
|
||||||
sprite.paletteMode = square_sprites[0].paletteMode();
|
|
||||||
sprite.palette = 0;
|
|
||||||
sprite.tileIndex = 0;
|
|
||||||
sprite.setSize(square_sprites[0].size());
|
|
||||||
|
|
||||||
var x: i32 = 96;
|
|
||||||
var y: i32 = 32;
|
|
||||||
|
|
||||||
var i: i32 = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
LCD.naiveVSync();
|
|
||||||
Input.readInput();
|
|
||||||
|
|
||||||
const shoulder = Input.getShoulderJustPressed();
|
|
||||||
if (shoulder != 0) {
|
|
||||||
i = (i + shoulder) & 0b11;
|
|
||||||
|
|
||||||
// Index must be comptime known unfortunately
|
|
||||||
// so we need this ugly switch statement
|
|
||||||
switch (i) {
|
|
||||||
0 => {
|
|
||||||
square_sprites[0].load();
|
|
||||||
sprite.setSize(square_sprites[0].size());
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
square_sprites[1].load();
|
|
||||||
sprite.setSize(square_sprites[1].size());
|
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
square_sprites[2].load();
|
|
||||||
sprite.setSize(square_sprites[2].size());
|
|
||||||
},
|
|
||||||
3 => {
|
|
||||||
square_sprites[3].load();
|
|
||||||
sprite.setSize(square_sprites[3].size());
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
x += Input.getHorizontal() * 2;
|
|
||||||
y += Input.getVertical() * 2;
|
|
||||||
|
|
||||||
sprite.setPosition(x, y);
|
|
||||||
|
|
||||||
OAM.update(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue