diff --git a/assets/characters/kupo/kupo_arrow1.ase b/assets/characters/kupo/kupo_arrow1.ase new file mode 100644 index 0000000..9381795 Binary files /dev/null and b/assets/characters/kupo/kupo_arrow1.ase differ diff --git a/assets/characters/kupo/kupo_arrow1.png b/assets/characters/kupo/kupo_arrow1.png new file mode 100644 index 0000000..000c649 Binary files /dev/null and b/assets/characters/kupo/kupo_arrow1.png differ diff --git a/assets/characters/kupo/kupo_bow.ase b/assets/characters/kupo/kupo_bow.ase index c789409..6ba4e32 100644 Binary files a/assets/characters/kupo/kupo_bow.ase and b/assets/characters/kupo/kupo_bow.ase differ diff --git a/assets/terrain/background.png b/assets/terrain/background.png deleted file mode 100644 index 7903666..0000000 Binary files a/assets/terrain/background.png and /dev/null differ diff --git a/assets/terrain/bg_0.png b/assets/terrain/bg_0.png deleted file mode 100644 index 36250bc..0000000 Binary files a/assets/terrain/bg_0.png and /dev/null differ diff --git a/assets/terrain/bg_1.png b/assets/terrain/bg_1.png deleted file mode 100644 index ff50f9a..0000000 Binary files a/assets/terrain/bg_1.png and /dev/null differ diff --git a/assets/terrain/bg_2.png b/assets/terrain/bg_2.png deleted file mode 100644 index 1187e6c..0000000 Binary files a/assets/terrain/bg_2.png and /dev/null differ diff --git a/assets/terrain/fg_0.png b/assets/terrain/fg_0.png deleted file mode 100644 index b21d7d1..0000000 Binary files a/assets/terrain/fg_0.png and /dev/null differ diff --git a/assets/terrain/fg_1.png b/assets/terrain/fg_1.png deleted file mode 100644 index acf2ec2..0000000 Binary files a/assets/terrain/fg_1.png and /dev/null differ diff --git a/assets/terrain/tileset2.png b/assets/terrain/tileset2.png deleted file mode 100644 index 0dc2aa1..0000000 Binary files a/assets/terrain/tileset2.png and /dev/null differ diff --git a/assets/terrain/waterfall_anim.gif b/assets/terrain/waterfall_anim.gif deleted file mode 100644 index a7724fe..0000000 Binary files a/assets/terrain/waterfall_anim.gif and /dev/null differ diff --git a/assets/terrain/waterfall_anim_strip_4.png b/assets/terrain/waterfall_anim_strip_4.png deleted file mode 100644 index 871d47e..0000000 Binary files a/assets/terrain/waterfall_anim_strip_4.png and /dev/null differ diff --git a/assets/terrain/waterfall_bottom_anim.gif b/assets/terrain/waterfall_bottom_anim.gif deleted file mode 100644 index 8237dc5..0000000 Binary files a/assets/terrain/waterfall_bottom_anim.gif and /dev/null differ diff --git a/assets/terrain/waterfall_bottom_anim_strip_4.png b/assets/terrain/waterfall_bottom_anim_strip_4.png deleted file mode 100644 index 8ac0191..0000000 Binary files a/assets/terrain/waterfall_bottom_anim_strip_4.png and /dev/null differ diff --git a/data/scripts/debug.lua b/data/scripts/debug.lua index a4470d0..5ef3125 100644 --- a/data/scripts/debug.lua +++ b/data/scripts/debug.lua @@ -6,9 +6,9 @@ love.graphics.print("time: "..fps_total..", fps: "..fps_draw..", frametime: "..m love.graphics.print("[main_Player]",10*textScale,40*textScale, 0, textScale) love.graphics.print("position: {"..main_Player.pos.x..", "..main_Player.pos.y.."}",10*textScale,60*textScale, 0, textScale) love.graphics.print("velocity: {"..main_Player.vel.x..", "..main_Player.vel.y.."}",10*textScale,80*textScale, 0, textScale) - love.graphics.print("scale: {"..main_Player.scale.x..", "..main_Player.scale.y.."}",10*textScale,100*textScale, 0, textScale) - love.graphics.print("sprite: "..tostring(main_Player.sprite)..", anim_speed: "..main_Player.anim_speed,10*textScale,120*textScale, 0, textScale) - love.graphics.print("booleans: \"isOnGround\": "..tostring(main_Player.isOnGround),10*textScale,140*textScale, 0, textScale) + love.graphics.print("scale: {"..main_Player.sprite_scale.x..", "..main_Player.sprite_scale.y.."}",10*textScale,100*textScale, 0, textScale) + love.graphics.print("anim: "..tostring(main_Player.anim.path)..", anim.speed: "..main_Player.anim.speed,10*textScale,120*textScale, 0, textScale) + love.graphics.print("states: \"isOnGround\": "..tostring(main_Player.isOnGround),10*textScale,140*textScale, 0, textScale) love.graphics.print("[Camera]",10*textScale,160*textScale, 0, textScale) love.graphics.print("position: {"..Camera.pos.x..", "..Camera.pos.y.."}",10*textScale,180*textScale, 0, textScale) diff --git a/data/scripts/entities/arrow.lua b/data/scripts/entities/arrow.lua new file mode 100644 index 0000000..4c2d6b1 --- /dev/null +++ b/data/scripts/entities/arrow.lua @@ -0,0 +1,57 @@ +Arrow = Entity:New(x,y) + + function Arrow:New(x,y,rotation,speed) + local o = Entity:New(x,y) + + o.pos = {x = x, y = y} + o.speed = speed or 0 + o.sprite_rotation = rotation or 0 + o.vel = { + x = o.speed * math.cos(o.sprite_rotation), + y = o.speed * math.sin(o.sprite_rotation) + } + o.sprite_offset = {x = 13, y = 1} + o.stuck = false + + setmetatable(o, self) + self.__index = self + table.insert(LoadedEntities,o) + return o + end + +function Arrow:Smart() + +end + +function Arrow:HandleAnimation() + self:LoadAnimation(animation.kupo.arrow) +end + +function Arrow:DoPhysics() + -- horizontal collisions + if not isThereAnyCollisionAt(self.pos.x + self.vel.x, self.pos.y) then + self.pos.x = self.pos.x + self.vel.x + else + while not isThereCollisionAt(self.pos.x + math.sign(self.vel.x), self.pos.y) do + self.pos.x = self.pos.x + math.sign(self.vel.x) + end + self.stuck = true + end + -- vertical collision + if not isThereAnyCollisionAt(self.pos.x, self.pos.y + self.vel.y) then + self.pos.y = self.pos.y + self.vel.y + else + while not isThereCollisionAt(self.pos.x, self.pos.y + math.sign(self.vel.y)) do + self.pos.y = self.pos.y + math.sign(self.vel.y) + end + self.stuck = true + end + -- stuck into collisions + if self.stuck then + --lets allow the arrow to tip a bit into the thing + self.pos.x = self.pos.x + self.vel.x / 5 + self.pos.y = self.pos.y + self.vel.y / 5 + self.vel.x = 0 + self.vel.y = 0 + end +end diff --git a/data/scripts/entities/kupo.lua b/data/scripts/entities/kupo.lua index ff5a9ec..e4bcd33 100644 --- a/data/scripts/entities/kupo.lua +++ b/data/scripts/entities/kupo.lua @@ -5,22 +5,148 @@ Kupo = Entity:New(x,y) o.pos = {x = x, y = y} o.speed = 20 - o.range = 1000 - + o.range = 200 + o.target = {x = x, y = y} + o.sprite_offset = {x = 8, y = 5} + -- kupo bow + o.bow = self:NewAnimation(animation.kupo.bow) + o.bow_flip = 1 + o.bow_rotation = 0 + o.bow_frame = 1 + o.bow_subframe = 1 + o.bow_aim_frame = 0 + o.bow_speed = 1/10 + o.bow_frames = 6 + o.bow_extraframes = 18 + o.bow_aim_frames = 8 setmetatable(o, self) self.__index = self return o end -function Kupo:DoInput() +function Kupo:Smart() + self.target.x = main_Player.pos.x - main_Player.target_offset.x + self.target.y = main_Player.pos.y - main_Player.target_offset.y + local distance_x = self.target.x - self.pos.x + local distance_y = self.target.y - self.pos.y + local distance = math.sqrt(distance_x ^ 2 + distance_y ^ 2) + local angle = math.atan(distance_y/distance_x) + + if distance <= self.range then + self.draw_bow = true + + if distance_x > 0 then + self.sprite_flip.x = 1 + else + angle = angle + math.rad(180) + end + + -- fix so it can rotate from 0 to 360 + if math.deg(self.bow_rotation - angle) < 0 then + self.bow_rotation = self.bow_rotation + math.rad(360) + end + + -- fix so it can rotate from 360 to 0 + if math.deg(self.bow_rotation - angle) > 180 then + self.bow_rotation = self.bow_rotation - math.rad(360) + end + + -- actual rotation + if self.bow_rotation < angle then + self.bow_rotation = self.bow_rotation + math.rad(2) + else + self.bow_rotation = self.bow_rotation - math.rad(2) + end + --set in place + if math.abs(math.deg(self.bow_rotation) - math.deg(angle)) < 2 then + self.bow_rotation = angle + end + + -- holding tight dispersion -- also affets arrows + if self.bow_rotation == angle then + self.bow_rotation = self.bow_rotation + math.rad(math.random(math.abs(self.bow_frame-self.bow_aim_frames-self.bow_frames)/2)) + end + + -- AIMING AI + + self.bow_subframe = self.bow_subframe + current_dt + + if self.bow_subframe > self.bow_speed then + self.bow_subframe = self.bow_subframe - self.bow_speed + if self.bow_frame == 3 then + self.bow_aim_frame = self.bow_aim_frame + 1 + if self.bow_aim_frame > self.bow_aim_frames then + self.bow_aim_frame = self.bow_aim_frame - self.bow_aim_frames + self.bow_frame = self.bow_frame + 1 + Arrow:New(self.pos.x,self.pos.y,self.bow_rotation,30) + end + else + self.bow_frame = self.bow_frame + 1 + end + if self.bow_frame > self.bow_frames + self.bow_extraframes then + self.bow_frame = self.bow_frame - self.bow_frames - self.bow_extraframes + end + end + else + self.bow_frame = 6 + self.draw_bow = true + -- rest bow animation + if distance_x > 0 then + if self.bow_rotation > math.rad(45) then + self.bow_rotation = self.bow_rotation - math.rad(3) + elseif self.bow_rotation < math.rad(45) then + self.bow_rotation = self.bow_rotation + math.rad(3) + end + + -- set in place + if math.abs(math.deg(self.bow_rotation) - 45) < 3 then + self.bow_rotation = math.rad(45) + end + self.sprite_flip.x = 1 + else + if self.bow_rotation > math.rad(135) then + self.bow_rotation = self.bow_rotation - math.rad(3) + elseif self.bow_rotation < math.rad(135) then + self.bow_rotation = self.bow_rotation + math.rad(3) + end + -- set in place + if math.abs(math.deg(self.bow_rotation) - 135) < 3 then + self.bow_rotation = math.rad(135) + end + self.sprite_flip.x = -1 + end + end + self.angle = angle end function Kupo:HandleAnimation() -- flip sprite to look in the direction is moving - if self.vel.x ~= 0 then self.flip.x = math.sign(self.vel.x) end + if self.vel.x ~= 0 then self.sprite_flip.x = math.sign(self.vel.x) end self:LoadAnimation(animation.kupo.body) + if self.draw_bow == true then + DrawAnimationFrame( + self.bow, + math.min(self.bow_frame,self.bow_frames), + self.pos.x + ( 8 * math.sin(self.bow_rotation)) * game.scale, + self.pos.y + (2 - 6 * math.cos(self.bow_rotation)) * game.scale, + self.bow_rotation + ) + end +if debug_collision then + love.graphics.setColor(1,0,0) + love.graphics.line( + self.pos.x - Camera.pos.x, + self.pos.y - Camera.pos.y, + self.target.x - Camera.pos.x, + self.target.y - Camera.pos.y + ) + love.graphics.circle( "line", self.pos.x - Camera.pos.x, self.pos.y - Camera.pos.y, self.range ) + love.graphics.setColor(1,1,1) + love.graphics.print(self.bow_rotation, self.pos.x, self.pos.y+30) + love.graphics.print(self.angle, self.pos.x, self.pos.y+50) + end end function Kupo:DoPhysics() diff --git a/data/scripts/entities/player.lua b/data/scripts/entities/player.lua index 4a58123..fb25470 100644 --- a/data/scripts/entities/player.lua +++ b/data/scripts/entities/player.lua @@ -1,6 +1,44 @@ Player = Entity:New(x,y) -function Player:DoInput() + + function Player:New(x,y) + local o = Entity:New(x,y) + Player.health = 3 + Player.coins = 0 + + -- physics + o.vel = { + x = 0, + y = 0 + } + -- constants + o.acc = 90 + o.friction = 20 + o.gravity = 9.81 + o.climbHeight = 4 + o.jumpForce = 5 + o.maxSpeed = 600 + o.jumpMaxSpeed = 9.5 + o.zeroSpeed = 0.001 + -- bools + o.isJumping = false + o.isOnGround = 0 + o.coyoteValue = 10 + o.isOnLadder = false + o.canJump = true + o.canFall = true + o.canFriction = true + + -- sprite + o.sprite_offset = {x = 8, y = 16} + o.target_offset = {x = 4, y = 12} + setmetatable(o, self) + self.__index = self + + return o + end + +function Player:Smart() -- PLATFORMER INPUT if self.isOnGround > 0 then -- apply friction @@ -42,7 +80,7 @@ end function Player:HandleAnimation() -- flip sprite to look in the direction is moving - if self.vel.x ~= 0 then self.flip.x = math.sign(self.vel.x) end + if self.vel.x ~= 0 then self.sprite_flip.x = math.sign(self.vel.x) end -- animation manager if self.isOnLadder then @@ -163,40 +201,3 @@ function Player:DoPhysics() self.vel.x = self.vel.x * (1 - math.min(current_dt * self.friction/20, 1)) end end - - -function Player:New(x,y) - local o = Entity:New(x,y) - Player.health = 3 - Player.coins = 0 - - -- physics - o.vel = { - x = 0, - y = 0 - } - -- constants - o.acc = 90 - o.friction = 20 - o.gravity = 9.81 - o.climbHeight = 4 - o.jumpForce = 5 - o.maxSpeed = 600 - o.jumpMaxSpeed = 9.5 - o.zeroSpeed = 0.001 - -- bools - o.isJumping = false - o.isOnGround = 0 - o.coyoteValue = 10 - o.isOnLadder = false - o.canJump = true - o.canFall = true - o.canFriction = true - - -- sprite - o.offset = {x = -8, y = -16} - setmetatable(o, self) - self.__index = self - - return o -end diff --git a/data/scripts/entity.lua b/data/scripts/entity.lua index 17f71e4..b5c25cd 100644 --- a/data/scripts/entity.lua +++ b/data/scripts/entity.lua @@ -6,12 +6,15 @@ function Entity:New(x,y) o.pos = {x = x, y = y} o.vel = {x = 0, y = 0} o.class = "Entity" - o.anim_subframe = 0 - o.anim_frame = 0 - o.anim_imgs = {} - o.offset = {x = 0, y = 0} - o.scale = {x = 1, y = 1} - o.flip = { x = 1, y = 1} + o.anim = {} + o.anim.subframe = 0 + o.anim.frame = 1 + o.anim.imgs = {} + o.animations = {} + o.sprite_offset = {x = 0, y = 0} + o.sprite_scale = {x = 1, y = 1} + o.sprite_rotation = math.rad(0) + o.sprite_flip = { x = 1, y = 1} setmetatable(o, self) self.__index = self return o @@ -23,52 +26,128 @@ end function Entity:Draw() if self.sprite ~= nil then + local relative_position_x = self.pos.x - Camera.pos.x + local relative_position_y = self.pos.y - Camera.pos.y + local origin_compensation_x = - ( (self.sprite_offset.x) * math.cos(self.sprite_rotation) - (self.sprite_offset.y) * math.sin(self.sprite_rotation)) * game.scale + local origin_compensation_y = - ( (self.sprite_offset.x) * math.sin(self.sprite_rotation) + (self.sprite_offset.y) * math.cos(self.sprite_rotation)) * game.scale + local dimensions_x = self.sprite_scale.x * self.sprite_flip.x + local dimensions_y = self.sprite_scale.y * self.sprite_flip.y love.graphics.draw( self.sprite, - self.pos.x - Camera.pos.x + self.offset.x * game.scale * self.scale.x * self.flip.x, - self.pos.y - Camera.pos.y + self.offset.y * game.scale * self.scale.y * self.flip.y, - 0, - game.scale * self.scale.x * self.flip.x, - game.scale * self.scale.y * self.flip.y + relative_position_x + origin_compensation_x * dimensions_x, + relative_position_y + origin_compensation_y * dimensions_y, + self.sprite_rotation, + game.scale * self.sprite_scale.x * self.sprite_flip.x, + game.scale * self.sprite_scale.y * self.sprite_flip.y ) + if debug_collision then + love.graphics.setColor(1, 0, 0) + love.graphics.circle( "line", relative_position_x, relative_position_y, 2 ) + love.graphics.setColor(0, 1 ,0) + love.graphics.circle( "line", + relative_position_x + origin_compensation_x * dimensions_x, + relative_position_y + origin_compensation_y * dimensions_y, + 2 + ) + end + love.graphics.setColor(1, 1 ,1) end end +function Entity:NewAnimation(anim,frames,speed) + local anim_data = { + frame = 1, + subframe = 1, + path = anim.path, + frames = anim.frames, + speed = anim.speed, + imgs = anim.imgs + } + self.animations[#self.animations+1] = anim_data + + return self.animations[#self.animations] +end + +function DrawAnimationFrame(animation, frame, x, y, rotate, sx, sy) + local x = x or 0 + local y = y or 0 + local sx = sx or 1 + local sy = sy or 1 + love.graphics.draw( + animation.imgs[frame], + x - Camera.pos.x, + y - Camera.pos.y, + rotate, + game.scale * sx, + game.scale * sy + ) +end + +function DrawAnimation(animation, x, y, rotate, sx, sy) + local x = x or 0 + local y = y or 0 + local sx = sx or 1 + local sy = sy or 1 + if game_paused ~= true then + -- try to animate + animation.subframe = animation.subframe + current_dt + + if animation.subframe >= animation.speed then + animation.frame = animation.frame + 1 + animation.subframe = animation.subframe - animation.speed + end + + -- cycle + if animation.frame >= animation.frames+1 then + animation.frame = animation.frame - animation.frames + end + end + love.graphics.draw( + animation.imgs[animation.frame], + x - Camera.pos.x, + y - Camera.pos.y, + rotate, + game.scale * sx, + game.scale * sy + ) +end + function Entity:Animate() if game_paused ~= true then -- try to animate - self.anim_subframe = self.anim_subframe + current_dt + self.anim.subframe = self.anim.subframe + current_dt - if self.anim_subframe >= self.anim_speed then - self.anim_frame = self.anim_frame + 1 - self.anim_subframe = self.anim_subframe - self.anim_speed + if self.anim.subframe >= self.anim.speed then + self.anim.frame = self.anim.frame + 1 + self.anim.subframe = self.anim.subframe - self.anim.speed end -- cycle - if self.anim_frame >= self.anim_frames+1 then - self.anim_frame = self.anim_frame - self.anim_frames + if self.anim.frame >= self.anim.frames+1 then + self.anim.frame = self.anim.frame - self.anim.frames end -- change - self.sprite = self.anim_imgs[self.anim_frame] + self.sprite = self.anim.imgs[self.anim.frame] end end function Entity:LoadAnimation(anim,frames,speed) - if self.anim_path ~= anim and self.anim_path ~= anim.path then + if self.anim.path ~= anim and self.anim.path ~= anim.path then if frames ~= nil and speed ~= nil then - self.anim_path = anim or nil - self.anim_frames = frames or 4 - self.anim_speed = speed or frames + self.anim.path = anim or nil + self.anim.frames = frames or 4 + self.anim.speed = speed or frames else - self.anim_path = anim.path - self.anim_frames = anim.frames - self.anim_speed = anim.speed + self.anim.path = anim.path + self.anim.frames = anim.frames + self.anim.speed = anim.speed end - self.anim_imgs = anim.imgs + self.anim.imgs = anim.imgs end end require "data/scripts/entities/kupo" +require "data/scripts/entities/arrow" require "data/scripts/entities/player" diff --git a/data/scripts/enums.lua b/data/scripts/enums.lua index de9de92..f5bfc0b 100644 --- a/data/scripts/enums.lua +++ b/data/scripts/enums.lua @@ -1,6 +1,3 @@ -image = { - background = love.graphics.newImage("assets/terrain/background.png") -} -- animations animation = { kupo = { @@ -12,7 +9,12 @@ animation = { bow = { path = "assets/characters/kupo/kupo_bow", frames = 6, - speed = 1/8 + speed = 1/10 + }, + arrow = { + path = "assets/characters/kupo/kupo_arrow", + frames = 1, + speed = 1 } }, nancy = { diff --git a/data/scripts/math.lua b/data/scripts/math.lua index 5501086..f2e3a48 100644 --- a/data/scripts/math.lua +++ b/data/scripts/math.lua @@ -6,4 +6,4 @@ function math.sign(x) else return 0 end -end \ No newline at end of file +end diff --git a/main.lua b/main.lua index 77b0989..1420dd3 100644 --- a/main.lua +++ b/main.lua @@ -11,7 +11,7 @@ function love.load() love.keyboard.setKeyRepeat(true) love.graphics.setDefaultFilter("nearest") -- good pixel game = { - scale = 2, + scale = 1, width = love.graphics.getWidth(), height = love.graphics.getHeight(), paused = false @@ -26,7 +26,8 @@ function love.load() main_Player = Player:New(1220,220) LoadedEntities = {} table.insert(LoadedEntities,main_Player) - table.insert(LoadedEntities,Kupo:New(800,200)) + table.insert(LoadedEntities,Kupo:New(700,200)) + table.insert(LoadedEntities,Kupo:New(500,300)) main_Player.sprite = love.graphics.newImage("assets/characters/nancy/idle1.png") main_Player:LoadAnimation(animation.nancy.idle) end @@ -52,10 +53,8 @@ function love.update(dt) if not do_pause then SetCollisionFlags(main_Player) for _, enty in pairs(LoadedEntities) do - enty:DoInput() + enty:Smart() enty:DoPhysics() - enty:HandleAnimation() - enty:Animate() end AnimateTiles() Camera:CenterAt(main_Player.pos.x, main_Player.pos.y,LevelInfo.Width,LevelInfo.Height) @@ -105,6 +104,8 @@ end function love.draw() LevelDisplayBackground() for _, enty in pairs(LoadedEntities) do + enty:HandleAnimation() + enty:Animate() enty:Draw() end LevelDisplayForeground()