瀏覽代碼

Oops the game is fun;

bjorn 10 年之前
父節點
當前提交
ebf458e326
共有 6 個文件被更改,包括 92 次插入16 次删除
  1. 10 0
      data/animation/pigeon.lua
  2. 1 1
      game.lua
  3. 1 1
      loader.lua
  4. 2 4
      media/skeletons/pigeon/pigeon.json
  5. 26 9
      person.lua
  6. 52 1
      pigeon.lua

+ 10 - 0
data/animation/pigeon.lua

@@ -4,4 +4,14 @@ Pigeon.scale = .15
 Pigeon.default = nil
 Pigeon.states = {}
 
+Pigeon.states.idle = {
+  loop = true,
+  priority = 1
+}
+
+Pigeon.states.peck = {
+  loop = false,
+  priority = 2
+}
+
 return Pigeon

+ 1 - 1
game.lua

@@ -2,7 +2,7 @@ Game = class()
 
 function Game:load()
   self.event = Event()
-  self.world = love.physics.newWorld(0, 500)
+  self.world = love.physics.newWorld(0, 1000)
   self.view = View()
   self.map = Map(ctx)
   self.pigeon = Pigeon()

+ 1 - 1
loader.lua

@@ -103,7 +103,7 @@ data.load = function()
         end
       end)
 
-      lume.each(animation.states[i].mix, function(time, to)
+      lume.each(animation.states[i].mix or {}, function(time, to)
         s.animationStateData:setMix(animation.states[i].name, to, time)
       end)
     end

+ 2 - 4
media/skeletons/pigeon/pigeon.json

@@ -103,9 +103,7 @@
 			}
 		},
 		"beaktop": {
-			"beaktop": { "x": 10.96, "y": 0.08, "scaleX": 0.305, "scaleY": 0.305, "rotation": 48.2, "width": 111, "height": 132 }
-		},
-		"beaktop_bb": {
+			"beaktop": { "x": 10.96, "y": 0.08, "scaleX": 0.305, "scaleY": 0.305, "rotation": 48.2, "width": 111, "height": 132 },
 			"beaktop_bb": {
 				"type": "boundingbox",
 				"vertices": [ 36.72046, -0.79315, -4.59355, 12.52102, -7.11737, -5.9205 ]
@@ -641,4 +639,4 @@
 		]
 	}
 }
-}
+}

+ 26 - 9
person.lua

@@ -15,23 +15,35 @@ function Person:init(x, y, dir)
 
   self.body:setUserData(self)
 
-  self.body:setMass(10)
+  self.body:setMass(100)
+  self.body:setFixedRotation(true)
   self.fixture:setFriction(.35)
   self.fixture:setCategory(self.category)
   self.fixture:setMask(self.category, Building.category)
 
-  self.stable = true
+  self.dead = false
   self.walkTimer = 1
+  self.deathTimer = 0
 
   ctx.event:emit('view.register', {object = self})
 end
 
 function Person:update()
-  self.body:setFixedRotation(self.stable)
-  self.walkTimer = timer.rot(self.walkTimer, function()
-    self.body:applyLinearImpulse(self.direction * 50, -100)
-    return .6 + love.math.random() * .2
-  end)
+  if not self.dead then
+    self.walkTimer = timer.rot(self.walkTimer, function()
+      self.body:applyLinearImpulse(self.direction * 50, -100)
+      return .6 + love.math.random() * .2
+    end)
+  end
+
+  if self.dead then
+    local x, y = self.body:getLinearVelocity()
+    if (math.abs(x) < 1 and math.abs(y) < 1) or (math.abs(x) > 5000 and math.abs(y) > 5000) then
+      lume.remove(ctx.people, self)
+      self.body:destroy()
+      ctx.event:emit('view.unregister', {object = self})
+    end
+  end
 end
 
 function Person:draw()
@@ -45,6 +57,11 @@ function Person:draw()
 end
 
 function Person:die()
-  self.body:destroy()
-  ctx.event:emit('view.unregister', {object = self})
+  if not self.dead then
+    self.dead = true
+    self.body:applyLinearImpulse(-500 + love.math.random() * 1000, love.math.random() * -800)
+    self.body:applyTorque(-200 * love.math.random() * 400)
+    self.body:setFixedRotation(false)
+    self.deathTimer = 1
+  end
 end

+ 52 - 1
pigeon.lua

@@ -18,6 +18,13 @@ function Pigeon:init()
   self.maxHealth = 100
 
   self.animation = data.animation.pigeon()
+  self.animation:set('idle')
+
+  self.animation:on('complete', function(event)
+    if event.state.name == 'peck' then
+      self.animation:set('idle', {force = true})
+    end
+  end)
 
   ctx.view.target = self
 
@@ -29,13 +36,15 @@ function Pigeon:update()
   self.prevy = self.y
 
   -- Movement
-  do
+  if self.animation.state.name ~= 'peck' then
     if love.keyboard.isDown('left') then
       self.x = self.x - self.speed * ls.tickrate
       self.targetDirection.x = -1
+      self.animation.flipped = true
     elseif love.keyboard.isDown('right') then
       self.x = self.x + self.speed * ls.tickrate
       self.targetDirection.x = 1
+      self.animation.flipped = false
     end
 
     if love.keyboard.isDown('up') then
@@ -54,6 +63,7 @@ function Pigeon:update()
   -- Laser
   do
     self.laser = love.keyboard.isDown(' ')
+    self.laser = false
 
     if self.laser then
       self.laserTween = flux.to(self, 1, {laserLength = 1000}):ease('expoout')
@@ -103,6 +113,12 @@ function Pigeon:update()
 
   -- Health decay
   self.health = self.health - 10 * ls.tickrate
+
+  if love.keyboard.isDown(' ') then self.animation:set('peck') end
+
+  if self.animation.state.name == 'peck' then
+    self:killThingsOnBeak()
+  end
 end
 
 function Pigeon:draw()
@@ -123,3 +139,38 @@ function Pigeon:draw()
 
   self.animation:draw(x, y)
 end
+
+-- Kill everything near the beak. Uses very dumb AABB checking but can be improved.
+function Pigeon:killThingsOnBeak()
+  local spine = self.animation.spine
+
+  spine.skeleton.flipY = true
+  spine.skeleton:updateWorldTransform()
+  spine.skeletonBounds:update(spine.skeleton)
+  spine.skeleton.flipY = false
+
+  for _, slotName in pairs({'beakbottom', 'beaktop'}) do
+    local beakSlot = spine.skeleton:findSlot(slotName)
+    local beakAttachment = spine.skeleton:getAttachment(beakSlot.data.name, beakSlot.data.name .. '_bb')
+    local polygon = spine.skeletonBounds:getPolygon(beakAttachment)
+
+    if polygon then
+      local x1, y1, x2, y2
+      for i = 1, #polygon, 2 do
+        x1 = math.min(x1 or math.huge, polygon[i])
+        x2 = math.max(x2 or -math.huge, polygon[i])
+        y1 = math.min(y1 or math.huge, polygon[i + 1])
+        y2 = math.max(y2 or -math.huge, polygon[i + 1])
+      end
+
+      ctx.world:queryBoundingBox(x1, y1, x2, y2, function(fixture)
+        local person = fixture:getBody():getUserData()
+        if person and person.die then
+          person:die()
+
+          return true
+        end
+      end)
+    end
+  end
+end