Page 1 of 2
[SOLVED] Is the way Love handles sprites inefficient?
Posted: Sun May 07, 2017 5:55 pm
by Jetmate
In the previous game development API's I've worked in, each sprite was treated as a separate object, and so the process of displaying it on the screen simply required a reference to that sprite along with the coordinates of where it was to be displayed. This is unlike Love, where instead a "sprite" is just a table with coordinates and dimensions, and displaying it requires a call to the original image (such as a spritesheet, in my case). A consequence of this is that when some sprite needs to be modified (such as being rotated), that operation must be performed every frame, after the sprite is extracted from the original image. In my mind this seems far less efficient than just storing individual sprites with their own images that could retain operations such as a rotation - am I wrong in my assumption? Does love somehow optimize this process? Thank you.
Re: Is the way Love handles sprites inefficient?
Posted: Sun May 07, 2017 8:06 pm
by raidho36
Yes you are - LOVE used transformation matrices to render textured quads. If you call render function with transform parameters, it's generated for this sprite anew, but you can also do it manually however you please and then it omits this step. It's as efficient as it gets.
Re: Is the way Love handles sprites inefficient?
Posted: Sun May 07, 2017 8:33 pm
by zorg
Not sure what APIs were those that you used, but those "Objects" probably had properities themselves, just more or less hidden from you; also, the definition for what a sprite may be is vague at best. Also, those rotations were probably computed each frame in whatever framework/engine you used before as well, just, as i said again, hidden from you.
Löve provides more chances for you to mess up, in that way, it's a bit more "low-level" than other game engines may be.
But really, nothing's stopping you to do the necessary speed-memory tradeoffs you think are important, and create and store however many rotations and scalings of an image you want to.
Löve also allows you to use separate images for sprites, or you can use Spritebatches with one image, used as an atlas with Quads, or just as a single image replicated many times, with different transforms, for example.
Re: Is the way Love handles sprites inefficient?
Posted: Sun May 07, 2017 8:37 pm
by Jetmate
How do you manually apply an operation to an image? Also, since I normally use spritesheets, how can I extract smaller images (sprites) from them?
Re: Is the way Love handles sprites inefficient?
Posted: Mon May 08, 2017 12:02 am
by raidho36
You can use graphics transformation routines, those manipulate the transform matrix directly. You can still use sprite-specific transform and it'll be applied on top of that.
A default image render function produces a quad matching dimensions of the whole texture. You can manually create a quad that only spans a fragment of the texture.
Re: Is the way Love handles sprites inefficient?
Posted: Mon May 08, 2017 12:45 am
by Jetmate
What specific graphics transformation routines are you talking about? The wiki only lists functions for rotation/scaling/etc the entire screen, but not specific textures.
Re: Is the way Love handles sprites inefficient?
Posted: Mon May 08, 2017 1:06 am
by zorg
Jetmate wrote: ↑Mon May 08, 2017 12:45 am
What specific graphics transformation routines are you talking about? The wiki only lists functions for rotation/scaling/etc the entire screen, but not specific textures.
That's not how those work, they manipulate the graphic state at the current point in time (relative to your code, i mean), meaning if you draw your image before and after doing love.graphics.scale(2,2) for example, the first image will draw unscaled, the second will draw scaled up to twice its size.
Also, some more info:
Quad - Basically just holds the top and left coords, and width and height, of a quadrangle... or in other words, it contains 4 values.
ImageData - Holds a texture basically.
Image - Is a Drawable thing that you can draw to the screen. It has its own internal ImageData, so you don't need to use those if you won't need to edit the image contents.
SpriteBatch - Is a Drawable; Uses an Image with which you can define instances of itself (or parts of it, if you use Quads with it), then you can draw all the defined "sprites" inside it with one call to OpenGL, meaning it's faster than doing everything with only Images.
Mesh - Is a Drawable; If you want to draw any other shape other than a quadrangle (square, rectangle), you'll need to use this.
Re: Is the way Love handles sprites inefficient?
Posted: Mon May 08, 2017 3:17 am
by Jetmate
So, from what I understand, there is no way to take a central spritesheet and then copy specific parts of it into new images? Quads are the only option?
Just as a side question - images in Love are immutable, right? Meaning if I have a bunch of objects that each have a variable that holds their spritesheet, which I need for drawing their sprites, I'm not duplicating a large image hundreds of time.
Re: Is the way Love handles sprites inefficient?
Posted: Mon May 08, 2017 6:12 am
by zorg
Well, you can get a reference to the Image's ImageData with its :getData method, create a new ImageData with a specific size, and copy over a certain area of pixels, finally creating a new Image with the new ImageData, but i don't see why you'd need to do that if Image + Quads (or even Spritebatch + Quads) would work faster.
Also, strictly speaking, Images are mutable in that, via the above method, using :getData, you get its own ImageData, edit that, then use the Image's :refresh method, will update it... but otherwise, yeah, they're immutable; you can also have as many references to an Image as you want, all löve Data and Object types are references, only their pointers are copied around.
Re: Is the way Love handles sprites inefficient?
Posted: Mon May 08, 2017 10:28 am
by s-ol
Jetmate wrote: ↑Mon May 08, 2017 3:17 am
So, from what I understand, there is no way to take a central spritesheet and then copy specific parts of it into new images? Quads are the only option?
Just as a side question - images in Love are immutable, right? Meaning if I have a bunch of objects that each have a variable that holds their spritesheet, which I need for drawing their sprites, I'm not duplicating a large image hundreds of time.
I think you are getting confused a bit by the abstractions in other engines. Love is very close to the actual GPU Api (OpenGL) it uses.
Images aren't immutable, just as GL textures aren't, but you try to not really modify them because then you'd have to send the whole texture again. You also usually don't cut up a texture into smaller ones, simply because it doesn't help with anything and a Quad is a much more lightweight way of addressing it and allows you to draw a lot of things without asking the GPU to bind a new texture.
This is mostly the same in other engines, for example In Unity, when you cut up an image into sprites, you use them as if they were separate sprite-files or textures, but I'm pretty sure that on the GPU level they use one Texture per file and uvs to map them just like in love 2d.