Did the SNES have pixel perfect movement

Started by
11 comments, last by ifstatement 5 years, 1 month ago

For example in Zelda or Castlevania on the SNES, did the character move one pixel at a time or several pixels?

I've programmed a tile-based graphics game. Each tile is 4x4 pixels and moving the camera or character moves everything by 1 tile, so 4 pixels at a time. I do this so I can have collision detection that is not cpu heavy by checking the tiles next to the character, whether they are walkable or not. The characters and other objects, and background, etc. are made up of multiple tiles.

Did the SNES do the same or did it separate the grid-based layout of levels from the actual movement of the camera and character. So the level would be displayed according to a grid but then the movement of objects and characters, and the camera would be one pixel at a time? I've watched videos on youtube and it seems like the movement on the SNES is grid based and not pixel based.

Advertisement

The movement of an object, so long as it did not overshoot the dimensions of a grid-tile, could have been "pixel perfect" and still use a grid for collision detection, in the manner you describe.

Languages; C, Java. Platforms: Android, Oculus Go, ZX Spectrum, Megadrive.

Website: Mega-Gen Garage

Different games used different approaches, but the SNES was certainly capable of pixel-perfect movement.  To pick an obvious example, Super Mario Brothers was pixel-perfect (if not sub-pixel) even on the NES.

2 hours ago, a light breeze said:

Different games used different approaches, but the SNES was certainly capable of pixel-perfect movement.  To pick an obvious example, Super Mario Brothers was pixel-perfect (if not sub-pixel) even on the NES.

Yeah that's the sense I get when watching it on youtube. I've also played it.

4 hours ago, Anri said:

The movement of an object, so long as it did not overshoot the dimensions of a grid-tile, could have been "pixel perfect" and still use a grid for collision detection, in the manner you describe.

Yes, so I have also programmed an algorithm that would achieve pixel perfect movement.

I use the tile map array to detect collision. The character you control has coordinates for that tile map and I check the next tile if it is marked as walkable or not. I use another tile map array with the same dimensions and that one holds boolean values. True means it's blocked, so not walkable, and False means it's walkable. I then use another set of variables for the same character that tracks it's offset in pixels from the tile map coordinates. The offset ranges from 0 to 15 because each tile is 16x16. When the character's offset are <0 or >15 the character's variables for the tile map are incremented by 1. I also have a variable for incrementing the offset variables by more than 1 (1 is a bit slow and would be comparable to walking in a game) so that the character can move faster, which is like running or sprinting I guess.

The camera or view area (how many tiles are displayed on screen) has it's own coordinates for which tiles should be displayed (start x, y and end x, y: which makes the view area). The display on screen of those are also offset by another set of variables for the camera and those variables follow the same rules as the character's offset variables.

The issue I'm having is I cannot seem to take into account the offset variables and tile map variables correctly so that the collision is detected properly between the character and a hard object on screen. My algorithm uses the tile map array to detect if the tile next to the character in the direction they are walking is walkable or not, if it's not, it will get the pixel coordinates of that tile and the pixel coordinates of the character and then check each pixel the character and the tile are comprised of until they overlap (I plan to also check the actual pixel value of the surface matching the textures of the character and object and consider a pixel only if it's different than the colorkey (255,0,255), that way I can have pixel perfect collision) at which point a collision would have occurred and the character's offset variables are not incremented. That works partially when I run and play the game. The character stops when it encounters the object but when the character is aligned in a certain way with the object it walks through it because, I assume, the tile map coordinates and the object are not aligned in a way that detects as collision.

At the moment the grid-based movement I have programmed works perfectly but pixel perfect looks smoother, lol.

Sorry if I'm bad at explaining this, I did not study how to make a game nor programming, but I have been playing games and programming for 22 years. So I can figure out a lot of things to make a game I would enjoy playing, and hopefully others too.

I would appreciate if anyone would know of a way to achieve pixel perfect movement or can point me towards a website. Also I'm using SDL2 and Free Pascal for my game. Too late to switch to another programming language, I have 19198 lines of code: character and npc menus and interactions, world/level creation, combat and so on. Been working on this for over a year.

 

I've actually done a bit of SNES homebrew programming, so I can answer this!

The main dynamic sprites (also called objects in the SNES docs) can be positioned at any pixel. Each sprite the OAM table (Object Attribute Memory) has 9-bit X and Y values that specify the position of the upper-left corner of the sprite, with a max of 128 sprites. The SNES had a resolution of 256x224 (which is less than the standard NTSC resolution of 640x480), so each internal pixel in the SNES ended up taking up multiple pixels on screen. But in terms of its internal resolution, the sprites could be arbitrarily positioned anywhere in the [-32, 255] range. This is pretty typical of the kind of sprite hardware that you would find in other consoles, PC's, and arcade boards from that era.

The background tiles are different. Those are either 8x8 or 16x16 in size, and you can not arbitrarily position them. Instead they are laid out in a 2D grid, with an index per grid entry specifying which tile sprite to use. You could still do smooth scrolling of the BG tiles in response to camera movement by setting two special registers that contained X and Y pixel offsets for each BG layer. By setting those you could do smooth pixel-level scrolling of the entire tile grid. So in other words you can't arbitrarily position each BG tile relative to each other, but you can per-pixel scroll all of the tiles in a layer at once (you could do up to 4 BG layers depending on the mode being used at the time). This functionality was also fairly typical of console/arcade hardware from the 80's and early 90's.

Let me know if you have any other questions, and I can (maybe) answer them. 

one pixel movement per frame is pretty slow as I found out pretty fast on C64 with 320px. Now use an Amiga with 1280 px horizontally and it is even slower. I like these 120 frames/second monitors: no flicker and better collision detection. Going from 50 fps (C64) to 72 fps (PC with VGA) was already a big win.

To utilize the collision hardware on the C64 I thought about rendering intermediate frames in the vertical borders. But then I am too much of a CPU guy that I would probably do full vector sub-pixel preciscon calculations on the MOS 6502.

17 hours ago, MJP said:

I've actually done a bit of SNES homebrew programming, so I can answer this!

The main dynamic sprites (also called objects in the SNES docs) can be positioned at any pixel. Each sprite the OAM table (Object Attribute Memory) has 9-bit X and Y values that specify the position of the upper-left corner of the sprite, with a max of 128 sprites. The SNES had a resolution of 256x224 (which is less than the standard NTSC resolution of 640x480), so each internal pixel in the SNES ended up taking up multiple pixels on screen. But in terms of its internal resolution, the sprites could be arbitrarily positioned anywhere in the [-32, 255] range. This is pretty typical of the kind of sprite hardware that you would find in other consoles, PC's, and arcade boards from that era.

The background tiles are different. Those are either 8x8 or 16x16 in size, and you can not arbitrarily position them. Instead they are laid out in a 2D grid, with an index per grid entry specifying which tile sprite to use. You could still do smooth scrolling of the BG tiles in response to camera movement by setting two special registers that contained X and Y pixel offsets for each BG layer. By setting those you could do smooth pixel-level scrolling of the entire tile grid. So in other words you can't arbitrarily position each BG tile relative to each other, but you can per-pixel scroll all of the tiles in a layer at once (you could do up to 4 BG layers depending on the mode being used at the time). This functionality was also fairly typical of console/arcade hardware from the 80's and early 90's.

Let me know if you have any other questions, and I can (maybe) answer them. 

Thank you! I've programmed something along these lines but I can't seem to get the collision right (more details in my previous comments). I've decided to stick to purely grid-based movement and collision detection. There are too many calculations involved in pixel perfect collision, that will take up the cpu more than if I was doing simple grid-based. At least my solution has too many compared to simple grid-based. A tile on my grid is 4x4 so whenever the player, an object or the camera moves it's by 4 pixels at a time. I think some snes action rpgs like alcahest and terranigma use the same method, and those play and look just fine. Plus I have to reserve cpu power for a whole bunch of other gameplay things I want to implement. Also it makes detecting hits/attacks a lot faster and less cpu intensive.

3 hours ago, arnero said:

one pixel movement per frame is pretty slow as I found out pretty fast on C64 with 320px. Now use an Amiga with 1280 px horizontally and it is even slower. I like these 120 frames/second monitors: no flicker and better collision detection. Going from 50 fps (C64) to 72 fps (PC with VGA) was already a big win.

To utilize the collision hardware on the C64 I thought about rendering intermediate frames in the vertical borders. But then I am too much of a CPU guy that I would probably do full vector sub-pixel preciscon calculations on the MOS 6502.

Yeah that's why in my alternate algorithm for pixel-perfect movement I ended up implementing movement by more than one pixel at a time. But also allowed for one pixel at a time. The amount of pixels would increase the longer the player would keep pressing the directional button.

Even in the old days the physics of free fall (parabola) and the differences between PAL and NTSC (or different aspect ratio of the pixels on different systems, or a port to GBA) would favour a game which uses sub-pixel precision. Or acceleration of Super Mario while running (your longer pressing diagonal button). Also Sonic the Hedgehog is fully simulated. The CPU used had 32 bit regs, so plenty of bits for fixed point high precision math. But I have to say: Pool billard games look strange in lowres 2d.

So learn the phyics   and learn the tiles (sort of image compression). Combine them. There is not much synergy or so, but they are compatible.

Also the bullet physics engine has to run at 1000 fps to get bouncing of off walls right.

Or use this: https://box2d.org/

somehow the links within are broken: https://www.pascalgamedevelopment.com/showthread.php?4838-Box2d-wrapper-for-Pascal

When reading game tests I always wondered why  control  of the characters was so important for testing.  Me only playing   arcade or super mario never had an issue. I think the collision detection in the old jump and runs suffered from low CPU power. in all but the most polished titles. I mean that was in the 8-bit time.

This topic is closed to new replies.

Advertisement