Player Movement - Pythagorean formula - 8 directions

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
TheGuardian163
Prole
Posts: 2
Joined: Fri Dec 11, 2015 5:54 pm

Player Movement - Pythagorean formula - 8 directions

Post by TheGuardian163 »

I was following a space invaders tutorial on youtube (just started learning Lua) and deciding to play around instead of following it

You can move in 8 different directions using the arrow keys, you can sprint using the Z key and shoot using the X key (only upwards)

I used pythagorean formula to get the right speed when going on a 'combined' direction (the diagonal of a square is longer than it's height, so doing "player.y = player.speed / 2" and "player.x = player.speed / 2" made the player move faster than it should

I'd like to learn about structuring my code better - how could I make it cleaner?

Here's the code:
http://pastebin.com/VDSHsbSL
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Player Movement - Pythagorean formula - 8 directions

Post by airstruck »

I'd get the x input and y input as values in (-1, 0, 1), create a unit vector from that, and scale it by the desired speed. Something like this maybe:

Code: Select all

-- this normalizes and then scales a vector
local function setVectorLength (vx, vy, length)
    local currentLength = math.sqrt(vx * vx + vy * vy)
    return vx / currentLength * length, vy / currentLength * length
end

local function getInputX ()
    local value = 0
    if love.keyboard.isDown("left") then
        value = value - 1
    end
    if love.keyboard.isDown("right") then
        value = value + 1
    end
    return value
end

local function getInputY ()
    local value = 0
    if love.keyboard.isDown("up") then
        value = value - 1
    end
    if love.keyboard.isDown("down") then
        value = value + 1
    end
    return value
end

-- inside update...

local speed = love.keyboard.isDown("z") and player.fastSpeed or player.slowSpeed
local vx, vy = setVectorLength(getInputX(), getInputY(), speed)

player.x = player.x + vx -- * dt
player.y = player.y + vy -- * dt
User avatar
Ortimh
Citizen
Posts: 90
Joined: Tue Sep 09, 2014 5:07 am
Location: Indonesia

Re: Player Movement - Pythagorean formula - 8 directions

Post by Ortimh »

For the sake of simplifying everything I'd use square root of 2.
For me this is the code that looks clean:

Code: Select all

local sqrt2 = math.sqrt(2)

function love.load()
	player = {
		x = 0,
		y = 525,
		bullets = {},
		cooldown = 0,
		speed = {
			normal = 120,
			fast = 240
		},
		fire = function()
			if (player.cooldown <= 0) then
				player.cooldown = 45
				
				table.insert(player.bullets, {
					x = player.x + 30,
					y = player.y - 30
				})
			end
		end
	}
end

function love.update(dt)
	player.cooldown = player.cooldown < 0 and 0 or player.cooldown - 120 * dt
	
	local speed = love.keyboard.isDown("z") and player.speed.fast or player.speed.normal
	local velocityX = love.keyboard.isDown("left") and -speed or (love.keyboard.isDown("right") and speed or 0)
	local velocityY = love.keyboard.isDown("up") and -speed or (love.keyboard.isDown("down") and speed or 0)
	local diagonal = velocityX ~= 0 and velocityY ~= 0
	
	player.x = player.x + (diagonal and velocityX / sqrt2 or velocityX) * dt
	player.y = player.y + (diagonal and velocityY / sqrt2 or velocityY) * dt
	
	if (love.keyboard.isDown("x")) then
		player.fire()
	end
	
	for index, bullet in ipairs(player.bullets) do
		if (bullet.y < -10) then
			table.remove(player.bullets, index)
		else
			bullet.y = bullet.y - 720 * dt
		end
	end
end

function love.draw()
	love.graphics.setColor(140, 0, 140)
	love.graphics.rectangle("fill", player.x, player.y, 60, 40)
	love.graphics.setColor(255, 255, 125)
	
	for index, bullet in ipairs(player.bullets) do
		love.graphics.rectangle("fill", bullet.x, bullet.y, 2, 30)
	end
end
Lovingsoul1337
Citizen
Posts: 54
Joined: Fri Feb 21, 2020 1:26 pm

Re: Player Movement - Pythagorean formula - 8 directions

Post by Lovingsoul1337 »

Code: Select all

--player

local gameObject = require('gameObjects/gameObject')
local player = gameObject:new()

--player sprite

player.image = love.graphics.newImage('assets/testRectangle.png')

--class vars

player.x = 0
player.y = 0
player.speed = 0
player.acceleration = 15
player.deceleration = 7
player.maxSpeed = 25
player.velocityX = 0
player.velocityY = 0

--enums

player.directions = {
    UP = 'UP',
    DOWN = 'DOWN',
    LEFT = 'LEFT',
    RIGHT = 'RIGHT',
    RIGHTUP = 'RIGHTUP',
    RIGHTDOWN = 'RIGHTDOWN',
    LEFTUP = 'LEFTUP',
    LEFTDOWN = 'LEFTDOWN',
    NONE = 'NONE'
}

player.direction = player.directions.NONE

player.states = {
    IDLE = 'IDLE'
}

player.state = player.states.IDLE

function player:new()
    local obj = {}
    setmetatable(obj, self)
    self.__index = self
    return obj
end
 
function player:applyVelocity(dt)

    if self.direction == self.directions.UP then
        self.velocityY = self.velocityY - self.acceleration * dt
    end

    if self.direction == self.directions.LEFT then
        self.velocityX = self.velocityX - self.acceleration * dt
    end

    if self.direction == self.directions.DOWN then
        self.velocityY = self.velocityY + self.acceleration * dt
    end

    if self.direction == self.directions.RIGHT then
        self.velocityX = self.velocityX + self.acceleration * dt
    end

    if self.direction == self.directions.RIGHTUP then
        self.velocityX = self.velocityX + self.acceleration * dt
        self.velocityY = self.velocityY - self.acceleration * dt
    end

    if self.direction == self.directions.LEFTUP then
        self.velocityX = self.velocityX - self.acceleration * dt
        self.velocityY = self.velocityY - self.acceleration * dt
    end

    if self.direction == self.directions.RIGHTDOWN then
        self.velocityX = self.velocityX + self.acceleration * dt
        self.velocityY = self.velocityY + self.acceleration * dt
    end

    if self.direction == self.directions.LEFTDOWN then
        self.velocityX = self.velocityX - self.acceleration * dt
        self.velocityY = self.velocityY + self.acceleration * dt
    end

    self:normalizeVector()

end

function player:applyDeceleration(dt)
    self.velocityX = self.velocityX * (1 - self.deceleration * dt)
    self.velocityY = self.velocityY * (1 - self.deceleration * dt)
end

function player:setPosition()
    self.x = self.x + self.velocityX
    self.y = self.y + self.velocityY   
end 

function player:checkForInput(dt)

    self.direction = self.directions.NONE

    if love.keyboard.isDown('w') then
        self.direction = self.directions.UP
    end

    if love.keyboard.isDown('a') then
        self.direction = self.directions.LEFT
    end

    if love.keyboard.isDown('s') then
        self.direction = self.directions.DOWN
    end

    if love.keyboard.isDown('d') then
        self.direction = self.directions.RIGHT
    end

    if love.keyboard.isDown('w') and love.keyboard.isDown('d') then
        self.direction = self.directions.RIGHTUP
    end

    if love.keyboard.isDown('w') and love.keyboard.isDown('a') then
        self.direction = self.directions.LEFTUP
    end

    if love.keyboard.isDown('s') and love.keyboard.isDown('d') then
        self.direction = self.directions.RIGHTDOWN
    end

    if love.keyboard.isDown('s') and love.keyboard.isDown('a') then
        self.direction = self.directions.LEFTDOWN
    end

    if love.keyboard.isDown('return') then
        print(self.direction)
    end

end

function player:normalizeVector()
    local length = math.sqrt(self.velocityX * self.velocityX + self.velocityY * self.velocityY)
    if length > self.maxSpeed then
        self.velocityX = (self.velocityX / length) * self.maxSpeed
        self.velocityY = (self.velocityY / length) * self.maxSpeed
    end
end

function player:update(dt)
    self:checkForInput()
    self:applyVelocity(dt)
    self:setPosition()
    self:applyDeceleration(dt)
end

function player:draw()
    love.graphics.draw(self.image, self.x, self.y)
    love.graphics.print(self.velocityX, 0, 0)
    love.graphics.print(self.velocityY, 0, 10)
end

function player:sayHi()
end

return player
i have it like this.
User avatar
dusoft
Party member
Posts: 547
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Player Movement - Pythagorean formula - 8 directions

Post by dusoft »

TheGuardian163 wrote: Fri Dec 11, 2015 9:47 pm I was following a space invaders tutorial on youtube (just started learning Lua) and deciding to play around instead of following it

You can move in 8 different directions using the arrow keys, you can sprint using the Z key and shoot using the X key (only upwards)

I used pythagorean formula to get the right speed when going on a 'combined' direction (the diagonal of a square is longer than it's height, so doing "player.y = player.speed / 2" and "player.x = player.speed / 2" made the player move faster than it should

I'd like to learn about structuring my code better - how could I make it cleaner?

Here's the code:
http://pastebin.com/VDSHsbSL
Also, please use Support forum for requests/questions like this instead of Libraries and Tools. This forum is strictly for reusable / open source libs or useful tools.
Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot] and 1 guest