From 664d57ee0fee78a624796c3712abbe7d1a708497 Mon Sep 17 00:00:00 2001 From: Aki Date: Wed, 11 May 2016 22:23:07 +0200 Subject: Initial commit :boom: --- .gitignore | 2 + animations.lua | 45 ++++++++++++ assets/readme.md | 2 + conf.lua | 7 ++ ground.lua | 24 ++++++ main.lua | 104 ++++++++++++++++++++++++++ player.lua | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 404 insertions(+) create mode 100644 .gitignore create mode 100644 animations.lua create mode 100644 assets/readme.md create mode 100644 conf.lua create mode 100644 ground.lua create mode 100644 main.lua create mode 100644 player.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d4df9a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.png +*.xcf \ No newline at end of file diff --git a/animations.lua b/animations.lua new file mode 100644 index 0000000..b7bcf3d --- /dev/null +++ b/animations.lua @@ -0,0 +1,45 @@ +-- Animations spritesheet array for `Player` +local animations = { + idle = { + [1] = love.graphics.newQuad( 1, 1, 24,24, 376,26), + frames = 1, + repeated = true + }, + walk = { + [1] = love.graphics.newQuad( 1, 1, 24,24, 376,26), + [2] = love.graphics.newQuad( 26, 1, 24,24, 376,26), + [3] = love.graphics.newQuad( 51, 1, 24,24, 376,26), + [4] = love.graphics.newQuad( 76, 1, 24,24, 376,26), + frames = 4, + repeated = true + }, + attack = { + [1] = love.graphics.newQuad(101, 1, 24,24, 376,26), + [2] = love.graphics.newQuad(126, 1, 24,24, 376,26), + [3] = love.graphics.newQuad(151, 1, 24,24, 376,26), + frames = 3, + repeated = false + }, + attack_up = { + [1] = love.graphics.newQuad(176, 1, 24,24, 376,26), + [2] = love.graphics.newQuad(201, 1, 24,24, 376,26), + [3] = love.graphics.newQuad(226, 1, 24,24, 376,26), + frames = 3, + repeated = false + }, + attack_down = { + [1] = love.graphics.newQuad(251, 1, 24,24, 376,26), + [2] = love.graphics.newQuad(276, 1, 24,24, 376,26), + [3] = love.graphics.newQuad(301, 1, 24,24, 376,26), + frames = 3, + repeated = false + }, + damage = { + [1] = love.graphics.newQuad(326, 1, 24,24, 376,26), + [2] = love.graphics.newQuad(326, 1, 24,24, 376,26), + [3] = love.graphics.newQuad(351, 1, 24,24, 376,26), + frames = 3, + repeated = false + }, +} +return animations \ No newline at end of file diff --git a/assets/readme.md b/assets/readme.md new file mode 100644 index 0000000..7059265 --- /dev/null +++ b/assets/readme.md @@ -0,0 +1,2 @@ +# Duh! +Not on [Github](http://github.com/). \ No newline at end of file diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..51841e1 --- /dev/null +++ b/conf.lua @@ -0,0 +1,7 @@ +function love.conf(t) + t.title = "notnauts" + t.version = "0.10.1" + t.window.width = 290 + t.window.height = 200 + t.console = true +end \ No newline at end of file diff --git a/ground.lua b/ground.lua new file mode 100644 index 0000000..47c4ec7 --- /dev/null +++ b/ground.lua @@ -0,0 +1,24 @@ +-- `Ground` +-- Collision category: [1] + +-- Metatable of `Ground` +-- nils initialized in constructor +Ground = { + body = nil, + shape = nil, + fixture = nil, + sprite = nil +} +-- Constructor of `Ground` +function Ground:new (world, x, y, shape, sprite) + local o = {} + setmetatable(o, self) + self.__index = self + o.body = love.physics.newBody(world, x, y) + o.shape = love.physics.newPolygonShape(shape) + o.fixture = love.physics.newFixture(o.body, o.shape) + o.sprite = love.graphics.newImage(sprite) + o.fixture:setCategory(1) + o.fixture:setFriction(0.7) + return o +end \ No newline at end of file diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..b534665 --- /dev/null +++ b/main.lua @@ -0,0 +1,104 @@ +require "ground" +require "player" + +debug = false + +function love.load() + -- Graphics + love.graphics.setBackgroundColor(189, 95, 93) + love.graphics.setDefaultFilter("nearest", "nearest") + + -- World physics + love.physics.setMeter(64) + world = love.physics.newWorld(0, 9.81*64, true) + world:setCallbacks(beginContact, endContact, preSolve, postSolve) + + -- Platforms (`Ground`) + Platforms = {} + table.insert(Platforms, Ground:new(world, 290/2, 180/2, {-91,0, 90,0, 90,10, 5,76, -5,76, -91,10}, "assets/platform_big.png")) + table.insert(Platforms, Ground:new(world, 290/2+140, 180/2+50, {-26,0, 26,0, 26,30, -26,30}, "assets/platform_small.png")) + table.insert(Platforms, Ground:new(world, 290/2-140, 180/2+50, {-26,0, 26,0, 26,30, -26,30}, "assets/platform_small.png")) + table.insert(Platforms, Ground:new(world, 290/2, 180/2-50, {-17,0, 17,0, 17,17, -17,17}, "assets/platform_top.png")) + + -- Nauts (`Player`) + Nauts = {} + table.insert(Nauts, Player:new(world, 290/2-10, 180/2 - 80, "assets/leon.png")) + table.insert(Nauts, Player:new(world, 290/2+10, 180/2 - 80, "assets/lonestar.png")) + + -- Temporary settings for second player + Nauts[2].name = "Player2" + Nauts[2].key_left = "a" + Nauts[2].key_right = "d" + Nauts[2].key_up = "w" + Nauts[2].key_down = "s" + Nauts[2].key_jump = "h" + Nauts[2].key_hit = "g" +end + +function love.update(dt) + -- Put world in motion! + world:update(dt) + -- Players + for k,naut in pairs(Nauts) do + naut:update(dt) + end +end + +function love.keypressed(key) + -- Switch hitbox display on/off + if key == "x" then + debug = not debug + end + -- Players + for k,naut in pairs(Nauts) do + naut:keypressed(key) + end +end + +function love.keyreleased(key) + -- Players + for k,naut in pairs(Nauts) do + naut:keyreleased(key) + end +end + +function love.draw() + -- Draw ground + for k,platform in pairs(Platforms) do + love.graphics.setColor(255,255,255,255) + love.graphics.draw(platform.sprite, platform.body:getX()-math.ceil(platform.sprite:getWidth()/2), platform.body:getY()) + if debug then + love.graphics.setColor(220, 220, 220, 100) + love.graphics.polygon("fill", platform.body:getWorldPoints(platform.shape:getPoints())) + end + end + + -- Draw player + for k,naut in pairs(Nauts) do + love.graphics.setColor(255,255,255,255) + love.graphics.draw(naut.sprite, naut.current[naut.frame], naut.body:getX(), naut.body:getY(), naut.rotate, naut.facing, 1, 12, 15) + if debug then + love.graphics.setColor(50, 255, 50, 100) + love.graphics.polygon("fill", naut.body:getWorldPoints(naut.shape:getPoints())) + love.graphics.setColor(255,255,255,255) + love.graphics.points(naut.body:getX()+12*naut.facing,naut.body:getY()-2) + love.graphics.points(naut.body:getX()+6*naut.facing,naut.body:getY()+2) + love.graphics.points(naut.body:getX()+18*naut.facing,naut.body:getY()+2) + love.graphics.points(naut.body:getX()+12*naut.facing,naut.body:getY()+6) + end + end +end + +function beginContact(a, b, coll) + local x,y = coll:getNormal() + if y == -1 then + print(b:getUserData().name .. " is not in air") + b:getUserData().inAir = false + b:getUserData().jumpdouble = true + end +end + +function endContact(a, b, coll) + print(b:getUserData().name .. " is in air") + b:getUserData().inAir = true +end \ No newline at end of file diff --git a/player.lua b/player.lua new file mode 100644 index 0000000..b0604c3 --- /dev/null +++ b/player.lua @@ -0,0 +1,220 @@ +-- `Player` +-- Collision category: [2] + +-- Metatable of `Player` +-- nils initialized in constructor +Player = { + -- General and physics + name = "Player", + body = nil, + shape = nil, + fixture = nil, + sprite = nil, + rotate = 0, -- "angle" would sound better + facing = 1, + max_velocity = 105, + combo = 1, + -- Animation + animations = require "animations", + current = nil, + frame = 1, + delay = 0.10, + initial = nil, + -- Movement + inAir = true, + jumpactive = false, + jumpdouble = true, + jumptimer = 0.14, + -- Keys + key_jump = "rshift", + key_left = "left", + key_right = "right", + key_up = "up", + key_down = "down", + key_hit = "return" -- don't ask +} + +-- Constructor of `Player` +function Player:new(world, x, y, spritesheet) + -- Meta + local o = {} + setmetatable(o, self) + self.__index = self + -- Physics + o.body = love.physics.newBody(world, x, y, "dynamic") + o.shape = love.physics.newRectangleShape(10, 17) + o.fixture = love.physics.newFixture(o.body, o.shape, 8) + o.sprite = love.graphics.newImage(spritesheet) + o.fixture:setUserData(o) + o.fixture:setCategory(2) + o.fixture:setMask(2) + o.body:setFixedRotation(true) + o.body:setLinearDamping(0.1) + -- Animation + o.initial = o.delay + o.current = o.animations.idle + return o +end + +-- Update callback of `Player` +function Player:update(dt) + -- Jumping + if self.jumpactive and self.jumptimer > 0 then + local x,y = self.body:getLinearVelocity() + self.body:setLinearVelocity(x,-160) + self.jumptimer = self.jumptimer - dt + end + + -- Walking + if love.keyboard.isDown(self.key_left) then + self.facing = -1 + local x,y = self.body:getLinearVelocity() + if math.abs(x) > self.max_velocity then + self.body:applyForce(-200, 0) + else + self.body:setLinearVelocity(-self.max_velocity/2, y) + end + end + if love.keyboard.isDown(self.key_right) then + self.facing = 1 + local x,y = self.body:getLinearVelocity() + if math.abs(x) > self.max_velocity then + self.body:applyForce(200, 0) + else + self.body:setLinearVelocity(self.max_velocity/2, y) + end + end + + -- Animation + self.delay = self.delay - dt + if self.delay < 0 then + self.delay = self.delay + self.initial + -- Thank you De Morgan! + if self.current.repeated or not (self.frame == self.current.frames) then + self.frame = (self.frame % self.current.frames) + 1 + elseif love.keyboard.isDown(self.key_right) or + love.keyboard.isDown(self.key_left) + then + -- If nonrepeatable animation is finished and player is walking + self:changeAnimation("walk") + elseif self.current == self.animations.damage then + self:changeAnimation("idle") + end + end + + -- Salto mothafocka + if not self.jumpdouble and self.inAir then + self.rotate = (self.rotate + 17 * dt * self.facing) % 360 + else + self.rotate = 0 + end + + --[[ + -- Limit `Player` horizontal speed + -- Maximum speed may be actually a little bit higher or lower + local x,y = self.body:getLinearVelocity() + if x > self.max_velocity then + self.body:setLinearVelocity(self.max_velocity, y) + end + if x < -self.max_velocity then + self.body:setLinearVelocity(-self.max_velocity, y) + end + --]] +end + +-- Keypressed callback of `Player` +function Player:keypressed(key) + -- Jumping + if key == self.key_jump then + if not self.inAir then + self.jumpactive = true + elseif self.jumpdouble then + self.jumpactive = true + self.jumpdouble = false + end + end + + -- Walking + if key == self.key_left or key == self.key_right then + self:changeAnimation("walk") + end + + -- Punching + if key == self.key_hit then + -- Punch up + if love.keyboard.isDown(self.key_up) then + self:hit(0, -1) + -- Punch down + elseif love.keyboard.isDown(self.key_down) and self.inAir then + self:hit(0, 1) + -- Punch horizontal + else + self:hit(self.facing, 0) + end + end +end + +-- Keyreleased callback of `Player` +function Player:keyreleased(key) + -- Jumping + if key == self.key_jump then + self.jumpactive = false + self.jumptimer = 0.12 + end + + -- Walking + if (key == self.key_left or key == self.key_right) and not + (love.keyboard.isDown(self.key_left) or love.keyboard.isDown(self.key_right)) and + self.current == self.animations.walk + then + self:changeAnimation("idle") + end +end + +-- Change animation of `Player` +-- idle, walk, attack, attack_up, attack_down, damage +function Player:changeAnimation(animation) + self.frame = 1 + self.delay = self.initial + self.current = self.animations[animation] +end + +-- Punch of `Player` +function Player:hit(horizontal, vertical) + if vertical == -1 then + self:changeAnimation("attack_up") + elseif vertical == 1 then + self:changeAnimation("attack_down") + else + self:changeAnimation("attack") + self.body:applyForce(800*self.facing, 0) + end + for k,n in pairs(Nauts) do + if n ~= self then + local didHit = false + if n.fixture:testPoint(self.body:getX()+12*horizontal,self.body:getY()-2) then + didHit = true + end + if n.fixture:testPoint(self.body:getX()+7*horizontal,self.body:getY()+2) then + didHit = true + end + if n.fixture:testPoint(self.body:getX()+17*horizontal,self.body:getY()+2) then + didHit = true + end + if n.fixture:testPoint(self.body:getX()+12*horizontal,self.body:getY()+6) then + didHit = true + end + if didHit then + n:damage(horizontal, vertical) + n.combo = n.combo + 1 + print(n.combo) + end + end + end +end + +-- Taking damage of `Player` by successful hit test +function Player:damage(horizontal, vertical) + self.body:applyLinearImpulse((10+10*self.combo)*horizontal, (50+10*self.combo)*vertical + 15) + self:changeAnimation("damage") +end \ No newline at end of file -- cgit v1.1