fixed
This commit is contained in:
parent
7c7f76b188
commit
a9af97925e
12 changed files with 329 additions and 30 deletions
|
|
@ -360,6 +360,11 @@ function editorMouseHandler(x, y, button)
|
|||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- click landed on the grid (game area): place the selected asset
|
||||
if editorView == "room" and button == 1 and selectedAsset then
|
||||
currentRoom:attemptPlace(selectedAsset, gameAssets[selectedAsset], x, y, selectedColor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -117,9 +117,9 @@ function GUI:onClic(button)
|
|||
print(button)
|
||||
print("hey!!! u cliced on me. my name is ", self.name, self.text)
|
||||
GUI.pressSound:play()
|
||||
if button == "l" then
|
||||
if button == 1 then
|
||||
self.clic:left()
|
||||
elseif button == "r" then
|
||||
elseif button == 2 then
|
||||
self.clic:right()
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit b18c399defaa52ae61499ad56ced8c311b82c191
|
||||
Subproject commit 08937cc0ecf72d1a964a8de6cd552c5e136bf0d4
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 40fb13b0ec4a70e36f88812848511c5867bed857
|
||||
Subproject commit a0da807dca77baf07d287631f5ad41a9097fc25c
|
||||
63
libs/libs/TSerial.lua
Normal file
63
libs/libs/TSerial.lua
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
--- Tserial v1.51d, a simple table serializer which turns tables into Lua script
|
||||
-- @author Taehl (SelfMadeSpirit@gmail.com)
|
||||
Tserial = {}
|
||||
TSerial = Tserial -- for backwards-compatibility
|
||||
|
||||
--- Serializes a table into a string, in form of Lua script.
|
||||
-- @param t table to be serialized (may not contain any circular reference)
|
||||
-- @param drop if true, unserializable types will be silently dropped instead of raising errors
|
||||
-- if drop is a function, it will be called to serialize unsupported types
|
||||
-- if drop is a table, it will be used as a serialization table (where {[value] = serial})
|
||||
-- @param indent if true, output "human readable" mode with newlines and indentation (for debug)
|
||||
-- @return string recreating given table
|
||||
function Tserial.pack(t, drop, indent)
|
||||
assert(type(t) == "table", "Can only Tserial.pack tables.")
|
||||
local s, empty, indent = "{"..(indent and "\n" or ""), true, indent and math.max(type(indent)=="number" and indent or 0,0)
|
||||
local function proc(k,v, omitKey) -- encode a key/value pair
|
||||
empty = nil -- helps ensure empty tables return as "{}"
|
||||
local tk, tv, skip = type(k), type(v)
|
||||
if type(drop)=="table" and drop[k] then k = "["..drop[k].."]"
|
||||
elseif tk == "boolean" then k = k and "[true]" or "[false]"
|
||||
elseif tk == "string" then
|
||||
local f = string.format("%q",k)
|
||||
if f ~= '"'..k..'"' or string.find(k, " ") then k = '['..f..']' end
|
||||
elseif tk == "number" then k = "["..k.."]"
|
||||
elseif tk == "table" then k = "["..Tserial.pack(k, drop, indent and indent+1).."]"
|
||||
elseif type(drop) == "function" then k = "["..string.format("%q",drop(k)).."]"
|
||||
elseif drop then skip = true
|
||||
else error("Attempted to Tserial.pack a table with an invalid key: "..tostring(k))
|
||||
end
|
||||
if type(drop)=="table" and drop[v] then v = drop[v]
|
||||
elseif tv == "boolean" then v = v and "true" or "false"
|
||||
elseif tv == "string" then v = string.format("%q", v)
|
||||
elseif tv == "number" then -- no change needed
|
||||
elseif tv == "table" then v = Tserial.pack(v, drop, indent and indent+1)
|
||||
elseif type(drop) == "function" then v = string.format("%q",drop(v))
|
||||
elseif drop then skip = true
|
||||
else error("Attempted to Tserial.pack a table with an invalid value: "..tostring(v))
|
||||
end
|
||||
if not skip then return string.rep("\t",indent or 0)..(omitKey and "" or k.."=")..v..","..(indent and "\n" or "") end
|
||||
return ""
|
||||
end
|
||||
local l, did=-1,{} repeat l=l+1 until t[l+1]==nil -- #t "can" lie!
|
||||
for i=1,l do s = s..proc(i, t[i], true) did[i]=true end -- use ordered values when possible for better string
|
||||
for k, v in pairs(t) do if not did[k] then s = s..proc(k, v) end end
|
||||
if not empty then s = string.sub(s,1,string.len(s)-1) end
|
||||
if indent then s = string.sub(s,1,string.len(s)-1).."\n" end
|
||||
return s..string.rep("\t",(indent or 1)-1).."}"
|
||||
end
|
||||
|
||||
--- Loads a table into memory from a string (like those output by Tserial.pack)
|
||||
-- @param s a string of Lua defining a table, such as "{2,4,8,ex='ample'}"
|
||||
-- @param safe if true, all extraneous parts of the string will be removed, leaving only a table (prevents running anomalous code when unpacking untrusted strings). Will also cause malformed tables to quietly return nil and an error message, instead of throwing an error (so your program can't be crashed with a bad string)
|
||||
-- @return a table recreated from the given string.
|
||||
function Tserial.unpack(s, safe)
|
||||
if safe then s = string.match(s, "(%b{})") end
|
||||
assert(type(s) == "string", "Can only Tserial.unpack strings.")
|
||||
local f, result = loadstring("Tserial.table="..s)
|
||||
if not safe then assert(f,result) elseif not f then return nil, result end
|
||||
result = f()
|
||||
local t = Tserial.table
|
||||
Tserial.table = nil
|
||||
return t, result
|
||||
end
|
||||
1
libs/libs/hump
Submodule
1
libs/libs/hump
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 08937cc0ecf72d1a964a8de6cd552c5e136bf0d4
|
||||
1
libs/libs/json4lua
Submodule
1
libs/libs/json4lua
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a0da807dca77baf07d287631f5ad41a9097fc25c
|
||||
182
libs/libs/middleclass.lua
Normal file
182
libs/libs/middleclass.lua
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
local middleclass = {
|
||||
_VERSION = 'middleclass v3.0.1',
|
||||
_DESCRIPTION = 'Object Orientation for Lua',
|
||||
_URL = 'https://github.com/kikito/middleclass',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2011 Enrique García Cota
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
local function _setClassDictionariesMetatables(aClass)
|
||||
local dict = aClass.__instanceDict
|
||||
dict.__index = dict
|
||||
|
||||
local super = aClass.super
|
||||
if super then
|
||||
local superStatic = super.static
|
||||
setmetatable(dict, super.__instanceDict)
|
||||
setmetatable(aClass.static, { __index = function(_,k) return dict[k] or superStatic[k] end })
|
||||
else
|
||||
setmetatable(aClass.static, { __index = function(_,k) return dict[k] end })
|
||||
end
|
||||
end
|
||||
|
||||
local function _setClassMetatable(aClass)
|
||||
setmetatable(aClass, {
|
||||
__tostring = function() return "class " .. aClass.name end,
|
||||
__index = aClass.static,
|
||||
__newindex = aClass.__instanceDict,
|
||||
__call = function(self, ...) return self:new(...) end
|
||||
})
|
||||
end
|
||||
|
||||
local function _createClass(name, super)
|
||||
local aClass = { name = name, super = super, static = {}, __mixins = {}, __instanceDict={} }
|
||||
aClass.subclasses = setmetatable({}, {__mode = "k"})
|
||||
|
||||
_setClassDictionariesMetatables(aClass)
|
||||
_setClassMetatable(aClass)
|
||||
|
||||
return aClass
|
||||
end
|
||||
|
||||
local function _createLookupMetamethod(aClass, name)
|
||||
return function(...)
|
||||
local method = aClass.super[name]
|
||||
assert( type(method)=='function', tostring(aClass) .. " doesn't implement metamethod '" .. name .. "'" )
|
||||
return method(...)
|
||||
end
|
||||
end
|
||||
|
||||
local function _setClassMetamethods(aClass)
|
||||
for _,m in ipairs(aClass.__metamethods) do
|
||||
aClass[m]= _createLookupMetamethod(aClass, m)
|
||||
end
|
||||
end
|
||||
|
||||
local function _setDefaultInitializeMethod(aClass, super)
|
||||
aClass.initialize = function(instance, ...)
|
||||
return super.initialize(instance, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local function _includeMixin(aClass, mixin)
|
||||
assert(type(mixin)=='table', "mixin must be a table")
|
||||
for name,method in pairs(mixin) do
|
||||
if name ~= "included" and name ~= "static" then aClass[name] = method end
|
||||
end
|
||||
if mixin.static then
|
||||
for name,method in pairs(mixin.static) do
|
||||
aClass.static[name] = method
|
||||
end
|
||||
end
|
||||
if type(mixin.included)=="function" then mixin:included(aClass) end
|
||||
aClass.__mixins[mixin] = true
|
||||
end
|
||||
|
||||
local Object = _createClass("Object", nil)
|
||||
|
||||
Object.static.__metamethods = { '__add', '__call', '__concat', '__div', '__ipairs', '__le',
|
||||
'__len', '__lt', '__mod', '__mul', '__pairs', '__pow', '__sub',
|
||||
'__tostring', '__unm'}
|
||||
|
||||
function Object.static:allocate()
|
||||
assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
|
||||
return setmetatable({ class = self }, self.__instanceDict)
|
||||
end
|
||||
|
||||
function Object.static:new(...)
|
||||
local instance = self:allocate()
|
||||
instance:initialize(...)
|
||||
return instance
|
||||
end
|
||||
|
||||
function Object.static:subclass(name)
|
||||
assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
|
||||
assert(type(name) == "string", "You must provide a name(string) for your class")
|
||||
|
||||
local subclass = _createClass(name, self)
|
||||
_setClassMetamethods(subclass)
|
||||
_setDefaultInitializeMethod(subclass, self)
|
||||
self.subclasses[subclass] = true
|
||||
self:subclassed(subclass)
|
||||
|
||||
return subclass
|
||||
end
|
||||
|
||||
function Object.static:subclassed(other) end
|
||||
|
||||
function Object.static:isSubclassOf(other)
|
||||
return type(other) == 'table' and
|
||||
type(self) == 'table' and
|
||||
type(self.super) == 'table' and
|
||||
( self.super == other or
|
||||
type(self.super.isSubclassOf) == 'function' and
|
||||
self.super:isSubclassOf(other)
|
||||
)
|
||||
end
|
||||
|
||||
function Object.static:include( ... )
|
||||
assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'")
|
||||
for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
|
||||
return self
|
||||
end
|
||||
|
||||
function Object.static:includes(mixin)
|
||||
return type(mixin) == 'table' and
|
||||
type(self) == 'table' and
|
||||
type(self.__mixins) == 'table' and
|
||||
( self.__mixins[mixin] or
|
||||
type(self.super) == 'table' and
|
||||
type(self.super.includes) == 'function' and
|
||||
self.super:includes(mixin)
|
||||
)
|
||||
end
|
||||
|
||||
function Object:initialize() end
|
||||
|
||||
function Object:__tostring() return "instance of " .. tostring(self.class) end
|
||||
|
||||
function Object:isInstanceOf(aClass)
|
||||
return type(self) == 'table' and
|
||||
type(self.class) == 'table' and
|
||||
type(aClass) == 'table' and
|
||||
( aClass == self.class or
|
||||
type(aClass.isSubclassOf) == 'function' and
|
||||
self.class:isSubclassOf(aClass)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function middleclass.class(name, super, ...)
|
||||
super = super or Object
|
||||
return super:subclass(name, ...)
|
||||
end
|
||||
|
||||
middleclass.Object = Object
|
||||
|
||||
setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
|
||||
|
||||
return middleclass
|
||||
1
libs/libs/sfxrlua
Submodule
1
libs/libs/sfxrlua
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 949429d4618aee8b019899af101bd5f793d07a64
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 7a542bb53151c0c9596c7b7fdfad096fe81d728a
|
||||
Subproject commit 949429d4618aee8b019899af101bd5f793d07a64
|
||||
13
main.lua
13
main.lua
|
|
@ -49,15 +49,13 @@ function love.update(dt)
|
|||
end
|
||||
|
||||
function love.draw()
|
||||
gameCanvas:clear()
|
||||
finalCanvas:clear()
|
||||
sideBarCanvas:clear()
|
||||
|
||||
love.graphics.setCanvas(gameCanvas)
|
||||
love.graphics.clear()
|
||||
love.graphics.setBlendMode("screen")
|
||||
currentRoom:draw()
|
||||
|
||||
love.graphics.setCanvas(finalCanvas)
|
||||
love.graphics.clear()
|
||||
|
||||
local scaleCoefficient = .93
|
||||
local samples = 7
|
||||
|
|
@ -78,6 +76,7 @@ function love.draw()
|
|||
love.graphics.setCanvas()
|
||||
|
||||
love.graphics.setCanvas(sideBarCanvas)
|
||||
love.graphics.clear()
|
||||
editorDraw()
|
||||
love.graphics.setCanvas()
|
||||
|
||||
|
|
@ -120,8 +119,8 @@ function love.keypressed(key)
|
|||
end
|
||||
|
||||
function love.mousepressed(x, y, button)
|
||||
if button == "r" then
|
||||
currentRoom:attemptDelete(x, y)
|
||||
if button == 2 then
|
||||
currentRoom:attemptDelete(x, y, selectedColor)
|
||||
end
|
||||
editorMouseHandler(x, y, button)
|
||||
end
|
||||
|
|
@ -175,7 +174,7 @@ function _initSounds()
|
|||
staticWave.envelope.release = 0
|
||||
staticWave.envelope.sustain = 1
|
||||
staticWave.envelope.decay = 0
|
||||
static = love.audio.newSource(staticWave:generateSoundData())
|
||||
static = love.audio.newSource((staticWave:generateSoundData()))
|
||||
static:setLooping(true)
|
||||
static:setVolume(.15)
|
||||
static:play()
|
||||
|
|
|
|||
83
room.lua
83
room.lua
|
|
@ -556,39 +556,86 @@ function Room:getCellFromMousePos(mouseX, mouseY)
|
|||
return cell
|
||||
end
|
||||
|
||||
function Room:attemptDelete(mouseX, mouseY)
|
||||
function Room:attemptDelete(mouseX, mouseY, color)
|
||||
local cell = self:getCellFromMousePos(mouseX, mouseY)
|
||||
for color, player in pairs(self.player) do
|
||||
if player:occupiesCell(cell) then
|
||||
self.player[color] = nil
|
||||
self.colorsPlayerHas[color] = false
|
||||
end
|
||||
|
||||
-- "white" (or nil) deletes every channel; otherwise just the picked one
|
||||
local colors
|
||||
if not color or color == "white" then
|
||||
colors = {"red", "green", "blue"}
|
||||
else
|
||||
colors = {color}
|
||||
end
|
||||
local entities = {}
|
||||
for color, entityArray in pairs(self.collideables) do
|
||||
for index, entity in pairs(entityArray) do
|
||||
if entity:occupiesCell(cell) then
|
||||
table.remove(self.collideables[color], index)
|
||||
|
||||
for _, c in ipairs(colors) do
|
||||
-- player
|
||||
if self.player[c] and self.player[c]:occupiesCell(cell) then
|
||||
self.player[c] = nil
|
||||
self.colorsPlayerHas[c] = false
|
||||
end
|
||||
-- collidables (iterate backwards so table.remove is safe)
|
||||
local entityArray = self.collideables[c]
|
||||
for index = #entityArray, 1, -1 do
|
||||
if entityArray[index]:occupiesCell(cell) then
|
||||
table.remove(entityArray, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
for color, switches in pairs(self.switches) do
|
||||
for index, switch in pairs(switches) do
|
||||
if switch:occupiesCell(cell) then
|
||||
print("assssss occupied scellsll")
|
||||
table.remove(self.switches[color], index)
|
||||
-- switches
|
||||
local switchArray = self.switches[c]
|
||||
for index = #switchArray, 1, -1 do
|
||||
if switchArray[index]:occupiesCell(cell) then
|
||||
table.remove(switchArray, index)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:tick()
|
||||
end
|
||||
|
||||
function Room:attemptPlace()
|
||||
local placeImageCache = {}
|
||||
local function loadPlaceImage(path)
|
||||
if not placeImageCache[path] then
|
||||
placeImageCache[path] = love.graphics.newImage(path)
|
||||
end
|
||||
return placeImageCache[path]
|
||||
end
|
||||
|
||||
function Room:attemptPlace(name, props, mouseX, mouseY, color)
|
||||
if not props or not props.sprites then return end
|
||||
local cell = self:getCellFromMousePos(mouseX, mouseY)
|
||||
|
||||
-- "white" (or nil) means every channel; otherwise just the picked channel
|
||||
local colors
|
||||
if not color or color == "white" then
|
||||
colors = {"red", "green", "blue"}
|
||||
else
|
||||
colors = {color}
|
||||
end
|
||||
|
||||
-- one generic entity per placed channel; each lives on its own collision
|
||||
-- layer and the additive blend combines them into full color
|
||||
for _, c in ipairs(colors) do
|
||||
local path = props.sprites[c]
|
||||
if path then
|
||||
local sprite = loadPlaceImage(path)
|
||||
local entity
|
||||
if props.class == "moveable" then
|
||||
entity = GenericMoveable:new(cell.x, cell.y, c, sprite, name)
|
||||
else
|
||||
entity = GenericUnmoveable:new(cell.x, cell.y, c, sprite)
|
||||
end
|
||||
self:registerCollidable(entity, {c})
|
||||
end
|
||||
end
|
||||
self:tick()
|
||||
end
|
||||
|
||||
function Room:load(name)
|
||||
local room = love.filesystem.read("rooms/" .. name .. ".sav")
|
||||
if not room then
|
||||
-- no save yet: start with a blank room to build in the editor
|
||||
print("no save for '" .. name .. "', starting blank")
|
||||
return
|
||||
end
|
||||
self:deserialize(TSerial.unpack(room))
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue