Page 1 of 1

Spritebatch explanation

Posted: Mon Mar 15, 2010 12:43 am
by zugamifk
I was reading over info on quads in the wiki and it all makes good sense with examples and such, but I don't understand the spritebatch at all. From what I understand, quads are simply a collection of coordinates you can apply to any image to get a subsprite from that image, and that sounds extremely useful for a tile based game, which is exactly what I'm working on.

However, it seems like spritebatch is made even more specifically for this purpose, but I don't understand how it works. Is it a table that stores images as values?

Here's an example of the table I store all of my images in:

Code: Select all

images = {
	world = {
		tiles = {
			earth = {
				love.graphics.newImage("tiles/earth/1.png"),
				love.graphics.newImage("tiles/earth/2.png"),
				love.graphics.newImage("tiles/earth/3.png"),
				love.graphics.newImage("tiles/earth/4.png"),
				love.graphics.newImage("tiles/earth/loam.png"),
				},
			grass = {
				meadow_foxtail = love.graphics.newImage("tiles/grass/meadow_foxtail.png"),
				},
			flowers = {
				wild_lupin = love.graphics.newImage("tiles/flowers/wild_lupin.png"),
				field_poppy = love.graphics.newImage("tiles/flowers/field_poppy.png"),
				},
			trees = {
				red_maple = {love.graphics.newImage("tiles/trees/saplings/red_maple.png"),
							love.graphics.newImage("tiles/trees/trunks/red_maple.png"),
							love.graphics.newImage("tiles/trees/leaf cover/red_maple.png"),	},
				}
			},
		items = {
			natural = {
				seeds = {
					--grass
					meadow_foxtail = love.graphics.newImage("tiles/items/seed_meadowfoxtail.png"),
					--flowers
					wild_lupin = love.graphics.newImage("tiles/items/seed_wildlupin.png"),
					field_poppy = love.graphics.newImage("tiles/items/seed_fieldpoppy.png"),
					--trees
					red_maple = love.graphics.newImage("tiles/items/seed_redmaple.png"),
					},
				},
			},
		player = {
			idle = {
				down = newAnimation(love.graphics.newImage( "tiles/character/idle_down.png" ), 25, 50, 0.1, 0),
				up = newAnimation(love.graphics.newImage( "tiles/character/idle_up.png" ), 25, 50, 0.1, 0),
				right = newAnimation(love.graphics.newImage( "tiles/character/idle_right.png" ), 25, 50, 0.1, 0),
				left = newAnimation(love.graphics.newImage( "tiles/character/idle_left.png" ), 25, 50, 0.1, 0),
			},
			walk = {
				right = newAnimation(love.graphics.newImage( "tiles/character/walk_right.png" ), 25, 50, 0.1, 0),
				left = newAnimation(love.graphics.newImage( "tiles/character/walk_left.png" ), 25, 50, 0.1, 0),
				up = newAnimation(love.graphics.newImage( "tiles/character/walk_up.png" ), 25, 50, 0.1, 0),
				down = newAnimation(love.graphics.newImage( "tiles/character/walk_down.png" ), 25, 50, 0.1, 0),
			},
		},
	},

	hud = {
		main = {
			bar = love.graphics.newImage("tiles/hud/hud_bar.png"),
		},
		windows = {
			context_window = love.graphics.newImage("tiles/hud/hud_context.png"),

			examine_window = love.graphics.newImage("tiles/hud/hud_examine.png"),

			help_window = love.graphics.newImage("tiles/hud/help_window.png"),

			inventory_window = love.graphics.newImage("tiles/hud/inventory_window_2.png"),
			inventory_window_info = love.graphics.newImage("tiles/hud/hud_inventory_info.png"),

		},
		buttons = {
			examine = love.graphics.newImage("tiles/hud/button_examine.png"),
			inventory = love.graphics.newImage("tiles/hud/button_inventory.png"),
			help = love.graphics.newImage("tiles/hud/button_help.png"),
			nextgen = love.graphics.newImage("tiles/hud/hud_newgen.png"),
			close = love.graphics.newImage("tiles/hud/close.png"),

			inventory_slot = love.graphics.newImage("tiles/hud/inventory_slot_1.png"),
			inventory_action = love.graphics.newImage("tiles/hud/hud_inventory_action.png"),
			context_item = love.graphics.newImage("tiles/hud/hud_context_itemslot.png"),
			context_action = love.graphics.newImage("tiles/hud/hud_action_itemslot.png"),
		},
		boxes = {
			inventory_main = love.graphics.newImage("tiles/hud/hud_inventorytextbox.png"),
			inventory_grid = love.graphics.newImage("tiles/hud/hud_inventorygrid.png"),
		},
		menus = {
			menu_action = love.graphics.newImage("tiles/hud/menu_actions.png"),

		},
		items = {
			natural = {
				seeds = {
					--grass
					meadow_foxtail = love.graphics.newImage("tiles/grass/icons/seed_meadowfoxtail.png"),
					--flowers
					wild_lupin = love.graphics.newImage("tiles/flowers/icons/seed_wildlupin.png"),
					field_poppy = love.graphics.newImage("tiles/flowers/icons/seed_fieldpoppy.png"),
					--trees
					red_maple = love.graphics.newImage("tiles/trees/icons/seed_redmaple.png"),
				},
			},
		},
	},
	cursors = {
		default = love.graphics.newImage("tiles/cursors/crs_default.png"),
		tileselect = love.graphics.newImage("tiles/cursors/crs_tileselect.png"),
	},

}
Is there some way this would better work out as a sprite batch? Can I take an image from a spritebatch and apply a quad to it?

Re: Spritebatch explanation

Posted: Mon Mar 15, 2010 8:58 am
by pekka
Every time you create a SpriteBatch with the newSpriteBatch function, you need to specify an image. Since the SpriteBatch object methods don't provide a way of adding new images, this means that for each batch, you only get one image. It seems to be limiting, but the solution for drawing different things with one batch is to make a mosaic of images and store it as one image, and to then use Quads to pick the right subimages to draw.

SpriteBatches are good for storing drawing operations that will often be repeated but which don't vary between frames. You can use them, for example, to draw a section of the background. Assuming the background does not change, its tiles will all be the same and in the same relative positions to each other. Then you need only provide the location of the whole section (that is, the batch) when drawing it, and the SpriteBatch code in LÖVE will take care of placing all the tiles in the right positions. You only need to specify these positions once, when creating the SPriteBatch and adding the Quads into it.

SpriteBatches use a special internal representaiton for the drawing commands, and thus should be faster that doing the same drawing by one call to draw or drawq at a time. You can try measuring this difference by writing a program that times a lot of drawing operations done in both ways and compares the results. (The difference is probably slight if you draw only a few images.) You can also read the LÖVE sources to see how they're implemented, if you are familiar with C++ and OpenGL.

Re: Spritebatch explanation

Posted: Mon Mar 15, 2010 7:26 pm
by zugamifk
Thank you, that was extremely helpful.

This is like a godsend for my tile based RPG project. Do I draw spritebatches with love.graphics.draw? Also, can I remove a specific image from a spritebatch and replace it with something else?

Mamny thanks for the answer by the way, that explained it to me perfectly.

Re: Spritebatch explanation

Posted: Tue Mar 16, 2010 5:36 am
by pekka
SpriteBatch is a Drawable object, so you call love.graphics.draw to draw it. Unfortunately, there is no method for removing data from a batch, but only a way to remove all the sprites: SpriteBatch:clear.