Browse Source

Physics stuff; Kinda meh;

bjorn 10 years ago
parent
commit
715f73d6f7
6 changed files with 124 additions and 59 deletions
  1. 6 0
      deps/util.lua
  2. 12 10
      game.lua
  3. 21 0
      map.lua
  4. 17 7
      person.lua
  5. 67 42
      pigeon.lua
  6. 1 0
      require.lua

+ 6 - 0
deps/util.lua

@@ -15,3 +15,9 @@ function math.hlora(x1, y1, x2, y2, rx, ry, rw, rh) -- Hot line on rectangle act
       or math.hlola(x1, y1, x2, y2, rxw, ry, rxw, ryh)
       or math.hlola(x1, y1, x2, y2, rx, ryh, rxw, ryh)
 end
+
+function drawPhysicsObject(how, obj)
+  if obj.shape:typeOf('PolygonShape') then
+    love.graphics.polygon(how, obj.body:getWorldPoints(obj.shape:getPoints()))
+  end
+end

+ 12 - 10
game.lua

@@ -1,8 +1,10 @@
 Game = class()
 
 function Game:load()
+  self.world = love.physics.newWorld(0, 98)
+  self.map = Map(ctx)
   self.pigeon = Pigeon()
-  self.people = {Person()}
+  self.people = {}
   self.hud = Hud()
 end
 
@@ -13,25 +15,25 @@ function Game:update()
   end)
 
   if love.math.random() < .5 * ls.tickrate then
-    local p = Person()
+    local x, dir
 
     if love.math.random() < .5 then
-      p.x = 0
-      p.direction = 1
+      x = 0
+      dir = 1
     else
-      p.x = 800
-      p.direction = -1
+      x = 800
+      dir = -1
     end
 
-    lume.push(self.people, p)
+    lume.push(self.people, Person(x, 400, dir))
   end
+
+  self.world:update(ls.tickrate)
 end
 
 function Game:draw()
-  local g = love.graphics
   flux.update(ls.dt)
-  g.setColor(0, 50, 0)
-  g.rectangle('fill', 0, 0, 800, 600)
+  self.map:draw()
   self.pigeon:draw()
   lume.each(self.people, function(person)
     person:draw()

+ 21 - 0
map.lua

@@ -0,0 +1,21 @@
+Map = class()
+Map.width = 800
+Map.height = 600
+
+function Map:init()
+  self.ground = {}
+  self.ground.height = 100
+  self.ground.body = love.physics.newBody(ctx.world, self.width / 2, self.height - self.ground.height / 2, 'static')
+  self.ground.shape = love.physics.newRectangleShape(self.width, self.ground.height)
+
+  self.ground.fixture = love.physics.newFixture(self.ground.body, self.ground.shape)
+end
+
+function Map:draw()
+  local g = love.graphics
+  g.setColor(0, 50, 0)
+  g.rectangle('fill', 0, 0, self.width, self.height)
+
+  g.setColor(100, 80, 0)
+  drawPhysicsObject('fill', self.ground)
+end

+ 17 - 7
person.lua

@@ -1,21 +1,31 @@
 Person = class()
 
-function Person:init()
-  self.x = 800
-  self.direction = -1
-  self.y = 500
+function Person:init(x, y, dir)
+  self.x = x
+  self.y = y
+  self.direction = dir
   self.w = 20
   self.h = 40
+
+  self.body = love.physics.newBody(ctx.world, self.x - self.w / 2, self.y - self.h / 2, 'dynamic')
+  self.shape = love.physics.newRectangleShape(self.w, self.h)
+  self.fixture = love.physics.newFixture(self.body, self.shape)
+
+  self.body:setUserData(self)
+
+  self.body:setMass(10)
 end
 
 function Person:update()
-  self.x = self.x + 100 * self.direction * ls.tickrate
+  self.body:applyLinearImpulse(300 * self.direction * ls.tickrate, 0)
 end
 
 function Person:draw()
   local g = love.graphics
   g.setColor(255, 255, 255)
-  g.rectangle('line', self.x - self.w / 2, self.y - self.h / 2, self.w, self.h)
+  drawPhysicsObject('line', self)
 end
 
-
+function Person:die()
+  self.body:destroy()
+end

+ 67 - 42
pigeon.lua

@@ -26,60 +26,84 @@ function Pigeon:update()
   self.prevx = self.x
   self.prevy = self.y
 
-  if love.keyboard.isDown('left') then
-    self.x = self.x - self.speed * ls.tickrate
-    self.targetDirection.x = -1
-  elseif love.keyboard.isDown('right') then
-    self.x = self.x + self.speed * ls.tickrate
-    self.targetDirection.x = 1
-  end
+  -- Movement
+  do
+    if love.keyboard.isDown('left') then
+      self.x = self.x - self.speed * ls.tickrate
+      self.targetDirection.x = -1
+    elseif love.keyboard.isDown('right') then
+      self.x = self.x + self.speed * ls.tickrate
+      self.targetDirection.x = 1
+    end
 
-  if love.keyboard.isDown('up') then
-    self.targetDirection.y = -1
-    self.y = self.y - self.speed * ls.tickrate
-  elseif love.keyboard.isDown('down') then
-    self.targetDirection.y = 1
-    self.y = self.y + self.speed * ls.tickrate
-  else
-    self.targetDirection.y = 0
-  end
+    if love.keyboard.isDown('up') then
+      self.targetDirection.y = -1
+    elseif love.keyboard.isDown('down') then
+      self.targetDirection.y = 1
+    else
+      self.targetDirection.y = 0
+    end
 
-  flux.to(self.direction, .4, self.targetDirection):ease('expoout')
+    flux.to(self.direction, .4, self.targetDirection):ease('expoout')
 
-  self.vy = self.vy + self.gravity * ls.tickrate
-  self.y = self.y + self.vy * ls.tickrate
+    self.vy = self.vy + self.gravity * ls.tickrate
+    self.y = self.y + self.vy * ls.tickrate
 
-  if self.y + self.h / 2 > 600 then
-    self.vy = math.abs(self.vy) * -1
+    if self.y + self.h / 2 > 600 then
+      self.vy = math.abs(self.vy) * -1
+    end
   end
 
-  self.laser = love.keyboard.isDown(' ')
+  local kills = 0
+
+  -- Laser
+  do
+    self.laser = love.keyboard.isDown(' ')
+
+    if self.laser then
+      self.laserTween = flux.to(self, 1, {laserLength = 1000}):ease('expoout')
+
+      if self.laserLength > 0 then
+        local x1, y1 = self.x, self.y - self.h / 2
+        local x2, y2 = self.x + self.direction.x * self.laserLength, self.y + self.direction.y * self.laserLength - self.h / 2
+
+        ctx.world:rayCast(x1, y1, x2, y2, function(fixture)
+          local person = fixture:getBody():getUserData()
+          if person and person.die then
+            person:die()
+            lume.remove(ctx.people, person)
+            kills = kills + 1
+            return 1
+          end
+          return -1
+        end)
+      end
 
-  if self.laser then
-    self.laserTween = flux.to(self, 1, {laserLength = 1000}):ease('expoout')
-    local kills = 0
+      --[[for i, person in lume.ripairs(ctx.people) do
 
-    local x1, y1 = self.x, self.y
-    local x2, y2 = self.x + self.direction.x * self.laserLength, self.y + self.direction.y * self.laserLength
+        local px, py, px2, py2 = person.body:getWorldPoints(person.shape:getPoints())
+        local pw, ph = px2 - px, py2 - py
+        if math.hlora(x1, y1, x2, y2, px, py, pw, ph) then
+          kills = kills + 1
+          table.remove(ctx.people, i)
+        end
+      end]]
 
-    for i, person in lume.ripairs(ctx.people) do
-      if math.hlora(x1, y1, x2, y2, person.x - person.w / 2, person.y - person.h / 2, person.w, person.h) then
-        kills = kills + 1
-        table.remove(ctx.people, i)
+    else
+      if self.laserTween then
+        self.laserTween:stop()
+        self.laserLength = 0
       end
     end
+  end
 
-    if kills > 0 then
-      flux.to(self, .6, {w = self.w + 5 * kills, h = self.h + 10 * kills}):ease('elasticout')
-      self.health = math.min(self.health + 15 * kills, self.maxHealth)
-    end
-  else
-    if self.laserTween then
-      self.laserTween:stop()
-      self.laserLength = 0
-    end
+  -- Increase size and health on kill
+  if kills > 0 then
+    flux.to(self, .6, {w = self.w + 5 * kills, h = self.h + 10 * kills}):ease('elasticout')
+    self.health = math.min(self.health + 15 * kills, self.maxHealth)
   end
 
+  -- Death
   if self.health < 0 then
     if self.lives == 0 then
       print('you lose')
@@ -93,6 +117,7 @@ function Pigeon:update()
     self.h = self.h / 2
   end
 
+  -- Health decay
   self.health = self.health - 10 * ls.tickrate
 end
 
@@ -101,14 +126,14 @@ function Pigeon:draw()
   local x = lume.lerp(self.prevx, self.x, ls.accum / ls.tickrate)
   local y = lume.lerp(self.prevy, self.y, ls.accum / ls.tickrate)
   g.setColor(255, 255, 255)
-  g.rectangle('line', x - self.w / 2, y - self.h / 2, self.w, self.h)
+  g.rectangle('line', x - self.w / 2, y - self.h, self.w, self.h)
 
   if self.laser then
     local x2, y2 = x + self.direction.x * self.laserLength, y + self.direction.y * self.laserLength
 
     g.setColor(255, 0, 0)
     g.setLineWidth(self.w / 5)
-    g.line(x, y, x2, y2)
+    g.line(x, y - self.h / 2, x2, y2 - self.h / 2)
     g.setLineWidth(1)
   end
 end

+ 1 - 0
require.lua

@@ -9,5 +9,6 @@ require 'context'
 require 'game'
 require 'person'
 require 'pigeon'
+require 'map'
 
 require 'hud'