Page 1 of 1

Question about Spritebatch:setColor

Posted: Wed Jun 03, 2015 8:32 pm
by dartvalince
I tried searching here on the forum, but couldn't find a clear answer, or found posts of similar questions with no replies. I'm hoping someone can help me with this.

I am currently experimenting with using SpriteBatches to reduce the amount of draw calls I am producing in my current project/game. The game itself is simple, and relies on circles being drawn to the screen, all of different sizes, but as well different colors. I set out to make a sandboxed version of this using SpriteBatches to test it out, but I'm hitting a brick wall with the color part.

What i expect my code to do
  1. Create large canvas to draw a single circle to (large used so scaling doesn't look terrible)
  2. Draw circle to the canvas
  3. Get the ImageData from the canvas
  4. Create a new image based on the ImageData
  5. Create a new SpriteBatch using the new image created
  6. Create x # of circles and add them to the SpriteBatch. For each circle use SpriteBatch:setColor() to give it a random color
  7. Update movments of circles in the love.update() callback
  8. Draw the SpriteBatch to the screen
Step 6 above is where I'm having a problem. You can see in the code below, i use the following (sb is the SpriteBatch, lm is love.math):

Code: Select all

sb:setColor(lm.random(0, 255), lm.random(0, 255), lm.random(0, 255))
sb.set(  ... )
Now based on what is said on the wiki page, this should set the color for the next sprite added yes?
https://love2d.org/wiki/SpriteBatch:setColor wrote: Sets the color that will be used for the next add and set operations. Calling the function without arguments will clear the color.
However when I actually run this, all of the sprites are the same color everytime. Is there something i'm missing? or does the setColor method set the color for the SpriteBatch overall and not each one added?


Here is my code

Code: Select all

local lg = love.graphics
local lm = love.math
function love.load()
  font = love.graphics.newFont(20)
  love.window.setMode(1280, 720)

  --[[
    first create the canvas that a single
    circle will be drawn to
  --]]
  local cw = 100 -- canvas width
  local ch = 100 -- canvas height
  circleCanvas = lg.newCanvas(cw,ch)
  lg.setCanvas(circleCanvas)
    circleCanvas:clear()
    lg.setColor(255,255,255,100)
    lg.circle('fill', cw/2, ch/2, (cw/2) - 1)
    lg.setColor(255,255,255,255)
    lg.circle('line', cw/2, ch/2, (cw/2) -1 )
  lg.setCanvas()

  -- next, get the image data from the canvas
  circleImageData = circleCanvas:getImageData()

  --  now create an image from the ImageData object
  circleImg = lg.newImage(circleImageData)

  --  finally add the image to a new SpriteBatch
  sb = lg.newSpriteBatch(circleImg, 5000, 'stream')


  --[[
    To test the Spritebatch, we are going to create
    x# of circles with the for loop below, and store
    each circle in the circles table.  This will
    be used in the love.update() to move them
  ]]
  circles = {}

  --[[
   Adjust this value to test different number of circles
  and how it will affect the overall FPS
  --]]
  numCircles = 100

  --  Create the circles and add them to the SpriteBatch
  for i=1, numCircles, 1 do
    local circle = {}
    circle.x = lm.random(0, lg.getWidth())
    circle.y = lm.random(0, lg.getHeight())
    circle.radius = lm.random(10, 50)
    circle.velocity = {
      x = lm.random(-20, 20),
      y = lm.random(-20, 20)
    }

    circle.ox = circleImg:getWidth()/2
    circle.oy = circleImg:getHeight()/2
    circle.sx = ((circle.radius * 2)/circleImg:getWidth())
    circle.sy = ((circle.radius * 2)/circleImg:getHeight())
    circle.rotation = 0

    sb:bind()
      sb:setColor(lm.random(0, 255), lm.random(0, 255), lm.random(0, 255))
      circle.id = sb:add(circle.x, circle.y, circle.rotation, circle.sx, circle.sy, circle.ox, circle.oy, 0, 0)
    sb:unbind()

    table.insert(circles, circle)
  end


end

function love.update(dt)
  --  Update the x & y of each circle
  for i, circle in ipairs(circles) do
    circle.x = circle.x + (circle.velocity.x * dt)
    circle.y = circle.y + (circle.velocity.y * dt)
    sb:set(circle.id, circle.x, circle.y, circle.rotation, circle.sx, circle.sy, circle.ox, circle.oy, 0, 0)
  end
end

function love.draw()
  love.graphics.setFont(font)
  lg.draw(sb)
  lg.print('FPS: ' .. love.timer.getFPS(), 0, 0)

end
and attached is the game.love file for this

Re: Question about Spritebatch:setColor

Posted: Wed Jun 03, 2015 10:04 pm
by bartbes
Well, the phrasing might be awkward, but it affects all next adds and sets, so the first time love.update runs (which is before the first time love.draw runs), all sprites get set, and thus their colour changes to the last one specified using setColor.

Re: Question about Spritebatch:setColor

Posted: Wed Jun 03, 2015 11:17 pm
by dartvalince
That makes a ton of sense. So, there really wouldn't be any way of controlling the color of each individual item added to the spritebatch through set color. Technically, i only need two colors for the game, so I could do two separate spritebatchs. Would this hinder performance much, or is there a much better way of doing this?

Re: Question about Spritebatch:setColor

Posted: Thu Jun 04, 2015 8:02 am
by bartbes
There is a way, and before love.update they do all have different colours, if you want that to persist though, you need to call setColor with the right colours in love.update too.