首页 > 解决方案 > 如何让玩家在 Lua 中以流畅和标准的方式跳跃?

问题描述

学习编程游戏四年了,但我仍然不知道玩家如何正确跳跃(我只需要平台游戏的基本跳跃方法但我仍然不会)。我在网上搜了很多教程,但是很少,或者是的,那些语言和Lua不一样。

过去4年,在做平台游戏的时候,为了让角色跳跃,我尝试了很多方法,每一种都不完整,还有一个bug(比如玩家穿墙,卡住,跳跃的时候卡在玩家头上的墙,以及许多其他奇怪的东西)。

现在我将介绍我最近尝试过的方法。这是我的播放器文件:我正在使用 bump.lua 库的支持。访问这里的库:https ://github.com/kikito/bump.lua 。

这是我的文件:

Knight = Object:extend()

function Knight:new(x, y)
    --- properties
    self.x = x
    self.y = y
    self.width = 36
    self.height = 48
    -----
    self.scaleX = 1
    ---- art 
    self.sprite = love.graphics.newImage("sources/art/player/knight/knight.png")
    self.grid = anim8.newGrid(48, 81, self.sprite:getWidth(), self.sprite:getHeight())
    self.animations = {}
    self.animations.idle = anim8.newAnimation(self.grid(1, 1, 2, 1, 3, 1, 2, 1), 0.1)
    self.animations.walk = anim8.newAnimation(self.grid(4, 1, 5, 1, 6, 1, 7, 1, 8, 1, 4, 1), 0.05)
    self.animations.jump = anim8.newAnimation(self.grid(9, 1), 0.1)
    self.anim = self.animations.idle
    ----- 
    ----- physics value
    self.xVelocity = 0
    self.yVelocity = 0
    self.onGround = false
    self.gravity = 10
    --- add to bump world 
    world:add(self, self.x, self.y, self.width, self.height)
end

local knightFilter = function(item, other)
  if     other.isCoin   then return 'cross'
  elseif other.isBlock   then return 'slide'
  elseif other.isExit   then return 'touch'
  elseif other.isSpring then return 'bounce'
  end
  -- else return nil
end

function Knight:update(dt)
    if love.keyboard.isDown('a') then 
        self.xVelocity = -200
        self.scaleX = -1
    elseif love.keyboard.isDown('d') then
        self.xVelocity = 200
        self.scaleX = 1
    else
        self.xVelocity = 0
    end

    if self.onGround == false then self.yVelocity = self.yVelocity + self.gravity end

    local goalX, goalY = self.x + self.xVelocity * dt, self.y + self.yVelocity * dt
    local actualX, actualY, cols, len = world:move(self, goalX, goalY, knightFilter)
    self.x, self.y = actualX, actualY
    self.onGround = false
    for i = 1, len do
        local other = cols[i].other
        if other.isBlock then
            self.onGround = true
        else
            self.onGround = false
        end
    end

    self.anim:update(dt)
end

function Knight:draw()
    love.graphics.setColor(1, 1, 1)
    self.anim:draw(self.sprite, math.floor(self.x) + 18, math.floor(self.y) + 4, nil, self.scaleX, 1, 24, 36)
    love.graphics.rectangle("line", self.x, self.y, self.width, self.height)
end

这是main.lua(你只需要注意函数love.keypressed ()love.keyreleased ()):

Object = require "libs/classic"
bump = require "libs/bump"
anim8 = require "libs/anim8"

function love.load()
    world = bump.newWorld()
    addPlayer("knight")
    variableandrequire()
    --- gameplay level1
    loadDataLevel1()
    buildMap()
    -------
end

function variableandrequire()
    listOfBlocks = {}
    -----
    require "entities/blocks/block"
end

function love.update(dt)
    dt = math.min(dt, 0.025)
    player:update(dt)
end

function love.draw()
    player:draw()
    drawBlocks()
end

function drawBlocks()
    for i, v in ipairs(listOfBlocks) do
        v:draw()
    end
end

function addPlayer(name)
    local character = name
    if character == "knight" then
        require "entities/characters/knight"
        player = Knight (100, 100)
    end
end

function loadDataLevel1()
    map = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
           {1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},}

end

function buildMap()
    --id : 1.grass 2.dirt
    for y = 1, 10 do
        for x = 1, 15 do
            if map[y][x] == 1 then
                table.insert(listOfBlocks, Block((x - 1) * 64, (y - 1) * 64, 1))
            elseif map[y][x] == 2 then
                table.insert(listOfBlocks, Block((x - 1) * 64, (y - 1) * 64, 2))
            end
        end
    end
end

function love.keypressed(key) 
    if key == 'w' then
        if player.onGround then
            player.yVelocity = -350
            player.onGround = false
        end
    end
end

function love.keyreleased(key)
    if key == 'w' then
        if player.yVelocity < -60 then player.yVelocity = -60 end
    end
end 

我遇到了以下bug:当玩家自由落体时,下落速度还可以,但是如果玩家站在一个方块上,然后慢慢按下左或右按钮直到它落下(然后玩家触摸关闭墙边),下落的速度非常快,当玩家靠近墙站立并跳跃时,玩家似乎紧贴着墙慢慢爬上去,虽然墙远高于跳跃高度。

我认为这是我的转储方式。因为它会产生很多错误,一个接一个。当然,我的工作方式从来都不是完美的。如果没有人教,我这辈子都不会知道一种标准的方法。

我很乐意为你分享一个标准和基本的跳跃方法(我不需要太高),就像今天大多数平台游戏一样,跳跃看起来很流畅(我很欣赏这种方式)。同样重要的是,它是在 Lua 中执行的。

标签: lualove2d

解决方案


推荐阅读