From 8bb18a89060ecd581a06238ce3fa5d2170ee3a15 Mon Sep 17 00:00:00 2001 From: the lemons Date: Sat, 27 Aug 2022 01:23:20 -0500 Subject: implement component system --- Bolvis.lua | 218 ++++++++++++++++++++++------------------------- Camera.lua | 25 +++--- Drawable.lua | 9 ++ Input.lua | 6 ++ Obj.lua | 68 --------------- Sprite.lua | 48 +++++++++++ Transform.lua | 28 ++++++ apioform.png | Bin 645 -> 0 bytes bolvis-blink.png | Bin 107353 -> 0 bytes bolvis-left.png | Bin 135883 -> 0 bytes bolvis-right.png | Bin 135225 -> 0 bytes bolvis.png | Bin 145016 -> 0 bytes component.lua | 24 ++++++ conf.lua | 2 +- game.lua | 43 ---------- globals.lua | 23 +++++ hand-closed.png | Bin 8067 -> 0 bytes hand-open.png | Bin 10843 -> 0 bytes main.lua | 113 +++++++++++++----------- physics.lua | 70 --------------- sprite/apioform.png | Bin 0 -> 645 bytes sprite/bolvis/blink.png | Bin 0 -> 18317 bytes sprite/bolvis/bolvis.png | Bin 0 -> 28926 bytes sprite/bolvis/left.png | Bin 0 -> 27672 bytes sprite/bolvis/right.png | Bin 0 -> 27548 bytes sprite/hand/closed.png | Bin 0 -> 3983 bytes sprite/hand/hand.png | Bin 0 -> 5516 bytes sprite/test.png | Bin 0 -> 41407 bytes sprite/utah-teapot.png | Bin 0 -> 75038 bytes stuff.lua | 10 --- test.png | Bin 41407 -> 0 bytes utah-teapot.png | Bin 75038 -> 0 bytes world.lua | 119 ++++++++++++++++++++++++++ 33 files changed, 438 insertions(+), 368 deletions(-) create mode 100644 Drawable.lua create mode 100644 Input.lua delete mode 100644 Obj.lua create mode 100644 Sprite.lua create mode 100644 Transform.lua delete mode 100644 apioform.png delete mode 100644 bolvis-blink.png delete mode 100644 bolvis-left.png delete mode 100644 bolvis-right.png delete mode 100644 bolvis.png create mode 100644 component.lua delete mode 100644 game.lua create mode 100644 globals.lua delete mode 100644 hand-closed.png delete mode 100644 hand-open.png delete mode 100644 physics.lua create mode 100644 sprite/apioform.png create mode 100644 sprite/bolvis/blink.png create mode 100644 sprite/bolvis/bolvis.png create mode 100644 sprite/bolvis/left.png create mode 100644 sprite/bolvis/right.png create mode 100644 sprite/hand/closed.png create mode 100644 sprite/hand/hand.png create mode 100644 sprite/test.png create mode 100644 sprite/utah-teapot.png delete mode 100644 stuff.lua delete mode 100644 test.png delete mode 100644 utah-teapot.png create mode 100644 world.lua diff --git a/Bolvis.lua b/Bolvis.lua index 43e8953..8d53c44 100644 --- a/Bolvis.lua +++ b/Bolvis.lua @@ -1,83 +1,64 @@ -local game = require 'game' -local physics = require 'physics' +local component = require 'component' +local Drawable = require 'Drawable' +local Input = require 'Input' +local Sprite = require 'Sprite' +local Transform = require 'Transform' local Camera = require 'Camera' -local Bolvis = physics.Object:extend() -Bolvis.sprite_center = love.graphics.newImage("bolvis.png", {dpiscale = 5}) -Bolvis.sprite_left = love.graphics.newImage("bolvis-left.png", {dpiscale = 5}) -Bolvis.sprite_right = love.graphics.newImage("bolvis-right.png", {dpiscale = 5}) -Bolvis.sprite_blink = love.graphics.newImage("bolvis-blink.png", {dpiscale = 5}) -Bolvis.z = 50 - -local Hand = physics.Object:extend() -Hand.sprite_open = love.graphics.newImage("hand-open.png", {dpiscale = 3.5}) -Hand.sprite_closed = love.graphics.newImage("hand-closed.png", {dpiscale = 3.5}) -Hand.max_speed = 10 -Hand.z = 49 - -function Bolvis:new(pos, rotation) - self.sprite = self.sprite_center - self.blink = 10 - - physics.Object.new(self, pos, rotation, nil, 'dynamic') - self.shape = love.physics.newRectangleShape(90, 90) - self.fixture = love.physics.newFixture(self.body, self.shape) - self.fixture:setRestitution(0.2) - self.fixture:setDensity(20) - self.hand = Hand(self) - self.camera = Camera() - self.camera:follow(self) +local Bolvis = component( + {Drawable, {z = 50}}, + {Input}, + {Sprite, {name = "bolvis"}} +) + +local Hand = component( + {Drawable, {z = 49}}, + {Input}, + {Sprite, {name = "hand", z = 1}} +) + +function Bolvis:init(inst) + inst.hand = self.obj.world:object(Hand {bolvis = self.obj}) + inst.camera = self.obj.world:object(Camera {following = self.obj}) + inst.blink = 10 end function Bolvis:update(dt) - self.body:setAngle(0) - physics.Object.update(self, dt) - - self.blink = self.blink - (dt * 30) - if self.blink <= 0 then - if self.sprite == self.sprite_blink then - self.sprite = self.sprite_center - self.blink = math.random(30, 256) + local sprite = self.obj:get(Sprite) + self.i.blink = self.i.blink - (dt * 30) + if self.i.blink <= 0 then + if sprite.i.state == "blink" then + sprite.i.state = "bolvis" + self.i.blink = math.random(30, 256) else - self.sprite = self.sprite_blink - self.blink = 4 - end - end - if self.sprite ~= self.sprite_blink then - if self.hand.grab_joint then - local offsx = self.hand:present_offset() - if offsx > 150 then - self.sprite = self.sprite_right - elseif offsx < -150 then - self.sprite = self.sprite_left - else - self.sprite = self.sprite_center - end - elseif self.sprite ~= self.sprite_center then - if math.random(1, 4) == 1 then - self.sprite = self.sprite_blink - self.blink = 4 - else - self.sprite = self.sprite_center - end + sprite.i.state = "blink" + self.i.blink = 4 end end +-- if self.sprite ~= self.sprite_blink then +-- if self.hand.grab_joint then +-- local offsx = self.hand:present_offset() +-- if offsx > 150 then +-- self.sprite = self.sprite_right +-- elseif offsx < -150 then +-- self.sprite = self.sprite_left +-- else +-- self.sprite = self.sprite_center +-- end +-- elseif self.sprite ~= self.sprite_center then +-- if math.random(1, 4) == 1 then +-- self.sprite = self.sprite_blink +-- self.blink = 4 +-- else +-- self.sprite = self.sprite_center +-- end +-- end +-- end end -function Hand:new(bolvis) - physics.Object.new(self) - self.offset = {100, -100} - self.bolvis = bolvis - self.sprite = self.sprite_open -end - -function Hand:angle() - local x, y = unpack(self.pos) - local bx, by = unpack(self.bolvis.pos) - local ox, oy = x - bx, y - by - local a = math.atan(oy / math.abs(ox)) + math.pi / 2 - if ox < 0 then a = -a end - return a +function Hand:init(inst) + assert(inst.bolvis) + inst.offset = {100, -100} end local function clamp(n, max, min) @@ -85,77 +66,84 @@ local function clamp(n, max, min) end function Hand:update() - self.rot = self:angle() - if not self.grab_joint then - self.pos[1] = self.bolvis.pos[1] + self.offset[1] - self.pos[2] = self.bolvis.pos[2] + self.offset[2] + local this = self.obj:get(Transform) + local bolvis = self.i.bolvis:get(Transform) + this.i.angle = self:angle() + if not self.i.grab then + this.i.pos[1] = bolvis.i.pos[1] + self.i.offset[1] + this.i.pos[2] = bolvis.i.pos[2] + self.i.offset[2] else - self.pos = {self.grabbed.body:getWorldPoint(unpack(self.grab_pos))} + -- self.pos = {self.grabbed.body:getWorldPoint(unpack(self.grab_pos))} end end function Hand:present_offset() - local x, y = unpack(self.pos) - local bx, by = unpack(self.bolvis.pos) + local x, y = unpack(self.obj:get(Transform).i.pos) + local bx, by = unpack(self.i.bolvis:get(Transform).i.pos) return x - bx, y - by end +function Hand:angle() + local ox, oy = self:present_offset() + local a = math.atan(oy / math.abs(ox)) + math.pi / 2 + if ox < 0 then a = -a end + return a +end + + function Hand:mousemoved(_, _, dx, dy) - dx = clamp(dx, self.max_speed, -self.max_speed) - dy = clamp(dy, self.max_speed, -self.max_speed) - self.offset[1] = clamp(self.offset[1] + dx, 1920 / 2, -1920 / 2) - self.offset[2] = clamp(self.offset[2] + dy, 1080 / 2, -1080 / 2) - if self.grab_joint then - local x, y = unpack(self.offset) - self.grab_joint:setLinearOffset(x + self.grab_pos[1], y + self.grab_pos[2]) - end + self.i.offset[1] = clamp(self.i.offset[1] + dx, 1920 / 2, -1920 / 2) + self.i.offset[2] = clamp(self.i.offset[2] + dy, 1080 / 2, -1080 / 2) + --if self.grab_joint then + -- local x, y = unpack(self.offset) + -- self.grab_joint:setLinearOffset(x + self.grab_pos[1], y + self.grab_pos[2]) + --end end function Hand:mousepressed(_, _, button) if button == 1 then - self.sprite = self.sprite_closed - local grabbed - for o in pairs(game.all_objects) do - if o.fixture then - if o.fixture:testPoint(unpack(self.pos)) then - if o ~= self.bolvis then - self.grabbed = o - break - end - end - end - end - if self.grabbed then - local x1, y1 = unpack(self.bolvis.pos) - local x2, y2 = unpack(self.bolvis.pos) - self.grab_joint = love.physics.newMotorJoint( - self.bolvis.body, self.grabbed.body, 0.5, true) - self.grab_joint:setMaxForce(500) - self.grab_pos = {self.grabbed.body:getLocalPoint(unpack(self.pos))} - end + self.obj:get(Sprite).i.state = "closed" +-- local grabbed +-- for o in pairs(game.all_objects) do +-- if o.fixture then +-- if o.fixture:testPoint(unpack(self.pos)) then +-- if o ~= self.bolvis then +-- self.grabbed = o +-- break +-- end +-- end +-- end +-- end +-- if self.grabbed then +-- local x1, y1 = unpack(self.bolvis.pos) +-- local x2, y2 = unpack(self.bolvis.pos) +-- self.grab_joint = love.physics.newMotorJoint( +-- self.bolvis.body, self.grabbed.body, 0.5, true) +-- self.grab_joint:setMaxForce(500) +-- self.grab_pos = {self.grabbed.body:getLocalPoint(unpack(self.pos))} +-- end end end function Hand:mousereleased(_, _, button) if button == 1 then - self.sprite = self.sprite_open - if self.grab_joint then - self.grabbed = nil - self.grab_joint:destroy() - self.grab_joint = nil - end - self.offset = {self:present_offset()} + self.obj:get(Sprite).i.state = "hand" +-- if self.grab_joint then +-- self.grabbed = nil +-- self.grab_joint:destroy() +-- self.grab_joint = nil +-- end +-- self.offset = {self:present_offset()} end end function Hand:draw() - local x1, y1 = unpack(self.bolvis.pos) - local x2, y2 = unpack(self.pos) + local x1, y1 = unpack(self.i.bolvis[Transform].i.pos) + local x2, y2 = unpack(self.obj[Transform].i.pos) love.graphics.setColor(0.73, 0.76, 0.91) love.graphics.setLineWidth(15) love.graphics.line(x1, y1, x2, y2) love.graphics.setColor(1, 1, 1) - game.Object.draw(self) end return Bolvis diff --git a/Camera.lua b/Camera.lua index 8a12fa8..3b3f1a3 100644 --- a/Camera.lua +++ b/Camera.lua @@ -1,23 +1,26 @@ -local game = require 'game' +local component = require 'component' +local Transform = require 'Transform' -local Camera = game.Object:extend() +-- a view of the world +local Camera = component({Transform}) function Camera:use() - local x, y = unpack(self.pos) - local scale = 1 / self.scale - local transform = love.math.newTransform( - -x + 1920 / 2, -y + 1080 / 2, -self.rot, scale, scale) - love.graphics.applyTransform(transform) + local trans = self.obj:get(Transform):love() + local cam_trans = love.math.newTransform(1920 / 2, 1080 / 2) + love.graphics.applyTransform(cam_trans * trans:inverse()) end function Camera:follow(obj) - self.following = obj + assert(obj:get(Transform)) + self.i.following = obj end function Camera:update(dt) - if self.following then - self.pos[1] = self.following.pos[1] - self.pos[2] = self.following.pos[2] + if self.i.following then + local this = self.obj:get(Transform) + local follow = self.i.following:get(Transform) + this.i.pos[1] = follow.i.pos[1] + this.i.pos[2] = follow.i.pos[2] end end diff --git a/Drawable.lua b/Drawable.lua new file mode 100644 index 0000000..54e0f46 --- /dev/null +++ b/Drawable.lua @@ -0,0 +1,9 @@ +local component = require 'component' + +-- component for objects that are drawable +local Drawable = component() +function Drawable:init(inst) + inst.z = inst.z or 0 +end + +return Drawable diff --git a/Input.lua b/Input.lua new file mode 100644 index 0000000..a7dd2e6 --- /dev/null +++ b/Input.lua @@ -0,0 +1,6 @@ +local component = require 'component' + +-- component for objects that can recieve input events +local Input = component() + +return Input diff --git a/Obj.lua b/Obj.lua deleted file mode 100644 index cbd6f81..0000000 --- a/Obj.lua +++ /dev/null @@ -1,68 +0,0 @@ --- --- classic --- --- Copyright (c) 2014, rxi --- --- This module is free software; you can redistribute it and/or modify it under --- the terms of the MIT license. See LICENSE for details. --- - - -local Object = {} -Object.__index = Object - - -function Object:new() -end - - -function Object:extend() - local cls = {} - for k, v in pairs(self) do - if k:find("__") == 1 then - cls[k] = v - end - end - cls.__index = cls - cls.super = self - setmetatable(cls, self) - return cls -end - - -function Object:implement(...) - for _, cls in pairs({...}) do - for k, v in pairs(cls) do - if self[k] == nil and type(v) == "function" then - self[k] = v - end - end - end -end - - -function Object:is(T) - local mt = getmetatable(self) - while mt do - if mt == T then - return true - end - mt = getmetatable(mt) - end - return false -end - - -function Object:__tostring() - return "Object" -end - - -function Object:__call(...) - local obj = setmetatable({}, self) - obj:new(...) - return obj -end - - -return Object diff --git a/Sprite.lua b/Sprite.lua new file mode 100644 index 0000000..dac5ce8 --- /dev/null +++ b/Sprite.lua @@ -0,0 +1,48 @@ +local component = require 'component' +local Transform = require 'Transform' +local Drawable = require 'Drawable' + +local Sprite = component({Drawable}, {Transform}) + +local function load_image(path) + return love.graphics.newImage(path, {dpiscale = 2}) +end + +local loaded = setmetatable({}, {__mode = 'v'}) +local function get_states(name) + if loaded[name] then return loaded[name] end + loaded[name] = {} + + local path = "sprite/"..name + if love.filesystem.getInfo(path..".png", 'file') then + loaded[name][name] = load_image(path..".png") + elseif love.filesystem.getInfo(path, 'directory') then + local files = love.filesystem.getDirectoryItems(path) + for _, file in ipairs(files) do + local state = file:match '^(.*)%.png$' + if state then + loaded[name][state] = load_image(path.."/"..file) + end + end + end + return loaded[name] +end + +function Sprite:init(inst) + assert(inst.name) + inst.state = inst.state or inst.name + inst.states = get_states(inst.name) +end + +function Sprite:draw() + self.obj[Transform]:use() + local i = self.i.states[self.i.state] + local w, h = i:getDimensions() + love.graphics.draw(i, 0, 0, 0, 1, 1, w / 2, h / 2) +end + +function Sprite:bee() + print "apioform" +end + +return Sprite diff --git a/Transform.lua b/Transform.lua new file mode 100644 index 0000000..0038cce --- /dev/null +++ b/Transform.lua @@ -0,0 +1,28 @@ +local component = require 'component' + +-- component for objects that have a position in the world +local Transform = component() +function Transform:init(inst) + inst.pos = inst.pos or {0, 0} + inst.angle = inst.angle or 0 + inst.scale = inst.scale or {1, 1} + if type(inst.scale) == 'number' then + inst.scale = {inst.scale, inst.scale} + end +end + +function Transform:love(trans) + local trans = trans or love.math.newTransform() + local x, y = unpack(self.i.pos) + local sx, sy = unpack(self.i.scale) + trans:setTransformation(x, y, self.i.angle, sx, sy) + return trans +end + +local trans = love.math.newTransform() +function Transform:use() + self:love(trans) -- this is literally me + love.graphics.applyTransform(trans) +end + +return Transform diff --git a/apioform.png b/apioform.png deleted file mode 100644 index cc04a1a..0000000 Binary files a/apioform.png and /dev/null differ diff --git a/bolvis-blink.png b/bolvis-blink.png deleted file mode 100644 index 209060d..0000000 Binary files a/bolvis-blink.png and /dev/null differ diff --git a/bolvis-left.png b/bolvis-left.png deleted file mode 100644 index 2eb1fb3..0000000 Binary files a/bolvis-left.png and /dev/null differ diff --git a/bolvis-right.png b/bolvis-right.png deleted file mode 100644 index e6e48c9..0000000 Binary files a/bolvis-right.png and /dev/null differ diff --git a/bolvis.png b/bolvis.png deleted file mode 100644 index bb2a29a..0000000 Binary files a/bolvis.png and /dev/null differ diff --git a/component.lua b/component.lua new file mode 100644 index 0000000..c1c16d8 --- /dev/null +++ b/component.lua @@ -0,0 +1,24 @@ +local mt = {} +function mt:__call(instance) + instance = instance or {} + assert(type(instance) == 'table') + local ci = setmetatable({i = instance, inited = false, obj = false}, + {__index = self, __newindex = function()assert(false)end}) + return ci +end + +-- create a new component type. the arguments are interpreted as a list of +-- dependences. each dependency is expressed as an array. the first value is +-- the component type. the optional second value is the default properties +local function component(...) + local c = {} + c.component_type = c + c.deps = {...} + for i, dep in ipairs(c.deps) do + assert(#dep ~= 0) + end + c.init = function() end + return setmetatable(c, mt) +end + +return component diff --git a/conf.lua b/conf.lua index ec855bf..873f9ff 100644 --- a/conf.lua +++ b/conf.lua @@ -1,6 +1,6 @@ function love.conf(t) t.identity = "bolvis" t.window.title = "bolvis the spintholeom" - t.window.icon = "bolvis.png" + t.window.icon = "sprite/bolvis/bolvis.png" t.window.resizable = true end diff --git a/game.lua b/game.lua deleted file mode 100644 index 16b1e06..0000000 --- a/game.lua +++ /dev/null @@ -1,43 +0,0 @@ -local Obj = require 'Obj' - -local M = {} - -M.all_objects = {} - -M.Object = Obj:extend() -M.Object.z = 0 - -function M.Object:new(pos, rotation, scale) - self.pos = pos or {0, 0, 0} - self.rot = rotation or 0 - self.scale = scale or 1 - self:enable() -end - -function M.Object:enable() - M.all_objects[self] = true -end - -function M.Object:disable() - M.all_objects[self] = nil -end - -function M.Object:update() -end - -function M.Object:draw() - if self.sprite then - local x, y = unpack(self.pos) - local w, h = self.sprite:getDimensions() - ox = (w * self.scale) / 2 - oy = (h * self.scale) / 2 - love.graphics.draw( - self.sprite, x, y, self.rot, self.scale, self.scale, ox, oy) - end -end - -function M.Object:visible() - return not self.hidden -end - -return M diff --git a/globals.lua b/globals.lua new file mode 100644 index 0000000..6ee62a9 --- /dev/null +++ b/globals.lua @@ -0,0 +1,23 @@ +local gbl_mt = {} +local decl = {} + +function gbl_mt:__index(k) + if not decl[k] then + error("unknown global: "..k, 2) + end + return rawget(self, k) +end + +function gbl_mt:__newindex(k, v) + if not decl[k] then + error("unknown global: "..k, 2) + end + rawset(self, k, v) +end + +function global(k, v) + decl[k] = true + rawset(_G, k, v) +end + +setmetatable(_G, gbl_mt) diff --git a/hand-closed.png b/hand-closed.png deleted file mode 100644 index c6df3d3..0000000 Binary files a/hand-closed.png and /dev/null differ diff --git a/hand-open.png b/hand-open.png deleted file mode 100644 index 1ad33a9..0000000 Binary files a/hand-open.png and /dev/null differ diff --git a/main.lua b/main.lua index 2540c01..cca90b4 100644 --- a/main.lua +++ b/main.lua @@ -1,22 +1,31 @@ -local game = require 'game' -local physics = require 'physics' +require "globals" + +local Transform = require 'Transform' +local Drawable = require 'Drawable' +local Input = require 'Input' +local Camera = require 'Camera' local Bolvis = require 'Bolvis' -local stuff = require 'stuff' +--local stuff = require 'stuff' +local world = require 'world' +local level local camera function love.load() + love.setDeprecationOutput(false) + love.mouse.setRelativeMode(true) + level = world() + + local bolvis = level:object(Transform {pos = {960, 540}}, Bolvis()) + camera = bolvis[Bolvis].i.camera[Camera] - local bolvis = Bolvis({960, 540}) - camera = bolvis.camera - - stuff.Teapot({400, 540}, 0) - stuff.Apioform({600, 540}, 0) - stuff.TestPlatform({960, 300}) - stuff.TestPlatform({960, 700}) - stuff.TestPlatform({430, 700}) - stuff.TestPlatform({1490, 700}) + -- level:object(Transform {pos = {400, 540}}, stuff.Teapot()) + -- level:object(Transform {pos = {600, 540}}, stuff.Apioform()) + -- level:object(Transform {pos = {960, 300}}, stuff.TestPlatform()) + -- level:object(Transform {pos = {960, 700}}, stuff.TestPlatform()) + -- level:object(Transform {pos = {430, 700}}, stuff.TestPlatform()) + -- level:object(Transform {pos = {1490, 700}}, stuff.TestPlatform()) end local function screen_transform() @@ -34,60 +43,64 @@ local function screen_transform() return love.math.newTransform(x, y, 0, scale, scale) end -local to_draw -local events = {} -local handlers = {} - -local function event(name) - love[name] = function(...) - table.insert(events, {type = name, ...}) +local function call(ct, method, ...) + for o in level:iterate(ct) do + o:call(method, ...) end end -function love.update(dt) - to_draw = {} - physics.world:update(dt, 20, 20) - for _, e in ipairs(events) do - if handlers[e.type] then - handlers[e.type](unpack(e)) - end +function love.draw() + love.graphics.applyTransform(screen_transform()) + camera:use() + local to_draw = {} + for o in level:iterate(Drawable) do + table.insert(to_draw, o) end - for o in pairs(game.all_objects) do - for _, e in ipairs(events) do - if o[e.type] then - o[e.type](o, unpack(e)) - end + table.sort(to_draw, function(a, b) + return a:get(Drawable).i.z < b:get(Drawable).i.z + end) + for _, o in ipairs(to_draw) do + love.graphics.push() + local cmps = {} + for c in o:all_components() do + table.insert(cmps, c) end - o:update(dt) - if o:visible() then - table.insert(to_draw, o) + table.sort(cmps, function(a, b) + return (a.i.z or 0) < (b.i.z or 0) + end) + for _, c in ipairs(cmps) do + if c.draw then c:draw() end end + love.graphics.pop() end - events = {} end -function love.draw() - love.graphics.applyTransform(screen_transform()) - camera:use() - table.sort(to_draw, function(a, b) return a.z < b.z end) - for _, o in ipairs(to_draw) do - o:draw() - end +function love.update(dt) + -- physics.world:update(dt, 20, 20) + call(nil, 'update', dt) end -event "mousemoved" -event "mousepressed" -event "mousereleased" -event "keypressed" -event "keyreleased" +function love.mousemoved(...) + call(Input, 'mousemoved', ...) +end -function handlers.keypressed(key) +function love.mousepressed(...) + love.mouse.setRelativeMode(true) + call(Input, 'mousepressed', ...) +end + +function love.mousereleased(...) + call(Input, 'mousereleased', ...) +end + +function love.keypressed(key, ...) if key == 'tab' and (love.keyboard.isDown 'ralt' or love.keyboard.isDown 'lalt') then love.mouse.setRelativeMode(false) end + call(Input, 'keypressed', key, ...) end -function handlers.mousepressed() - love.mouse.setRelativeMode(true) +function love.keyreleased(...) + call(Input, 'keyreleased', ...) end diff --git a/physics.lua b/physics.lua deleted file mode 100644 index 336a7c2..0000000 --- a/physics.lua +++ /dev/null @@ -1,70 +0,0 @@ -local game = require 'game' - -local M = {} - -love.physics.setMeter(300) -M.world = love.physics.newWorld(0, 2000) -M.Object = game.Object:extend() - -local bodies = {} -setmetatable(bodies, {__mode = 'kv'}) -function M.body_object(body) - return bodies[body] -end - -function M.Object:new(pos, rotation, scale, type) - game.Object.new(self, pos, rotation, scale) - local x, y = unpack(self.pos) - self.body = love.physics.newBody(M.world, x, y, type) - self.body:setAngle(self.rot) - bodies[self.body] = self -end - -function M.Object:enable() - game.Object.enable(self) - if body then - self.body:setActive(true) - end -end - -function M.Object:disable() - game.Object.disable(self) - self.body:setActive(false) -end - -function M.Object:update() - local x, y = self.body:getWorldPoint(0, 0) - self.pos[1], self.pos[2] = x, y - self.rot = self.body:getAngle() -end - -local sprites = {} -setmetatable(sprites, {__mode = 'v'}) - -function M.simple(sprite, shape, body_type, restitution) - local class = M.Object:extend() - if type(sprite) == 'string' then - sprite = sprites[sprite] or love.graphics.newImage(sprite, {dpiscale = 2}) - end - class.sprite = sprite - - local w, h = sprite:getDimensions() - function class:new(pos, rotation, scale) - M.Object.new(self, pos, rotation, scale, body_type or 'dynamic') - - if not shape or shape == 'rect' then - self.shape = love.physics.newRectangleShape(w, h) - elseif shape == 'circle' then - self.shape = love.physics.newCircleShape(w / 2) - else - self.shape = love.physics.newPolygonShape(unpack(shape)) - end - self.fixture = love.physics.newFixture(self.body, self.shape) - if restitution then - self.fixture:setRestitution(restitution) - end - end - return class -end - -return M diff --git a/sprite/apioform.png b/sprite/apioform.png new file mode 100644 index 0000000..cc04a1a Binary files /dev/null and b/sprite/apioform.png differ diff --git a/sprite/bolvis/blink.png b/sprite/bolvis/blink.png new file mode 100644 index 0000000..f66f162 Binary files /dev/null and b/sprite/bolvis/blink.png differ diff --git a/sprite/bolvis/bolvis.png b/sprite/bolvis/bolvis.png new file mode 100644 index 0000000..ca7896e Binary files /dev/null and b/sprite/bolvis/bolvis.png differ diff --git a/sprite/bolvis/left.png b/sprite/bolvis/left.png new file mode 100644 index 0000000..d0012c1 Binary files /dev/null and b/sprite/bolvis/left.png differ diff --git a/sprite/bolvis/right.png b/sprite/bolvis/right.png new file mode 100644 index 0000000..17ce03f Binary files /dev/null and b/sprite/bolvis/right.png differ diff --git a/sprite/hand/closed.png b/sprite/hand/closed.png new file mode 100644 index 0000000..9f6e823 Binary files /dev/null and b/sprite/hand/closed.png differ diff --git a/sprite/hand/hand.png b/sprite/hand/hand.png new file mode 100644 index 0000000..8980981 Binary files /dev/null and b/sprite/hand/hand.png differ diff --git a/sprite/test.png b/sprite/test.png new file mode 100644 index 0000000..864afbf Binary files /dev/null and b/sprite/test.png differ diff --git a/sprite/utah-teapot.png b/sprite/utah-teapot.png new file mode 100644 index 0000000..a4a7e92 Binary files /dev/null and b/sprite/utah-teapot.png differ diff --git a/stuff.lua b/stuff.lua deleted file mode 100644 index 8fde7d1..0000000 --- a/stuff.lua +++ /dev/null @@ -1,10 +0,0 @@ -local game = require 'game' -local physics = require 'physics' - -local M = {} - -M.TestPlatform = physics.simple("test.png", 'rect', 'static') -M.Teapot = physics.simple("utah-teapot.png") -M.Apioform = physics.simple("apioform.png") - -return M diff --git a/test.png b/test.png deleted file mode 100644 index 864afbf..0000000 Binary files a/test.png and /dev/null differ diff --git a/utah-teapot.png b/utah-teapot.png deleted file mode 100644 index a4a7e92..0000000 Binary files a/utah-teapot.png and /dev/null differ diff --git a/world.lua b/world.lua new file mode 100644 index 0000000..a219589 --- /dev/null +++ b/world.lua @@ -0,0 +1,119 @@ +local obj_proto = {} +local obj_mt = {__newindex = function()assert(false)end} + +function obj_proto:get(ct) + assert(ct, "component type") + return self.components[ct] +end + +function obj_proto:all_components() + local k, v + return function() + k, v = next(self.components, k) + return v + end +end + +function obj_proto:call(method, ...) + for c in self:all_components() do + if c[method] then + c[method](c, ...) + end + end +end + +function obj_proto:enable() + self.world:registered(self, nil, true) + for c in self:all_components() do + self.world:registered(self, c.component_type, true) + if c.enable then c:enable() end + end +end + +function obj_proto:disable() + self.world:registered(self, nil, false) + for c in self:all_components() do + self.world:registered(self, c.component_type, false) + if c.disable then c:disable() end + end +end + +function obj_mt:__index(k) + return obj_proto[k] or self:get(k) +end + +local function init_cmp(obj, c) + assert(not c.inited) + c.obj = obj + for _, dep in ipairs(c.deps) do + local ct, inst = unpack(dep) + assert(ct, "component type") + obj:require(ct, inst) + end + c:init(c.i) + if c.enable then c:enable() end + c.inited = true +end + +function obj_proto:add(c) + assert(not self.components[c.component_type]) + self.components[c.component_type] = c + init_cmp(self, c) + return c +end + +function obj_proto:remove(ct) + local c = assert(self:get(ct)) + self.world:unreg_component(c) + if c.disable then c:disable() end +end + +function obj_proto:require(ct, instance) + if self:get(ct) then return end + return self:add(ct(instance)) +end + +local world_proto = {} +local world_mt = + {__index = world_proto, __newindex = function()assert(false)end} + +local function world() + local w = setmetatable({objects = {}, components = {}}, world_mt) + return w +end + +-- create an object in the world with the components specified in the arguments +function world_proto:object(...) + local components = {...} + local o = setmetatable({world = self, components = {}}, obj_mt) + for _, c in ipairs(components) do + assert(type(c) == 'table') + o.components[c.component_type] = c + end + for _, c in pairs(o.components) do + if not c.inited then + init_cmp(o, c) + end + end + o:enable() + return o +end + +function world_proto:registered(object, ct, is_reg) + if ct then + self.components[ct] = self.components[ct] or {} + self.components[ct][object] = is_reg and true or nil + else + self.objects[object] = is_reg and true or nil + end +end + +function world_proto:iterate(ct) + if ct then + return pairs(self.components[ct] or {}) + else + return pairs(self.objects) + end +end + +return world -- cgit v1.2.3