6502 Newbie / First Game Prototype
Moderator: Moderators
6502 Newbie / First Game Prototype
Hello NesDev community!
Making an own full-fledged game for a retro console like the NES has always been one of my biggest dreams. I often tried to learn Assembly but then gave up quickly.
It was when I stumbled upon Gustavo Pezzis (Pikuma.com) 6502 NES Assembly course, that I began to understand Assembly & the NES hardware structure.
I completed the course and would say that I am now over the "beginner" level. What I am quite comfortable with is:
- Load up Background tiles to nametables
- Load up palettes and attributes
- Load up multiple Sprites/MetaSprites
- Move Sprites around the screen by controller input
- Very simple AI (random sprite spawning/movement)
- Sprite to Sprite Collision
- Switching CHR banks
- Split Screen (Sprite0)
However I still can't figure out how to do an own small game.
Scrolling is giving Me a lot of headaches, so I would prefer for my first project not to do scrolling.
My idea was to do a top-down zelda like game with single screens that are transition from one to another.
I love the classic Final Fantasy Adventure (Mystic Quest) on the Game Boy and would love to create a "prototype" on the NES in that style.
What I have so far is:
CHR file with tiles for the player, one NPC, one enemy, one boss and background tiles for a overworld map and one for a dungeon.
In the current project I loaded up the first nametable with a overworld screen. Player Sprite can be moved around by Controller Inputs.
The enemy sprite is moving around randomly.
What I am struggling to accomplish is:
I am unsure how to do sprite animations (for the player and the enemy)
.
Also I have no idea how to implement background collision. I restricted the player movement to the edges of the screen, but the player can move through all the tiles, including trees and walls etc.
Where do I store and check tile definitions? I need at least to check if a tile is solid or not. Would also like to make tiles act as a "trigger" to start a event or something else.
How can I progress the player from one screen to another? For example if I move to the edge of a map where is not solid tile, it should transition to the next screen. On the next screen I should also be able to go back to the previous screen and so on.
It is really difficult to find more "advanced" tutorials.
Making an own full-fledged game for a retro console like the NES has always been one of my biggest dreams. I often tried to learn Assembly but then gave up quickly.
It was when I stumbled upon Gustavo Pezzis (Pikuma.com) 6502 NES Assembly course, that I began to understand Assembly & the NES hardware structure.
I completed the course and would say that I am now over the "beginner" level. What I am quite comfortable with is:
- Load up Background tiles to nametables
- Load up palettes and attributes
- Load up multiple Sprites/MetaSprites
- Move Sprites around the screen by controller input
- Very simple AI (random sprite spawning/movement)
- Sprite to Sprite Collision
- Switching CHR banks
- Split Screen (Sprite0)
However I still can't figure out how to do an own small game.
Scrolling is giving Me a lot of headaches, so I would prefer for my first project not to do scrolling.
My idea was to do a top-down zelda like game with single screens that are transition from one to another.
I love the classic Final Fantasy Adventure (Mystic Quest) on the Game Boy and would love to create a "prototype" on the NES in that style.
What I have so far is:
CHR file with tiles for the player, one NPC, one enemy, one boss and background tiles for a overworld map and one for a dungeon.
In the current project I loaded up the first nametable with a overworld screen. Player Sprite can be moved around by Controller Inputs.
The enemy sprite is moving around randomly.
What I am struggling to accomplish is:
I am unsure how to do sprite animations (for the player and the enemy)
.
Also I have no idea how to implement background collision. I restricted the player movement to the edges of the screen, but the player can move through all the tiles, including trees and walls etc.
Where do I store and check tile definitions? I need at least to check if a tile is solid or not. Would also like to make tiles act as a "trigger" to start a event or something else.
How can I progress the player from one screen to another? For example if I move to the edge of a map where is not solid tile, it should transition to the next screen. On the next screen I should also be able to go back to the previous screen and so on.
It is really difficult to find more "advanced" tutorials.
-
- Posts: 1669
- Joined: Tue Feb 07, 2017 2:03 am
Re: 6502 Newbie / First Game Prototype
Background collision is
TileX = PixelX/SizeOfTileX
TileY = PixelY/SizeOfTileY
maybe you set your collision in 8x8 blocks, maybe 16x16 block maybe 32x32 blocks, depends on your game. Where do you store your collision map, in RAM somewhere.
Player animations, you change which tile the player sprite shows, so the image changes, and then you change it every so many frames.
Transition screen.
If Player X > X_right_side_of_playarea then "go to next screen"
If Player X < X_left_side_of_playarea then "go to prev screen"
and likewise with the Y
TileX = PixelX/SizeOfTileX
TileY = PixelY/SizeOfTileY
maybe you set your collision in 8x8 blocks, maybe 16x16 block maybe 32x32 blocks, depends on your game. Where do you store your collision map, in RAM somewhere.
Player animations, you change which tile the player sprite shows, so the image changes, and then you change it every so many frames.
Transition screen.
If Player X > X_right_side_of_playarea then "go to next screen"
If Player X < X_left_side_of_playarea then "go to prev screen"
and likewise with the Y
-
- Posts: 1669
- Joined: Tue Feb 07, 2017 2:03 am
Re: 6502 Newbie / First Game Prototype
I have a SNES port of my C64 game, there is also a CX16 port. So its not 1:1 a NES, but there is an 8bit only code that is 99.98% 6502, and it is heavily commented, which will help you understand the "engine aspects" https://github.com/oziphantom/QwakSNES
Re: 6502 Newbie / First Game Prototype
At the simplest level, an animation is just a sequence of frames, each one displayed for X amount of time. For an NES game, you could store this information in ROM in a straightforward way like this:
Code: Select all
PlayerAttackAnimation:
;frame header
.db 4, 6 ;first frame has 4 sprites and displays for 6 NES frames
;first frame
.db $f8, $f8, $10, $00 ;relative X, relative Y, tile, attributes
.db $00, $f8, $11, $00
.db $f8, $00, $12, $00
.db $00, $00, $13, $00
frame header
.db 4, 4 ;second frame has 4 sprites and displays for 4 NES frames
;second frame
.db $f8, $f8, $14, $00 ;relative X, relative Y, tile, attributes
.db $00, $f8, $15, $00
.db $f8, $00, $16, $00
.db $00, $00, $17, $00
;loop command
.db $80 ;since it's impossible for frames to use 128+ sprites, we can use bit 7 as a flag for special commands
.dw PlayerAttackAnimation ;address of which animation frame to display next
A "StartAnimation" function can be used to set an object's animation pointer and initialize the delay counter for the first frame. You can call this function whenever an action that requires a new animation happens.
You also need a "PlayAnimation" function, that you call every frame for each object. It will decrement the delay counter, and when it reaches 0 it will advance to the next animation frame, updating the animation pointer and setting the new value for the delay counter. This function also needs to process special commands, such as "jump" or "stop".
Lastly, a "DrawSprite" function has to be used every frame on every object so that the correct animation frame for each one is actually displayed for players to see. Basically this function will take the pointer to the object's current animation frame and process each sprite, generating OAM entries. Normally you'd take the relative X and Y coordinates, add them to the object's reference coordinates, and if the resulting coordinates are not off-screen, you write them to the OAM buffer (usually $0200-$02ff) along with the tile index and attribute byte.
This is the basic gist of sprite animations. It's not ridiculously easy to do but not terribly advanced either. Take some time to design a good animation script format that works for you, code these few functions that make use of this data, and you're pretty much done.
Re: 6502 Newbie / First Game Prototype
Known as the "flip-screen" technique. It's a very sound idea as scrolling is a pretty advanced subject, flip-screens are easy to implement and just works very well for many types of games.
There used to be several tutorials on the Nintendo Age forums and I think they can still be found using Waybackmachine. Some of them covers sprite animations and things like that, but I don't think they were all very useful. The best ones of them are the Nerdy Nights tutorial series, but your level has already surpassed everything that one taught except perhaps the audio tutorial, which is also the largest one.
As for background collisions, I usually make the level map in RAM where each byte is a "metatile" that covers a screen area of 4x4 hardware tiles (16x16 pixels). This level map would be loaded to RAM when you move into a new screen and your level-drawing routine may also use the map to figure out what tiles to draw at in the nametable.
When the player or an enemy moves into a metatile you check the tile from a LUT (look-up table) to see if it's a solid tile or not and other things such as a damage floor or something and act accordingly. You need some math to calculate your metasprite's screen position into the position of the level map which uses metatiles. There are many discussion about metatiles on these forums if you search for them, but basically if you are using 16x16 pixel metatiles you divide by 16 (logical shift right 4 times).
I don't see if you have learned to buffer VRAM yet in your list. It's also a basic technique that about any game may need. It would be necessary if say for example you would have Zelda-style bombable walls. After bombing such a wall you may want to change the wall tile into a cave opening tile and you don't want to blank the whole screen just for this small change to the background, that would be very annoying to the player. To avoid that you need to be able to update part of the background during vblank. The OAM DMA routine takes care of this for sprites but there is no equalent DMA solution for VRAM (nametable, pattern table and palettes), you would need to assign a portion of RAM as a VRAM buffer and make a routine that run each vblank and scans this buffer and make any changes to VRAM found in it. The VRAM buffer needs to have the VRAM address that is to be changed and the data to write to it.
I recommend to search the wiki and these forums as they are both loaded with this type of information, but they might not always be easy to find.
Some useful links:
Mirror of Nerdy Nights
You might want to check out the sound tutorial, it also touches on VRAM buffering.
NMI thread
The Frame and NMIs
Tile compression
These are various subjects on VRAM buffering.
Re: 6502 Newbie / First Game Prototype
Thanks to all! That seems to be valuable information you gave Me.
At least in theory I have a better feeling now, of what needs to be done and how it could be done; But still not really sure how to accomplish it in a practical way within my CA65 code
I guess there are perhaps still some smaller „foundational“ topics I have to re-check too.
Ah, yes in the Pikuma 6502 NES course was also a section on Background Buffering, used to display Score on the Split Screen (HUD) section.
I will need to re-do that section to get more comfortable with it.
So regarding background collision and tile definition:
At the moment I have just the background data exported from NEXXT tile editor and include the binary file in ROM and use my LoadBackground routine to fetch the background data and fill the nametable with the background tiles, palette and attributes.
Did I understand correctly that I would need to re-Write the background data, to include attributes for each tile/metatile and re-write the LoadBackground routine too?
Can I keep the background data in ROM or does it have to go to RAM?
At least in theory I have a better feeling now, of what needs to be done and how it could be done; But still not really sure how to accomplish it in a practical way within my CA65 code
I guess there are perhaps still some smaller „foundational“ topics I have to re-check too.
Ah, yes in the Pikuma 6502 NES course was also a section on Background Buffering, used to display Score on the Split Screen (HUD) section.
I will need to re-do that section to get more comfortable with it.
So regarding background collision and tile definition:
At the moment I have just the background data exported from NEXXT tile editor and include the binary file in ROM and use my LoadBackground routine to fetch the background data and fill the nametable with the background tiles, palette and attributes.
Did I understand correctly that I would need to re-Write the background data, to include attributes for each tile/metatile and re-write the LoadBackground routine too?
Can I keep the background data in ROM or does it have to go to RAM?
-
- Posts: 1669
- Joined: Tue Feb 07, 2017 2:03 am
Re: 6502 Newbie / First Game Prototype
By the point you get to this stage your 6502 should be good enough and your understanding of the machine enough that the theory is all you need to start coding for general engine logic. If animating is change the tiles the sprites use every N frames in a loop across M frames isn't a "oh yeah okay I just code that", you should focus on practicing 6502 more before continuing.
you can store the map data in ROM, just that sometimes banking to read the map data for the current screen each time can be a pain, but then it gives you more RAM if you don't cache it.
you can store the map data in ROM, just that sometimes banking to read the map data for the current screen each time can be a pain, but then it gives you more RAM if you don't cache it.
Re: 6502 Newbie / First Game Prototype
Yeah ROM or RAM doesn't matter as long as you have the space. RAM has many benefits since it allows you to change the map during gameplay (Mario games benefits from this with their many breakable bricks), but ROM might be easier to start out with. In either case you may need some sort of compression, using metatiles can be considered a simple but effective form of compression.
Another thing that is a bit more advanced than the fundamentals but is still commonly needed in games is one or more entity systems. It's a system for handling enemies, powerups, missiles and other in-game objects. Basically you have a list of entities and when you spawn a new enemy or other entity you check that list for any empty entity slots to allocate the new enemy to a slot you find, when an enemy or item is destroyed you free its slot etc.
But you can worry about entities later, I'd focus on getting the level map to load, moving the player character and background collisions first.
Another thing that is a bit more advanced than the fundamentals but is still commonly needed in games is one or more entity systems. It's a system for handling enemies, powerups, missiles and other in-game objects. Basically you have a list of entities and when you spawn a new enemy or other entity you check that list for any empty entity slots to allocate the new enemy to a slot you find, when an enemy or item is destroyed you free its slot etc.
But you can worry about entities later, I'd focus on getting the level map to load, moving the player character and background collisions first.
Practicing how though? Coding seems to be a way to practice to me. I guess if you know some good "programming kata" that may be good to repeat until it becomes second nature though.Oziphantom wrote: ↑Sat Aug 31, 2024 5:50 am you should focus on practicing 6502 more before continuing.
-
- Posts: 1669
- Joined: Tue Feb 07, 2017 2:03 am
Re: 6502 Newbie / First Game Prototype
There are plenty of books on the subject. With guides, and questions/challenges for one to improve ones self with if needed.
Re: 6502 Newbie / First Game Prototype
There are indeed many good books for old home computers that are scanned and can be downloaded. Since Apple and Commodore computers uses 6502 you could check out books for those.
I'm not sure if there are any that are easy to adapt for NES though or if you have to get into Apple or Commodore computing. If only there was an assembler for Family BASIC.
If OP wants to try out Apple II programming for any reason, I'd recommend the emulator Applewin, it's very easy to use (but it's obviously Windows only) and there are really tons of Apple II books.
I'm not sure about Commodore, but Vice is a popular emulator for C64. You could also try Commodore PET, you may just need a simple environment for playing around with 6502 in and PET is about as simple as you get for home computers (though rivaled by Apple I), Vice should emulate the PET too.
Apple II, PET, VIC-20 and C64 are probably all good choices, it all hang on what books you can find.
I'm not sure if there are any that are easy to adapt for NES though or if you have to get into Apple or Commodore computing. If only there was an assembler for Family BASIC.
If OP wants to try out Apple II programming for any reason, I'd recommend the emulator Applewin, it's very easy to use (but it's obviously Windows only) and there are really tons of Apple II books.
I'm not sure about Commodore, but Vice is a popular emulator for C64. You could also try Commodore PET, you may just need a simple environment for playing around with 6502 in and PET is about as simple as you get for home computers (though rivaled by Apple I), Vice should emulate the PET too.
Apple II, PET, VIC-20 and C64 are probably all good choices, it all hang on what books you can find.
-
- Posts: 1669
- Joined: Tue Feb 07, 2017 2:03 am
Re: 6502 Newbie / First Game Prototype
The Commodore community is 3 ivory towers in a massive complex with a lot of other smaller towers, huts, and general urban sprawl.
https://commodore.bombjack.org/commodore/books.htm is the easiest source, but there is also zimmers and then general online tutorial, documents, fan magazines, magazines from back in the day such as Compute and Ahoy etc. Bombjack also has an "other languages" section if English is not your native and you speak an European Language.
The archive also has an Apple section for those curious.
The general how to program 6502 books tend to focus on general, maths, algorithms etc so you could just code them in easy6502, but once you get into the game programming books, they are very tied to the C64 hardware. But the C64 uses similar concepts to a NES, sprites + chars so you could probably adapt them fairly easily. While Apple ][ is bitmap based.
https://commodore.bombjack.org/commodore/books.htm is the easiest source, but there is also zimmers and then general online tutorial, documents, fan magazines, magazines from back in the day such as Compute and Ahoy etc. Bombjack also has an "other languages" section if English is not your native and you speak an European Language.
The archive also has an Apple section for those curious.
The general how to program 6502 books tend to focus on general, maths, algorithms etc so you could just code them in easy6502, but once you get into the game programming books, they are very tied to the C64 hardware. But the C64 uses similar concepts to a NES, sprites + chars so you could probably adapt them fairly easily. While Apple ][ is bitmap based.
Re: 6502 Newbie / First Game Prototype
Ah that's a great resource of books for all kinds of computers including all that I mentioned above.
There are also some books like Machine Language For Beginners which has examples for multiple systems.
If not willing to play around with another system, it might be best to to make a sandbox program for NES and try to adapt exercises that can't be done in easy6502 to that environment.
There are also some books like Machine Language For Beginners which has examples for multiple systems.
If not willing to play around with another system, it might be best to to make a sandbox program for NES and try to adapt exercises that can't be done in easy6502 to that environment.
Re: 6502 Newbie / First Game Prototype
Thanks for all your replies and suggestions.
Surprisingly I have never thought about trying to find materials/tutorials etc. About the C64.
But I like the idea to go also that route in parallel.
I guess I could also need more know-how about general game engine things, both in theory and practical.
Currently trying to accomplish the things you mentioned.
Today I got an entity component system in place and it works together with the other routines like updating/drawing sprites etc.
It will loop through all entities, finding „free“ slots in the array and use them. The update/draw routines are then only doing the „active“ entities and free up the ones not active anymore.
Next I will try my luck with simple animation
And then background collision which is still the biggest question mark to Me.
Surprisingly I have never thought about trying to find materials/tutorials etc. About the C64.
But I like the idea to go also that route in parallel.
I guess I could also need more know-how about general game engine things, both in theory and practical.
Currently trying to accomplish the things you mentioned.
Today I got an entity component system in place and it works together with the other routines like updating/drawing sprites etc.
It will loop through all entities, finding „free“ slots in the array and use them. The update/draw routines are then only doing the „active“ entities and free up the ones not active anymore.
Next I will try my luck with simple animation
And then background collision which is still the biggest question mark to Me.
-
- Posts: 1669
- Joined: Tue Feb 07, 2017 2:03 am
Re: 6502 Newbie / First Game Prototype
Sorry I missed you are from Germany, so I should have linked the German section https://commodore.bombjack.org/commodor ... german.htm
For entities you can do a "compacted array" as the order of update doesn't usually matter. so what you do is you keep an index of which is the last one, and then when you remove an entity you copy the last data into the slot you are removing and then decrement your "last entity" counter. Depends on how much entity data you have etc. If there is a lot of data you can make an "index array" that holds an index in to larger array, or make a linked list.
For entities you can do a "compacted array" as the order of update doesn't usually matter. so what you do is you keep an index of which is the last one, and then when you remove an entity you copy the last data into the slot you are removing and then decrement your "last entity" counter. Depends on how much entity data you have etc. If there is a lot of data you can make an "index array" that holds an index in to larger array, or make a linked list.
Re: 6502 Newbie / First Game Prototype
That's an interesting idea, but as games get more complex, I think it's more likely that the order of updates will matter (e.g. a moving platform may need to be updated before entities that are riding it), and that entities will reference others via their slot indices (e.g. objects being carried, multi-segmented objects, etc.), so I wouldn't recommend this approach.Oziphantom wrote: ↑Wed Sep 04, 2024 11:06 amFor entities you can do a "compacted array" as the order of update doesn't usually matter. so what you do is you keep an index of which is the last one, and then when you remove an entity you copy the last data into the slot you are removing and then decrement your "last entity" counter.
I personally am very partial toward linked lists, and they're pretty simple to use as far as lists of game entities go.Depends on how much entity data you have etc. If there is a lot of data you can make an "index array" that holds an index in to larger array, or make a linked list.
On your first project you shouldn't worry too much about these kinds of optimizations though, it's better to do these tasks in a way that feels natural to you. With time, as you gain experience, you're naturally going to notice possible shortcomings of basic techniques and gradually make things more robust, versatile and efficient.