"I would be calculating the positions of around 96 sprites" divided by "about 8 to 12 enemies" equals 96/12 = 8 sprites in a cel.Celius wrote:Where does the number 8 come from?tepples wrote:So the case described by Celius would involve 44 tests against the view: 12 for entire cels, and 8 for each of the four actors that can be partially on the screen at once.
Sprite mappings
Moderator: Moderators
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
Oh, okay. Most of my enemies are 8 sprites per cel, I just didn't know how you figured that. But now it's completely obvious.
For my game, I think I'll be able to use the "hit box" to detect whether or not the enemy is on screen. The hit box ranges from head to toe, and the width is generally how wide the enemy is. There'd at most be 2 pixels of the actor's graphic outside of the hit box. I know that if these few pixels should be rendered on screen while the rest of the actor is off screen, the graphic won't be displayed. But I don't think it'll be too noticable.
Take your actor for example (The one you displayed). If you were to check whether or not the actor's hit box was on screen instead of the cel border, I don't think it'd make much difference. It'd only be a few pixels worth of clipping. I know many of you probably disagree with me, but that's just what I think.
For my game, I think I'll be able to use the "hit box" to detect whether or not the enemy is on screen. The hit box ranges from head to toe, and the width is generally how wide the enemy is. There'd at most be 2 pixels of the actor's graphic outside of the hit box. I know that if these few pixels should be rendered on screen while the rest of the actor is off screen, the graphic won't be displayed. But I don't think it'll be too noticable.
Take your actor for example (The one you displayed). If you were to check whether or not the actor's hit box was on screen instead of the cel border, I don't think it'd make much difference. It'd only be a few pixels worth of clipping. I know many of you probably disagree with me, but that's just what I think.
I think that calculating the coordinates of the new hit box is worse than wasting a few more bytes (I'd waste bytes over time any day)... and I don't even see why you'd have to waste 8 more bytes... AFAIK, you could just use the same bytes to hold the information about the new box after you're done with the old one.Celius wrote:I will save space by using the hit box instead of sacrificing another 8 bytes per object for cel border definitions.
BTW, I just finished implementing my sprite drawing routine. After some tweaking, I got it working. Flipping, clipping, everything seems to work fine. The bad part is how long it takes to execute... Here is a Nintendulator shot of some results:

Don't mind the terrible color scheme, I just picked random colors. Here I just called the sprite drawing routine 3 times, once for each of those tall blocky things (notice that the one to the far left is clipped). I turned red emphasis on after all the processing was done, which means that the lighter strip at the top represents the time it took to draw everything (actually, there are a few other things happening too, so it's unfair to say that all of that time was spent with the sprites, but most of it was). I wasn't expecting on spending so much time just drawing sprites.
I don't think I'll be able to optimize this any further, but I could probably render sprites every other frame (intercalating that with some other task), and just modify the coordinates of the sprites that were rendered last time to reflect any changes in the coordinates of the camera (there are games that don't do this and it looks weird, don't you think?).
Anyway, any new ideas on how to reduce the amount of time used to render sprites is greatly appreciated.
EDIT: I feel I should say something about what kind of sprite cycling I'm using. I'm not cycling the individual sprites, instead I process the objects in a somewhat random order, so that each time different objects get to use sprites of different priorities. I always fill the OAM page sequentially, but I have 2 pointers to it, one to the start and one to the end, so that I can draw to either end (by sending a "SpriteStep" value to the drawing routine, which can be 4 or -4) and force a few objects to be in front of all the others (explosions, for example) if I have to. Also, the priority of the sprites in the same object are respected, which allows for layered sprites and such.
Yes I sort my object so that the bottommost object is rendered first and the topmost object is rendered last. This completely avoid sprite cycling, but gives a top-down 3D effect (not many games did thig, Double Dragon comes in mind). I only cycle sprites if their position is close enough.So you don't have to clip them or sort them.
I 100% agree with you here, but what about the other way arround ? If the sprite hit box is entierely on the screen, but it's leftmost (or rightmost) sprites that made it are off the screen, if your routine doesn't check this, the sprites will warp arround and this will look terrible. So you have to check for the sprites to overflow anyway. Checking if the entiere sprite is on the screen at all is necessary only if you're short of time. (I mean a check is probably better than two additions then check several times).I know that if these few pixels should be rendered on screen while the rest of the actor is off screen, the graphic won't be displayed. But I don't think it'll be too noticable.
My sprite displaying routine isn't very optimised, yet it works fine, and my games doesn't lag with the maximum of 8 normal enemies on the screen (enemies are probably the most time consuming object). In this worst case I guess I had about 60% of the CPU used. However, I never made any huge enemies with lot of sprites yet (no inspiration). I'll post more details later because I don't remember how I handled all of this since I wrote routine for this more than one year ago.
Also, tepple's exemple is rather bad, because the hit box almost matches the bouning box. In my game, I have enemies with a hit box twice as small as the place they take on the screen, mainly because the hit box of my player is large, and because the "head" of the enemies isn't supposed to hit with the "foot" of another object, because it's a top-down view (think of it being like Secret of Mana) and not a 2D side-view.
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
I wouldn't be wasting time. I'd only need to calculate coords for 1 box. Making 2 boxes takes more time than making one.tokumaru wrote:I think that calculating the coordinates of the new hit box is worse than wasting a few more bytes (I'd waste bytes over time any day)... and I don't even see why you'd have to waste 8 more bytes... AFAIK, you could just use the same bytes to hold the information about the new box after you're done with the old one.Celius wrote:I will save space by using the hit box instead of sacrificing another 8 bytes per object for cel border definitions.
So yeah, it looks like that's gonna take a while. Do you refresh OAM every frame?
One thing that's always kind of confused me was how people talk about doing all these things in different frames, and having your game run at 30 fps. How does this go unnoticed? Do most games not run at 60 fps?
EDIT: I only meant for the hit box to be checked for whether or not the object was on screen at all. I don't need to check if it's all the way on screen, or partially on screen, since I will have a universal routine that calculates for both. This problem that you mention, Bregalad, would only occur if I told the game to draw the entire object when the whole hit box was on screen. I don't think there'll be warping, just the slight clipping.
Plenty of Game Boy games run at 30 fps so that the slow LCD can keep up. The launch titles were developed on Wide Boy (SGB predecessor), so they show up blurrier on the LCD than the developers had seen on the CRT, but later titles used a lower frame rate to correct for this.
Films run at 24 fps, but they have natural motion blur to hide things.
Films run at 24 fps, but they have natural motion blur to hide things.
I believe that most games do run at 60 fps (meaning that every frame presents some sort of change over the previous one), but not all tasks are performed every frame. I can't think of a specific game right now, but I'm sure I've seen games where the sprites seem to shake a little, because their coordinates are not always aligned to the background. I think some of the GameGear Sonic games do this (Tripple Trouble?), and some of the NES Mega Man games too, I think. I can only assume this happens because they intercalate the updating of sprites with the updating of the background?Celius wrote:Do most games not run at 60 fps?
Anyway, if I decide to not update the sprites every frame, I'd still want to maze the previously rendered ones a bit (so that sprite flickering happens at 60Hz, not 30Hz) and update all the coordinates to compensate for the movement of the camera, getting rid of the ones that went out of the screen. Hoever, this also seems very time-consuming and not such a big advantage after all.
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
I see how some things don't need to be updated every frame, but those things are usually game mechanics, such as your character's health. That doesn't need to be so immediate and constant. But the things that matter really should be done every frame. Cutting your frame rate in half is a big deal to me. Have any of you played Bugs Bunny's Birthday Blowout? Everyone that has ever played that game knows that it has a terrible framerate (I still love that game though). It's really important that sprites and scrolling are updated every frame.
It's funny how those things take up so much time. I counted the cycles of my scrolling/updating routine, and I like to overestimate, so I assume that every instruction takes 5 cycles. It took about 2300 cycles with that assumption, so it takes a couple hundred less cycles than that, but it's still a lot. That does deal with scrolling, updating the name table, and attribute table correctly.
I suppose there is quite a bit of time left in each frame. I don't think it's impossible to have the game run at 60hz.
It's funny how those things take up so much time. I counted the cycles of my scrolling/updating routine, and I like to overestimate, so I assume that every instruction takes 5 cycles. It took about 2300 cycles with that assumption, so it takes a couple hundred less cycles than that, but it's still a lot. That does deal with scrolling, updating the name table, and attribute table correctly.
I suppose there is quite a bit of time left in each frame. I don't think it's impossible to have the game run at 60hz.
Yeah, you still have a lot of time left in the frame. I'm worried about my sprite drawing routine though. It's taking about 4000 cycles just to render those 3 metasprites.
I'm considering the idea of having more than one type of sprite drawing routine, and more than one type of sprite definitions. I could make another one to use with simpler objects, that do not need layering, special attributes or different palettes. It would always draw sprites arranged in grids (something that makes it possible to skip entire rows or columns that are outside of the screen). I'm sure many of the objects in the game could be drawn like this. This way I can get some speed while not giving up on complex sprites where I really need them.
Another option would be to tell if the object is completely inside the screen or if it's clipped, so that an optimized routine could handle the first case without checking if each one of the damn sprites is visible or not!
Celius, do you have a routine that renders sprites yet? I believe yours will be a bit simpler than mine, because it seems that your game is a side-scroller (which eliminates a bunch of the Y coordinate logic), but I'd still like to know your times.
I also expect to use more time rendering the background than you do, because of the vertical scrolling, in addition to horizontal. The only thing that makes me a bit more confident is that the enemy AI in sonic games is very simple, most of the time the enemies don't even collide with the level map, they just move in a certain pattern, so I expect to spend more time drawing sprites than processing their logic.
The physics for the playr will be quite complex though, and that scares me. I'll probably have to face some serious optimization step soon!
I'm considering the idea of having more than one type of sprite drawing routine, and more than one type of sprite definitions. I could make another one to use with simpler objects, that do not need layering, special attributes or different palettes. It would always draw sprites arranged in grids (something that makes it possible to skip entire rows or columns that are outside of the screen). I'm sure many of the objects in the game could be drawn like this. This way I can get some speed while not giving up on complex sprites where I really need them.
Another option would be to tell if the object is completely inside the screen or if it's clipped, so that an optimized routine could handle the first case without checking if each one of the damn sprites is visible or not!
Celius, do you have a routine that renders sprites yet? I believe yours will be a bit simpler than mine, because it seems that your game is a side-scroller (which eliminates a bunch of the Y coordinate logic), but I'd still like to know your times.
I also expect to use more time rendering the background than you do, because of the vertical scrolling, in addition to horizontal. The only thing that makes me a bit more confident is that the enemy AI in sonic games is very simple, most of the time the enemies don't even collide with the level map, they just move in a certain pattern, so I expect to spend more time drawing sprites than processing their logic.
The physics for the playr will be quite complex though, and that scares me. I'll probably have to face some serious optimization step soon!
That one's closer to between 15 and 20 frames per second. A lot of 16-bit (EGA/VGA era) PC games also ran at 18.2 fps due to how one of the built-in timers was programmed. And Castlevania (at least the first one on the NES; I haven't played Dracula X) is less of a twitch game than, say, Sonic.Celius wrote:Have any of you played Bugs Bunny's Birthday Blowout?
-
Celius
- Posts: 2159
- Joined: Sun Jun 05, 2005 2:04 pm
- Location: Minneapolis, Minnesota, United States
- Contact:
I haven't made my sprite routine yet. When I sat down to start coding for the object engine, I realized there were a ton of things I don't know. As in everything. I'm still working on the ideas for how everything works. Once I know all that, I'll start coding.
My game will scroll all 4 directions just as yours does (Not nearly as fast), so I'll have to worry about the same things. I haven't even started coding my object engine, I'm getting all the ideas down on paper before starting. But I can probably do my drawing routine by tommorow or the next day. I can probably get that figured out without knowing too much else. It'll be a while before I can even start coding for enemy handling and whatnot.
So it took you 4000 cycles just to draw those three metasprites? I guess I'll have to see how long it'll take for my routine. But I have to ask. What exactly is happening in your drawing routine?
My game will scroll all 4 directions just as yours does (Not nearly as fast), so I'll have to worry about the same things. I haven't even started coding my object engine, I'm getting all the ideas down on paper before starting. But I can probably do my drawing routine by tommorow or the next day. I can probably get that figured out without knowing too much else. It'll be a while before I can even start coding for enemy handling and whatnot.
So it took you 4000 cycles just to draw those three metasprites? I guess I'll have to see how long it'll take for my routine. But I have to ask. What exactly is happening in your drawing routine?