Created
August 8, 2012 04:16
-
-
Save randrews/3291998 to your computer and use it in GitHub Desktop.
Example code for nice-feeling player movement in Love
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'point' | |
function love.load() | |
math.randomseed(os.time()) | |
love.physics.setMeter(32) | |
love.graphics.setBackgroundColor(64, 120, 64) | |
world = love.physics.newWorld(0, 0) | |
crates = { makeCrate(world, 5, 5), | |
makeCrate(world, 5, 6) } | |
player = makePlayer(world) | |
end | |
function makeCrate(world, x, y) | |
local b = love.physics.newBody(world, x*32 + 16, y*32 + 16, 'dynamic') | |
local s = love.physics.newRectangleShape(0, 0, 32, 32) | |
love.physics.newFixture(b, s) | |
b:setFixedRotation(true) | |
b:setMass(5) | |
b:setLinearDamping(4) | |
return {body=b, shape=s} | |
end | |
function makePlayer(world) | |
local b = love.physics.newBody(world, 48, 48, 'dynamic') | |
local s = love.physics.newCircleShape(16) | |
love.physics.newFixture(b, s) | |
b:setMass(1) | |
return {body=b, shape=s} | |
end | |
function love.draw() | |
local g = love.graphics | |
-- Draw player | |
g.setColor(160, 64, 64) | |
g.circle('fill', player.body:getX(), player.body:getY(), 16) | |
-- Draw crates | |
g.setColor(180, 120, 90) | |
for _, c in ipairs(crates) do | |
g.rectangle('fill', c.body:getX()-16, c.body:getY()-16, 32, 32) | |
end | |
end | |
-------------------------------------------------- | |
function love.update(dt) | |
local k = love.keyboard.isDown | |
local kd = 0 | |
local dir = point(0, 0) | |
if k('up') then dir = dir + point.up ; kd = kd + 1 end | |
if k('down') then dir = dir + point.down ; kd = kd + 1 end | |
if k('left') then dir = dir + point.left ; kd = kd + 1 end | |
if k('right') then dir = dir + point.right ; kd = kd + 1 end | |
if kd > 0 then | |
player.body:setLinearDamping(0) | |
else | |
player.body:setLinearDamping(8) | |
end | |
max_speed(player.body, 320) | |
local f = dir * 320 | |
player.body:applyForce(f.x, f.y) | |
if kd == 1 then | |
dampenSidewaysVelocity(player.body, dir, dt) | |
end | |
for _, c in ipairs(crates) do | |
local sq = point( | |
math.floor(c.body:getX() / 32), | |
math.floor(c.body:getY() / 32)) | |
nudgeToSquare(c.body, sq, 20) | |
end | |
world:update(dt) | |
end | |
function max_speed(body, spd) | |
local x, y = body:getLinearVelocity() | |
if x*x + y*y > spd*spd then | |
local a = math.atan2(y,x) | |
body:setLinearVelocity(spd * math.cos(a), | |
spd * math.sin(a)) | |
end | |
end | |
function dampenSidewaysVelocity(body, dir, dt) | |
local a = 1 - 4 * dt | |
if a > 1.0 then a = 1.0 elseif a < 0 then a = 0 end | |
local v = point(body:getLinearVelocity()) | |
if dir.y == 0 then v.y = v.y * a end | |
if dir.x == 0 then v.x = v.x * a end | |
body:setLinearVelocity(v()) | |
end | |
function nudgeToSquare(body, sq, acc) | |
local y = body:getY() - 16 | |
local ty = sq.y * 32 | |
local f = acc * (ty - y) | |
body:applyForce(0, f) | |
local x = body:getX() - 16 | |
local tx = sq.x * 32 | |
local f = acc * (tx - x) | |
body:applyForce(f, 0) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module(..., package.seeall) | |
local methods = {} | |
local instance = {__index=methods} | |
function new(x,y) | |
local tbl = {x=x, y=y} | |
return setmetatable(tbl, instance) | |
end | |
north = new(0, -1) ; up = north | |
south = new(0, 1) ; down = south | |
west = new(-1, 0) ; left = west | |
east = new(1, 0) ; right = east | |
local mt = getmetatable(_M) | |
mt.__call=function(t,x,y) | |
return t.new(x,y) | |
end | |
function methods:copy() | |
return new(self.x, self.y) | |
end | |
function methods:ortho(pt2) | |
return self.x == pt2.x or self.y == pt2.y | |
end | |
function methods:toward(pt2) | |
if not self:ortho(pt2) then error(self .. ' not in a straight line with ' .. pt2) | |
else | |
local v = pt2 - self | |
if v.x > 0 then v.x=1 end | |
if v.x < 0 then v.x=-1 end | |
if v.y > 0 then v.y=1 end | |
if v.y < 0 then v.y=-1 end | |
return v | |
end | |
end | |
function methods:adjacent(pt2) | |
local d = pt2-self | |
return (d.x == 0 or d.y == 0) and (math.abs(d.x+d.y) == 1) | |
end | |
function instance.__add(pt1, pt2) | |
assert(pt1 and pt2) | |
return new(pt1.x+pt2.x, pt1.y+pt2.y) | |
end | |
function instance.__sub(pt1, pt2) | |
assert(pt1 and pt2) | |
return new(pt1.x-pt2.x, pt1.y-pt2.y) | |
end | |
function instance.__mul(pt1, pt2) | |
assert(pt1 and pt2) | |
if type(pt2) == 'number' then | |
return new(pt1.x * pt2, pt1.y * pt2) | |
else | |
return new(pt1.x*pt2.x, pt1.y*pt2.y) | |
end | |
end | |
methods.translate = instance.__add | |
function instance.__tostring(pt) | |
return string.format('(%d, %d)', pt.x, pt.y) | |
end | |
function instance.__call(pt) | |
return pt.x, pt.y | |
end | |
function instance.__eq(pt1, pt2) | |
return pt1.x == pt2.x and pt1.y == pt2.y | |
end | |
-- A point is "less than" a point if each | |
-- coord is less than the corresponding one | |
function instance.__lt(pt1, pt2) | |
return pt1.x < pt2.x and pt1.y < pt2.y | |
end | |
function instance.__le(pt1, pt2) | |
return pt1.x <= pt2.x and pt1.y <= pt2.y | |
end | |
function test() | |
local p = point(2,3) | |
assert(p.x == 2 and p.y == 3) | |
assert(tostring(p) == "(2, 3)") | |
p = p + point(1,1) | |
assert(tostring(p) == "(3, 4)") | |
local p2 = p:copy() | |
p2.y = p2.y-1 | |
assert(tostring(p) == "(3, 4)") | |
assert(tostring(p2) == "(3, 3)") | |
assert(p2 + point(1, 1) == point(4, 4)) | |
local o1, o2 = point(3, 3), point(3, 5) | |
assert(o1:ortho(o2)) | |
assert(o2-o1 == point(0, 2)) | |
assert(o1:toward(o2) == point(0, 1)) | |
local a1, a2, a3 = point(2, 2), point(1, 2), point(3, 3) | |
assert(a1:adjacent(a2)) | |
assert(a2:adjacent(a1)) | |
assert(not a2:adjacent(a3)) | |
assert(not a1:adjacent(a3)) | |
assert(not a1:adjacent(a1)) | |
assert(a2 <= a1) | |
assert(a1 < a3) | |
assert(a3 > a1) | |
assert(not(a2 < a1)) | |
end | |
test() -- Run the tests on load, error if any fail |
ay sorry bro ima gonna steal this code
Go for it but I doubt it'll work as-is at this point, it's for a version of Love2d that's several years old and the APIs have changed since then.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ay sorry bro ima gonna steal this code