summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthe lemons <citrons@mondecitronne.com>2022-08-27 01:23:20 -0500
committerthe lemons <citrons@mondecitronne.com>2022-08-27 01:23:20 -0500
commit8bb18a89060ecd581a06238ce3fa5d2170ee3a15 (patch)
tree25baba9d2c267b986adfe7af661b3cd99a32b346
parent001272dbcbaa1110541e0666af3cea1c97bc199f (diff)
implement component system
-rw-r--r--Bolvis.lua218
-rw-r--r--Camera.lua25
-rw-r--r--Drawable.lua9
-rw-r--r--Input.lua6
-rw-r--r--Obj.lua68
-rw-r--r--Sprite.lua48
-rw-r--r--Transform.lua28
-rw-r--r--bolvis-blink.pngbin107353 -> 0 bytes
-rw-r--r--bolvis-left.pngbin135883 -> 0 bytes
-rw-r--r--bolvis-right.pngbin135225 -> 0 bytes
-rw-r--r--bolvis.pngbin145016 -> 0 bytes
-rw-r--r--component.lua24
-rw-r--r--conf.lua2
-rw-r--r--game.lua43
-rw-r--r--globals.lua23
-rw-r--r--hand-closed.pngbin8067 -> 0 bytes
-rw-r--r--hand-open.pngbin10843 -> 0 bytes
-rw-r--r--main.lua113
-rw-r--r--physics.lua70
-rw-r--r--sprite/apioform.png (renamed from apioform.png)bin645 -> 645 bytes
-rw-r--r--sprite/bolvis/blink.pngbin0 -> 18317 bytes
-rw-r--r--sprite/bolvis/bolvis.pngbin0 -> 28926 bytes
-rw-r--r--sprite/bolvis/left.pngbin0 -> 27672 bytes
-rw-r--r--sprite/bolvis/right.pngbin0 -> 27548 bytes
-rw-r--r--sprite/hand/closed.pngbin0 -> 3983 bytes
-rw-r--r--sprite/hand/hand.pngbin0 -> 5516 bytes
-rw-r--r--sprite/test.png (renamed from test.png)bin41407 -> 41407 bytes
-rw-r--r--sprite/utah-teapot.png (renamed from utah-teapot.png)bin75038 -> 75038 bytes
-rw-r--r--stuff.lua10
-rw-r--r--world.lua119
30 files changed, 438 insertions, 368 deletions
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/bolvis-blink.png b/bolvis-blink.png
deleted file mode 100644
index 209060d..0000000
--- a/bolvis-blink.png
+++ /dev/null
Binary files differ
diff --git a/bolvis-left.png b/bolvis-left.png
deleted file mode 100644
index 2eb1fb3..0000000
--- a/bolvis-left.png
+++ /dev/null
Binary files differ
diff --git a/bolvis-right.png b/bolvis-right.png
deleted file mode 100644
index e6e48c9..0000000
--- a/bolvis-right.png
+++ /dev/null
Binary files differ
diff --git a/bolvis.png b/bolvis.png
deleted file mode 100644
index bb2a29a..0000000
--- a/bolvis.png
+++ /dev/null
Binary files 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
--- a/hand-closed.png
+++ /dev/null
Binary files differ
diff --git a/hand-open.png b/hand-open.png
deleted file mode 100644
index 1ad33a9..0000000
--- a/hand-open.png
+++ /dev/null
Binary files 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/apioform.png b/sprite/apioform.png
index cc04a1a..cc04a1a 100644
--- a/apioform.png
+++ b/sprite/apioform.png
Binary files differ
diff --git a/sprite/bolvis/blink.png b/sprite/bolvis/blink.png
new file mode 100644
index 0000000..f66f162
--- /dev/null
+++ b/sprite/bolvis/blink.png
Binary files differ
diff --git a/sprite/bolvis/bolvis.png b/sprite/bolvis/bolvis.png
new file mode 100644
index 0000000..ca7896e
--- /dev/null
+++ b/sprite/bolvis/bolvis.png
Binary files differ
diff --git a/sprite/bolvis/left.png b/sprite/bolvis/left.png
new file mode 100644
index 0000000..d0012c1
--- /dev/null
+++ b/sprite/bolvis/left.png
Binary files differ
diff --git a/sprite/bolvis/right.png b/sprite/bolvis/right.png
new file mode 100644
index 0000000..17ce03f
--- /dev/null
+++ b/sprite/bolvis/right.png
Binary files differ
diff --git a/sprite/hand/closed.png b/sprite/hand/closed.png
new file mode 100644
index 0000000..9f6e823
--- /dev/null
+++ b/sprite/hand/closed.png
Binary files differ
diff --git a/sprite/hand/hand.png b/sprite/hand/hand.png
new file mode 100644
index 0000000..8980981
--- /dev/null
+++ b/sprite/hand/hand.png
Binary files differ
diff --git a/test.png b/sprite/test.png
index 864afbf..864afbf 100644
--- a/test.png
+++ b/sprite/test.png
Binary files differ
diff --git a/utah-teapot.png b/sprite/utah-teapot.png
index a4a7e92..a4a7e92 100644
--- a/utah-teapot.png
+++ b/sprite/utah-teapot.png
Binary files 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/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