love2d教程12--画布和批量绘图

这次主要介绍两个批量绘图的结构canvas和spritebatch,到此love.graphics模块的数据类型就基本介绍完了.
canvas(0.8之前是framebuffer,现已不用)
画布用于离屏渲染,你可以认为它是一个不可见的屏幕,能在上面绘图,但是玩家看不见它,直到你把它绘制到
实际的屏幕上。它也被称为“渲染到纹理”。把不常动的物体(如背景)绘制到画布上,之后把整个画布绘制到屏幕上,可以提高效率.
spritebatch
批量精灵(我直译的),可以仅使用一次draw绘制单一图像的任意数量副本。把图像纹理集 (包含许多独立图像的单个图像)添加quad到批处理,
可以绘制纹理集中的的不同子图(就是前面文章中我说的图块)。

先看一下canvas的使用
1创建
canvas = love.graphics.newCanvas( width, height ) --若不带参数则是窗口大小
2在画布上绘图
一种是
canvas:renderTo( func ) --func是函数
另一种
love.graphics.setCanvas( canvas )
func()
love.graphics.setCanvas()
3显示,在love.draw()回调函数里
love.graphics.draw(canvas,0,0)

注意不要在love.draw()和love.update(dt)函数里在canvas上画图,否则速度比不用canvas还慢.
canvas里还有一个比较重要的函数setWrap(),它用来设置如何处理变换后的canvas.有两种模式
"clamp"变换后超出canvas边界的部分将消失,"repeat"变换后超出的部分会在另一边绘制.

再看spritebatch的使用
1创建
mybatch=love.graphics.newSpriteBatch(img,number) --number最大为1000
2向batch里添加要绘制的图像
--添加普通图片
id = mybatch:add( x, y, r, sx, sy, ox, oy, kx, ky) --与love.graphics.draw()参数意义相同
--或添加quad
id=mybatch:addq( quad,x, y, r, sx, sy, ox, oy, kx, ky)

注意这里的quad是创建spritebatch的参数img中的,id为数字,编号从0开始,添加一次增一.
(lua都是以1为起始,而且love里其它地方也是,可这里竟然从0开始,真是让我意外)
3显示,在love.draw()回调函数里
love.graphics.draw(mybatch,0,0)

spritebatch其它函数还有bind(),即把spirebatch绑定到内存.当更新spirtebatch里内容时,使用bind()
可以提高效率,用法看wiki;setq()更换编号为id的quad.

例子如下,按"c"切换canvas和spritebatch,按"空格"打开测试,可以看到使用canvas比直接绘图几乎快了一倍.不过
spritebatch的使用bind和不用bind没有变化,可能bind只有当更新内容时有效果,或者我用错地方了,希望读者指正.
main.lua (canvas测试修改自love官方论坛里TechnoCat的framebuffer)

lg=love.graphics

function testCanvas()
  img= lg.newImage("tuzi.png")

  translate = {x=0, y=0}
  scene = {}
  scene.width = 2048
  scene.height = 2048

  --初始化Canvas
  myCanvas = lg.newCanvas(scene.width, scene.height)

  --创建随机物体
  imageSet = {} --为图片坐标集合
  for i = 1, 10000 do
    local entry = {}
    entry.x = math.random(scene.width-128)
    entry.y = math.random(scene.height-128)
    imageSet[i] = entry
  end
  --设置绘图操作
  lg.setCanvas(myCanvas)
  for _,v in ipairs(imageSet) do
    lg.draw(img, v.x, v.y)
  end
  lg.setCanvas()
   --另一种方法
  --[[
  myCanvas:renderTo(
      function()
        for _,v in ipairs(imageSet) do
          lg.draw(image, v.x, v.y)
        end
      end
  )
  --]]
end

function drawCanvas()
  lg.push()
  lg.translate(translate.x, translate.y)
  if testOn then
    lg.draw(myCanvas, 0, 0)
  else
    for _,v in ipairs(imageSet) do
      lg.draw(img, v.x, v.y)
    end
  end
  lg.pop()

 local  fps = love.timer.getFPS()
  if testOn then
    lg.setCaption("开启canvas时FPS:" ..fps,0,0)
  else
  lg.setCaption("关闭canvas时FPS:" ..fps,0,0)
  end
end


function testBatch()
    tex=lg.newImage("run.png")
      quad={}
      local w,h=84,108
    local texW,texH=tex:getWidth(),tex:getHeight()
    local col,row=texW/w,texH/h
    for i=1,row do
      for j=1,col do
      table.insert (quad,lg.newQuad((j-1)*w,(i-1)*h,w,h,texW,texH))
      end
    end
    --创建512个需要绘制的图片
    mySprite = lg.newSpriteBatch( tex,512)
end

function drawBatch()
  if testOn then
      mySprite:bind()
      for i=1,8 do
        for j=1,64 do
          --84,108为图块的宽和高,864为图片的高
          mySprite:setColor(math.random(0,255),math.random(0,255),math.random(0,255))
          mySprite:addq(quad[j],(j-1)*84,(j-1)*104+(i-1)*864,0,1,1,0,0,0,0)
        end
      end

      mySprite:unbind()

  else
   for i=1,8 do
        for j=1,64 do
          --84,108为图块的宽和高,864为图片的高
          mySprite:setColor(math.random(0,255),math.random(0,255),math.random(0,255))
          mySprite:addq(quad[j],math.ceil(j%8-1)*84,math.ceil(j/8-1)*104+(i-1)*864,0,1,1,0,0,0,0)
        end
    end
  end
  lg.draw(mySprite,0,0)
  local  fps = love.timer.getFPS()
  if testOn then
  lg.setCaption("使用bind时fps:" .. fps )
  else
  lg.setCaption("关闭bind时fps:" .. fps)
  end
end

function love.load()
  testOn=false --testOn为false时关闭canvas/spritebatch的bind,为true时开启
  mode=false  --mode为false测试spritebatch,为true测试canvas
  testCanvas()
  testBatch()
end



function love.update(dt)

  if love.keyboard.isDown("left") then
    translate.x = translate.x + 1000*dt
  elseif love.keyboard.isDown("right") then
    translate.x = translate.x - 1000*dt
  end

  if love.keyboard.isDown("up") then
    translate.y = translate.y + 1000*dt
  elseif love.keyboard.isDown("down") then
    translate.y = translate.y - 1000*dt
  end

end

function love.draw()
  lg.print("press <c> change mode, press <space> open stest",10,10)
    if mode then
     drawCanvas()
    else
      drawBatch()
    end


  lg.setCaption("FPS:" .. love.timer.getFPS() )
end

function love.keypressed(k)
  if k=="c" then
    mode = not mode
  end
  if k==" " then
    testOn= not testOn
  end
end

代码下载,已clone的直接git pull
git clone git://gitcafe.com/dwdcth/love2d-tutor.git
或git clone https://github.com/dwdcth/mylove2d-tutor-in-chinese.git

posted @ 2013-01-03 13:20  半山th  阅读(1458)  评论(1编辑  收藏  举报