love2d教程5--摄相机1视角跟随玩家
这篇教程来自wiki的Tutorial:Cameras的阅读笔记,有些没看懂,先写一部分.
Part 1: The Basics
http://nova-fusion.com/2011/04/19/cameras-in-love2d-part-1-the-basics/
Part 2: Parallax Scrolling
http://nova-fusion.com/2011/04/22/cameras-in-love2d-part-2-parallax-scrolling/
Part 3: Movement Bounds
http://nova-fusion.com/2011/05/09/cameras-in-love2d-part-3-movement-bounds/
作者为BlackBulletIV,感想他的好教程,大家可以到他的网站看看
有很多非常好的love2d和lua文章,他的github https://github.com/BlackBulletIV,也有很多好东西
love2d的坐标系统变换有三个函数
love.graphics.translate( dx, dy ) --平移变换,变换后坐标为x+dx,y+dy
love.graphics.rotate( angle ) --旋转变换,逆时针旋转angle弧度
love.graphics.scale( sx, sy ) --缩放变换,参数大于1会放大,小于1则缩小,0没意义.
整个坐标系都会变换,当为负数时会左右/上下颠倒.
首先介绍坐标系统状态的保存与恢复.
push 首先保存绘图前的状态,pop用push保存的状态.
下面是例子,你可以试试注释掉部分函数.
function love.draw() --如果把push和pup注释,你会看到它们挤在一起 love.graphics.push() love.graphics.scale(2, 2) love.graphics.print("scaled text", 50, 50) love.graphics.pop() love.graphics.print("normal text", 50, 50) end
摄相机的原理就是让视角和玩家相对静止,
地图向相反方向移动,所以我们把地图的
初始坐标减去某个坐标差就得到了地图
的正确位置.
现在我们创建一个摄相机类camera
camera = {} --平移变换的x,y偏移 camera._x = 0 camera._y = 0 --缩放变换的x,y系数 camera.scaleX = 1 camera.scaleY = 1 --旋转变换的角度 camera.rotation = 0
由于坐标变换时每次都要
love.graphics.push()
--变换函数的代码
love.graphics.pup()
可以写个函数把它们统一,如下
--保存坐标系统
function camera:set() love.graphics.push() --self前的"-"表示负号 love.graphics.rotate(-self.rotation) love.graphics.scale(1 / self.scaleX, 1 / self.scaleY) love.graphics.translate(-self._x, -self._y) end --恢复保存的坐标系统 function camera:unset() love.graphics.pop() end
为什么都是负的呢? 如果物体不和摄相机一同移动,让
其坐标落在摄相机后面(-rotation,-x,-y);远处的物体运动慢,近
处的运动快,远处物体小,近处物体大(-rotation).这和生活中坐
车是一样的道理.
这样当需要变换坐标时,先set,变换完后unset恢复,就方便多了.
下面我们来实现视角跟随玩家
这里只涉及平移,当玩家向左移动时,坐标系统向右平移.
如果我们在平移后画地图和玩家,由于整体都向右移动了,如果让坐标系统平移的距离和玩家向左
运动的距离相等,那么玩家的实际运动距离就为0了.
即让camera._x=player.X(本次)-player.X(上次)
显然玩家的坐标在不断的变化,我们可以直接在update回调函数里加上一句:
camera:setOffset(player.X-player.X(初始), player.Y-player.Y(初始))
因为玩家已经不动了,所以直接让player.X(上次)=player.X(初始),
在代码里你会看到(400,300)那是我把player的坐标设为了(400,300)了.
camera:setOffse()的代码如下:
--设置摄相机的x偏移
function camera:setX(value)
self._x = value
end
--设置摄相机的y偏移
function camera:setY(value)
self._y = value
end
function camera:setOffset(x, y)
if x then self:setX(x) end
if y then self:setY(y) end
end
完整的代码如下:我添加了玩家的放大,缩小,旋转事件,可以用鼠标操作.
代码下载:
http://pan.baidu.com/share/link?shareid=132873&uk=1913510140
main.lua
tilemap=require('tilemap') require('maptool') require('camera') --地图在屏幕上显示的左上角x,y坐标 tilemap._X,tilemap._Y=-80,-180 tilemap._rot=0 tilemap._sx=1 tilemap._sy=1 quadtable={} player={} player.X=400 player.Y=300 player.rot=0 player.sx=1 player.sy=1 speed=300 function love.load() image=love.graphics.newImage("assets/" .. tilemap["tilesets"][1].name ..tilemap["properties"]["format"]) makeQuad(tilemap) player.img=love.graphics.newImage("assets/player.png") mainfont = love.graphics.newFont( 20 ) end function love.draw() camera:set() drawMap(tilemap,image) love.graphics.draw(player.img,player.X,player.Y, player.rot,player.sx,player.sy,player. --设置图片的中心 img:getWidth() / 2,player.img:getHeight() / 2) camera:unset() love.graphics.setFont(mainfont); love.graphics.print("player.X=" .. player.X .. " player.Y=" .. player.Y,20,20) end function love.update(dt) --平移 if(love.keyboard.isDown("up")) then player.Y=player.Y-speed*dt end if(love.keyboard.isDown("down")) then player.Y=player.Y+speed*dt end if(love.keyboard.isDown("left")) then player.X=player.X-speed*dt end if(love.keyboard.isDown("right")) then player.X=player.X+speed*dt end --旋转 if(love.keyboard.isDown("j")) then player.rot=player.rot-0.5 end if(love.keyboard.isDown("l")) then player.rot=player.rot+0.5 end --缩放 if (love.keyboard.isDown("i")) then player.sx=player.sx+0.1 player.sy=player.sy+0.1 end if (love.keyboard.isDown("k")) then player.sx=player.sx-0.1 player.sy=player.sy-0.1 end --设置摄相机的偏移 camera:setOffset(player.X-400, player.Y-300) end function love.keypressed(key) end --鼠标事件 function love.mousepressed(x,y,button) if button=="wd" then player.sx=player.sx-0.1 player.sy=player.sy-0.1 end if button=="wu" then player.sx=player.sx+0.1 player.sy=player.sy+0.1 end end
camera.lua
camera = {} --平移变换的x,y偏移 camera._x = 0 camera._y = 0 --缩放变换的x,y系数 camera.scaleX = 1 camera.scaleY = 1 --旋转变换的角度 camera.rotation = 0 --保存变换前的坐标系统,并进行平移,缩放,旋转变换 function camera:set() love.graphics.push() love.graphics.rotate(-self.rotation) love.graphics.scale(1 / self.scaleX, 1 / self.scaleY) love.graphics.translate(-self._x, -self._y) end --恢复保存的坐标系统 function camera:unset() love.graphics.pop() end function camera:rotate(dr) self.rotation = self.rotation + dr end function camera:scale(sx, sy) sx = sx or 1 self.scaleX = self.scaleX * sx self.scaleY = self.scaleY * (sy or sx) end --设置摄相机的x偏移 function camera:setX(value) self._x = value end --设置摄相机的y偏移 function camera:setY(value) self._y = value end function camera:setOffset(x, y) if x then self:setX(x) end if y then self:setY(y) end end
作者:半山
出处:http://www.cnblogs.com/xdao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。