8x16 and whatever else unreg wants to know

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

unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

qbradq wrote:So I'm not going to read 52 pages back :D I assume from the few pages I've caught up on this is not cell-based (like Zelda II's overworld), but subpixel-based (like Mario).
Yes, I guess it's subpixel-based like Mario. :)
qbradq wrote:Typically I use a velocity variable for every object. So in the above code snippet I would set the player's X velocity value to some value. Then during the object update routine I apply the velocity to the position, then check for collisions, and if there is a collision react to it. If you do go this route, do Y movement and collision detection first, then X. Trust me on that one :D
Ok, thank you qbradq! :D
qbradq wrote:Also, sounds like you've got good parents and a pretty awesome sister :D
YES! Thank you so very much qbradq! :D
tokumaru wrote:Controller input shouldn't directly affect the horizontal position of the player. Instead, it should affect the horizontal velocity (just like gravity affects its vertical velocity), and the velocity, whatever it is, should be added to the player's position every frame (again, like happens with vertical movement).

If a direction is pressed, increase velocity in that direction, if no direction is pressed, gradually decrease the velocity until it reaches 0 (this creates a nice inertia effect). After adding the velocity variable to the current position, check whether the block(s) at the edge of the player in the direction of the movement are solid, in which case you need to push the character back, like we discussed before.

Ejecting from the right should be exactly same as repelling from the ground, while the formula for ejecting from the left or from the ceiling is a bit different, but I'm sure you'll figure it out.
Thank you very much tokumaru! :D
qbradq wrote:Yea, platformer physics can be painful at times.

So OP, here's a list of games off the top of my head you can look at that do it right:

Zelda II: Adventure of Link, The
Super Mario Bro.s
Super Mario Bro.s 3
Metroid
I have metroid but have not played it much. Though, I do remember the great platforming it has; it has jumps as in Mario. :)
qbradq wrote:And here's a few that do it very poorly:

EVERY Castlevania game, but especially CV1
Most Mega Man games, especially MM1
Any Donkey Kong game
Ghosts 'n Goblins
I have CV1 and MM3 and Ghosts 'n Goblins. Castlevania is interesting... but I don't see how it does very poorly. I'm hoping you will explain what you mean by that. I'm eager to learn! :D

---
I spent some time last night looking up velocity in my Physics textbook. Velocity is speed/time, right? I'm going to look up inertia tomorrow. :)
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Re: 8x16 sprite is really a 16x32 pixel image?

Post by qbradq »

For inertia in games you can do this:

1. When striking a solid object, zero out velocity
2. When trying to stop (I.E. letting off the DPad), you can reduce the velocity toward zero by a fixed amount.

In CV1, here's what they got wrong (or at least wrong in my opinion)

1. Jumps are not controllable at all
2. Difficult to jump horizontally from a standing start
3. No acceleration / deceleration while walking
4. Collision detection is VERY off. You don't collide with anything from the top, and there's all sorts of bugs with the collision detection they did implement

The main thing I don't like about CV1 is the inability to control your jump. That's very bad for a platformer.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re:

Post by unregistered »

tokumaru[color=#00BFFF], on page 35,[/color] wrote:
Dwedit wrote:When using jump tables, be very careful about safety. Don't allow out-of-range values to be used. Use bounds checking, or bit masking and dummy entries.
I was gonna say something like that... Jump tables are great when your cases are all consecutive numbers (and you should always try to make it so, since it's easier that way), but when the cases are scattered values or ranges of different sizes, jump tables are not so good.
Ok... I need your help. I currently have cases numbered 21 through 28. So they are all consecutive right now! :) But I thought of trying something... would this improve my jump table? My code will follow Kasumi's example...
Kasumi[color=#00BFFF], also on page 35,[/color] wrote:

Code: Select all

;y contains the case number
lda jumptablelow,y
sta tempaddress
lda jumptablehigh,y
sta tempaddress+1

jmp [tempaddress]

jumptablehigh:
.db high(case0)
.db high(case1)
.db high(case2)
jumptablelow:
.db low(case0)
.db low(case1)
.db low(case2)
case0:

case1:

case2:
Underneath each case label would be the code corresponding to the case. Then, we store the addresses of all the cases in two tables. We load the low and high byte of the address we want, and store them in two contiguous bytes in low/high order. Then we jmp indirect to byte where the low part of the address was stored which will take us to the case label.

There's actually a small bug with the 6502 jmp indirection instruction. From here:

An original 6502 has does not correctly fetch the target address if the indirect vector falls on a page boundary (e.g. $xxFF where xx is and value from $00 to $FF). In this case fetches the LSB from $xxFF as expected but takes the MSB from $xx00. This is fixed in some later chips like the 65SC02 so for compatibility always ensure the indirect vector is not at the end of the page.
This is susposed to run animation as character moves across the screen... my sister is an animator. :D

Code: Select all

;if left is pressed,
    lda Next-1
    jmp +
;if right is pressed,
    lda Next+1
+   sta NewNext

;y contains the case number
lda jumptablelow,y
sta tempaddress
lda jumptablehigh,y
sta tempaddress+1

jmp [tempaddress] ;<??????????? what do [] mean? :?

jumptablehigh:
.db >case0, >case0, >case1, >case2, >case2, >case2, >case1, >case0
jumptablelow:
.db <case0, <case0, <case1, <case2, <case2, <case2, <case1, <case0

case0:
  jsr record ;<--this is just an idea right now
  bne case2

case1:
  lda Next
  sta NewNext
  jmp endCaseJump

case2:
  ;this is just an idea also
  
endCaseJump:

...So if I modified Kasumi's jump table like this would this be bad or good? It would still work the same way... I think... let's say y is equal to 22 - 20...2 ... it would run case 1 right? Well, that's what I want it to do.... :oops:
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Re: 8x16 sprite is really a 16x32 pixel image?

Post by qbradq »

If Y is in the range 20-28 inclusive, then you'll need to modify one section of code:

Code: Select all

;y contains the case number (20-28 inclusive)
lda jumptablelow-20,y
sta tempaddress
lda jumptablehigh-20,y
sta tempaddress+1

jmp [tempaddress] ;<??????????? what do [] mean?

; It means Jump Indirect. Here's how it works:
; Load the value at tempaddress into the program counter
; Continue to next instruction, which is now the instruction at the address stored in tempaddress
Note that you're applying some static math to the pointer table address to account for the minimum value of Y. This is more efficient that doing math at run-time, but also a little less clear (to some folks).

Without doing this then when Y is 20 you'll be accessing the 20'th element of the array, which is well outside it's bounds, and you'll get junk data.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: Re:

Post by unregistered »

unregistered wrote:It would still work the same way... I think... let's say y is equal to 22 - 20...2 ... it would run case 1 right? Well, that's what I want it to do.... :oops:
edit: ... sorry. :( Thanks qbradq. :) Next time I hope to provide better coding that describes my purpose and logic better. :)
qbradq wrote:

Code: Select all

jmp [tempaddress] ;<??????????? what do [] mean?

; It means Jump Indirect. Here's how it works:
; Load the value at tempaddress into the program counter
; Continue to next instruction, which is now the instruction at the address stored in tempaddress
I think I remember tokumaru telling me that [] aren't used in asm6, that's the assembler i'm using. Though, that's a great description... I'll have to memorize that! :D[/color]
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Re: 8x16 sprite is really a 16x32 pixel image?

Post by qbradq »

The normal syntax would be:

Code: Select all

jmp (tempaddress)
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

qbradq wrote:The normal syntax would be:

Code: Select all

jmp (tempaddress)
...well my assembler is complaining Unknown Label... so I'm guessing Kasumi ment

Code: Select all

jmp (tempaddress), y
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 sprite is really a 16x32 pixel image?

Post by tepples »

The (d),y addressing mode does not work with JMP. "Unknown label" means there isn't a symbol called tempaddress.
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

tepples wrote:The (d),y addressing mode does not work with JMP. "Unknown label" means there isn't a symbol called tempaddress.
Oh :oops: ... well, it was actually my fault, I read the wrong line... after correcting it... it said Illegal Instruction to my JMP (d),y line and so I deleted the ,y part and it compiled correctly and made an nes file! :o I didn't know that JMP (d) was possible and I was wrong to say imply that it wouldn't work. Im sorry qbradq. :(

tepples, thank you for correcting me! :oops:

edited
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

OK! :D I finally figured out what the problem is... the ground is continuous across the entire screen and so I move our girl character right and then it scrolls a little bit at first. Eventually a new screen scrolls over with a hole of water at the end, but I just figured out that our attribute table doesn't scroll yet and that's why she never decends into the water. And I haven't studied the scrolling knowledge that yall've taught me last... a little more than a year ago; I'll go read right that now. I don't think I got to this question back then; so, how can we get the attribute table to scroll with the screen? Sounds crazy... :?

edit: Ok... I read all of the scrolling knowledge shared... it starts on page 14. This picture is helpful to me on how to scroll the attribute tables... I would enjoy your help if you give it. Maybe I can do this. :)
tepples[color=#BF00FF], on [url=http://forums.nesdev.com/viewtopic.php?p=82825#p82825]page 15[/url],[/color] wrote:
tokumaru wrote:I just don't recommend it to newbies because sometimes it's hard for them to grasp the concept of the progressive name table updates
Would this GIF make the concept easier for them to grasp?

Image

edit2: Right now my method for building attribute tables builds an entire attribute table... and that would take too long to build an attribute table for each screen that appears, right? :? Do you have any tips for just building the 2 collums of questionmark blocks each time? edit3: I remember that there's a way to go down a collum... it's somehow accomplished by setting a bit somewhere.
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Re: 8x16 sprite is really a 16x32 pixel image?

Post by qbradq »

Going down a column by setting the PPU increment to 32 bytes per increment won't help with the attribute tables. You need an increment of 8 for that.

What I did when I made a scrolling engine (and there's plenty of folks on here with more experience than me) was to keep a copy of both nametable's attribute area in RAM. Then I could make my inserts, then write what I had to the VRAM during NMI.

If you're doing whole attribute bytes at once you don't have to do this though. Just calculate all the bytes, then write them and manually increment the VRAM pointer. You might do this with reads, or more efficiently by setting the address before each byte write.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 sprite is really a 16x32 pixel image?

Post by tepples »

Tip: If your levels are 12 metatiles tall (as in the GIF example above), you can calculate six bytes of attributes (one for each set of four metatiles in the strip), set the PPU to +32, and write bytes 0 and 4, then 1 and 5, then 2, then 3.
User avatar
qbradq
Posts: 972
Joined: Wed Oct 15, 2008 11:50 am

Re: 8x16 sprite is really a 16x32 pixel image?

Post by qbradq »

MIND = BLOWN

Cool! I never even thought of that :D
unregistered
Posts: 1318
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 sprite is really a 16x32 pixel image?

Post by unregistered »

qbradq wrote:Going down a column by setting the PPU increment to 32 bytes per increment won't help with the attribute tables. You need an increment of 8 for that.
Wow, I'm really glad you understood what I was mumbling about. Thank you! Now I remember that the attribute table is much smaller than the screen! :D
qbradq wrote:What I did when I made a scrolling engine (and there's plenty of folks on here with more experience than me) was to keep a copy of both nametable's attribute area in RAM. Then I could make my inserts, then write what I had to the VRAM during NMI.
What do you mean by inserts?
qbradq wrote:If you're doing whole attribute bytes at once you don't have to do this though. Just calculate all the bytes, then write them and manually increment the VRAM pointer. You might do this with reads, or more efficiently by setting the address before each byte write.
AH, :D Setting the address before each byte write will be good... ok! Thank you incredibly much qbradq! :D
tepples wrote:Tip: If your levels are 12 metatiles tall (as in the GIF example above), you can calculate six bytes of attributes (one for each set of four metatiles in the strip), set the PPU to +32, and write bytes 0 and 4, then 1 and 5, then 2, then 3.
qbradq wrote:MIND = BLOWN

Cool! I never even thought of that :D
Thank you tepples... I don't quite understand... but I kind of do. It will make sense after I attempt what qbradq said. I do get that you are saying that setting the PPU to +32 could be a possibility for attribute tables. That's amazing to me! :D I hope to have my mind blown out too :lol: ... that seems good to me... thinking. :oops:
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: 8x16 sprite is really a 16x32 pixel image?

Post by tepples »

Say you have prepared a column of attribute data. You want to write it to offsets 0, 8, 16, 24, 32, 40, 48, and 56 in the attribute table. But the PPU has no +8 increment mode, just +1 and +32. What you can do is this:
  1. Set the PPU to +32.
  2. Seek (set the address) to 0 and write the entries for 0 and 32.
  3. Seek to 8 and write the entries for 8 and 40.
  4. Seek to 16 and write the entries for 16 and 48.
  5. Seek to 24 and write the entries for 24 and 56.
Post Reply