2015-02-17 19:17:09 +00:00
|
|
|
require "collisions"
|
|
|
|
|
|
|
|
local ninja = {}
|
|
|
|
ninja.__index = ninja
|
|
|
|
|
2017-06-25 13:06:49 +00:00
|
|
|
function newNinja(object)
|
|
|
|
local n = object
|
2015-02-17 19:17:09 +00:00
|
|
|
n.width = 16
|
|
|
|
n.height = 32
|
|
|
|
n.xspeed = 0
|
|
|
|
n.yspeed = 0
|
2017-06-28 22:13:41 +00:00
|
|
|
n.xaccel = 900
|
2017-06-28 15:37:55 +00:00
|
|
|
n.yaccel = 600
|
2017-06-28 22:13:41 +00:00
|
|
|
n.max_xspeed = 150
|
2017-06-28 22:51:08 +00:00
|
|
|
n.max_yspeed = 280
|
2017-06-28 22:13:41 +00:00
|
|
|
n.friction = 20
|
2017-06-28 21:42:53 +00:00
|
|
|
n.groundfriction = 20
|
2017-06-28 22:13:41 +00:00
|
|
|
n.airfriction = 2
|
2017-06-25 13:06:49 +00:00
|
|
|
n.direction = "right"
|
2015-02-17 19:17:09 +00:00
|
|
|
n.stance = "fall"
|
2017-06-25 10:00:45 +00:00
|
|
|
n.type = "ninja"
|
2015-08-20 19:37:09 +00:00
|
|
|
n.DO_JUMP = 0
|
2017-06-26 21:26:37 +00:00
|
|
|
n.DO_THROW = 0
|
2017-06-29 13:01:54 +00:00
|
|
|
n.DO_SWORD = 0
|
2017-06-25 12:36:36 +00:00
|
|
|
n.hit = 0
|
2017-06-25 23:18:38 +00:00
|
|
|
n.dying = 0
|
2017-06-26 21:26:37 +00:00
|
|
|
n.throw = 0
|
2017-06-29 13:01:54 +00:00
|
|
|
n.sword = 0
|
2017-07-01 17:41:42 +00:00
|
|
|
n.yoffset = 0
|
2015-02-17 19:17:09 +00:00
|
|
|
|
|
|
|
n.animations = {
|
|
|
|
stand = {
|
2015-02-23 00:14:37 +00:00
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_stand_left.png"), 48, 48, 100, 10),
|
2015-02-23 00:14:37 +00:00
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_stand_right.png"), 48, 48, 100, 10)
|
|
|
|
},
|
|
|
|
run = {
|
2015-02-23 00:14:37 +00:00
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_run_left.png"), 48, 48, 1, 10),
|
2015-02-23 00:14:37 +00:00
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_run_right.png"), 48, 48, 1, 10)
|
|
|
|
},
|
|
|
|
jump = {
|
2015-02-23 00:14:37 +00:00
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_jump_left.png"), 48, 48, 1, 10),
|
2015-02-23 00:14:37 +00:00
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_jump_right.png"), 48, 48, 1, 10)
|
|
|
|
},
|
|
|
|
fall = {
|
2015-02-23 00:14:37 +00:00
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_fall_left.png"), 48, 48, 1, 10),
|
2015-02-23 00:14:37 +00:00
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
2015-02-17 19:17:09 +00:00
|
|
|
"assets/ninja_fall_right.png"), 48, 48, 1, 10)
|
|
|
|
},
|
2017-06-25 08:16:29 +00:00
|
|
|
duck = {
|
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_duck_left.png"), 48, 48, 1, 10),
|
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_duck_right.png"), 48, 48, 1, 10)
|
|
|
|
},
|
2017-06-25 12:36:36 +00:00
|
|
|
hit = {
|
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_hit_left.png"), 48, 48, 1, 10),
|
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_hit_right.png"), 48, 48, 1, 10)
|
|
|
|
},
|
2017-06-25 23:18:38 +00:00
|
|
|
dead = {
|
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_dead_left.png"), 48, 48, 100, 10),
|
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_dead_right.png"), 48, 48, 100, 10)
|
|
|
|
},
|
2017-06-26 21:26:37 +00:00
|
|
|
throw = {
|
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_throw_left.png"), 48, 48, 1, 30),
|
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
|
|
|
"assets/ninja_throw_right.png"), 48, 48, 1, 30)
|
|
|
|
},
|
2017-06-29 13:01:54 +00:00
|
|
|
sword = {
|
|
|
|
left = newAnimation(lutro.graphics.newImage(
|
2017-07-01 18:02:37 +00:00
|
|
|
"assets/ninja_sword_left.png"), 48, 48, 1, 30),
|
2017-06-29 13:01:54 +00:00
|
|
|
right = newAnimation(lutro.graphics.newImage(
|
2017-07-01 18:02:37 +00:00
|
|
|
"assets/ninja_sword_right.png"), 48, 48, 1, 30)
|
2017-06-29 13:01:54 +00:00
|
|
|
},
|
2015-02-17 19:17:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
n.anim = n.animations[n.stance][n.direction]
|
2017-06-25 10:04:06 +00:00
|
|
|
|
2015-02-17 19:17:09 +00:00
|
|
|
return setmetatable(n, ninja)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ninja:on_the_ground()
|
2017-07-01 17:50:30 +00:00
|
|
|
return (solid_at(self.x + 1, self.y + self.height, self)
|
|
|
|
or solid_at(self.x + self.width - 1, self.y + self.height, self))
|
2017-06-25 21:56:38 +00:00
|
|
|
and self.yspeed >= 0
|
2017-06-25 23:18:38 +00:00
|
|
|
and hp > 0
|
2015-02-17 19:17:09 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ninja:update(dt)
|
|
|
|
|
2017-06-28 19:43:26 +00:00
|
|
|
local on_the_ground = self:on_the_ground()
|
|
|
|
|
2017-06-25 23:18:38 +00:00
|
|
|
if hp <= 0 then
|
|
|
|
self.dying = self.dying + 1
|
|
|
|
self.anim = self.animations["dead"][self.direction]
|
|
|
|
self.anim:update(dt)
|
|
|
|
if self.dying == 1 then
|
|
|
|
lutro.audio.play(sfx_dead)
|
|
|
|
end
|
2017-06-26 22:35:05 +00:00
|
|
|
if self.dying == 40 then
|
2017-06-25 23:18:38 +00:00
|
|
|
lutro.audio.play(sfx_gameover)
|
|
|
|
self.yspeed = -300
|
|
|
|
end
|
2017-06-26 22:35:05 +00:00
|
|
|
if self.dying >= 40 then
|
2017-06-25 23:18:38 +00:00
|
|
|
self.yspeed = self.yspeed + self.yaccel * dt
|
|
|
|
self.y = self.y + dt * self.yspeed
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-06-26 21:26:37 +00:00
|
|
|
if self.throw > 0 then
|
|
|
|
self.throw = self.throw - 1
|
|
|
|
else
|
|
|
|
self.throw = 0
|
|
|
|
end
|
|
|
|
|
2017-06-29 13:01:54 +00:00
|
|
|
if self.sword > 0 then
|
|
|
|
self.sword = self.sword - 1
|
|
|
|
else
|
|
|
|
self.sword = 0
|
|
|
|
end
|
|
|
|
if self.sword == 1 then
|
|
|
|
entities_remove(sword)
|
|
|
|
end
|
|
|
|
|
2017-06-25 12:36:36 +00:00
|
|
|
if self.hit > 0 then
|
|
|
|
self.hit = self.hit - 1
|
|
|
|
end
|
|
|
|
|
2015-02-17 19:17:09 +00:00
|
|
|
-- gravity
|
2017-06-28 19:43:26 +00:00
|
|
|
if not on_the_ground then
|
2015-02-17 19:17:09 +00:00
|
|
|
self.yspeed = self.yspeed + self.yaccel * dt
|
2017-06-28 22:51:08 +00:00
|
|
|
self.yspeed = math.min(self.yspeed, self.max_yspeed)
|
2015-02-17 19:17:09 +00:00
|
|
|
self.y = self.y + dt * self.yspeed
|
|
|
|
end
|
|
|
|
|
|
|
|
-- jumping
|
2017-06-29 13:26:49 +00:00
|
|
|
if JOY_B and self.hit == 0 then
|
2015-08-20 19:37:09 +00:00
|
|
|
self.DO_JUMP = self.DO_JUMP + 1
|
|
|
|
else
|
|
|
|
self.DO_JUMP = 0
|
|
|
|
end
|
|
|
|
|
2017-06-25 22:43:48 +00:00
|
|
|
if self.DO_JUMP == 1 and JOY_DOWN
|
2017-07-01 18:33:19 +00:00
|
|
|
and not solid_at(self.x + 8, self.y + self.height + 3) then
|
2017-06-25 22:43:48 +00:00
|
|
|
self.y = self.y + 3
|
2017-06-28 19:43:26 +00:00
|
|
|
elseif self.DO_JUMP == 1 and on_the_ground then
|
2017-07-01 17:41:42 +00:00
|
|
|
self.y = self.y - 1 - self.yoffset
|
2017-06-28 22:13:41 +00:00
|
|
|
self.yspeed = -210
|
2017-06-25 10:04:06 +00:00
|
|
|
lutro.audio.play(sfx_jump)
|
2015-02-17 19:17:09 +00:00
|
|
|
end
|
|
|
|
|
2017-06-25 22:24:49 +00:00
|
|
|
-- variable jump height
|
2017-06-28 22:26:12 +00:00
|
|
|
if self.DO_JUMP > 1 and self.DO_JUMP <= 50 and self.yspeed < 0 then
|
2017-06-28 22:13:41 +00:00
|
|
|
self.yspeed = self.yspeed - 4
|
|
|
|
end
|
2017-06-25 22:24:49 +00:00
|
|
|
|
2017-06-28 22:26:12 +00:00
|
|
|
-- additionnal frames of hang time at the top of a high jump
|
|
|
|
if not on_the_ground and self.DO_JUMP > 1 and math.abs(self.yspeed) <= 20 then
|
|
|
|
self.y = self.y - dt * self.yspeed
|
|
|
|
end
|
|
|
|
|
2017-06-26 21:26:37 +00:00
|
|
|
-- throwing
|
2017-06-29 13:26:49 +00:00
|
|
|
if JOY_A and self.hit == 0 then
|
2017-06-26 21:26:37 +00:00
|
|
|
self.DO_THROW = self.DO_THROW + 1
|
|
|
|
else
|
|
|
|
self.DO_THROW = 0
|
|
|
|
end
|
|
|
|
|
2017-06-26 22:20:12 +00:00
|
|
|
if self.DO_THROW == 1 and self.throw == 0 then
|
2017-06-26 21:26:37 +00:00
|
|
|
lutro.audio.play(sfx_throw)
|
|
|
|
self.throw = 15
|
|
|
|
table.insert(entities, newShuriken())
|
|
|
|
end
|
|
|
|
|
2017-06-29 13:01:54 +00:00
|
|
|
-- sword swinging
|
|
|
|
if JOY_Y and self.hit == 0 then
|
|
|
|
self.DO_SWORD = self.DO_SWORD + 1
|
|
|
|
else
|
|
|
|
self.DO_SWORD = 0
|
|
|
|
end
|
|
|
|
|
|
|
|
if self.DO_SWORD == 1 and self.sword == 0 then
|
|
|
|
lutro.audio.play(sfx_throw)
|
2017-07-01 18:02:37 +00:00
|
|
|
self.sword = 15
|
2017-06-29 13:01:54 +00:00
|
|
|
sword = newSword(self)
|
|
|
|
table.insert(entities, sword)
|
|
|
|
end
|
|
|
|
|
2015-02-17 19:17:09 +00:00
|
|
|
-- moving
|
2017-07-01 17:16:05 +00:00
|
|
|
if JOY_LEFT and self.hit == 0 and self.sword == 0 and not JOY_DOWN then
|
2015-02-17 19:17:09 +00:00
|
|
|
self.xspeed = self.xspeed - self.xaccel * dt;
|
2017-06-28 21:24:01 +00:00
|
|
|
self.xspeed = math.max(self.xspeed, -self.max_xspeed)
|
2015-02-17 19:17:09 +00:00
|
|
|
self.direction = "left";
|
|
|
|
end
|
|
|
|
|
2017-07-01 17:16:05 +00:00
|
|
|
if JOY_RIGHT and self.hit == 0 and self.sword == 0 and not JOY_DOWN then
|
2015-02-17 19:17:09 +00:00
|
|
|
self.xspeed = self.xspeed + self.xaccel * dt;
|
2017-06-28 21:24:01 +00:00
|
|
|
self.xspeed = math.min(self.xspeed, self.max_xspeed)
|
2015-02-17 19:17:09 +00:00
|
|
|
self.direction = "right";
|
|
|
|
end
|
|
|
|
|
|
|
|
-- apply speed
|
|
|
|
self.x = self.x + self.xspeed * dt;
|
|
|
|
|
|
|
|
-- decelerating
|
2017-06-28 21:42:53 +00:00
|
|
|
self.friction = on_the_ground and self.groundfriction or self.airfriction
|
|
|
|
|
2017-06-28 22:51:08 +00:00
|
|
|
if not JOY_RIGHT and not JOY_LEFT
|
2015-02-17 19:17:09 +00:00
|
|
|
then
|
|
|
|
if self.xspeed > 0 then
|
2017-06-28 21:42:53 +00:00
|
|
|
self.xspeed = self.xspeed - self.friction
|
2015-02-17 19:17:09 +00:00
|
|
|
if self.xspeed < 0 then
|
|
|
|
self.xspeed = 0;
|
|
|
|
end
|
|
|
|
elseif self.xspeed < 0 then
|
2017-06-28 21:42:53 +00:00
|
|
|
self.xspeed = self.xspeed + self.friction;
|
2015-02-17 19:17:09 +00:00
|
|
|
if self.xspeed > 0 then
|
|
|
|
self.xspeed = 0;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- animations
|
2017-06-28 19:43:26 +00:00
|
|
|
if on_the_ground then
|
2015-02-17 19:17:09 +00:00
|
|
|
if self.xspeed == 0 then
|
|
|
|
self.stance = "stand"
|
|
|
|
else
|
|
|
|
self.stance = "run"
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if self.yspeed > 0 then
|
|
|
|
self.stance = "fall"
|
|
|
|
else
|
|
|
|
self.stance = "jump"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-07-01 17:41:42 +00:00
|
|
|
if on_the_ground and JOY_DOWN then
|
|
|
|
self.xspeed = 0
|
|
|
|
self.stance = "duck"
|
2017-06-25 08:16:29 +00:00
|
|
|
end
|
|
|
|
|
2017-06-26 21:26:37 +00:00
|
|
|
if self.throw > 0 then
|
|
|
|
self.stance = "throw"
|
|
|
|
end
|
|
|
|
|
2017-06-29 13:01:54 +00:00
|
|
|
if self.sword > 0 then
|
|
|
|
self.stance = "sword"
|
|
|
|
end
|
|
|
|
|
2017-06-25 12:36:36 +00:00
|
|
|
if self.hit > 0 then
|
|
|
|
self.stance = "hit"
|
|
|
|
end
|
|
|
|
|
2017-07-01 17:41:42 +00:00
|
|
|
if self.stance == "duck" then
|
|
|
|
if self.yoffset == 0 then
|
|
|
|
self.y = self.y + 16
|
|
|
|
end
|
|
|
|
self.yoffset = 16
|
|
|
|
self.height = 16
|
|
|
|
else
|
2017-07-01 19:22:41 +00:00
|
|
|
if self.yoffset == 16 then
|
|
|
|
self.y = self.y - 16
|
|
|
|
end
|
2017-07-01 17:41:42 +00:00
|
|
|
self.yoffset = 0
|
|
|
|
self.height = 32
|
|
|
|
end
|
|
|
|
|
2015-02-17 19:17:09 +00:00
|
|
|
local anim = self.animations[self.stance][self.direction]
|
|
|
|
-- always animate from first frame
|
|
|
|
if anim ~= self.anim then
|
|
|
|
anim.timer = 0
|
|
|
|
end
|
|
|
|
self.anim = anim;
|
|
|
|
|
|
|
|
self.anim:update(dt)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ninja:draw()
|
2017-07-01 17:41:42 +00:00
|
|
|
self.anim:draw(self.x - 16, self.y - 16 - self.yoffset)
|
2015-02-17 19:17:09 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
function ninja:on_collide(e1, e2, dx, dy)
|
2017-06-25 23:18:38 +00:00
|
|
|
|
|
|
|
if hp <= 0 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2017-06-25 08:43:05 +00:00
|
|
|
if e2.type == "ground" then
|
|
|
|
|
|
|
|
if math.abs(dy) < math.abs(dx) and dy ~= 0 then
|
2017-06-26 15:39:04 +00:00
|
|
|
if self.yspeed > 200 then
|
|
|
|
lutro.audio.play(sfx_step)
|
|
|
|
end
|
2017-06-25 08:43:05 +00:00
|
|
|
self.yspeed = 0
|
|
|
|
self.y = self.y + dy
|
|
|
|
end
|
|
|
|
|
|
|
|
if math.abs(dx) < math.abs(dy) and dx ~= 0 then
|
|
|
|
self.xspeed = 0
|
|
|
|
self.x = self.x + dx
|
|
|
|
end
|
2015-02-17 19:17:09 +00:00
|
|
|
|
2017-06-26 15:39:04 +00:00
|
|
|
elseif e2.type == "bridge" or e2.type == "elevator" then
|
2017-06-25 21:56:38 +00:00
|
|
|
|
2017-06-25 22:43:48 +00:00
|
|
|
if math.abs(dy) < math.abs(dx) and dy ~= 0 and self.yspeed > 0
|
2017-06-26 15:39:04 +00:00
|
|
|
and not JOY_DOWN
|
|
|
|
and self.y + self.height > e2.y
|
|
|
|
then
|
2017-06-25 21:56:38 +00:00
|
|
|
self.yspeed = 0
|
|
|
|
self.y = self.y + dy
|
|
|
|
lutro.audio.play(sfx_step)
|
|
|
|
end
|
|
|
|
|
2017-06-26 00:23:54 +00:00
|
|
|
elseif e2.type == "spikes" then
|
|
|
|
|
|
|
|
hp = 0
|
|
|
|
|
2017-07-01 16:50:19 +00:00
|
|
|
elseif (e2.type == "obake" or e2.type == "porc" or e2.type == "demon")
|
|
|
|
and self.hit == 0 and e2.die == 0 then
|
2017-06-25 12:36:36 +00:00
|
|
|
|
2017-06-25 12:43:05 +00:00
|
|
|
lutro.audio.play(sfx_hit)
|
2017-06-29 14:06:03 +00:00
|
|
|
screen_shake = 15
|
2017-06-25 12:36:36 +00:00
|
|
|
self.hit = 60
|
|
|
|
if dx > 0 then
|
|
|
|
self.xspeed = 200
|
|
|
|
else
|
|
|
|
self.xspeed = -200
|
|
|
|
end
|
|
|
|
self.y = self.y - 1
|
|
|
|
self.yspeed = -1
|
2017-06-25 12:43:05 +00:00
|
|
|
hp = hp - 1
|
2017-06-25 12:36:36 +00:00
|
|
|
|
2017-07-01 16:50:19 +00:00
|
|
|
elseif (e2.type == "fireball")
|
|
|
|
and self.hit == 0 and e2.die == 0 then
|
|
|
|
|
|
|
|
lutro.audio.play(sfx_hit)
|
|
|
|
screen_shake = 15
|
|
|
|
self.hit = 60
|
|
|
|
if dx > 0 then
|
|
|
|
self.xspeed = 200
|
|
|
|
else
|
|
|
|
self.xspeed = -200
|
|
|
|
end
|
|
|
|
self.y = self.y - 1
|
|
|
|
self.yspeed = -1
|
|
|
|
hp = hp - 1
|
2015-02-17 19:17:09 +00:00
|
|
|
end
|
2015-03-05 03:47:22 +00:00
|
|
|
end
|