diff --git a/TODO b/TODO index bcecc10..52e4f2e 100644 --- a/TODO +++ b/TODO @@ -1,55 +1,100 @@ -# TODO -TODO of TODOs: move these into issues +## ~~Boilerplate ~~ +* ~~Project setup ~~ +* ~~Input engine ~~ -## Player -* Jumping -* Climbing and ladders/ropes -* Metasprite animations (walking, jumping, climbing) -* Inventory -* Combat statistics -* Basic attack by pressing A +## Maps +* ~~Player-background collision ~~ +* ~~32x32 maps ~~ +* ~~Map scrolling through SCX/SCY ~~ +* 127x127 maps +* Update background collision to be aware of map changes +* Portals between maps + * Write editor for collision maps + * Update map generation script to use new collision map format + * New collision map flag + * Load new map on collision +* Ladders/ropes + * New collision map flag + * Play climbing animation when player collides + * Allow movement up/down without gravity ## Items * Item entity type * Render item on map + * Create data structure for storing items on the map + * Copy item OAM data to shadow OAM on each frame + * Make items float up and down a little bit + +## Player +* ~~Movement ~~ +* ~~Jump physics ~~ +* Velocity should not exceed 7px per frame +* Animations + * Keep track of animation state + * Update metasprite tile indexes on new frame + * Add jumping animation + * Add walking animation +* Create inventory data structure + * Add inventory item + * Remove inventory item + * Check for having at least N of an item * Player item pickup to inventory -* Player pickup (press B? collide?) + * Remove item from map + * When pickup button pressed and player colliding with item, pick up item +* Combat statistics type +* Basic attack by pressing A + * Display attack animation + * Implement battle formula + * Connect to button press + +## Menu +* Menu UI + * Render start menu + * Select menu item +* Switch between menu and game states +* Render statistics screen +* Render equipment screen +* Player inventory + * Render inventory screen + * Allow selecting an inventory item + * Equip/use/drop item ## Monsters * Monster entity type * Render monster -* Metasprite -* Take damage if attacked -* Death -* Attacks (animations + closed curve movement + speed) + * Create data structure for storing monsters on the map + * Generalize player metasprite code +* Update player attack routine to check for monster collision +* Death + * Play death animation + * Drop items from drop table + * Remove monster from map + * Player experience / level up routines + * Allow point distribution in stats menu +* Attacks + * Play attack animation + * Check for player collision and damage player + * Translate monster position along a closed curve +* Randomly pace to the left/right ## NPC * NPC entity type -* Read NPC description from file * Render NPC + * Create data structure for NPCs on map + * Use metasprite code for NPCs * Scrolling text display engine * Render NPC dialogue * Dialogue prompt - * Prompts should present themselves as a modal containing a set of buttons - corresponding to a provided set of replies + * Render modal with yes/no answer buttons * Cursor to select button - * Clicking button updates NPC state with response + * Run NPC dialogue handler when answer given ## Quests * Extend dialogue to display item requests * Keep track of completed quests +* Display icon above NPC when a quest is available -## Maps -* 32x32 maps - * Implement map scrolling through SCX/SCY - * Update collision routine to fetch new index -* NxM maps (where N, M > 32) - * Long way off, may not make it -* Portals between maps - * New collision map flag - * Transition between maps on collision - -## General -* Generalize metasprites to work across monsters, players, NPCs +## Nice to have * Metasprites of different sizes? (Could enable boss monsters) -* Battle formula +* Animated damage number for attacks +* Player name select \ No newline at end of file diff --git a/inc/util.inc b/inc/util.inc index 08906cf..a913c0f 100644 --- a/inc/util.inc +++ b/inc/util.inc @@ -50,27 +50,18 @@ MACRO LD16 ld LOW(\1), LOW(\2) ENDM -MACRO SLA16 - sla LOW(\1) - rl HIGH(\1) -ENDM - -; Performs SLA on a register N times -; \1 8-bit register -; \2 N, a value 1-8 -MACRO slan - ASSERT 1 <= \2 && \2 <= 8 - REPT \2 - sla \1 - ENDR -ENDM - ; Performs SRL on a register N times ; \1 8-bit register -; \2 N, a value 1-8 +; \2 Number of shifts (1-7) MACRO srln - ASSERT 1 <= \2 && \2 <= 8 + ASSERT \2 >= 1 && \2 <= 7 REPT \2 srl \1 ENDR ENDM + +; SLA on a 16-bit register +MACRO SLA16 + sla LOW(\1) + rl HIGH(\1) +ENDM diff --git a/src/map.s b/src/map.s index e12fd7c..991d0e9 100644 --- a/src/map.s +++ b/src/map.s @@ -86,6 +86,40 @@ Map_Load:: ret +; Loads the map X-coordinate into B +MACRO LOAD_MAPX + ; if SCX <= 0x7f + ld a, [rSCX] + cp $80 + jr nc, .wrap\@ + + ; B = CAMERA_X - SCX/8 + ld a, [rSCX] + ld b, a + ld a, [CURRENT_CAMERA_X] + srln b, 3 + sub b + ld b, a + jr .done\@ + + ; else SCX > 0x7f +.wrap\@: + ; B = CAMERA_X - PAGE_X/8 + ld a, [PAGEX] + ld b, a + ld a, [CURRENT_CAMERA_X] + srln b, 3 + sub b + ld b, a + + ; HL += PAGE_X/8 + ld a, [PAGEX] + srln a, 3 + ADD16 hl + +.done\@: +ENDM + ; Update map state based on SCX/SCY Map_Scroll:: ; If SCY = PAGEY, write map row @@ -94,15 +128,7 @@ Map_Scroll:: cp [hl] jr nz, .scroll_down_check - ; B = CAMERA_X - SCX/8 - ld a, [rSCX] - srl a - srl a - srl a - ld b, a - ld a, [CURRENT_CAMERA_X] - sub b - ld b, a + LOAD_MAPX ; C = CAMERA_Y - 2 ld a, [CURRENT_CAMERA_Y] @@ -140,15 +166,7 @@ Map_Scroll:: dec a call get_row_ptr - ; B = CAMERA_X - SCX/8 - ld a, [rSCX] - ld b, a - ld a, [CURRENT_CAMERA_X] - srl b - srl b - srl b - sub b - ld b, a + LOAD_MAPX ; C = CAMERA_Y + 18 + 1 ld a, [CURRENT_CAMERA_Y] @@ -254,7 +272,27 @@ Map_Update:: ld hl, PENDING_ROW_DATA ld d, SCRN_VX_B - MEMCPY bc, hl, d +.copy_row: + ld a, [hl+] + ld [bc], a + inc bc + + ; if BC % 32 == 0 (we just crossed a row boundary) + ld a, c + and %11111 + jr nz, .copy_row1 + + ; BC -= 32 (reset back to beginning of row) + ld a, c + sub 32 + ld c, a + ld a, b + sbc 0 + ld b, a + +.copy_row1: + dec d + jr nz, .copy_row .update_col: ; Skip column update if PENDING_COL_PTR is 0 @@ -340,6 +378,14 @@ enqueue_row_write: ld c, SCRN_VX_B ld de, PENDING_ROW_DATA + ; If X > 0, increment map pointer by X + bit 7, b + jr nz, .pad_left + + ld a, b + ADD16 hl + jr .copy_middle + ; Note: Can skip checking BYTES_LEFT > 0 in this loop. If there were ; SCRN_VX_B zeros to write, then Y would be 1 greater and we would have ; jumped into .zero_row before reaching this code @@ -425,6 +471,7 @@ write_map_row: ld a, [PENDING_ROW_PTR + 1] ld b, a + ; TODO: Fix ld hl, PENDING_ROW_DATA ld d, SCRN_VX_B MEMCPY bc, hl, d diff --git a/src/player.s b/src/player.s index e3ba365..443e06d 100644 --- a/src/player.s +++ b/src/player.s @@ -303,6 +303,7 @@ Player_UpdateOAM:: or c jr z, .done + ; TODO: Can be sped up by using LD A, [NN] ld_OAM_tile hl, SPRITE_OAM_IDX ld [hl], SPRITE_IDX + 1