I'm trying to implement slope on my platform game.
I have already implemented the slope (left / right) and work well.
I have only one problem, when the player down the slope (left / right), this does not follow the slope.
I hope you can help me.
preview
This is the code I use to check the slope:
Code: Select all
-- check if there is a collision with a slope
function checkForSlopes()
--
-- left slope.
--
local xtile = math.floor((player.x + ((tileMap.TileWidth / 2) - 2)) / tileMap.TileWidth);
local ytile = math.floor((player.y) / tileMap.TileHeight);
--
local ylerp = (ytile * tileMap.TileHeight) - (player.x - (xtile * tileMap.TileWidth));
if tileMap.map[ytile + 1][xtile] == 2 then ytile = ytile + 1; end
if tileMap.map[ytile][xtile] == 2 and player.ySpeed >= 0 then
--
ylerp = (ytile * tileMap.TileHeight) - (player.x - (xtile * tileMap.TileWidth));
if player.y >= ylerp then
player.onFloor = true;
--
player.y = ylerp;
player.ySpeed = 0;
end
--
end
--
-- right slope.
--
xtile = math.floor((player.x - ((tileMap.TileWidth / 2) - 2)) / tileMap.TileWidth);
ytile = math.floor((player.y) / tileMap.TileHeight);
--
if tileMap.map[ytile + 1][xtile] == 3 then ytile = ytile + 1; end
if tileMap.map[ytile][xtile] == 3 and player.ySpeed >= 0 then
--
ylerp = (ytile * tileMap.TileHeight) - (tileMap.TileWidth - (player.x - (xtile * tileMap.TileWidth)));
if player.y >= ylerp then
player.onFloor = true;
--
player.y = ylerp;
player.ySpeed = 0;
end
--
end
--
end
Code: Select all
-- vector2
-- =====================================================================
vector2 = {};
vector2.new = function(...)
local obj = {};
local a, b = ...;
--
obj.x = a or 0;
obj.y = b or 0;
--
return obj;
end
--
-- MathHelper
-- =====================================================================
function math.clamp(x, min, max)
return x < min and min or (x > max and max or x)
end
--
-- draw Slopes and collision
-- =====================================================================
-- left slope
function drawslopeLeft(x0, y0, x1, y1)
for i = 0, 32 do
love.graphics.line(x0 + i, y0, x1, y1);
end
end
-- right slope
function drawslopeRight(x0, y0, x1, y1)
for i = 0, 32 do
love.graphics.line(x0, y0 + i, x1, y1);
end
end
--
-- check if there is a collision with a slope
function checkForSlopes()
--
-- left slope.
--
local xtile = math.floor((player.x + ((tileMap.TileWidth / 2) - 2)) / tileMap.TileWidth);
local ytile = math.floor((player.y) / tileMap.TileHeight);
--
local ylerp = (ytile * tileMap.TileHeight) - (player.x - (xtile * tileMap.TileWidth));
if tileMap.map[ytile + 1][xtile] == 2 then ytile = ytile + 1; end
if tileMap.map[ytile][xtile] == 2 and player.ySpeed >= 0 then
--
ylerp = (ytile * tileMap.TileHeight) - (player.x - (xtile * tileMap.TileWidth));
if player.y >= ylerp then
player.onFloor = true;
--
player.y = ylerp;
player.ySpeed = 0;
end
--
end
--
-- right slope.
--
xtile = math.floor((player.x - ((tileMap.TileWidth / 2) - 2)) / tileMap.TileWidth);
ytile = math.floor((player.y) / tileMap.TileHeight);
--
if tileMap.map[ytile + 1][xtile] == 3 then ytile = ytile + 1; end
if tileMap.map[ytile][xtile] == 3 and player.ySpeed >= 0 then
--
ylerp = (ytile * tileMap.TileHeight) - (tileMap.TileWidth - (player.x - (xtile * tileMap.TileWidth)));
if player.y >= ylerp then
player.onFloor = true;
--
player.y = ylerp;
player.ySpeed = 0;
end
--
end
--
end
--
-- player
-- =====================================================================
player = {};
function player.load()
player.xSpeed = 0;
player.ySpeed = 0;
player.xSpeedMax = 800;
player.ySpeedMax = 800;
player.x = 4 * 32;
player.y = 3 * 32;
player.width = 32;
player.height = 32;
gravity = 2800;
player.onFloor = false;
player.runSpeed = 500;
player.jumpSpeed = -800;
end
-- Movement functions
function player.jump()
if player.onFloor then
player.ySpeed = player.jumpSpeed;
player.onFloor = false;
end
end
function player.moveRight()
player.xSpeed = player.runSpeed;
end
function player.moveLeft()
player.xSpeed = -1 * player.runSpeed;
end
function player.stop()
player.xSpeed = 0;
end
-- Do various things when the player hits a tile
function player:collide(event)
if event == "floor" then
player.ySpeed = 0;
player.onFloor = true;
end
if event == "ceiling" then
player.ySpeed = 0;
end
end
function player.update(dt)
local halfX = player.width / 2;
local halfY = player.height / 2;
-- apply gravity
player.ySpeed = player.ySpeed + (gravity * dt);
-- limit the player's speed
player.xSpeed = math.clamp(player.xSpeed, -player.xSpeedMax, player.xSpeedMax);
player.ySpeed = math.clamp(player.ySpeed, -player.ySpeedMax, player.ySpeedMax);
-- calculate vertical position and adjust if needed
local nextY = math.floor(player.y + (player.ySpeed * dt));
if player.ySpeed < 0 then -- check upward
if not(player.isColliding(player.x - halfX, nextY - halfY)) and not(player.isColliding(player.x + halfX - 1, nextY - halfY)) then
-- no collision, move normally
player.y = nextY;
player.onFloor = false;
else
-- collision, move to nearest tile border
player.y = nextY + map.tileHeight - ((nextY - halfY) % tileMap.TileHeight);
player.collide("ceiling");
end
elseif player.ySpeed > 0 then -- check downward
if not(player.isColliding(player.x - halfX, nextY + halfY)) and not(player.isColliding(player.x + halfX - 1, nextY + halfY)) then
-- no collision, move normally
player.y = nextY;
player.onFloor = false;
else
-- collision, move to nearest tile border
player.y = nextY - ((nextY + halfY) % tileMap.TileHeight);
player:collide("floor");
end
end
-- calculate horizontal position and adjust if needed
local nextX = math.floor(player.x + (player.xSpeed * dt));
if player.xSpeed > 0 then -- check right
if not(player.isColliding(nextX + halfX, player.y - halfY))
and not(player.isColliding(nextX + halfX, player.y + halfY - 1)) then
-- no collision
player.x = nextX;
else
-- collision, move to nearest tile
player.x = nextX - ((nextX + halfX) % tileMap.TileWidth);
end
elseif player.xSpeed < 0 then -- check left
if not(player.isColliding(nextX - halfX, player.y - halfY))
and not(player.isColliding(nextX - halfX, player.y + halfY - 1)) then
-- no collision
player.x = nextX;
else
-- collision, move to nearest tile
player.x = nextX + tileMap.TileWidth - ((nextX - halfX) % tileMap.TileWidth);
end
end
-- check all slope collider and responce.
checkForSlopes();
end
-- returns true if the coordinates given intersect a map tile
function player.isColliding(x, y)
-- get tile coordinates
local tileX, tileY = math.floor(x / tileMap.TileWidth), math.floor(y / tileMap.TileHeight);
-- grab the tile at given point
if tileMap.map[tileY][tileX] == 1 then
return true;
end
-- return true if the point overlaps a solid tile
return false;
end
function player.draw()
-- round our x, y values
local x, y = math.floor(player.x), math.floor(player.y)
-- draw the player
love.graphics.setColor(255, 0, 0, 200);
love.graphics.rectangle("fill", x - player.width / 2, y - player.height / 2, player.width, player.height);
love.graphics.setColor(255, 255, 255);
end
--
--Function love engine
-- =====================================================================
function love.load()
io.stdout:setvbuf("no");
--
tileMap = {};
tileMap.map = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
tileMap.TileWidth = 32;
tileMap.TileHeight = 32;
-- initialize player.
player.load();
hasJumped = false;
end
function love.update(dt)
-- check controls
if love.keyboard.isDown("right") then
player.moveRight();
end
if love.keyboard.isDown("left") then
player.moveLeft();
end
if (love.keyboard.isDown("x") or love.keyboard.isDown("up")) and not(hasJumped) then
hasJumped = true;
player.jump();
end
player.update(dt);
end
function love.keyreleased(key)
if key == "escape" then
love.event.push("quit") -- actually causes the app to quit
end
if (key == "right") or (key == "left") then
player.stop()
end
if (key == "x" or key == "up") then
hasJumped = false
end
end
function love.draw()
-- draw tile map.
drawTileMap();
-- draw player.
player.draw();
end
-- draw tile map.
function drawTileMap()
for y = 1, #tileMap.map do
for x = 1, #tileMap.map[1] do
love.graphics.setColor(0, 0, 255); -- blue color
--
if tileMap.map[y][x] == 1 then
love.graphics.rectangle("fill", x * tileMap.TileWidth, y * tileMap.TileHeight, tileMap.TileWidth, tileMap.TileHeight);
end
--
love.graphics.setColor(255, 255, 255);
love.graphics.setColor(0, 255, 0); -- green color
--
-- left slope.
if tileMap.map[y][x] == 2 then
drawslopeLeft(x * 32, (y * 32) + 32, (x * 32) + 32, (y * 32));
end
-- right slope.
if tileMap.map[y][x] == 3 then
drawslopeRight(x * 32, (y * 32), (x * 32) + 32, (y * 32) + 32);
end
love.graphics.setColor(255, 255, 255);
end
end
end