Skip to content

Instantly share code, notes, and snippets.

@romgerman
Created February 6, 2017 05:48
Show Gist options
  • Select an option

  • Save romgerman/7e5b3b6e75a3a51d832d3af87ed0fd38 to your computer and use it in GitHub Desktop.

Select an option

Save romgerman/7e5b3b6e75a3a51d832d3af87ed0fd38 to your computer and use it in GitHub Desktop.
Love2d asteroids (pseudo 3d)
local function Vector2(x, y)
local v = {
x = x,
y = y
}
return v;
end
local function Mat2( m11, m12, m21, m22 )
local m = {
m11 = m11, m12 = m12,
m21 = m21, m22 = m22
}
return m
end
local function Vec2MulMat2( v, m )
local r = {
x = m.m11 * v.x + m.m12 * v.y,
y = m.m21 * v.x + m.m22 * v.y
}
return r
end
local function Centroid( poly )
local x = 0
local y = 0
for i,v in ipairs(poly) do
x = x + v.x
y = y + v.y
end
local v = {
x = x / #poly,
y = y / #poly
}
return v
end
local function CalcRectForPoly( p, x, y )
local rect = {
x = 0,
y = 0,
x2 = 0,
y2 = 0
}
for i, v in ipairs(p) do
if v.x < rect.x then
rect.x = v.x
end
if v.y < rect.y then
rect.y = v.y
end
if v.x > rect.x2 then
rect.x2 = v.x
end
if v.y > rect.y2 then
rect.y2 = v.y
end
end
rect.x = rect.x + x
rect.y = rect.y + y
rect.x2 = rect.x2 + x
rect.y2 = rect.y2 + y
return rect
end
local function PointInRect( p, r )
return (p.x > r.x and p.x < r.x2 and p.y > r.y and p.y < r.y2)
end
-- HELPER FUNCTIONS
function lerp(a, b, t)
return a + (b - a) * t
end
function ilerp(a, b, t)
return a - (b + a) * t
end
-- END
-- LOAD RESOURCES
local shootSound = love.audio.newSource("Assets/Sound/shoot1.wav", 'static')
local blowSound = love.audio.newSource("Assets/Sound/blow.wav", 'static')
local ainsSoundData = love.sound.newSoundData("Assets/Sound/asteroid is near the ship.wav")
local ainsSound = love.audio.newSource(ainsSoundData)
-- END
local screenWidth
local screenHeight
local screenWidth2
local screenHeight2
local windowWidth
local windowHeight
local windowWidth2
local windowHeight2
local warningSoundVol = 0
function love.load()
screenWidth = love.graphics.getWidth()
screenHeight = love.graphics.getHeight()
screenWidth2 = screenWidth / 2
screenHeight2 = screenHeight / 2
windowWidth = screenWidth / 1.2
windowHeight = screenHeight / 1.5
windowWidth2 = windowWidth / 2
windowHeight2 = windowHeight / 2
love.mouse.setVisible( false )
ainsSound:setVolume(warningSoundVol)
ainsSound:setLooping(true)
ainsSound:play()
shootSound:setVolume(0.5)
blowSound:setVolume(0.5)
end
local zFar = 100
local bSpeed = 2
local bSize = 50
local shootRate = 60/122
local spawnRate = 1
local modX = 0
local modY = 0
local BulletList = { }
local function ShootBullet( x, y, sx, sy )
local bullet = {
ex = x,
ey = y,
x = sx + bSize,
y = sy + bSize,
z = 0,
r = bSize
}
table.insert(BulletList, bullet)
shootSound:play()
end
local function DrawBullet( b )
love.graphics.circle('fill', b.x, b.y, b.r)
end
local function UpdateBullet( i, b, dt )
b.ex = lerp(b.ex, b.ex - modX, dt * bSpeed)
b.ey = lerp(b.ey, b.ey - modY, dt * bSpeed)
b.x = lerp(b.x, b.ex - modX, dt * bSpeed)
b.y = lerp(b.y, b.ey - modY, dt * bSpeed)
b.z = lerp(b.z, zFar, dt * bSpeed * 0.5)
if b.r <= 1 then
table.remove(BulletList, i)
else
b.r = lerp(b.r, 0, dt * bSpeed * 1.5)
end
end
local AsteroidList = { }
local function SpawnAsteroid()
local x = love.math.random( 100, screenWidth - 100 )
local y = love.math.random( 100, screenHeight - 100 )
local a = {
x = x,
y = y,
z = zFar,
size = 1,
--oldsize = 1,
poly = {
Vector2(0, 0),
Vector2(5, 5),
Vector2(10, 1),
Vector2(13, -10),
Vector2(4, -10),
Vector2(5, -5)
},
rect = {
x = 0,
y = 0,
x2 = 0,
y2 = 0
}
}
table.insert(AsteroidList, a)
end
local function DrawAsteroid( a )
local poly = { }
for i,v in ipairs(a.poly) do
table.insert(poly, v.x + a.x)
table.insert(poly, v.y + a.y)
end
love.graphics.polygon('line', poly)
--[[love.graphics.polygon('line', a.rect.x, a.rect.y,
a.rect.x, a.rect.y2,
a.rect.x2, a.rect.y2,
a.rect.x2, a.rect.y)]]
end
local function UpdateAsteroid( i, a, dt )
--a.z = lerp(a.z, zFar, dt * 0.0001)
a.z = a.z - dt * 8
a.size = lerp(a.size, 10, dt * 0.0001)
a.x = a.x - modX * 0.1
a.y = a.y - modY * 0.1
if a.z <= 2 then
if (a.x < 0 and a.y < 0) or (a.x > screenWidth and a.y > screenHeight) then
table.remove(AsteroidList, i)
return
end
-- Game over
table.remove(AsteroidList, i)
return
end
local smat = Mat2(a.size, 0,
0, a.size)
local centroid = Centroid(a.poly)
for i,v in ipairs(a.poly) do
local x = v.x - centroid.x
local y = v.y - centroid.y
local vec = Vec2MulMat2(Vector2(x, y), smat)
a.poly[i].x = vec.x --+ v.x -- modX
a.poly[i].y = vec.y --+ v.y -- modY
end
a.rect = CalcRectForPoly(a.poly, a.x, a.y)
end
local function CheckCollisions()
for i,v in ipairs(AsteroidList) do
for i2,v2 in ipairs(BulletList) do
if PointInRect({x = v2.x, y = v2.y}, v.rect) and v2.z > v.z then
table.remove(AsteroidList, i)
table.remove(BulletList, i2)
blowSound:play()
end
end
end
end
local prevSTime = 0
local prevATime = 0
local changeVol = false
function love.update(dt)
local x, y = love.mouse.getPosition()
modX = lerp(modX, x - screenWidth2, dt * 2)
modY = lerp(modY, y - screenHeight2, dt * 2)
if love.mouse.isDown(1) then
if prevSTime >= shootRate then
ShootBullet(x, y, 0, windowHeight2)
ShootBullet(x, y, windowWidth, windowHeight2)
prevSTime = 0
end
end
if prevATime >= spawnRate then
SpawnAsteroid()
prevATime = 0
end
-- Collisions
CheckCollisions()
-- Bullets
for k,v in pairs(BulletList) do
UpdateBullet(k, v, dt)
end
-- Asteroids
for k,v in pairs(AsteroidList) do
UpdateAsteroid(k, v, dt)
if v.z < zFar / 2 then
changeVol = true
end
end
if changeVol then
warningSoundVol = lerp(warningSoundVol, 0.5, dt * 0.5)
else
warningSoundVol = 0
end
ainsSound:setVolume(warningSoundVol)
prevSTime = prevSTime + dt
prevATime = prevATime + dt
end
function love.draw()
-- Asteroids
love.graphics.setColor(200, 200, 255, 255)
love.graphics.setLineWidth( 2 )
for i,v in ipairs(AsteroidList) do
DrawAsteroid(v)
end
love.graphics.setLineWidth( 1 )
love.graphics.setColor(255, 50, 50, 255)
-- Bullets
for i,v in ipairs(BulletList) do
DrawBullet(v)
end
love.graphics.setColor(255, 255, 255, 255)
love.graphics.line(0, 0,
screenWidth2 + modX - windowWidth2, screenHeight2 + modY - windowHeight2)
love.graphics.line(0, 0,
screenWidth2 + modX + windowWidth2, screenHeight2 + modY - windowHeight2)
love.graphics.line(screenWidth2, 0,
screenWidth2 + modX, screenHeight2 + modY - windowHeight2)
love.graphics.line(screenWidth, 0,
screenWidth2 + modX + windowWidth2, screenHeight2 + modY - windowHeight2)
love.graphics.line(screenWidth, 0,
screenWidth2 + modX - windowWidth2, screenHeight2 + modY - windowHeight2)
love.graphics.line(screenWidth + 100, screenHeight2,
screenWidth2 + modX + windowWidth2, screenHeight2 + modY)
love.graphics.line(screenWidth2 - windowWidth2 + modX, screenHeight2 - windowHeight2 + modY,
screenWidth2 - windowWidth2 / 2 + modX, screenHeight2 - windowHeight2 / 2 + modY)
love.graphics.line(screenWidth2 + windowWidth2 + modX, screenHeight2 - windowHeight2 + modY,
screenWidth2 + windowWidth2 / 2 + modX, screenHeight2 - windowHeight2 / 2 + modY)
love.graphics.line(screenWidth, screenHeight,
screenWidth2 + modX + windowWidth2, screenHeight2 + modY + windowHeight2)
love.graphics.line(screenWidth2, screenHeight,
screenWidth2 + modX, screenHeight2 + modY + windowHeight2)
love.graphics.line(0, screenHeight,
screenWidth2 + modX + windowWidth2, screenHeight2 + modY + windowHeight2)
love.graphics.line(-100, screenHeight2,
screenWidth2 + modX - windowWidth2, screenHeight2 + modY)
love.graphics.line(0, screenHeight,
screenWidth2 - windowWidth2 + modX, screenHeight2 + windowHeight2 + modY)
love.graphics.line(screenWidth, screenHeight,
screenWidth2 - windowWidth2 + modX, screenHeight2 + windowHeight2 + modY)
love.graphics.line(screenWidth2 - windowWidth2 + modX, screenHeight2 + windowHeight2 + modY,
screenWidth2 - windowWidth2 / 2 + modX, screenHeight2 + windowHeight2 / 2 + modY)
love.graphics.line(screenWidth2 + windowWidth2 + modX, screenHeight2 + windowHeight2 + modY,
screenWidth2 + windowWidth2 / 2 + modX, screenHeight2 + windowHeight2 / 2 + modY)
-- Center window
love.graphics.line(screenWidth2 + modX, screenHeight2 - windowHeight2 + modY,
screenWidth2 + windowWidth2 + modX, screenHeight2 + modY)
love.graphics.line(screenWidth2 + windowWidth2 + modX, screenHeight2 + modY,
screenWidth2 + modX, screenHeight2 + windowHeight2 + modY)
love.graphics.line(screenWidth2 + modX, screenHeight2 + windowHeight2 + modY,
screenWidth2 - windowWidth2 + modX, screenHeight2 + modY)
love.graphics.line(screenWidth2 - windowWidth2 + modX, screenHeight2 + modY,
screenWidth2 + modX, screenHeight2 - windowHeight2 + modY)
love.graphics.setColor(255, 255, 255, 50)
local vertices = {
0, 0,
screenWidth2, 0,
screenWidth2 + modX, screenHeight2 - windowHeight2 + modY,
screenWidth2 - windowWidth2 + modX, screenHeight2 - windowHeight2 + modY
}
--love.graphics.polygon('fill', vertices)
local vertices = {
screenWidth, 0,
screenWidth2 + windowWidth2 + modX, screenHeight2 - windowHeight2 + modY,
screenWidth2 + modX, screenHeight2 - windowHeight2 + modY,
screenWidth2, 0
}
--love.graphics.polygon('fill', vertices)
love.graphics.setColor(255, 255, 255, 255)
-- Crosshair
love.graphics.line(screenWidth2 - 10 + modX, screenHeight2 - 5 + modY,
screenWidth2 + 10 + modX, screenHeight2 - 5 + modY)
love.graphics.line(screenWidth2 - 2 + modX, screenHeight2 + modY,
screenWidth2 + 2 + modX, screenHeight2 + modY)
love.graphics.line(screenWidth2 - 5 + modX, screenHeight2 + 5 + modY,
screenWidth2 + 5 + modX, screenHeight2 + 5 + modY)
love.graphics.line(screenWidth2 + modX, screenHeight2 + modY,
screenWidth2 + windowWidth2 + modX, screenHeight2 + modY)
-- FPS
love.graphics.print(tostring(love.timer.getFPS()), 10, 10)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment