Browse Source

Add actor engine

master
Forest Belton 2 years ago
parent
commit
6a1dd45ee2
6 changed files with 229 additions and 21 deletions
  1. +13
    -0
      .vscode/c_cpp_properties.json
  2. +6
    -0
      .vscode/settings.json
  3. +119
    -0
      src/actor.c
  4. +60
    -0
      src/actor.h
  5. +25
    -21
      src/main.c
  6. +6
    -0
      src/util.h

+ 13
- 0
.vscode/c_cpp_properties.json View File

@ -0,0 +1,13 @@
{
"version": 4,
"configurations": [
{
"name": "Default",
"includePath": [
"${default}",
"${workspaceFolder}/gbsdk/inc",
"${workspaceFolder}/include"
]
}
]
}

+ 6
- 0
.vscode/settings.json View File

@ -0,0 +1,6 @@
{
"files.associations": {
"hardware.h": "c",
"util.h": "c"
}
}

+ 119
- 0
src/actor.c View File

@ -0,0 +1,119 @@
#include "actor.h"
#include <stddef.h>
#include "sdk/oam.h"
#include "util.h"
#define MAX_UNIQUE_MOBS 3
#define MAX_ACTORS 5
#define NUM_OAM_ENTRIES 40
#define TILE_WIDTH 8
static uint8_t mob_ids[MAX_UNIQUE_MOBS];
static sprite16_mob mob_anim_data[MAX_UNIQUE_MOBS];
static sprite16_player player_anim_data;
static actor_t all_actors[MAX_ACTORS];
static uint8_t actor_load_mob_anim_data(uint8_t mob_id);
void actor_reset(void) {
for (uint8_t i = 0; i < ARRSIZE(mob_ids); ++i) {
mob_ids[i] = 0xff;
}
for (uint8_t i = 0; i < ARRSIZE(all_actors); ++i) {
all_actors[i].active = 0;
}
}
actor_t *actor_create_mob(uint8_t id) {
uint8_t mob_anim_idx = actor_load_mob_anim_data(id);
if (mob_anim_idx == 0xff) {
return NULL;
}
actor_t *a = NULL;
for (uint8_t i = 0; i < ARRSIZE(all_actors); ++i) {
if (all_actors[i].active) {
continue;
}
a = &all_actors[i];
a->active = 1;
a->mob_anim_idx = mob_anim_idx;
a->anim = ANIM_STAND;
a->frame_idx = 0;
a->frame_counter = 0;
break;
}
return a;
}
void actor_remove(actor_t *a) { a->active = 0; }
void actor_flush_oam(void) {
struct oam_entry *oam_ptr = &shadow_oam[0];
actor_t *a = &all_actors[0];
for (uint8_t i = 0; i < ARRSIZE(all_actors); ++i) {
if (!a->active) {
continue;
}
uint8_t *anim_ptr = mob_anim_data[a->mob_anim_idx].anims[a->anim];
anim_ptr += a->frame_idx * 4;
oam_ptr->y = a->y;
oam_ptr->x = a->x;
oam_ptr->tile = *anim_ptr++;
oam_ptr->attr = 0;
oam_ptr++;
oam_ptr->y = a->y;
oam_ptr->x = a->x + TILE_WIDTH;
oam_ptr->tile = *anim_ptr++;
oam_ptr->attr = 0;
oam_ptr++;
oam_ptr->y = a->y + TILE_WIDTH;
oam_ptr->x = a->x;
oam_ptr->tile = *anim_ptr++;
oam_ptr->attr = 0;
oam_ptr++;
oam_ptr->y = a->y + TILE_WIDTH;
oam_ptr->x = a->x + TILE_WIDTH;
oam_ptr->tile = *anim_ptr++;
oam_ptr->attr = 0;
oam_ptr++;
a++;
}
}
static uint8_t actor_load_mob_anim_data(uint8_t mob_id) {
uint8_t mob_anim_idx = 0xff;
for (uint8_t i = 0; i < ARRSIZE(mob_ids); ++i) {
if (mob_ids[i] == mob_id) {
mob_anim_idx = i;
break;
}
}
if (mob_anim_idx == 0xff) {
for (uint8_t i = 0; i < ARRSIZE(mob_ids); ++i) {
if (mob_ids[i] == 0xff) {
mob_ids[i] = mob_id;
// TODO: Load data into mob_anim_data[i]
mob_anim_idx = i;
break;
}
}
}
return mob_anim_idx;
}

+ 60
- 0
src/actor.h View File

@ -0,0 +1,60 @@
#ifndef IS_ACTOR_H_
#define IS_ACTOR_H_
#include <stdint.h>
typedef enum {
ANIM_STAND,
ANIM_WALK,
ANIM_JUMP,
ANIM_ATTACK,
ANIM_HURT,
ANIM_CLIMB,
} actor_anim_state_t;
typedef struct {
uint8_t active;
uint8_t mob_anim_idx;
actor_anim_state_t anim;
uint8_t frame_idx;
uint8_t frame_counter;
uint8_t x;
uint8_t y;
} actor_t;
typedef struct {
uint8_t *tiles;
uint16_t num_tiles;
uint8_t *anims[ANIM_HURT + 1];
} sprite16_mob;
typedef struct {
uint8_t *tiles;
uint16_t num_tiles;
uint8_t *anims[ANIM_CLIMB + 1];
} sprite16_player;
/**
* @brief Clear all actor data.
*/
void actor_reset(void);
/**
* @brief Register an actor for a mob.
* @param id The ID of the mob to create
* @return A pointer to the new actor or NULL if one could not be created
*/
actor_t *actor_create_mob(uint8_t id);
/**
* @brief Remove an actor from the screen.
* @param a The actor to remove
*/
void actor_remove(actor_t *a);
/**
* @brief Flush actor sprite data to OAM.
*/
void actor_flush_oam(void);
#endif

+ 25
- 21
src/main.c View File

@ -1,29 +1,31 @@
#include "sdk/hardware.h"
#include "sdk/video.h"
#include "sdk/oam.h"
#include <string.h>
#include "actor.h"
#include "sdk/assets.h"
#include "sdk/hardware.h"
#include "sdk/joypad.h"
#include <string.h>
#include "sdk/oam.h"
#include "sdk/video.h"
ASSET(tiles, "tiles.2bpp");
uint8_t cursor_x = 0;
uint8_t cursor_y = 0;
void main() {
//Load our initial vram (this is slow, but always works, even outside of vblank)
// Load our initial vram (this is slow, but always works, even outside of
// vblank)
vram_memcpy(0x8000, tiles, tiles_end - tiles);
vram_memcpy(0x9000, tiles, tiles_end - tiles);
//Setup the OAM for sprite drawing
// Setup the OAM for sprite drawing
oam_init();
//Set some default DMG palette data
// Set some default DMG palette data
rBGP = 0b11100100;
rOBP0 = 0b11100100;
rOBP1 = 0b11100100;
//Put some sprites on the screen
// Put some sprites on the screen
shadow_oam[0].y = 0x20;
shadow_oam[0].x = 0x20;
shadow_oam[0].tile = 0x04;
@ -33,31 +35,32 @@ void main() {
shadow_oam[1].tile = 0x02;
shadow_oam[1].attr = 0x00;
//Make sure sprites and the background are drawn
// Make sure sprites and the background are drawn
rLCDC = LCDC_ON | LCDC_OBJON | LCDC_BGON;
//Setup the VBLANK interrupt, but we don't actually enable interrupt handling.
// Setup the VBLANK interrupt, but we don't actually enable interrupt
// handling.
// We only do this, so HALT waits for VBLANK.
rIF = 0;
rIE = IE_VBLANK;
vram_memset(0x9800, 0x05, 32 * 18);
for(uint8_t x=0; x<20; x++) {
for (uint8_t x = 0; x < 20; x++) {
vram_set(0x9800 + x, 0x07);
vram_set(0x9A20 + x, 0x07);
}
for(uint8_t y=1; y<18; y++) {
for (uint8_t y = 1; y < 18; y++) {
vram_set(0x9800 + y * 0x20, 0x07);
vram_set(0x9800 + 19 + y * 0x20, 0x07);
}
vram_set(0x9800 + 3 + 3 * 0x20, 0x01);
while(1) {
while (1) {
joypad_update();
if (joypad_state & PAD_LEFT) cursor_x --;
if (joypad_state & PAD_RIGHT) cursor_x ++;
if (joypad_state & PAD_UP) cursor_y --;
if (joypad_state & PAD_DOWN) cursor_y ++;
if (joypad_state & PAD_LEFT) cursor_x--;
if (joypad_state & PAD_RIGHT) cursor_x++;
if (joypad_state & PAD_UP) cursor_y--;
if (joypad_state & PAD_DOWN) cursor_y++;
if (joypad_state & (PAD_A | PAD_B)) {
vram_set(0x9800 + cursor_x / 8 + cursor_y / 8 * 0x20, 0x03);
}
@ -66,11 +69,12 @@ void main() {
shadow_oam[0].y = cursor_y + 16;
shadow_oam[0].x = cursor_x + 8;
//Wait for VBLANK
// Wait for VBLANK
HALT();
rIF = 0; //As global interrupts are not enabled, we need to clear the interrupt flag.
rIF = 0; // As global interrupts are not enabled, we need to clear the
// interrupt flag.
//Copy the sprites into OAM memory
// Copy the sprites into OAM memory
oam_dma_copy();
}
}

+ 6
- 0
src/util.h View File

@ -0,0 +1,6 @@
#ifndef IS_UTIL_H_
#define IS_UTIL_H_
#define ARRSIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif

Loading…
Cancel
Save