You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

374 lines
6.2 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. INCLUDE "game.inc"
  2. INCLUDE "hardware.inc"
  3. INCLUDE "oam.inc"
  4. INCLUDE "util.inc"
  5. Section "Player Data", WRAM0
  6. DEF PLAYER_INV_SIZE EQU 32
  7. PLAYER_X:: db
  8. PLAYER_Y:: dw
  9. PLAYER_DIR:: db
  10. PLAYER_STATE:: db
  11. PLAYER_FRAME:: db
  12. PLAYER_VY:: dw
  13. PLAYER_INV:: ds (2 * PLAYER_INV_SIZE)
  14. Section "Player Code", ROM0
  15. standSprites:
  16. INCBIN "png/sprite/player-stand.2bpp"
  17. spriteData:
  18. INCBIN "png/sprite/player.2bpp"
  19. DEF SPRITE_OAM_IDX EQU 0
  20. DEF SPRITE_WIDTH EQU 2
  21. DEF SPRITE_HEIGHT EQU 2
  22. DEF PLAYER_SPEED EQU 2
  23. DEF GRAVITY EQU (0 << 8) | $2e ; 0.18
  24. DEF INIT_VY EQU (3 << 8) | $99 ; 3.60
  25. DEF INIT_FALL_VY EQU ($ff << 8) | $1a ; -1.1015625
  26. DEF MAX_VY EQU ($f9 << 8) | $00 ; -7.0
  27. Player_Init::
  28. ; Clear player data (X/Y initialized by map engine)
  29. ld hl, PLAYER_DIR
  30. xor a
  31. REPT (7 + 2 * PLAYER_INV_SIZE)
  32. ld [hl+], a
  33. ENDR
  34. ; Copy sprite to VRAM
  35. ld bc, _VRAM8000 + TILE_INDEX_PLAYER * TILE_SIZE
  36. ld hl, spriteData
  37. ld d, TILE_SIZE * (SPRITE_WIDTH * SPRITE_HEIGHT)
  38. call memcpy
  39. ; Initialize OAM entries with player state
  40. call Player_UpdateOAM
  41. ret
  42. Player_Update::
  43. ; check for jump
  44. ld a, [keys]
  45. and PADF_UP
  46. jr z, .jump_update_check
  47. ; initialize jump state if not already jumping
  48. ld a, [PLAYER_STATE]
  49. and PLAYER_STATEF_JUMP
  50. jr nz, .jump_update
  51. ld a, PLAYER_STATEF_JUMP
  52. ld [PLAYER_STATE], a
  53. ld hl, PLAYER_VY
  54. STORE16 INIT_VY
  55. ; todo: deduplicate
  56. .jump_update_check:
  57. ld a, [PLAYER_STATE]
  58. and PLAYER_STATEF_JUMP
  59. jr z, .right
  60. .jump_update:
  61. ; load y velocity into bc
  62. ld hl, PLAYER_VY
  63. ld b, [hl]
  64. inc hl
  65. ld c, [hl]
  66. ; adjust velocity by gravity
  67. ld a, c
  68. sub LOW(GRAVITY)
  69. ld c, a
  70. ld a, b
  71. sbc HIGH(GRAVITY)
  72. ld b, a
  73. ; ; we only need to clamp when moving down
  74. ; bit 7, b
  75. ; jr z, .no_clamp
  76. ; ; vy = MIN(MAX_VY, vy)
  77. ; ld a, b
  78. ; cp HIGH(MAX_VY)
  79. ; jr c, .no_clamp
  80. ; ld b, HIGH(MAX_VY)
  81. ; ld c, LOW(MAX_VY)
  82. .no_clamp:
  83. ld hl, PLAYER_VY
  84. STORE16 bc
  85. ; y -= floor(vy)
  86. ld hl, PLAYER_Y + 1
  87. ld a, [hl]
  88. sub c
  89. ld [hl-], a
  90. ld a, [hl]
  91. sbc b
  92. ld [hl], a
  93. ; roll back jump if there was a collision
  94. call player_bg_collides
  95. jr nz, .jump_Player_UpdateOAM
  96. ; TODO: Enable once scroll zones are implemented
  97. ; ld a, [PLAYER_VY]
  98. ; check if VY < 0 and call Map_ScrollUp / Map_ScrollDown
  99. .jump_rollback:
  100. ld hl, PLAYER_VY
  101. bit 7, [hl]
  102. ld hl, PLAYER_Y
  103. jr z, .jump_rollback_down
  104. dec [hl]
  105. jr .jump_rollback_check
  106. .jump_rollback_down:
  107. inc [hl]
  108. .jump_rollback_check:
  109. call player_bg_collides
  110. jr z, .jump_rollback
  111. ; set PLAYER_STATE = PLAYER_STATEF_WALK if VY < 0 (fell into ground)
  112. ld hl, PLAYER_VY
  113. bit 7, [hl]
  114. ; either way, set VY = 0.
  115. ; NOTE: MUST USE LD HERE TO KEEP FLAGS FROM BIT TEST
  116. ld [hl], 0
  117. ld hl, PLAYER_VY + 1
  118. ld [hl], 0
  119. jr z, .jump_Player_UpdateOAM
  120. ld a, PLAYER_STATEF_WALK
  121. ld [PLAYER_STATE], a
  122. .jump_Player_UpdateOAM:
  123. call Player_UpdateOAM
  124. ; check for move right
  125. .right:
  126. ld a, [keys]
  127. and PADF_RIGHT
  128. jr z, .left
  129. ; check for right boundary
  130. ld a, [PLAYER_X]
  131. add 16
  132. cp SCRN_X
  133. jr nc, .left
  134. .move_right:
  135. ld a, [PLAYER_X]
  136. add PLAYER_SPEED
  137. ld [PLAYER_X], a
  138. call player_bg_collides
  139. jr z, .right_rollback
  140. ; TODO: Enable once scroll zones are implemented
  141. ; ld d, PLAYER_SPEED
  142. ; call Map_ScrollRight
  143. xor a
  144. ld [PLAYER_DIR], a
  145. call Player_UpdateOAM
  146. ret
  147. .right_rollback:
  148. ld a, [PLAYER_X]
  149. sub PLAYER_SPEED
  150. ld [PLAYER_X], a
  151. ret
  152. .left:
  153. ; check for left button
  154. ld hl, keys
  155. ld a, [hl]
  156. and PADF_LEFT
  157. jr z, .fall
  158. ; check for left boundary
  159. ld a, [PLAYER_X]
  160. or a
  161. jr z, .fall
  162. sub PLAYER_SPEED
  163. ld [PLAYER_X], a
  164. call player_bg_collides
  165. jr z, .left_rollback
  166. ; TODO: Enable once scroll zones are implemented
  167. ; ld d, PLAYER_SPEED
  168. ; call Map_ScrollLeft
  169. ld a, $ff
  170. ld [PLAYER_DIR], a
  171. call Player_UpdateOAM
  172. jr .fall
  173. .left_rollback:
  174. ld hl, PLAYER_X
  175. inc [hl]
  176. inc [hl]
  177. .fall:
  178. call player_in_air
  179. ret z
  180. ; only set jump state if not already jumping
  181. ld hl, PLAYER_STATE
  182. ld a, [hl]
  183. and PLAYER_STATEF_JUMP
  184. ret nz
  185. ld [hl], PLAYER_STATEF_JUMP
  186. ld hl, PLAYER_VY
  187. STORE16 INIT_FALL_VY
  188. ret
  189. ; Update player metasprite with positional data
  190. Player_UpdateOAM::
  191. ld hl, PLAYER_DIR
  192. ld a, [hl-] ; dir (0 = right , $ff = left)
  193. and OAMF_XFLIP
  194. ld c, a
  195. dec hl ; skip fractional part
  196. ld a, [hl-] ; y
  197. add 16
  198. ld d, a
  199. ld a, [hl] ; x
  200. add 8
  201. ld b, a
  202. ld a, d
  203. ld_OAM_y hl, SPRITE_OAM_IDX
  204. ; top left sprite
  205. ld [hli], a
  206. ld [hl], b
  207. inc hl
  208. ld [hl], TILE_INDEX_PLAYER
  209. inc hl
  210. ld [hl], c
  211. inc hl
  212. ; top right
  213. ld d, a
  214. ld a, b
  215. add 8
  216. ld b, a
  217. ld a, d
  218. ld [hli], a
  219. ld [hl], b
  220. inc hl
  221. ld [hl], TILE_INDEX_PLAYER + 1
  222. inc hl
  223. ld [hl], c
  224. inc hl
  225. ; bottom left
  226. add 8
  227. ld d, a
  228. ld a, b
  229. sub 8
  230. ld b, a
  231. ld a, d
  232. ld [hli], a
  233. ld [hl], b
  234. inc hl
  235. ld [hl], TILE_INDEX_PLAYER + 2
  236. inc hl
  237. ld [hl], c
  238. inc hl
  239. ; bottom right
  240. ld d, a
  241. ld a, b
  242. add 8
  243. ld b, a
  244. ld a, d
  245. ld [hli], a
  246. ld [hl], b
  247. inc hl
  248. ld [hl], TILE_INDEX_PLAYER + 3
  249. inc hl
  250. ld [hl], c
  251. ; flip tile indices if necessary
  252. ld a, c
  253. or c
  254. jr z, .done
  255. ; TODO: Can be sped up by using LD A, [NN]
  256. ld_OAM_tile hl, SPRITE_OAM_IDX
  257. ld [hl], TILE_INDEX_PLAYER + 1
  258. ld_OAM_tile hl, SPRITE_OAM_IDX + 1
  259. ld [hl], TILE_INDEX_PLAYER
  260. ld_OAM_tile hl, SPRITE_OAM_IDX + 2
  261. ld [hl], TILE_INDEX_PLAYER + 3
  262. ld_OAM_tile hl, SPRITE_OAM_IDX + 3
  263. ld [hl], TILE_INDEX_PLAYER + 2
  264. .done:
  265. ret
  266. ; Add item(s) to the player's inventory
  267. ; @param b Item ID
  268. ; @param c Item quantity
  269. Player_AddInvItem::
  270. push de
  271. ld hl, PLAYER_INV
  272. ld e, PLAYER_INV_SIZE
  273. .find_inv_slot:
  274. ld a, [hl]
  275. cp b
  276. jr z, .update_item
  277. inc hl
  278. dec e
  279. jr nz, .find_inv_slot
  280. .update_item:
  281. ; set item id
  282. ld a, b
  283. ld [hl+], a
  284. ; update item qty
  285. ld a, [hl]
  286. add c
  287. ld [hl], a
  288. pop de
  289. ret
  290. ; Remove item(s) from the player's inventory
  291. ; @param b Item ID
  292. ; @param c Item quantity