Sprite System Update

BlitzMax Forums/BlitzMax Programming/Sprite System Update

sswift(Posted 2006) [#1]
I just released an update for my sprite system. Here is what has been updated:


1. You can now give sprites drop shadows!

The system does not require any special images to be loaded for this to work. You can specify the distance and angle of the shadow, or use a vector if you desire. One command, you have a shadow. Direction and distance can be set per sprite, so you could reduce the distance when a button is pushed down to give the impression that the button is moving in the Z axis. Shadows will become more transparent as the object that is casting them becomes more transparent as well.


2. You can now make sprites up to 2x brighter by setting color values over 255. This is done via add blending.


3. The system now gives you TFormPoint, TFormVector, and TFormNormal functions which act like 2D versions of the Blitz3D functions. They allow you to transform points and vectors from the space of one sprite to another (or global space). The shadow function uses TFormVector to determine where to draw the shadow for example.


Older sprite system info can be found here:
http://www.blitzbasic.com/Community/posts.php?topic=58037


Liquid(Posted 2006) [#2]
I there sswift.

I'm willing to buy a sprite system but right now the community have 2 at our disposal: yours and zsprite from zac-interactive.dk

To help anyone who wants to buy such a system, like myself, can you tell us why we should decide for your own?

Thanks.
Liquid


sswift(Posted 2006) [#3]
Well, I generally try to avoid directly comparing my systems to other people's offerings, but YOU LEAVE ME NO
ALTERNATIVE! :-)

Of course this is just asking for the creator of Zsprite to refute some of my claims and
point out flaws in my own system, but c'est la ve... whatever that means. :-)



There's lots of reasons to choose my system over Zsprite. For example, Zsprite has lots of documentation and
demos, but my system is much easier to use.

Here are some other reasons to choose my system over Zsprite:



Creating sprites:
-----------------

With Zsprite, you have to call a special function to load your images, which it calls "resources". You then have to
create a set of "layers". Each "layer" can only have one type of sprite in it. Once you've done that, you can add
sprites to the appropriate layers. Then if you want to change the order of stuff around you've got all these functions
for swapping layers and moving them to the front or back.

Does that sound simple to you?

My system is much simpler. With my system you just load images like you normally would. Then you create sprites, and
set the order they should draw in. Easy peasy.



Collisions:
-----------

With Zsprite, you literally have 15 different functions for determining collisions. Why so many? I have no idea.

With my system you have two collision functions: Pixel perfect sprite vs sprite, and pixel perfect sprite vs rect.
I coded an entire game for Lego using just these two collision functions and they served me quite well.

ZSprite does have the ability to call a function when a collision is detected automatically, and that's a useful feature.
So it gets a point there, but I wouldn't be surprised if I implement a similar feature in my own system in the not too
distant future. :-)



Updating:
---------

With Zsprite, you have to zsSystenBegin and zsSystemEnd at the beginning and end of your main loop AND call the update
function in the middle.

With my system you only have to call the functon to update the animation, and draw the sprites.

Also, with my system you specify the time which has passed. With ZSprite, I don't see a time passed parameter which you
pass to the update function, so I have to assume it is using millisecs to keep track of time itself. While this might
make things simpler initially, it doesn't make them much simpler, and you will probably find that you need to be able to
slow down or pause the animation of the sprites at some point. What if you alt-tab out of your app? Time, or in this
case, millisecs(), waits for no one! With my system you can detect those conditions and skip adding time to the game
timer when the frame time was over a second. With ZSprite, you're out of luck.



Effects:
--------

ZSprite has lots of effects. It has some my system doesn't. Like making a sprite blink, or shake.

But my system also has lots of effects. Like the ability to move sprites along a path, or make them move in a sine wave
pattern. Or make them move from one place to another with acceleration and deceleration.

And my system allows you to make ANY effect play one-shot, looped, or ping pong, in both forward and reverse.

ZSprite on the other hand only allows one-shot loop and ping pong with frame animation, and does not support playing
animations in reverse. Most if not all of the other effects it has support only one-shot animation.

Wouldn't you trade the ability to shake a sprite for the ability to play animations in reverse, and the ability to
continuously animate almost any sprite property?


My function names also make more sense. Compare "zsEffectRotateTo" to "Animate.Rotation" for example.



Single surface rendering:
-------------------------

Sounds nice on paper, but is unlikely to speed up most sprite based games, and requires you to deal with nasty things
like resources and layers and "preparing open gl contexts".



Fonts:
------

No font support in my system yet, but there will be, and you'll probably be able to animate the individual letters in
neat ways.



"Geometry Objects":
-------------------

A fancy term for 2D polygons. Are polygons all that useful in a 2D game? Perhaps in a few limited scenarios, but
otherwise, not really.




Now let's talk about what my system does that ZSprite doesn't do:
-----------------------------------------------------------------

Create paths for moving sprites along. Move sprite on X axis, it moves along path. Move sprite on Y axis, it moves
perpendicular to path.

Parenting. Extremely useful. Create a menu background, then put buttons on it. The buttons are children of the menu.
They are in menu space. When the menu moves, the buttons move with it. When the menu rotates, the buttons rotate with
it. When the menu is hidden, the buttons hide with it. And you can select certain attributes the children won't pick
up on. For example, you can make it so the children DON'T rotate with the parent when it rotates, but they move when it
moves, or rotates, or scales, because their position is still relative to parent space.

TFormPoint, TFormVector, TFormNormal. Really useful math functions that allow you to easily do things like determine if
a sprite is in a 45 degree arc in "front" of another sprite which is rotated, and then have that sprite apply thrust in
the correct direction because you can just pass a vector in the sprite's space that points forwards to the TFormVector
function and transform it into global space for your physics code.

Shadows. Cast a drop shadow from any sprite. No extra images required. One command, three parameters, bada bing, bada
boom, shadow!

Renderstate storage and restoration on a stack. Sprite system won't change what color you set. It saves all those
render parameters before it goes to work, and restores them after. And you can use those functions too.



Anyway I'll just wrap this up with this:
----------------------------------------

I wrote the original version of this system in Blitzplus, and used it to make Lego Builder Bots. When I ported it to
Blitmax, I made it 10x better. So I know I've got a rock solid design, and that if you use it you will be pleasantly
surprised at how often you need a particular feature, and find the system already supports it.


Liquid(Posted 2006) [#4]
What a very good description. Seems you have a very good system indeed ;)

And what about speed? Is your system fast? Are collisions fast? Will you add more collision functions?

Do you plan to improve the system or are you planning to just maintain some bug here and there or maybe improve some speed?

What about documentation and examples??

Ahhh one more thing, your system works with DX and OpenGL, right?


It would be nice to see the ZSystem author tell about his system.


--
Liquid


sswift(Posted 2006) [#5]
Liquid:
I am currenty programming a game using the system, so there will be more updates as I need different features.

Is the system fast? Fast enough to render over 1000 sprites per frame. As fast as Blitzmax is at drawing images normally.

Are collisions fast? They should be more than fast enough. They use the collision functions provided by Blitzmax, and those check bounding rects before they do the pixel perfect tests.

Will I add more collision functions? Maybe. As I mentioned above, I like the idea of being able to automatically call a function when a collision occurs. And I might add a point collision wrapper for the rect collision function.

Documentation? Each function has a block of comments above it, and there are other comments strewn about the code. ZSprite's docs are the same thing really, except he formatted his comments in a way which is compatable with the Max help system. I think the format the help system requires for comments looks messy though. So I chose to have the code be neat over seperate help docs.

Examples? There's a few examples with my system, but not many. I don't have time to write lots of examples, and there's really no need for them. The system is very simple to use. If you can't figure it out fairly easily after looking at the examples I provided to give you the basic jist of how things work, might I suggest you take up knitting? :-)

DX and OpenGL? Yes. Both. My system draws sprites with the same Max image functions you have access to. ZSprite on the other hand calls OpenGL functions. It probably does not work with DirectX.


Booticus(Posted 2006) [#6]
I gotta say sswift has put out about 4 updates since I bought his module, and so far its been great! He seems to be very interested in keeping the module growing and updating his customer! The sprite system of his is top notch! :) I'm always interested in purchasing quality products made for/by the Blitz Community!


AntonyWells(Posted 2006) [#7]
zSprite Sales Pre Swift's post: 27

zSprite Sales Post Swift's Post : -2342342354345345345


sswift(Posted 2006) [#8]
Aurora:
If he sold 27 copies, I don't feel bad, considering I've sold only SIX. :-)


AntonyWells(Posted 2006) [#9]
My last product prior to blitznet etc sold just one copy to a Microsoft executive of all people so I know the pain :)

Thankfully the new one has already sold 13x as many copies :)


Murilo(Posted 2006) [#10]
I must admit to being very temptedd by your sprite system sswift. Did I read somewhere that you're in the process of adding physics?


sswift(Posted 2006) [#11]
There is another post in this forum about that, I already did add physics and there is a demo:

http://www.blitzbasic.com/Community/posts.php?topic=59095

The physics system is still being updated, I should finish an update today that makes it much more convenient to use, and which makes the physics more stable.


tonyg(Posted 2006) [#12]
Has there been an update recently as I haven't received anthing?


sswift(Posted 2006) [#13]
If your verison has physics, then you have the latest update.


sswift(Posted 2006) [#14]
Just released another update:

This update makes the physics a little more stable by reversing the order in which the collisions are tested each time Physics.Update() is called.

This update also makes the sprites render much sharper by rendering them at whole pixel boundaries. I tested at 800x600, and I could not tell any difference in smoothness of movement with this change, but the difference in sharpness, especially when a sprite is moving back and forth a little bit at the subpixel level where it would go in and out of focus like mad, is amazing. (The sprites are still MOVED at subpixel levels, they simply aren't DRAWN at subpixel positions.) I think this also

Shadows too are now drawn at whole pixel increments, and a bug was fixed with the calculation of their offset (I was transforming it from sprite space to global space instead of sprite parent space to global space.) Drawing at whole pixel increments fixed an issue where the shadows would shake, changing their distance from the sprite slightly, if the sprite was moving at subpixel levels. This was noticeable when a sprite casting a shadow was moving slowly.


Grey Alien(Posted 2006) [#15]
I looked in V0.80 and couldn't see how you did this. Please tell as I find the blurring a bit annoying too...thanks.


sswift(Posted 2006) [#16]
Look in Sprite.Draw() I just used Floor() to floor the position when drawing.


Grey Alien(Posted 2006) [#17]
fair enough. I've got a round function that doesn't have bankers rounding. I'll use that instead as it's more accurate (but slower) than floor:

' -----------------------------------------------------------------------------
' ccRound (By Beaker from BlitzPlus forums)
' -----------------------------------------------------------------------------
Function ccRound(flot#)
	Return Floor(flot+0.5)
End Function
Of couse it can be inlined.

Q. Why aren't you using round on the DrawImage after this comment in the code:

' If the sprite's color is over 255, then draw it again at the same location with add blending.



Grey Alien(Posted 2006) [#18]
hmm did some testing and my game framework looked much worse with rounding. Seems that passing in floats makes things ultra smooth for steady moving objects that move in non-integer steps (which they will do with delta timing or similar). It may not be obvious on your physics demo but try moving a sprite in line at a constant speed...


sswift(Posted 2006) [#19]
"Why aren't you using round on the DrawImage after this comment in the code:"

Because I forgot. :-)


"hmm did some testing and my game framework looked much worse with rounding."

With YOUR rounding, or with Floor?


I've moved lots of sprites at a constant rate in Blitzplus where you can only move in integer increments. Seemed smooth enough to me. It may not be as smooth as drawing at non integer positions, but at what cost? The sprite going in and out of focus? That doesn't seem like a worthwhile tradeoff.


Grey Alien(Posted 2006) [#20]
With YOUR rounding, or with Floor?
both! I remember we had this discussion before lol. Some jittering on a minor level is inevitable with rounding. My sprites are all anti-aliased so you don't really notice any focus problems, just the edges seem to fluctuate if you look very closely. However, it is significantly smoother without rounding or flooring imho. My framework users can always uncomment the rounded DrawImage lines if they want.


Robert Cummings(Posted 2006) [#21]
This update also makes the sprites render much sharper by rendering them at whole pixel boundaries. I tested at 800x600, and I could not tell any difference in smoothness of movement with this change


Of course you won't with fast moving things or things moving at a constant speed. Everything else however will look shit. Make it optional at least.


ImaginaryHuman(Posted 2006) [#22]
Yah I wondered about that. OpenGL says you should render to the exact middle of a pixel to draw a pixel properly, ie 0.5,0.5 offset.


slenkar(Posted 2006) [#23]
you should create a flashy demo


sswift(Posted 2006) [#24]
"Of course you won't with fast moving things or things moving at a constant speed. Everything else however will look shit. Make it optional at least."

Everything else? You mean things moving a a slow speed, or a speed which varys?

How slow? Cause after the balls bouncer around in my physics demo, they start moving pretty slow. And in my own game I have done tests with balls that are accelerating from a standstill, which would fit the defintion of "not at a constant speed" and they look just fine.

Angel:
In BlitzMax, you should draw at integer coordinates if you want the sharpest picture. Blitzmax offsets the textures the 0.5 itself.


Grey Alien(Posted 2006) [#25]
I haven't experimented with this yet, but is there any different in a texture shown at a coord 0.2 say and 0.5? Or does any floating point coord just look the same?

Another important thing I found out early on is that if you have an image with non even dimensions e.g. 31 wide instead of 32, and you have automidhandle on, when you draw at an integer coord, of course it decides that the top left is something.5 and thus draws it all anti-aliased, so watch out for that one.

Hey, I've just noticed that sh*t got through the swear filter. Anyway, if I round the coords it is a bit jittery, just like is was in BPlus, a problem that I could never remove. Basically if the HZ is 60 and your object moves at 50 pixels per sec, it will NEVER look totally smooth. At least the anti-aliasing gives it a smooth effect. I've made my TSprite have the option of rounded or not, because for buttons and static scenery you might want it non rounded of course.


sswift(Posted 2006) [#26]
Hm... I just tested with my bug demo and made it so I could toggle the two modes, and not only do the bugs move more smoothly with integer positioning off, they look more detailed as well. I don't get it. In the other two demos I tested the balls definitely looked better with it on.

I may yet go back to the way it was.