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.

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