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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM