LoginLogin
Nintendo shutting down 3DS + Wii U online services, see our post

Second Opinion on Background Detection using Data Arrays? (No BGGET)

Root / Programming Questions / [.]

EsberntheTryhardCreated:
So recently, I've gotten back into using Smilebasic, and I've been trying to create a top-down RPG sort of like the original Legend of Zelda. I originally based the BG collision off of an invisible Layer 3 so that I could separate the design of the level from the actual BG detection for various reasons. Not-that-important reasoning:
SpoilerMostly because I had like 13 different hitbox tiles of different sizes (e.g. whole tile, top half of tile, lower right corner of the tile, etc.) just so I could fine-tune where the player could go instead of being confined to only 16*16 pixel tiles. Unnecessary? Probably, but it was really getting on my nerves.
Anyways, I wasn't really satisfied with this method because it required me to give up an entire BG layer, so I'm turning to data arrays. And ideas of an efficient way to implement this? I had an idea, but I'm not sure if it would be very resource-efficient, since I still have to take other factors like enemy AI into account. My Idea:
SpoilerI would use a 2D array to record the data. Each value codes for one of three possibilities in a corresponding 8 pixel * 8 pixel space:
  • 0 -- Allows player/enemies to walk through freely.
  • 1 -- Collision to all characters and objects. [used for walls]
  • 2 -- Collision to all grounded characters and objects, but none for flying enemies and projectiles. [used for empty space, such as pits]
When a player moves, the pixel coordinates of the corners of their sprite are taken, and after tweaking the numbers to adjust for movement, they are converted into the 8*8 format to check for BG collision.
Does anybody have any input on something wrong with this approach? I'd hate to do all of this only to find out that my method is too over complicated or anything like that, so any help would be appreciated!

That's definitely a good start. Personally what I might do in terms of the value codes is use a bitmask for each collision type. For example, 1 means collision with ground-based objects and 2 means collision with floating objects. It's a subtle difference, but that would make a tile that collides with both types be coded as a 3. Then for ground-based objects you'd check the code AND 1, for flying objects you'd check the code AND 2, etc. Something else to keep in mind is that if you have a tile whose collision box is only 8 pixels wide or high, you're going to want to check the middle edges of your sprites in addition to the corners (assuming 16x16 objects). Though now that I think of it, it's the easiest to only move in a single direction at once and check only along the sprite edge in the direction you're moving. In the case you need to move diagonally, just move horizontally and vertically in separate steps (though this is really rare in Legend of Zelda anyway outside of things like the boomerang). Also, one thing I've found to be a quite user-friendly feature, to avoid getting stuck on walls, is that if you collide with a wall on only a single corner of the sprite and not the other points along the edge, you move towards the empty points. For example, if you're moving upwards and you collide with a tile only on the upper left corner of the sprite, after forcing the sprite back down I'd also incur a slight movement to the right. I hope that makes sense and I wasn't just rambling, haha!

It made perfect sense to me, thank you! I didn't really think of bitmasking, but it definitely seems more flexible now that you mention it. I also completely forgot about wall corners. I actually managed to implement something like what you talked about in my first try at creating a top-down engine, and it was a huge help for small hallways that would have otherwise needed pixel-perfect positioning on the player's part, so I definitely need to add that, too. Thank you again for the help, I really appreciate it!