love2d教程9--角色移动

本来该早点写完的,可是由于一些小问题,拖到现在了,不过也好,我决定以后使用middleclass来实现

面向对象.角色移动也就是对动画的进一步加强,方便调用.

先上图,说明代码移植自以前学习hge时在网上下载的教程,不知原作者,如果你知道

请告知,我会补上.(数字1切换行走,2切换跑步,注意是键盘字母区的1,2)

 对于rpg游戏,角色肯定是经常用到,因此我们需要一个角色类.

require('Anim')
require('middleclass')

RpgRole=class('RpgRole')

--方向常数
RpgRole.static.DOWN=1
RpgRole.static.LEFT=2
RpgRole.static.RIGHT=3
RpgRole.static.UP=4
RpgRole.static.LEFTDOWN=5
RpgRole.static.RIGHTDOWN=6
RpgRole.static.LEFTUP=7
RpgRole.static.RIGHTUP=8

--tex 为Image类型,nfrmes一幅图片中成套动作的帧数,如演示的图片有64个动作,但一套动作里的帧数是8
--fps,每秒播放的帧数,w帧的宽,h帧的高
function RpgRole:initialize(tex,nframes,FPS,w,h)
    self.direction=RpgRole.DOWN
    self.role={}
    --这里的8表示八个方向,每个方向一个role,即anim
    for i=1,8 do
        self.role[i]=Anim:new(tex,nframes,FPS,0,(i-1)*h,w,h)
    end
end



--下面的-1表示改状态和原来一样,后面的也是
function RpgRole: update(dt,dir)
    dir=dir or -1
    if (dir == self.direction or dir== -1) then
        self.role[self.direction]:update(dt)
    else
        self.setDirection(dir)

    end
end

function RpgRole: stopAll()
    for i=1,8 do
        self.role[i]:stop()
    end
end

function RpgRole: move(speed,dt)
    self.speed=speed
    --就是一个switch case语句
    local dir={
    [RpgRole.UP]=function() self.roleY =self.roleY  - self.speed * dt end ,
    [RpgRole.DOWN]=function() self.roleY =self.roleY  +  self.speed * dt end  ,
    [RpgRole.LEFT]=function() self.roleX =self.roleX  -  self.speed * dt end  ,
    [RpgRole.RIGHT]=function() self.roleX =self.roleX +   self.speed * dt end ,
    [RpgRole.LEFTUP]=function() self.roleX , self.roleY =
        (self.roleX -   self.speed * dt),(self.roleY  -  self.speed * dt) end,
    [RpgRole.LEFTDOWN]=function() self.roleX , self.roleY =
        (self.roleX -   self.speed * dt),(self.roleY  +  self.speed * dt) end,
    [RpgRole.RIGHTUP]=function() self.roleX ,self.roleY =
        (self.roleX +  self.speed * dt),(self.roleY  - self.speed * dt ) end,
    [RpgRole.RIGHTDOWN]=function() self.roleX,self.roleY  =
        (self.roleX +  self.speed * dt),(self.roleY  +  self.speed * dt) end,

    }
    --这里就是执行条件了
    dir[self.direction]()
end
--调用anim的play方法,从第一帧开始播放,实际是设置播放起始帧为1
function RpgRole: play(dir)
    self.direction=dir
    self.role[dir]:play()
end

function RpgRole: render(x ,y)
    x=x or -1
    y=y or -1
    if (x == -1 or y == -1) then
        self.role[self.direction]:render(self.roleX, self.roleY)
    else
        self.roleX = x
        self.roleY = y
        self.role[self.direction]:render(x, y)
    end
    --调试输出
    if(self.debug==true) then
    love.graphics.print("x " .. self.roleX .. " y " .. self.roleY,10,10)
    end
end
--设置方向
function RpgRole:setDirection(dir)
    if (self.direction ~= dir) then
        self.role[self.direction]:stop()
        self.direction = dir
        self.role[self.direction]:play()
    end
end

--设置角色在屏幕的坐标
function RpgRole: setXY(x,y)
        self.roleX = x
        self.roleY = y
end

function RpgRole: getX()
    return self.roleX
end

function RpgRole: getY()
    return self.roleY
end

function RpgRole: getDirection()
    return self.direction
end

 

运动时的逻辑不是很复杂,不过写起来很长的if...else...

运动的原则是方向键按下,朝此方向运动;方向键弹起,停止运动;

若改变运动方向,先保存坐标,停止播放原方向的动画,设置为新方向,

当然还要结合运动的状态是行走,站立,跑步来分类处理.

main.lua

require('Anim')
require('RpgRole')
--角色状态
local ROLESTATE_STAND= 0
local ROLESTATE_WALK= 1
local ROLESTATE_RUN= 2
--运动状态
local MODE_WALK= 1
local MODE_RUN= 2

local movemode=nil
local ROLESTATE=nil
local currdir=RpgRole.DOWN

function love.load()
    font=love.graphics.newFont(16)
    love.graphics.setFont(font)
    imgS=love.graphics.newImage("assets/stand.png")
    imgW=love.graphics.newImage("assets/walk.png")
    imgR=love.graphics.newImage("assets/run.png")
    --参数为: 图片,一套动作的帧数,播放速度,帧宽,帧高
    role_stand=RpgRole:new(imgS,8,8,84,108)
    role_walk=RpgRole:new(imgW,8,8,84,108)
    role_run=RpgRole:new(imgR,8,8,84,108)

    --打开输出
    role_stand.debug=true
    role_stand.debug=true
    role_stand.debug=true

    --注意要先设置方向,再设置位置,因为位置是绑定在方向上的
    role_stand:setDirection(currdir)
    role_stand:setXY(400,300)

    role_state = ROLESTATE_STAND;
    movemode = MODE_WALK;


end

function love.update(dt)

    local dir=-1
    --检测键盘设置运动模式,
    if(love.keyboard.isDown("1")) then
    movemode=MODE_WALK
    end
    if(love.keyboard.isDown("2")) then
    movemode=MODE_RUN
    end

    --检测键盘,设置运动方向
    if(love.keyboard.isDown("left")) then
        if(love.keyboard.isDown("up")) then
            dir=RpgRole.LEFTUP
        elseif(love.keyboard.isDown("down")) then
            dir=RpgRole.LEFTDOWN
        else
            dir=RpgRole.LEFT
        end

    elseif(love.keyboard.isDown("right")) then
        if(love.keyboard.isDown("up")) then
            dir=RpgRole.RIGHTUP
        elseif(love.keyboard.isDown("down")) then
            dir=RpgRole.RIGHTDOWN
        else
            dir=RpgRole.RIGHT
        end

    elseif(love.keyboard.isDown("up")) then
        dir=RpgRole.UP
    elseif(love.keyboard.isDown("down")) then
        dir=RpgRole.DOWN
    end


    if (dir == -1) then
        --没有方向键按下,变为站立状态
        if (role_state == ROLESTATE_WALK) then
            role_stand:setXY(role_walk:getX(), role_walk:getY())
            role_stand:play(role_walk:getDirection())
            role_walk:stopAll()
            role_state = ROLESTATE_STAND
        elseif (role_state == ROLESTATE_RUN) then
            role_stand:setXY(role_run:getX(), role_run:getY())
            role_stand:play(role_run:getDirection())
            role_run:stopAll()
            role_state = ROLESTATE_STAND
        else
            role_stand:update(dt)
        end
    --有方向键按下,且为行走状态
    elseif(movemode == MODE_WALK) then
        -- 状态一致
        if (role_state == ROLESTATE_WALK) then
            role_walk:setDirection(dir)
            role_walk:move(50, dt)
            role_walk:update(dt)
        --跑步状态变为行走,先停止跑步,从行走的第一帧开始播放动画,并设置行走状态
        elseif (role_state == ROLESTATE_RUN) then
            role_walk:setXY(role_run:getX(), role_run:getY())
            role_walk:play(dir)
            role_run:stopAll()
            role_state = ROLESTATE_WALK
        else
            role_walk:setXY(role_stand:getX(), role_stand:getY())
            role_walk:play(dir)
            role_stand:stopAll()
            role_state = ROLESTATE_WALK
        end
    --有方向键按下,且为跑步状态
    else
        -- 状态一致
        if (role_state == ROLESTATE_WALK) then
            role_run:setXY(role_walk:getX(), role_walk:getY())
            role_run:play(dir)
            role_walk:stopAll()
            role_state = ROLESTATE_RUN
        elseif (role_state == ROLESTATE_RUN) then
            role_run:setDirection(dir)
            role_run:move(90, dt)
            role_run:update(dt)
        else
            role_run:setXY(role_stand:getX(), role_stand:getY())
            role_run:play(dir)
            role_stand:stopAll()
            role_state = ROLESTATE_RUN
        end
    end

 end

function love.draw()
    love.graphics.print("1--walk,2--run",10,25)
    if (role_state == ROLESTATE_STAND) then
        role_stand:render()
    elseif (role_state == ROLESTATE_WALK) then
        role_walk:render()
    else
        role_run:render()
    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 @ 2012-12-28 18:41  半山th  阅读(2099)  评论(4编辑  收藏  举报