Learning Action Game Basics

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Learning Action Game Basics

Post by Pokun »

Ah that was the problem. My math was wrong.

Ah good idea Fox. I actually solved it the other way around and combined them:
I changed all the "#(256-MOB_MSPD_L)" and "#(256-MOB_MSPD_H)" to "#<(-(MOB_MSPD_L+(MOB_MSPD_H*256)))" and "#>(-(MOB_MSPD_L+(MOB_MSPD_H*256)))" respectively and now the character moves in the same speed in both directions. But your way makes much more readable code.

Thanks a lot both of you!


I also just solved the jumping problem I think, so that's probably good now.
So I'm done with basic movement for now, next comes collision. I guess I'd need to load a collision map in RAM that matches the level map on screen.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Learning Action Game Basics

Post by unregistered »

Pokun wrote:One thing FCEUX is missing though is an OAM viewer.
I used to miss an OAM viewer too; but, after understanding that page 2 is jammed into OAM each frame using the OAM_DMA register, $4014, taking 513 cycles, I just check page 2 in the hex editor to look at OAM. :)

Code: Select all

sprite = $200

Code: Select all

.MACRO update_sprite
lda #>sprite
sta $4014
.ENDM
using asm6

edit: I don't understand most of this thread, but I'm happy your problem is solved! :D
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Learning Action Game Basics

Post by unregistered »

Pokun wrote:So I'm done with basic movement for now, next comes collision. I guess I'd need to load a collision map in RAM that matches the level map on screen.
No, you can access the collision values from ROM using lda (ptr), y :) Much easier accessing collision values from ROM than loading RAM with an entire screen worth of values. Think tokumaru told me something like that in my thread on page 50. :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Learning Action Game Basics

Post by tokumaru »

Many games use the same map for display and for collisions. It's very reasonable to assume that blocks that look the same will behave the same, so you actually save a lot of space by defining the collision information only once for each type of block, instead of multiple times, once for each instance of each type of block.

Depending on how your levels are compressed, you can read the collision information directly from ROM without problems. If you use something that doesn't allow random access though, such as RLE or LZ, then it does make sense to buffer a small section of the level in RAM, and update that as the player walks around.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Learning Action Game Basics

Post by Pokun »

I guess collision map was the wrong term. I didn't mean a separate collision mask, but actual level data: $00 = empty space, $01 = wall, $02 = one-way platform, $03 = water, $04 = spikes, $05 = ladder etc (as an example, currently I only have wall and empty space). Both collisions and the level drawing routine are going to use the same data.
I see, currently I have no compression at all though, I want to figure out how to get things to work first. One advantage I see with RAM, besides compression, is destructible tiles. ROM or RAM is something I can decide on later though, and if I run out of either I'll just use a mapper.

I'm not sure how I can calculate collision positions with level tiles though. With objects I can just compare their coordinates, but with level tiles I have to somehow translate the object coordinates to a position in my level map which is using 16x16 metatiles, one byte per metatile.
unregistered wrote:
Pokun wrote:One thing FCEUX is missing though is an OAM viewer.
I used to miss an OAM viewer too; but, after understanding that page 2 is jammed into OAM each frame using the OAM_DMA register, $4014, taking 513 cycles, I just check page 2 in the hex editor to look at OAM. :)
Yeah well actually FCEUX is able to show the internal OAM in the hex editor (click on "View"), not only the "shadow OAM" in RAM. But I meant a more visual sprite viewer like in Nintendulator and Mesen. I guess you can't have everything.
unregistered wrote:I don't understand most of this thread, but I'm happy your problem is solved! :D
Haha thank you. I tried to explain what I'm doing so people don't have to study my code too much, but it's hard to type short and concise text.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Learning Action Game Basics

Post by tokumaru »

Pokun wrote:I see, currently I have no compression at all though, I want to figure out how to get things to work first. One advantage I see with RAM, besides compression, is destructible tiles. ROM or RAM is something I can decide on later though, and if I run out of either I'll just use a mapper.
Even if you're not going to implement the final formats/algorithms for everything now, it helps to have an idea of what you'll want to do in the future to avoid having to throw out everything you're doing now.

If you think you can spare the RAM, it may be a good idea to have your engine working mostly with data from there, because later on when you do implement compression and such, you'll only have to change the code that populates those RAM buffers, while the bulk of the engine will remain the same.
I'm not sure how I can calculate collision positions with level tiles though. With objects I can just compare their coordinates, but with level tiles I have to somehow translate the object coordinates to a position in my level map which is using 16x16 metatiles, one byte per metatile.
Converting coordinates between different spaces is something that many games have to do quite often, specially if scrolling is involved. It's true, you will have to convert pixel coordinates into metatile coordinates to find out which blocks the sprites are touching. There's a very simple formula for this conversion:

Offset = (PixelY / 16) * MapWidth + (PixelX / 16)

If you don't have any scrolling (i.e the map width is 16 metatiles and coordinates are 8-bit), the conversion is dead simple:

Code: Select all

  lda PixelY
  and #%11110000
  sta Offset
  lda PixelX
  lsr
  lsr
  lsr
  lsr
  ora Offset
  sta Offset
Now you can just use the offset to load the metatile's index from the map:

Code: Select all

  ldx Offset
  lda LevelMap, x
And that's it. If you do have longer maps and 16-bit coordinates, the code is a bit more complex, but the principle is the same.
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Learning Action Game Basics

Post by rainwarrior »

Pokun wrote:Yeah well actually FCEUX is able to show the internal OAM in the hex editor (click on "View"), not only the "shadow OAM" in RAM. But I meant a more visual sprite viewer like in Nintendulator and Mesen. I guess you can't have everything.
tokumaru wrote a really nice lua script that does a pretty good job of it:
https://forums.nesdev.com/viewtopic.php ... 08#p181008
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Learning Action Game Basics

Post by unregistered »

rainwarrior wrote:
Pokun wrote:Yeah well actually FCEUX is able to show the internal OAM in the hex editor (click on "View"), not only the "shadow OAM" in RAM. But I meant a more visual sprite viewer like in Nintendulator and Mesen. I guess you can't have everything.
tokumaru wrote a really nice lua script that does a pretty good job of it:
https://forums.nesdev.com/viewtopic.php ... 08#p181008
Wow, thanks for the link rainwarrior! :D

ps. How did you find the post number? There used to be a permalink button, but I haven't found it in a long while. :(
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Learning Action Game Basics

Post by unregistered »

Pokun wrote:
unregistered wrote:I don't understand most of this thread, but I'm happy your problem is solved! :D
Haha thank you. I tried to explain what I'm doing so people don't have to study my code too much, but it's hard to type short and concise text.
I don't understand most of this thread because it takes me a lot of concentration to try and understand programming concepts... :oops: I just didn't apply myself; wasn't criticizing your efforts. :)
User avatar
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Learning Action Game Basics

Post by rainwarrior »

unregistered wrote:ps. How did you find the post number? There used to be a permalink button, but I haven't found it in a long while. :(
At the top of any post, there's a line with the subject on the left, and on the right there's a "posted" with a date and a little paper icon next to it. The link is the paper icon.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Learning Action Game Basics

Post by unregistered »

^Thank you rainwarrior so much!! :D

Pokun, I'll try to write future posts more clearly. Thanks for this learning experience. :)
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Learning Action Game Basics

Post by Pokun »

unregistered wrote:
Pokun wrote:
unregistered wrote:I don't understand most of this thread, but I'm happy your problem is solved! :D
Haha thank you. I tried to explain what I'm doing so people don't have to study my code too much, but it's hard to type short and concise text.
I don't understand most of this thread because it takes me a lot of concentration to try and understand programming concepts... :oops: I just didn't apply myself; wasn't criticizing your efforts. :)
I know what you mean, I only learned this stuff in this thread myself just before coding it. If you want to understand it, you may need to study signed 16-bit comparisons in the links in the first post.


Thanks everyone. The formula Tokumaru posted worked like a charm and now floor collision works like it should. Although jumping down with high speed makes the player's feet dig into the ground and jumping into the roof makes his head stuck in there so I have to eject him from the tile he collided with. I found a formula for how many pixels to eject in this post. The formula for positive velocity (eject_value = (pixel_coordinate AND $0F) + 1) works for the floor, but doing the the formula for negative velocity (eject_value = (pixel_coordinate EOR $0F) + 1) does not work for the ceiling. The player teleports far above the ceiling whenever he bumps his head into it.

Positive Y-velocity (for floors) Ejection:

Code: Select all

;This code works fine:
  lda #$00
  sta p1_vy+0
  sta p1_vy+1             ;stop velocity when landing on floor
  
  sta p1_y+0
  lda p1_y+1
  and #$0F
  sta temp+1
  lda p1_y+1
  clc
  adc #$08                ;+height
  sec
  sbc temp+1
  sta p1_y+1              ;eject from tile, Y = Y - (Y AND $0F)
  
  lda #$01
  sta p1_ground           ;set state to grounded
Negative Y-velocity (for ceilings) Ejection:

Code: Select all

;This code does not work correctly:
  lda #$00
  sta p1_vy+0
  sta p1_vy+1             ;stop velocity when banging head in ceiling
  
  sta p1_y+0
  lda p1_y+1
  eor #$0F
  sta temp+1
  lda p1_y+1
  clc
  adc temp+1
  sta p1_y+1              ;eject from tile, Y = Y + (Y XOR $0F)
I haven't yet added the +1 in either ejection calculations, but I don't think it would be the cause of the problem.
Did I misunderstand the formula or is the problem somewhere else?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Learning Action Game Basics

Post by tokumaru »

Pokun wrote:The player teleports far above the ceiling whenever he bumps his head into it.
Don't forget to account for the heights of the player and metatiles.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Learning Action Game Basics

Post by unregistered »

small note: when adding and you want to add one more, it's easy to do, just change your clc to sec. Learned that from Kasumi. :D
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Learning Action Game Basics

Post by tokumaru »

I believe I use a similar trick when calculating sprite coordinates, to compensate for the fact that sprites are positioned one scanline lower than the Y coordinate specified in their OAM entries. Instead of doing SpriteY = ObjectY - CameraY, I do SpriteY = ObjectY - CameraY - 1 by putting a CLC before the subtraction, instead of the usual SEC.
Post Reply