From 62b67be7882dffebd6de0c8241d253d806a6905c Mon Sep 17 00:00:00 2001 From: Aki Date: Fri, 26 May 2017 19:14:27 +0200 Subject: Halfway through with moving to new OOP module --- not/Entity.lua | 16 +++++++++ not/Hero.lua | 92 +++++++++++++++++++++++----------------------------- not/Object.lua | 3 ++ not/PhysicalBody.lua | 33 +++++++------------ not/Player.lua | 34 ++++++------------- not/Sprite.lua | 72 ++++++++++++++++------------------------ not/World.lua | 12 +++---- 7 files changed, 115 insertions(+), 147 deletions(-) create mode 100644 not/Entity.lua create mode 100644 not/Object.lua (limited to 'not') diff --git a/not/Entity.lua b/not/Entity.lua new file mode 100644 index 0000000..6ba1606 --- /dev/null +++ b/not/Entity.lua @@ -0,0 +1,16 @@ +require "not.Sprite" + +--- `Entity` +-- Basic, visible object to be used within World instance. Can be anything. Represented as `Sprite`. +-- We still need to keep old, global way of using modules but there are `returns` on the end at least. +Entity = Sprite:extends() + +Entity.world =--[[not.World]]nil + +-- Simple constructor for `Entity`. +function Entity:new (world, imagePath) + Entity.__super.new(self, imagePath) + self.world = world +end + +return Entity diff --git a/not/Hero.lua b/not/Hero.lua index feb61da..1f7cd8b 100644 --- a/not/Hero.lua +++ b/not/Hero.lua @@ -1,60 +1,48 @@ +require "not.PhysicalBody" + --- `Hero` -- Hero (often referred to as: "naut") entity that exists in a game world. -- Collision category: [2] -Hero = { - -- General and physics - name = "empty", - angle = 0, - facing = 1, - max_velocity = 105, - world = --[[not.World]]nil, - group = nil, - -- Combat - combo = 0, - lives = 3, - spawntimer = 2, - isAlive = true, - punchCooldown = 0.25, - punchdir = 0, -- a really bad thing - -- Movement - inAir = true, - salto = false, - isJumping = false, - isWalking = false, - jumpTimer = 0.16, - jumpCounter = 2, - -- Statics - portrait_sprite = nil, - portrait_frame = nil, - portrait_sheet = getNautsIconsList(), - portrait_box = love.graphics.newQuad( 0, 15, 32,32, 80,130), - sfx = require "config.sounds", -} +Hero = PhysicalBody:extends() --- `Hero` is a child of `PhysicalBody`. -require "not.PhysicalBody" -Hero.__index = Hero -setmetatable(Hero, PhysicalBody) +Hero.name = "empty" +Hero.angle = 0 +Hero.facing = 1 +Hero.max_velocity = 105 +Hero.group = nil +-- Combat +Hero.combo = 0 +Hero.lives = 3 +Hero.spawntimer = 2 +Hero.isAlive = true +Hero.punchCooldown = 0.25 +Hero.punchdir = 0 -- a really bad thing +-- Movement +Hero.inAir = true +Hero.salto = false +Hero.isJumping = false +Hero.isWalking = false +Hero.jumpTimer = 0.16 +Hero.jumpCounter = 2 +-- Statics +Hero.portrait_sprite = nil +Hero.portrait_frame = nil +Hero.portrait_sheet = getNautsIconsList() +Hero.portrait_box = love.graphics.newQuad(0, 15, 32,32, 80,130) +Hero.sfx = require "config.sounds" -- Constructor of `Hero`. -function Hero:new (game, world, x, y, name) - local o = setmetatable({}, self) - o:init(name, game, x, y) - -- Load portraits statically. - if self.portrait_sprite == nil then - self.portrait_sprite = love.graphics.newImage("assets/portraits.png") - self.portrait_frame = love.graphics.newImage("assets/menu.png") +function Hero:new (name, x, y, world) + -- TODO: Statics moved temporarily here. Should be moved to e.g. `load()`. + if Hero.portrait_sprite == nil then + Hero.portrait_sprite = love.graphics.newImage("assets/portraits.png") + Hero.portrait_frame = love.graphics.newImage("assets/menu.png") end - return o -end - --- Initializer of `Hero`. -function Hero:init (name, world, x, y) -- Find imagePath based on hero name. - local fileName = name or Hero.name -- INITIAL from metatable + local fileName = name or Hero.name -- INITIAL from prototype local imagePath = string.format("assets/nauts/%s.png", fileName) -- `PhysicalBody` initialization. - PhysicalBody.init(self, world, x, y, imagePath) + Hero.__super.new(self, x, y, world, imagePath) self:setBodyType("dynamic") self:setBodyFixedRotation(true) self.group = -1-#world.Nauts @@ -74,7 +62,7 @@ end -- Update callback of `Hero` function Hero:update (dt) - PhysicalBody.update(self, dt) + Hero.__super.update(self, dt) if self.body:isDestroyed() then return end -- Salto @@ -163,7 +151,7 @@ end -- Draw of `Hero` function Hero:draw (offset_x, offset_y, scale, debug) if not self.isAlive then return end - PhysicalBody.draw(self, offset_x, offset_y, scale, debug) + Hero.__super.draw(self, offset_x, offset_y, scale, debug) end -- Draw HUD of `Hero` @@ -209,7 +197,7 @@ end -- Sensor fixture is deleted after time set in UserData[1]; deleted by `not.Hero.update`. -- TODO: Magic numbers present in `not.Hero.punch`. function Hero:punch (direction) - self.punchCooldown = Hero.punchCooldown -- INITIAL from metatable + self.punchCooldown = Hero.punchCooldown -- INITIAL from prototype -- Choose shape based on punch direction. local shape if direction == "left" then shape = {-2,-6, -20,-6, -20,6, -2,6} end @@ -256,10 +244,10 @@ end -- DIE function Hero:die () self:playSound(1) - self.combo = Hero.combo -- INITIAL from metatable + self.combo = Hero.combo -- INITIAL from prototype self.lives = self.lives - 1 self.isAlive = false - self.spawntimer = Hero.spawntimer -- INITIAL from metatable + self.spawntimer = Hero.spawntimer -- INITIAL from prototype self:setBodyActive(false) self.world:onNautKilled(self) end diff --git a/not/Object.lua b/not/Object.lua new file mode 100644 index 0000000..fbc41e5 --- /dev/null +++ b/not/Object.lua @@ -0,0 +1,3 @@ +-- Wrapping library to game's hierarchy in a shameless way. +Object = require "lib.Object" +return Object diff --git a/not/PhysicalBody.lua b/not/PhysicalBody.lua index e9625fa..fd92f89 100644 --- a/not/PhysicalBody.lua +++ b/not/PhysicalBody.lua @@ -1,25 +1,15 @@ +require "not.Entity" + --- `PhysicalBody` -- Abstract class for drawable entity existing in `not.World`. -PhysicalBody = { - body =--[[love.physics.newBody]]nil, -} - --- `PhysicalBody` is a child of `Sprite`. -require "not.Sprite" -PhysicalBody.__index = PhysicalBody -setmetatable(PhysicalBody, Sprite) +PhysicalBody = Entity:extends() ---[[ Constructor of `PhysicalBody`. -function PhysicalBody:new (world, x, y, imagePath) - local o = setmetatable({}, self) - o:init(world, x, y, imagePath) - return o -end -]] +PhysicalBody.body =--[[love.physics.newBody]]nil --- Initializer of `PhysicalBody`. -function PhysicalBody:init (world, x, y, imagePath) - Sprite.init(self, imagePath) +-- Constructor of `PhysicalBody`. +-- `world` and `imagePath` are passed to parent's constructor (`Entity`). +function PhysicalBody:new (x, y, world, imagePath) + PhysicalBody.__super.new(self, world, imagePath) self.body = love.physics.newBody(world.world, x, y) end @@ -68,12 +58,12 @@ end -- Update of `PhysicalBody`. function PhysicalBody:update (dt) - Sprite.update(self, dt) + PhysicalBody.__super.update(self, dt) end -- Draw of `PhysicalBody`. function PhysicalBody:draw (offset_x, offset_y, scale, debug) - Sprite.draw(self, offset_x, offset_y, scale) + PhysicalBody.__super.draw(self, offset_x, offset_y, scale) if debug then for _,fixture in pairs(self.body:getFixtureList()) do local category = fixture:getCategory() @@ -86,8 +76,9 @@ function PhysicalBody:draw (offset_x, offset_y, scale, debug) if category == 3 then love.graphics.setColor(137, 0, 255, 40) end - -- TODO: `world` is not a member of `PhysicalBody` or its instance normally. love.graphics.polygon("fill", self.world.camera:translatePoints(self.body:getWorldPoints(fixture:getShape():getPoints()))) end end end + +return PhysicalBody diff --git a/not/Player.lua b/not/Player.lua index 2a4b2e6..5d108ce 100644 --- a/not/Player.lua +++ b/not/Player.lua @@ -1,31 +1,15 @@ +require "not.Hero" + --- `Player` -- Special `not.Hero` controllable by a player. -Player = { - -- TODO: move functions and properties related to controls from `not.Hero`. - controllerSet = --[[Controller.sets.*]]nil, -} +-- TODO: move functions and properties related to controls from `not.Hero`. +Player = Hero:extends() --- `Player` is a child of `Hero`. -require "not.Hero" -Player.__index = Player -setmetatable(Player, Hero) +Player.controllerSet =--[[Controller.sets.*]]nil -- Constructor of `Player`. -function Player:new (name, game, x, y) - local o = setmetatable({}, self) - o:init(name, game, x, y) - -- Load portraits statically to `not.Hero`. - -- TODO: this is heresy, put it into `load` method or something similar. - if Hero.portrait_sprite == nil then - Hero.portrait_sprite = love.graphics.newImage("assets/portraits.png") - Hero.portrait_frame = love.graphics.newImage("assets/menu.png") - end - return o -end - --- Initializer of `Player`. -function Player:init (...) - Hero.init(self, ...) +function Player:new (name, x, y, world) + Player.__super.new(self, name, x, y, world) end -- Controller set manipulation. @@ -43,7 +27,7 @@ end -- Update of `Player`. function Player:update (dt) - Hero.update(self, dt) -- TODO: It would be probably a good idea to add return to update functions to terminate if something goes badly in parent's update. + Player.__super.update(self, dt) -- TODO: It would be probably a good idea to add return to update functions to terminate if something goes badly in parent's update. if self.body:isDestroyed() then return end local x, y = self:getLinearVelocity() -- Jumping. @@ -157,3 +141,5 @@ function Player:controlreleased (set, action, key) end end end + +return Player diff --git a/not/Sprite.lua b/not/Sprite.lua index 25d85f1..3951e6e 100644 --- a/not/Sprite.lua +++ b/not/Sprite.lua @@ -1,34 +1,27 @@ +require "not.Object" + --- `Sprite` -- Abstract class for drawable animated entities. -Sprite = { - animations =--[[table with animations]]nil, - current =--[[animations.default]]nil, - image =--[[love.graphics.newImage]]nil, - frame = 1, - delay = .1, -} -Sprite.__index = Sprite - ---[[ Constructor of `Sprite`. +Sprite = Object:extends() + +Sprite.animations =--[[table with animations]]nil +Sprite.current =--[[animations.default]]nil +Sprite.image =--[[love.graphics.newImage]]nil +Sprite.frame = 1 +Sprite.delay = .1 + +-- Constructor of `Sprite`. function Sprite:new (imagePath) - local o = setmetatable({}, self) - o:init(imagePath) - return o + if type(imagePath) == "string" then + self:setImage(Sprite.newImage(imagePath)) + end end -]] -- Cleans up reference to image on deletion. function Sprite:delete () self.image = nil end --- Initializes new Sprite instance. -function Sprite:init (imagePath) - if type(imagePath) == "string" then - self:setImage(Sprite.newImage(imagePath)) - end -end - -- Creates new Image object from path. Key-colours two shades of green. Static. function Sprite.newImage (path) local imagedata = love.image.newImageData(path) @@ -64,7 +57,7 @@ end -- Sets current animation by table key. function Sprite:setAnimation (animation) self.frame = 1 - self.delay = Sprite.delay -- INITIAL from metatable + self.delay = Sprite.delay -- INITIAL from prototype self.current = self.animations[animation] end -- Returns current animation table. @@ -79,26 +72,15 @@ function Sprite:getQuad () end end --- TODO: Following five methods are stupid, do something about them! --- Sprite can't be moved by itself. Positioning should be handled by children's methods. -function Sprite:getPosition () - return 0,0 -end --- Sprite can't be rotated by itself. Rotation should be handled by children's methods. -function Sprite:getAngle () - return 0 -end --- Sprite can't be mirrored by itself. Mirroring should be handled by children's methods. -function Sprite:getHorizontalMirror () - return 1 -end -function Sprite:getVerticalMirror () - return 1 -end --- Sprite can't be offset by itself. Offsetting should be handled by children's methods. -function Sprite:getOffset () - return 0,0 -end +-- Sprite's position. Can be overriden to add functionality. +function Sprite:getPosition () return 0,0 end +-- Sprite's angle. Can be overriden to add functionality. +function Sprite:getAngle () return 0 end +-- Sprite's horizontal and vertical mirrors. Can be overriden to add functionality. +function Sprite:getHorizontalMirror () return 1 end +function Sprite:getVerticalMirror () return 1 end +-- Sprite's drawing offset from position. Can be overriden to add functionality. +function Sprite:getOffset () return 0,0 end -- Drawing self to LOVE2D buffer. -- If there is no Quad, it will draw entire image. It won't draw anything if there is no image. @@ -136,7 +118,7 @@ function Sprite:update (dt) if self.animations and self.current then self.delay = self.delay - dt if self.delay < 0 then - self.delay = self.delay + Sprite.delay -- INITIAL from metatable + self.delay = self.delay + Sprite.delay -- INITIAL from prototype self:goToNextFrame() end end @@ -149,4 +131,6 @@ function Sprite:goToNextFrame () else self:setAnimation("default") end -end \ No newline at end of file +end + +return Sprite diff --git a/not/World.lua b/not/World.lua index bbceec4..b4ad4fa 100644 --- a/not/World.lua +++ b/not/World.lua @@ -117,13 +117,13 @@ end -- Add new platform to the world -- TODO: it would be nice if function parameters would be same as `not.Platform.new`. function World:createPlatform (x, y, polygon, sprite, animations) - table.insert(self.Platforms, Platform:new(animations, polygon, self, x, y, sprite)) + table.insert(self.Platforms, Platform(animations, polygon, self, x, y, sprite)) end -- Add new naut to the world -- TODO: separate two methods for `not.Hero` and `not.Player`. function World:createNaut (x, y, name) - local naut = Player:new(name, self, x, y) + local naut = Player(name, x, y, self) table.insert(self.Nauts, naut) return naut end @@ -131,14 +131,14 @@ end -- Add new decoration to the world -- TODO: `not.World.create*` functions often have different naming for parameters. It is not ground-breaking but it makes reading code harder for no good reason. function World:createDecoration (x, y, sprite) - table.insert(self.Decorations, Decoration:new(x, y, sprite)) + table.insert(self.Decorations, Decoration(x, y, sprite)) end -- Add new cloud to the world -- TODO: extend variables names to provide better readability. -- TODO: follow new parameters in `not.Cloud.new` based on `not.Cloud.init`. function World:createCloud (x, y, t, v) - table.insert(self.Clouds, Cloud:new(x, y, t, v)) + table.insert(self.Clouds, Cloud(x, y, t, v)) end -- Randomize Cloud creation @@ -165,12 +165,12 @@ end -- TODO: follow new parameters in `not.Effect.new` based on `not.Effect.init`. -- TODO: along with `createRay` move this nearer reast of `create*` methods for readability. function World:createEffect (name, x, y) - table.insert(self.Effects, Effect:new(name, x, y)) + table.insert(self.Effects, Effect(name, x, y)) end -- Add a ray function World:createRay (naut) - table.insert(self.Rays, Ray:new(naut, self)) + table.insert(self.Rays, Ray(naut, self)) end -- get Nauts functions -- cgit v1.1