It is currently Thu Aug 16, 2018 3:17 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Mon Jul 30, 2018 3:43 pm 
Offline

Joined: Wed Jul 18, 2018 1:50 pm
Posts: 7
Hello all,

I am currently working on my first NES homebrew game, and I've just added in the scrolling and column drawing code. The object of the game is to avoid asteroids that scroll across the screen, which are randomly placed within the new columns. If the player collides with an asteroid, the game is over. I have written the code to draw the next column and scroll the screen, though this code currently just copies the data from a .bin file containing the level data. I want to write the asteroids to the background because they do not move independently of it, and I want to avoid issues with the 8-sprites-per-scanline limit.

I currently have a very rudimentary PRNG to determine the Y-coordinate of a given asteroid (I intend on expanding it to determine how many asteroids should be drawn on a given column, but would like to get this problem worked out first and expand later). I am looking for some advice from the more experienced NES developers here as to how to go about further development of the object placement. My current plan for the routine is:

1. Determine the Y coordnate of the asteroid to be drawn

2. Copy the nametable data to be drawn from the data file into a memory buffer; the buffer really only needs to contain data for the next column to be drawn.

3. Overwrite the data in the buffer at the Y coordinate of the asteroid to contain the asteroid image

4. Use buffer as data source when drawing the next column, rather than the .bin file

5. Track objects so that if they ever come into contact with the player sprite, the game ends.

The first question I have is regarding the memory buffer; I read in another thread that an easy way to create a buffer is to use the stack and set up a secondary stack pointer for the buffer. However, if I am going to be modifying the data in the buffer to draw the asteroids, I will either need to write directly into the stack (which seems like it defeats the purpose of the stack) or write something very long and convoluted to draw an asteroid instead of the regular background.

The second question I have is a little more broad, and it is regarding tracking these objects to determine whether they collide with the player. Should I track objects individually? Another idea I had was to check the value of the background at the boundaries of the player each frame to determine whether they have collided with anything. I'm wondering how feasible this is, considering VRAM can only be accessed in vblank. Any tips on doing collision tracking?
Edit: I also know some people include whether a cell is solid or not in their ma data, but I'm not quite sure how this works in practice/how to determine it.

Note that I'm not necessarily looking for code, though examples are always appreciated :)

Thank you all for your help, I really appreciate it!

Edit: to clarify, I'm only wondering about routines for placing the randomly generated position in the memory buffer and how to detect a collision with the player once it is there. I also do not need to worry about ejection as colliding with an object won't require this--colliding with an asteroid will trigger the game over sequence, so I really only need to worry about detecting the collision.


Last edited by truffly on Mon Jul 30, 2018 4:39 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 3:54 pm 
Online
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3476
Location: Mountain View, CA
I can't quite tell if the question is about PRNG or not. If it is, we do have a wiki page on that, which includes code and several reference links to such matters (particularly a good way to handle a pre-generated seed): https://wiki.nesdev.com/w/index.php/Ran ... _generator


Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 4:35 pm 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2197
Location: DIGDUG
All objects should exist in the RAM so you have access to it all the time. Collisions should happen from those.

How you visualize them should be handled separately.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 4:36 pm 
Offline

Joined: Wed Jul 18, 2018 1:50 pm
Posts: 7
koitsu wrote:
I can't quite tell if the question is about PRNG or not. If it is, we do have a wiki page on that, which includes code and several reference links to such matters (particularly a good way to handle a pre-generated seed): https://wiki.nesdev.com/w/index.php/Ran ... _generator


I'm not worried about a PRNG as I have a rudimentary version that I'm refining now. I understand how PRNGs work and am using player input as a source of randomness in seeding the numbers.


Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 5:19 pm 
Offline

Joined: Wed Jul 18, 2018 1:50 pm
Posts: 7
dougeff wrote:
All objects should exist in the RAM so you have access to it all the time. Collisions should happen from those.

How you visualize them should be handled separately.


That's what I was thinking. The issue to overcome there, I suppose, is tracking those objects, considering the amount that I will be using at any given time is random. Is there any recommended or best method for tracking a variable amount of objects? I can think of a few different ways it could be done, but surely some methods are better than others.

Thanks for all your help!


Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 5:37 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10713
Location: Rio de Janeiro - Brazil
Since you're generating map data dynamically (i.e. dynamic objects overlaid on top of the static map data), I suggest you maintain a larger buffer, containing everything that's visible on the screen plus a little padding, instead of just the columns you're updating. That could help with the second problem: collisions.

You may keep track of the asteroids as individual objects, each with its own bounding box, but depending on how many asteroids are active at once, that may end up consuming too much memory, being too slow, or even harder to manage (creating and destroying game objects). If they don't move independently from the background, it may be simpler to treat them as special background tiles.

If you go this route, all you have to do is check the tiles surrounding the player, and if you find any asteroid tiles in that bunch, you'll know a collision happened. The biggest advantage here is speed, because no matter how many asteroids there are on screen, you'll always only check the immediate surroundings of the player (and bullets, if you have them). However, if the asteroids are treated like individual game objects, you'll have to test for collisions against all active asteroids, meaning that a large number of them could cause slowdown.


Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 6:39 pm 
Offline

Joined: Wed Jul 18, 2018 1:50 pm
Posts: 7
Thanks for the reply, tokumaru.

Sounds like comparing the sprite boundaries against background data might be the most efficient/easiest option. If I do decide to go this route, is there anything to keep in mind regarding the scrolling? Going through Disch's the frame and NMIs, I can't help but notice he doesn't really cover what to do in the buffer when you're dealing with scrolling. Maybe it will seem more obvious once I'm actually at my computer testing it out, but if I'm going to keep everything visible plus the next column to be drawn in a buffer, it seems like handling the scroll will be a bit more involved than I currently have it right now -- I'm currently only drawing the next 30 bytes of data and letting it scroll into the next nametable.

In short, it's easy for me to imagine the routine for using a buffer for only the next column of data to be drawn, but it is much less clear once I start thinking about including the entire visible nametable in the buffer.


Top
 Profile  
 
PostPosted: Mon Jul 30, 2018 8:45 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10713
Location: Rio de Janeiro - Brazil
There has been a thread recently about this very subject: viewtopic.php?f=10&t=17572

The simplest thing you can do is have a buffer that's analogous to the name tables, and treat both as circular buffers. Circular buffers simply wrap around seamlessly when you reach either end. This can be implemented very easily by keeping track of everything in world coordinates, but masking the irrelevant upper bits when indexing the buffer (as long as the buffer length is a power of 2).

For example, say that your game scrolls horizontally, so you have 2 name tables side by side. To keep things simple, your buffer is also 2 screens wide. If your metatiles are 16 pixels wide, this means that the name tables and the buffer can hold 32 columns of them... 0 is the first, 1 is the second, 2 is the third... until you reach column 31 and try to use column 32, which exists in your level map in ROM but doesn't in your buffer. Turns out that all you have to do is get rid of the upper bits of the column index when dealing with the buffer and you get automatic wrap around.

Indexing 32 columns requires 5 bits (values ranging from 0 to 31), so just get rid of all but the first 5 bits and you'll find the counterpart of any level map column in the buffer. For example, when you decode column 32 from ROM, you just do 32 AND #%00011111 and you get 0, which is where in the buffer column 32 will go. Automatic wrap around.

IMO, it's best to keep everything (specially object coordinates) in world space, so that the wrapping around doesn't cause any weird problems with collisions and the like. It's better to keep it clean and treat everything as it existed in a long level, and just scale things back when dealing with the specific hardware limitation that doesn't allow you to keep a full level in RAM.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: FrankenGraphics, Google [Bot], koitsu, lidnariq, Nicole and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group