Compare commits
7 Commits
42fee54f99
...
6e9e74aa27
Author | SHA1 | Date |
---|---|---|
Alex Gentilucci | 6e9e74aa27 | |
Alex Gentilucci | ad75b20170 | |
Alex Gentilucci | d6937c6db2 | |
Alex Gentilucci | 7cb4979e59 | |
Alex Gentilucci | ac7dd7a4a2 | |
Alex Gentilucci | e90c80da0d | |
Alex Gentilucci | d2adeec4ac |
|
@ -0,0 +1,22 @@
|
|||
/* controls.h
|
||||
* manage input and actuate controls
|
||||
*
|
||||
* receive and manage user input & have them actuate in-game things
|
||||
*
|
||||
* For license details see COPYING.
|
||||
*/
|
||||
|
||||
#ifndef CONTROLS_H
|
||||
#define CONTROLS_H
|
||||
|
||||
/* copying shadow oam to true oam is left to the user to allow for many
|
||||
* operations on different sprites and then copy all of them at once */
|
||||
|
||||
// move player around the screen
|
||||
// sprite must have 2-frames, and should be toggled via xors of tile_toggle
|
||||
void player_update (struct spriteReg *sprite, int base_tile, int tile_toggle);
|
||||
|
||||
// scroll screen when player nears edges
|
||||
void player_scroll (struct spriteReg *sprite, struct bgReg *background);
|
||||
|
||||
#endif /* CONTROLS_H */
|
|
@ -0,0 +1,65 @@
|
|||
/* globals.h
|
||||
* all the good global stuff
|
||||
*
|
||||
* defines and global variables and more for use wherever needed
|
||||
*
|
||||
* For license details see COPYING.
|
||||
*/
|
||||
|
||||
#ifndef GLOBALS_H
|
||||
#define GLOBALS_H
|
||||
|
||||
/* Defines */
|
||||
// pixel widths for schnoz (since he doesn't take up the full 16x32 frame)
|
||||
#define SCHNOZ_L 0
|
||||
#define SCHNOZ_R 15
|
||||
#define SCHNOZ_T 9
|
||||
#define SCHNOZ_B 31
|
||||
|
||||
#define SCREEN_CENTER_X (SCREEN_WIDTH/2)-((SCHNOZ_R-SCHNOZ_L)/2)
|
||||
#define SCREEN_CENTER_Y (SCREEN_HEIGHT/2)-((SCHNOZ_B-SCHNOZ_T)/2)
|
||||
|
||||
// schnoz base tile id and animation toggle value
|
||||
#define SCHNOZ_BSE 0
|
||||
#define SCHNOZ_TGL 8
|
||||
|
||||
/* Inline Functions */
|
||||
|
||||
|
||||
/* Typedefs & composite types */
|
||||
/* Regular-type sprite
|
||||
* stores pointer to OBJect in shadow oam, Tile ID, PalBank, current X
|
||||
* coordinates, current Y coordinates, and the last Delta applied to X and Y
|
||||
* (deltas can be 0 if nothing was applied last time the sprite was updated)
|
||||
*/
|
||||
struct spriteReg {
|
||||
OBJ_ATTR *obj;
|
||||
u32 tid, pb;
|
||||
int x, y, dx, dy;
|
||||
};
|
||||
|
||||
/* regular-type background
|
||||
* charblock number, screenblock number, current screen
|
||||
* display coordinates, size (in tiles), and bg_reg_00x00 register
|
||||
*/
|
||||
struct bgReg {
|
||||
int cb, sb;
|
||||
s16 x, y;
|
||||
int sx, sy;
|
||||
};
|
||||
|
||||
// background tile types (extensible)
|
||||
enum bgTileTypes {
|
||||
EMPTY,
|
||||
SOLID,
|
||||
DAMAGING
|
||||
};
|
||||
|
||||
/* Globals */
|
||||
extern OBJ_ATTR obj_buffer[128];
|
||||
extern OBJ_AFFINE *obj_aff_buffer;
|
||||
extern uint frame_counter;
|
||||
extern int obj_counter;
|
||||
extern const GBFS_FILE *gbfs_start;
|
||||
|
||||
#endif /* GLOBALS_H */
|
|
@ -1,7 +1,7 @@
|
|||
/* load.h
|
||||
* Load things into memory
|
||||
* load things into memory
|
||||
*
|
||||
* Will eventually be used to quickly load levels and sprites from GBFS into
|
||||
* will eventually be used to quickly load levels and sprites from gbfs into
|
||||
* video memory
|
||||
*
|
||||
* For license details see COPYING.
|
||||
|
@ -10,31 +10,17 @@
|
|||
#ifndef LOAD_H
|
||||
#define LOAD_H
|
||||
|
||||
void load_region (
|
||||
const GBFS_FILE *gbfs_start,
|
||||
const char filename[],
|
||||
int filename_len,
|
||||
COLOR *palbank,
|
||||
TILE *charblock,
|
||||
SCR_ENTRY *screenblock
|
||||
);
|
||||
void load_region (const char filename[],
|
||||
int filename_len,
|
||||
COLOR *palbank,
|
||||
TILE *charblock,
|
||||
SCR_ENTRY *screenblock);
|
||||
|
||||
// varargs: num_frames of TILE* pointing to location in tile_mem
|
||||
// Assumes shared palette for all frames
|
||||
// Assumes filename convention of "<filename>_f<frame_number>.img.bin"
|
||||
void load_sprite (
|
||||
const GBFS_FILE *gbfs_start,
|
||||
const char filename[],
|
||||
int filename_len,
|
||||
int num_frames,
|
||||
...
|
||||
);
|
||||
// assumes shared palette for all frames
|
||||
// assumes filename convention of "<filename>_f<frame_number>.img.bin"
|
||||
void load_sprite (const char filename[], int filename_len, int num_frames, ...);
|
||||
|
||||
void load_hub (
|
||||
const GBFS_FILE *gbfs_start,
|
||||
COLOR *palbank,
|
||||
TILE *charblock,
|
||||
SCR_ENTRY *screenblock
|
||||
);
|
||||
void load_hub (COLOR *palbank, TILE *charblock, SCR_ENTRY *screenblock);
|
||||
|
||||
#endif /* LOAD_H */
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/* controls.c
|
||||
* manage input and actuate controls
|
||||
*
|
||||
* receive and manage user input & have them actuate in-game things
|
||||
*
|
||||
* For license details see COPYING.
|
||||
*/
|
||||
|
||||
#include <tonc.h>
|
||||
#include "gbfs.h" // needs to be included here or else globals.h freaks
|
||||
|
||||
#include "globals.h"
|
||||
#include "controls.h"
|
||||
|
||||
void player_update (struct spriteReg *sprite, int base_tile, int tile_toggle)
|
||||
{
|
||||
/* update deltas then set ->x and ->y later so that way additional deltas
|
||||
* could be applied in the future (knockback, etc.) then added all at once
|
||||
*/
|
||||
sprite->dx = key_tri_horz();
|
||||
sprite->dy = key_tri_vert();
|
||||
|
||||
// compiler (should) automatically expand n % 2^i to n & (2^i - 1)
|
||||
if ((key_tri_horz() || key_tri_vert()) && !(frame_counter % 16)) {
|
||||
sprite->tid ^= tile_toggle;
|
||||
} else if (!(key_tri_horz() || key_tri_vert())) {
|
||||
sprite->tid = base_tile;
|
||||
}
|
||||
|
||||
if (key_tri_horz() > 0) {
|
||||
sprite->obj->attr1 |= ATTR1_HFLIP;
|
||||
} else if (key_tri_horz() < 0) {
|
||||
sprite->obj->attr1 &= ~ATTR1_HFLIP;
|
||||
}
|
||||
|
||||
/* may remove or modify later if i decide that i want the player to be able
|
||||
* to go off screen for some reason */
|
||||
sprite->x = clamp(sprite->x+sprite->dx, SCHNOZ_L, SCREEN_WIDTH-SCHNOZ_R);
|
||||
sprite->y = clamp(sprite->y+sprite->dy, -SCHNOZ_T, SCREEN_HEIGHT-SCHNOZ_B);
|
||||
obj_set_pos(sprite->obj, sprite->x, sprite->y);
|
||||
sprite->obj->attr2 = ATTR2_BUILD(sprite->tid, sprite->pb, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void player_scroll (struct spriteReg *sprite, struct bgReg *background)
|
||||
{
|
||||
if (background->x == 0 && sprite->x < SCREEN_CENTER_X) {
|
||||
sprite->x = clamp(sprite->x, SCHNOZ_L, SCREEN_CENTER_X);
|
||||
} else if (background->x == 512-SCREEN_WIDTH && sprite->x > SCREEN_CENTER_X) {
|
||||
sprite->x = clamp(sprite->x, SCREEN_CENTER_X, SCREEN_WIDTH-SCHNOZ_R);
|
||||
} else {
|
||||
sprite->x = SCREEN_CENTER_X;
|
||||
background->x = clamp(background->x + sprite->dx, 0, 512-SCREEN_WIDTH+1);
|
||||
}
|
||||
|
||||
/* when physics are implemented, write in a way so the background isn't
|
||||
* constantly scrolling when jumping or falling
|
||||
*/
|
||||
if (background->y == 0 && sprite->y < SCREEN_CENTER_Y) {
|
||||
sprite->y = clamp(sprite->y, -SCHNOZ_T, SCREEN_CENTER_Y);
|
||||
} else if (background->y == 256-SCREEN_HEIGHT && sprite->y > SCREEN_CENTER_Y) {
|
||||
sprite->y = clamp(sprite->y, SCREEN_CENTER_Y, SCREEN_HEIGHT-SCHNOZ_B);
|
||||
} else {
|
||||
sprite->y = SCREEN_CENTER_Y;
|
||||
background->y = clamp(background->y + sprite->dy, 0, 256-SCREEN_HEIGHT+1);
|
||||
}
|
||||
|
||||
obj_set_pos(sprite->obj, sprite->x, sprite->y);
|
||||
return;
|
||||
}
|
118
src/load.c
118
src/load.c
|
@ -1,112 +1,84 @@
|
|||
/* load.c
|
||||
* Load things into memory
|
||||
* load things into memory
|
||||
*
|
||||
* Used to quickly load levels and sprites from GBFS into video memory and
|
||||
* used to quickly load levels and sprites from gbfs into video memory and
|
||||
* for running other memory loads as necessary
|
||||
*
|
||||
* For license details see COPYING.
|
||||
*/
|
||||
|
||||
#include <tonc.h>
|
||||
#include "gbfs.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "gbfs.h"
|
||||
|
||||
#include "globals.h"
|
||||
#include "load.h"
|
||||
|
||||
void load_region (
|
||||
const GBFS_FILE *gbfs_start,
|
||||
const char filename[],
|
||||
int filename_len,
|
||||
COLOR *palbank,
|
||||
TILE *charblock,
|
||||
SCR_ENTRY *screenblock
|
||||
)
|
||||
// lengths of gbfs filename extensions
|
||||
#define FILENAME_EXT_REG 8
|
||||
#define FILENAME_EXT_FRAMES 12
|
||||
|
||||
void load_region (const char filename[],
|
||||
int filename_len,
|
||||
COLOR *palbank,
|
||||
TILE *charblock,
|
||||
SCR_ENTRY *screenblock)
|
||||
{
|
||||
// filename + .typ.bin (filename_len + 8 chars)
|
||||
// It is expected that filename_len already includes the null terminator
|
||||
char pal_name[filename_len + 8];
|
||||
char img_name[filename_len + 8];
|
||||
char map_name[filename_len + 8];
|
||||
snprintf(pal_name, filename_len + 8, "%s.pal.bin", filename);
|
||||
snprintf(img_name, filename_len + 8, "%s.img.bin", filename);
|
||||
snprintf(map_name, filename_len + 8, "%s.map.bin", filename);
|
||||
|
||||
// LZ77 decompress files to proper vram location
|
||||
LZ77UnCompVram(
|
||||
(u32*) gbfs_get_obj(gbfs_start, pal_name, NULL),
|
||||
palbank
|
||||
);
|
||||
LZ77UnCompVram(
|
||||
(u32*) gbfs_get_obj(gbfs_start, img_name, NULL),
|
||||
charblock
|
||||
);
|
||||
LZ77UnCompVram(
|
||||
(u32*) gbfs_get_obj(gbfs_start, map_name, NULL),
|
||||
screenblock
|
||||
);
|
||||
// it is expected that filename_len already includes the null terminator
|
||||
char pal_name[filename_len + FILENAME_EXT_REG];
|
||||
char img_name[filename_len + FILENAME_EXT_REG];
|
||||
char map_name[filename_len + FILENAME_EXT_REG];
|
||||
snprintf(pal_name, filename_len + FILENAME_EXT_REG, "%s.pal.bin", filename);
|
||||
snprintf(img_name, filename_len + FILENAME_EXT_REG, "%s.img.bin", filename);
|
||||
snprintf(map_name, filename_len + FILENAME_EXT_REG, "%s.map.bin", filename);
|
||||
|
||||
// lz77 decompress files to proper vram location
|
||||
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, pal_name, NULL), palbank);
|
||||
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, img_name, NULL), charblock);
|
||||
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, map_name, NULL), screenblock);
|
||||
return;
|
||||
}
|
||||
|
||||
void load_sprite (
|
||||
const GBFS_FILE *gbfs_start,
|
||||
const char filename[],
|
||||
int filename_len,
|
||||
int num_frames,
|
||||
...
|
||||
)
|
||||
void load_sprite (const char filename[], int filename_len, int num_frames, ...)
|
||||
{
|
||||
va_list frame_location;
|
||||
va_start(frame_location, num_frames);
|
||||
|
||||
char pal_name[filename_len + 8];
|
||||
snprintf(pal_name, filename_len + 8, "%s.pal.bin", filename);
|
||||
char pal_name[filename_len + FILENAME_EXT_REG];
|
||||
snprintf(pal_name, filename_len + FILENAME_EXT_REG, "%s.pal.bin", filename);
|
||||
|
||||
// filename + _##.typ.bin (filename_len + 12 chars)
|
||||
// It is expected that filename_len already includes the null terminator
|
||||
char frame_names[num_frames][filename_len + 12];
|
||||
for (int i = 0; i < num_frames; i++) {
|
||||
snprintf(
|
||||
frame_names[i],
|
||||
filename_len + 12,
|
||||
"%s_f%i.img.bin",
|
||||
filename, i+1
|
||||
);
|
||||
// it is expected that filename_len already includes the null terminator
|
||||
char frame_names[num_frames][filename_len + FILENAME_EXT_FRAMES];
|
||||
for (int i = 0; i < num_frames; ++i) {
|
||||
snprintf(frame_names[i],
|
||||
filename_len + FILENAME_EXT_FRAMES,
|
||||
"%s_f%i.img.bin",
|
||||
filename, i+1);
|
||||
}
|
||||
|
||||
LZ77UnCompVram(
|
||||
(u32*) gbfs_get_obj(gbfs_start, pal_name, NULL),
|
||||
pal_obj_mem
|
||||
);
|
||||
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, pal_name, NULL), pal_obj_mem);
|
||||
|
||||
TILE *location;
|
||||
for (int i = 0; i < num_frames; i++) {
|
||||
for (int i = 0; i < num_frames; ++i) {
|
||||
location = va_arg(frame_location, TILE*);
|
||||
LZ77UnCompVram(
|
||||
(u32*) gbfs_get_obj(gbfs_start, frame_names[i], NULL),
|
||||
location
|
||||
);
|
||||
LZ77UnCompVram((u32*) gbfs_get_obj(gbfs_start, frame_names[i], NULL),
|
||||
location);
|
||||
}
|
||||
|
||||
va_end(frame_location);
|
||||
return;
|
||||
}
|
||||
|
||||
void load_hub (
|
||||
const GBFS_FILE *gbfs_start,
|
||||
COLOR *palbank,
|
||||
TILE *charblock,
|
||||
SCR_ENTRY *screenblock
|
||||
)
|
||||
void load_hub (COLOR *palbank, TILE *charblock, SCR_ENTRY *screenblock)
|
||||
{
|
||||
load_region(
|
||||
gbfs_start,
|
||||
"hub",
|
||||
4, // Length of "hub" including null char
|
||||
palbank,
|
||||
charblock,
|
||||
screenblock
|
||||
);
|
||||
load_region("hub",
|
||||
4, // length of "hub" including null char
|
||||
palbank,
|
||||
charblock,
|
||||
screenblock);
|
||||
return;
|
||||
}
|
||||
|
|
99
src/main.c
99
src/main.c
|
@ -1,99 +1,66 @@
|
|||
/* main.c
|
||||
* Initialization and game loop
|
||||
* initialization and game loop
|
||||
*
|
||||
* For license details see COPYING.
|
||||
*/
|
||||
|
||||
#include <tonc.h>
|
||||
#include "gbfs.h"
|
||||
#include "load.h" // Load from rom/gbfs into memory
|
||||
|
||||
#include "globals.h" // data types, miscellaneous structures
|
||||
#include "load.h" // load from rom/gbfs into memory
|
||||
#include "controls.h" // manage input & controls
|
||||
|
||||
OBJ_ATTR obj_buffer[128];
|
||||
OBJ_AFFINE *obj_aff_buffer = (OBJ_AFFINE*)obj_buffer;
|
||||
uint frame_counter = 0;
|
||||
int obj_counter = 0;
|
||||
|
||||
typedef struct {
|
||||
OBJ_ATTR *obj;
|
||||
u32 tid, pb;
|
||||
int x, y, x_prev, y_prev;
|
||||
} spriteReg;
|
||||
// make sure gbfs_start is a global even though it can't be initialized here
|
||||
const GBFS_FILE *gbfs_start;
|
||||
|
||||
int main (void)
|
||||
{
|
||||
// Find the beginning of the GBFS 'sector'
|
||||
const GBFS_FILE *gbfs_start = find_first_gbfs_file(find_first_gbfs_file);
|
||||
// find the beginning of the gbfs 'sector'
|
||||
gbfs_start = find_first_gbfs_file(find_first_gbfs_file);
|
||||
|
||||
// Load hub into palbank 0, charblock 0, and screenblock 30
|
||||
load_hub(gbfs_start, &pal_bg_mem[0], &tile_mem[0][0], &se_mem[30][0]);
|
||||
// load hub into palbank 0, charblock 0, and screenblock 30
|
||||
load_hub(&pal_bg_mem[0], &tile_mem[0][0], &se_mem[30][0]);
|
||||
|
||||
// Load schnoz into tile_mem[4][0] and tile_mem[4][8];
|
||||
load_sprite(gbfs_start, "schnoz", 7, 2, &tile_mem[4][0], &tile_mem[4][8]);
|
||||
// load schnoz into tile_mem[4][0] and tile_mem[4][8]
|
||||
// length of "schnoz" is 7, and 2 frames pointed to by remaining arguments
|
||||
load_sprite("schnoz", 7, 2, &tile_mem[4][0], &tile_mem[4][8]);
|
||||
|
||||
oam_init(obj_buffer, 128);
|
||||
spriteReg player = {&obj_buffer[0], 0, 0, 5, 80};
|
||||
obj_set_attr(
|
||||
player.obj,
|
||||
ATTR0_TALL,
|
||||
ATTR1_SIZE_32 | ATTR1_HFLIP,
|
||||
ATTR2_PALBANK(player.pb) | player.tid
|
||||
);
|
||||
|
||||
struct spriteReg player = {&obj_buffer[0], 0, 0, 5, 80, 0, 0};
|
||||
++obj_counter;
|
||||
obj_set_attr(player.obj,
|
||||
ATTR0_TALL,
|
||||
ATTR1_SIZE_32 | ATTR1_HFLIP,
|
||||
ATTR2_PALBANK(player.pb) | player.tid);
|
||||
obj_set_pos(player.obj, player.x, player.y);
|
||||
|
||||
oam_copy(oam_mem, obj_buffer, 1);
|
||||
|
||||
BG_POINT bg1_pos = {0, 96};
|
||||
struct bgReg bg1 = {0, 30, 0, 96, 64, 32};
|
||||
|
||||
// Use background 1 to leave background 0 free for sprites to move behind
|
||||
REG_BG1CNT = BG_CBB(0) | BG_SBB(30) | BG_4BPP | BG_REG_64x32;
|
||||
// use background 1 to leave background 0 free for sprites to move behind
|
||||
REG_BG1CNT = BG_CBB(bg1.cb) | BG_SBB(bg1.sb) | BG_4BPP | BG_REG_64x32;
|
||||
REG_DISPCNT = DCNT_BG1 | DCNT_OBJ | DCNT_OBJ_1D;
|
||||
|
||||
u32 fcounter = 0;
|
||||
while (1) {
|
||||
vid_vsync();
|
||||
++frame_counter;
|
||||
key_poll();
|
||||
++fcounter;
|
||||
|
||||
player.x_prev = player.x;
|
||||
player.y_prev = player.y;
|
||||
player.x += key_tri_horz();
|
||||
player.y += key_tri_vert();
|
||||
player_update(&player, SCHNOZ_BSE, SCHNOZ_TGL);
|
||||
player_scroll(&player, &bg1);
|
||||
|
||||
if ((key_tri_horz() || key_tri_vert()) && !(fcounter % 16)) {
|
||||
player.tid ^= 8;
|
||||
} else if (!(key_tri_horz() || key_tri_vert())) {
|
||||
player.tid = 0;
|
||||
}
|
||||
|
||||
if (key_tri_horz() > 0) {
|
||||
player.obj->attr1 |= ATTR1_HFLIP;
|
||||
} else if (key_tri_horz() < 0) {
|
||||
player.obj->attr1 &= ~ATTR1_HFLIP;
|
||||
}
|
||||
|
||||
if ((player.x >= 3*(SCREEN_WIDTH/4)-15) && (bg1_pos.x < 512-SCREEN_WIDTH)) {
|
||||
++bg1_pos.x;
|
||||
player.x = clamp(player.x, 0, 3*(SCREEN_WIDTH/4)-15);
|
||||
} else if ((player.x <= (SCREEN_WIDTH/4)) && (bg1_pos.x > 0)) {
|
||||
--bg1_pos.x;
|
||||
player.x = clamp(player.x, (SCREEN_WIDTH/4)+1, SCREEN_WIDTH);
|
||||
}
|
||||
|
||||
if ((player.y >= 3*(SCREEN_HEIGHT/4)-31) && (bg1_pos.y < 256-SCREEN_HEIGHT)) {
|
||||
++bg1_pos.y;
|
||||
player.y = clamp(player.y, -9, 3*(SCREEN_HEIGHT/4)-31);
|
||||
} else if ((player.y <= (SCREEN_HEIGHT/4)) && (bg1_pos.y > 0)) {
|
||||
--bg1_pos.y;
|
||||
player.y = clamp(player.y, (SCREEN_HEIGHT/4)+1, SCREEN_HEIGHT-9);
|
||||
}
|
||||
|
||||
player.x = clamp(player.x, 0, SCREEN_WIDTH-15);
|
||||
player.y = clamp(player.y, -9, SCREEN_HEIGHT-31);
|
||||
|
||||
obj_set_pos(player.obj, player.x, player.y);
|
||||
player.obj->attr2 = ATTR2_BUILD(player.tid, player.pb, 0);
|
||||
oam_copy(oam_mem, obj_buffer, 1);
|
||||
|
||||
REG_BG1HOFS = bg1_pos.x;
|
||||
REG_BG1VOFS = bg1_pos.y;
|
||||
oam_copy(oam_mem, obj_buffer, obj_counter);
|
||||
REG_BG1HOFS = bg1.x;
|
||||
REG_BG1VOFS = bg1.y;
|
||||
}
|
||||
return 0; // in case?
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue