finally make it object oriented and add shim support (nogame 0.9.0 now works)
This commit is contained in:
parent
f9198fec8b
commit
c5dbed728c
|
@ -47,12 +47,20 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/love2d/love/blob/3053278048cceb7ca71b944517e886804314a246/src/scripts/nogame.lua">LÖVE 10.0 <i>nogame.lua</i></a></td>
|
||||
<td>blending modes</td>
|
||||
<td>SpriteBatch</td>
|
||||
<td><span class="medium">Running</span></td>
|
||||
<td><span class="bad">Broken</span></td>
|
||||
<td><span class="bad">Broken</span></td>
|
||||
<td><span class="bad">Broken</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://bitbucket.org/rude/love/src/63ed6cbfb2853009bb49572d975569d43cba2705/src/scripts/boot.lua">LÖVE 0.9.0 <i>nogame.lua</i></a></td>
|
||||
<td>blending modes</td>
|
||||
<td><span class="medium">Running</span></td>
|
||||
<td><span class="bad">Broken</span></td>
|
||||
<td><span class="bad">Perfect</span></td>
|
||||
<td><span class="bad">Perfect</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/TurtleP/LovePotion/tree/master/nogame">LovePotion <i>nogame<i></a></td>
|
||||
<td><a href="https://github.com/TurtleP">Jeremy Postelnek</a></td>
|
||||
|
|
30
main.js
30
main.js
|
@ -2,35 +2,13 @@ window.infatuated = {};
|
|||
(function() {
|
||||
"use strict";
|
||||
|
||||
function assert(cond, msg) { if (!cond) { throw msg; } }
|
||||
|
||||
var images = {};
|
||||
infatuated.newImage = function(path, b64) {
|
||||
var image = new Image();
|
||||
images[path] = image;
|
||||
if (b64) {
|
||||
image.src = "data:image/png;base64,"+path;
|
||||
} else {
|
||||
image.src = infatuated.game+"/"+path;
|
||||
}
|
||||
image.getWidth = function() { return image.width; }
|
||||
image.getHeight = function() { return image.height; }
|
||||
return {
|
||||
"type": "Image",
|
||||
"path": path,
|
||||
"getWidth": function() { return image.width; },
|
||||
"getHeight": function() { return image.height; }
|
||||
};
|
||||
}
|
||||
infatuated.drawImage = function(ctx, obj, x, y) {
|
||||
if (!obj.type) { return; }
|
||||
assert(obj.type == "Image", "bad argument #2 to drawImage");
|
||||
if (images[obj.path].complete) {
|
||||
ctx.drawImage(images[obj.path], x, y);
|
||||
}
|
||||
infatuated.newImage = function() {
|
||||
return new Image();
|
||||
}
|
||||
|
||||
var url = new URL(location.href);
|
||||
var game = url.searchParams.get("game");
|
||||
infatuated.game = game ? "game-"+game : "game";
|
||||
var shim = url.searchParams.get("shim");
|
||||
infatuated.shim = shim ? shim : false;
|
||||
})();
|
||||
|
|
128
main.lua
128
main.lua
|
@ -61,10 +61,12 @@ infatuated.conf = {
|
|||
}
|
||||
}
|
||||
|
||||
class = require "middleclass"
|
||||
infatuated.classes = {}
|
||||
|
||||
local js = require "js"
|
||||
infatuated.js = js
|
||||
local window = js.global
|
||||
infatuated.path = window.infatuated.game;
|
||||
local document = window.document
|
||||
local canvas = document:getElementById("infatuated-canvas")
|
||||
infatuated.canvas = canvas
|
||||
|
@ -109,6 +111,9 @@ function infatuated.msgbox:hide()
|
|||
end
|
||||
--infatuated.msgbox:show("sample title", "the quick brown fox", {"a", "b", "c"}, oldprint)
|
||||
|
||||
infatuated.path = window.infatuated.game
|
||||
infatuated.shim = window.infatuated.shim
|
||||
|
||||
print("Running game from path %q", path)
|
||||
|
||||
local function errorprint(...)
|
||||
|
@ -139,7 +144,6 @@ function infatuated.parseColor(r, g, b, a)
|
|||
assert(type(g) == "number", "bad argument #2 to parseColor")
|
||||
assert(type(b) == "number", "bad argument #3 to parseColor")
|
||||
assert(type(a) == "number", "bad argument #4 to parseColor")
|
||||
--return {r, g, b, a}, string.format("rgba(%f, %f, %f, %f)", r, g, b, a)
|
||||
return {r, g, b, a}, string.format("rgba(%f, %f, %f, %f)", r*255, g*255, b*255, a)
|
||||
else
|
||||
error("bad argument #1 to parseColor")
|
||||
|
@ -209,66 +213,76 @@ end
|
|||
|
||||
print("Coroutining now")
|
||||
infatuated.thread = coroutine.create(function()
|
||||
require "modules.data"
|
||||
require "modules.event"
|
||||
require "modules.filesystem"
|
||||
require "modules.graphics"
|
||||
require "modules.handlers"
|
||||
require "modules.image"
|
||||
require "modules.math"
|
||||
require "modules.system"
|
||||
require "modules.timer"
|
||||
require "modules.window"
|
||||
|
||||
love.run()
|
||||
|
||||
local oldrequire = require
|
||||
infatuated.require = oldrequire
|
||||
function require(path)
|
||||
assert(type(path) == "string", "bad argument #1 to require")
|
||||
if path == "love" then return love end
|
||||
return oldrequire(infatuated.path.."."..path)
|
||||
end
|
||||
|
||||
print("Importing conf")
|
||||
xpcall(function()
|
||||
require "modules.data"
|
||||
require "modules.event"
|
||||
require "modules.filesystem"
|
||||
require "modules.graphics"
|
||||
require "modules.handlers"
|
||||
require "modules.image"
|
||||
require "modules.math"
|
||||
require "modules.system"
|
||||
require "modules.timer"
|
||||
require "modules.window"
|
||||
|
||||
love.run()
|
||||
|
||||
if infatuated.shim then
|
||||
print("Shimming %s", infatuated.shim)
|
||||
infatuated.shim = infatuated.shim:gsub("%.", "-")
|
||||
require("shims."..infatuated.shim)
|
||||
end
|
||||
|
||||
local oldrequire = require
|
||||
infatuated.require = oldrequire
|
||||
function require(path)
|
||||
assert(type(path) == "string", "bad argument #1 to require")
|
||||
if path == "love" then return love end
|
||||
return oldrequire(infatuated.path.."."..path)
|
||||
end
|
||||
|
||||
print("Importing conf")
|
||||
|
||||
local status, errmsg = pcall(oldrequire, infatuated.path..".conf")
|
||||
if not status and not errmsg:find("^module '.-%.conf' not found:") then
|
||||
infatuated.crash(errmsg)
|
||||
end
|
||||
local status, errmsg = pcall(love.conf, infatuated.conf)
|
||||
if not status then infatuated.crash(errmsg) end
|
||||
local status, errmsg = pcall(oldrequire, infatuated.path..".conf")
|
||||
if not status and not errmsg:find("^module '.-%.conf' not found:") then
|
||||
infatuated.crash(errmsg)
|
||||
end
|
||||
local status, errmsg = pcall(love.conf, infatuated.conf)
|
||||
if not status then infatuated.crash(errmsg) end
|
||||
|
||||
print("Importing main")
|
||||
print("Importing main")
|
||||
|
||||
local status, errmsg = pcall(oldrequire, infatuated.path..".main")
|
||||
if not status then infatuated.crash(errmsg) end
|
||||
local status, errmsg = pcall(love.run)
|
||||
if not status then
|
||||
infatuated.crash(errmsg)
|
||||
else
|
||||
infatuated.loopGuest = errmsg
|
||||
end
|
||||
|
||||
print("Starting event loop")
|
||||
|
||||
infatuated.dt1 = window.performance:now()
|
||||
local function resume()
|
||||
coroutine.resume(infatuated.thread)
|
||||
end
|
||||
while true do
|
||||
local dt2 = window.performance:now()
|
||||
infatuated.dt = (dt2-infatuated.dt1)/1000
|
||||
infatuated.dt1 = dt2
|
||||
local status, errmsg = pcall(infatuated.loopGuest)
|
||||
local status, errmsg = pcall(oldrequire, infatuated.path..".main")
|
||||
if not status then infatuated.crash(errmsg) end
|
||||
local status, errmsg = pcall(love.run)
|
||||
if not status then
|
||||
infatuated.crash(errmsg)
|
||||
elseif errmsg then
|
||||
print("Exited with code %d", errmsg or -1)
|
||||
return
|
||||
else
|
||||
infatuated.loopGuest = errmsg
|
||||
end
|
||||
window:requestAnimationFrame(resume)
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
print("Starting event loop")
|
||||
|
||||
infatuated.dt1 = window.performance:now()
|
||||
local function resume()
|
||||
coroutine.resume(infatuated.thread)
|
||||
end
|
||||
while true do
|
||||
local dt2 = window.performance:now()
|
||||
infatuated.dt = (dt2-infatuated.dt1)/1000
|
||||
infatuated.dt1 = dt2
|
||||
local status, errmsg = pcall(infatuated.loopGuest)
|
||||
if not status then
|
||||
infatuated.crash(errmsg)
|
||||
elseif errmsg then
|
||||
print("Exited with code %d", errmsg or -1)
|
||||
return
|
||||
end
|
||||
window:requestAnimationFrame(resume)
|
||||
coroutine.yield()
|
||||
end
|
||||
end, function(errmsg)
|
||||
infatuated.crash(errmsg)
|
||||
end)
|
||||
end)
|
||||
coroutine.resume(infatuated.thread)
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
local middleclass = {
|
||||
_VERSION = 'middleclass v4.1.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 _createIndexWrapper(aClass, f)
|
||||
if f == nil then
|
||||
return aClass.__instanceDict
|
||||
else
|
||||
return function(self, name)
|
||||
local value = aClass.__instanceDict[name]
|
||||
|
||||
if value ~= nil then
|
||||
return value
|
||||
elseif type(f) == "function" then
|
||||
return (f(self, name))
|
||||
else
|
||||
return f[name]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function _propagateInstanceMethod(aClass, name, f)
|
||||
f = name == "__index" and _createIndexWrapper(aClass, f) or f
|
||||
aClass.__instanceDict[name] = f
|
||||
|
||||
for subclass in pairs(aClass.subclasses) do
|
||||
if rawget(subclass.__declaredMethods, name) == nil then
|
||||
_propagateInstanceMethod(subclass, name, f)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function _declareInstanceMethod(aClass, name, f)
|
||||
aClass.__declaredMethods[name] = f
|
||||
|
||||
if f == nil and aClass.super then
|
||||
f = aClass.super.__instanceDict[name]
|
||||
end
|
||||
|
||||
_propagateInstanceMethod(aClass, name, f)
|
||||
end
|
||||
|
||||
local function _tostring(self) return "class " .. self.name end
|
||||
local function _call(self, ...) return self:new(...) end
|
||||
|
||||
local function _createClass(name, super)
|
||||
local dict = {}
|
||||
dict.__index = dict
|
||||
|
||||
local aClass = { name = name, super = super, static = {},
|
||||
__instanceDict = dict, __declaredMethods = {},
|
||||
subclasses = setmetatable({}, {__mode='k'}) }
|
||||
|
||||
if super then
|
||||
setmetatable(aClass.static, {
|
||||
__index = function(_,k)
|
||||
local result = rawget(dict,k)
|
||||
if result == nil then
|
||||
return super.static[k]
|
||||
end
|
||||
return result
|
||||
end
|
||||
})
|
||||
else
|
||||
setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) end })
|
||||
end
|
||||
|
||||
setmetatable(aClass, { __index = aClass.static, __tostring = _tostring,
|
||||
__call = _call, __newindex = _declareInstanceMethod })
|
||||
|
||||
return aClass
|
||||
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
|
||||
|
||||
for name,method in pairs(mixin.static or {}) do
|
||||
aClass.static[name] = method
|
||||
end
|
||||
|
||||
if type(mixin.included)=="function" then mixin:included(aClass) end
|
||||
return aClass
|
||||
end
|
||||
|
||||
local DefaultMixin = {
|
||||
__tostring = function(self) return "instance of " .. tostring(self.class) end,
|
||||
|
||||
initialize = function(self, ...) end,
|
||||
|
||||
isInstanceOf = function(self, aClass)
|
||||
return type(aClass) == 'table'
|
||||
and type(self) == 'table'
|
||||
and (self.class == aClass
|
||||
or type(self.class) == 'table'
|
||||
and type(self.class.isSubclassOf) == 'function'
|
||||
and self.class:isSubclassOf(aClass))
|
||||
end,
|
||||
|
||||
static = {
|
||||
allocate = function(self)
|
||||
assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
|
||||
return setmetatable({ class = self }, self.__instanceDict)
|
||||
end,
|
||||
|
||||
new = function(self, ...)
|
||||
assert(type(self) == 'table', "Make sure that you are using 'Class:new' instead of 'Class.new'")
|
||||
local instance = self:allocate()
|
||||
instance:initialize(...)
|
||||
return instance
|
||||
end,
|
||||
|
||||
subclass = function(self, 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)
|
||||
|
||||
for methodName, f in pairs(self.__instanceDict) do
|
||||
_propagateInstanceMethod(subclass, methodName, f)
|
||||
end
|
||||
subclass.initialize = function(instance, ...) return self.initialize(instance, ...) end
|
||||
|
||||
self.subclasses[subclass] = true
|
||||
self:subclassed(subclass)
|
||||
|
||||
return subclass
|
||||
end,
|
||||
|
||||
subclassed = function(self, other) end,
|
||||
|
||||
isSubclassOf = function(self, other)
|
||||
return type(other) == 'table' and
|
||||
type(self.super) == 'table' and
|
||||
( self.super == other or self.super:isSubclassOf(other) )
|
||||
end,
|
||||
|
||||
include = function(self, ...)
|
||||
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 middleclass.class(name, super)
|
||||
assert(type(name) == 'string', "A name (string) is needed for the new class")
|
||||
return super and super:subclass(name) or _includeMixin(_createClass(name), DefaultMixin)
|
||||
end
|
||||
|
||||
setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
|
||||
|
||||
return middleclass
|
|
@ -1,12 +1,13 @@
|
|||
love.filesystem = {}
|
||||
local FileData = class("FileData")
|
||||
infatuated.classes.FileData = FileData
|
||||
function FileData:initialize(contents, name)
|
||||
self.contents = contents
|
||||
self.name = name
|
||||
end
|
||||
function love.filesystem.newFileData(contents, name)
|
||||
if name then
|
||||
-- TODO: use an actual class
|
||||
return {
|
||||
type = "FileData",
|
||||
data = contents,
|
||||
name = name
|
||||
}
|
||||
return infatuated.classes.FileData:new(contents, name)
|
||||
else
|
||||
return nil, "not implemented"
|
||||
end
|
||||
|
|
|
@ -85,33 +85,71 @@ function love.graphics.setLineWidth(width)
|
|||
infatuated.lineWidth = width
|
||||
end
|
||||
|
||||
function love.graphics.newSpriteBatch(image, maxsprites, usage)
|
||||
maxsprites = maxsprites or 1000
|
||||
assert(type(image) == "userdata" and image.type == "Image", "bad argument #1 to newSpriteBatch (expected Image)")
|
||||
assert(type(maxsprites) == "number" and maxsprites > 0, "bad argument #2 to newSpriteBatch")
|
||||
return {
|
||||
type = "SpriteBatch",
|
||||
maxsprites = maxsprites,
|
||||
getBufferSize = function(self) return self.maxsprites end,
|
||||
setBufferSize = function(self, maxsprites)
|
||||
assert(type(maxsprites) == "number" and maxsprites > 0, "bad argument #2 to setBufferSize (expected number)")
|
||||
self.maxsprites = maxsprites
|
||||
end,
|
||||
add = function() end,
|
||||
flush = function() end,
|
||||
clear = function() end
|
||||
}
|
||||
local SpriteBatch = class("SpriteBatch")
|
||||
infatuated.classes.SpriteBatch = SpriteBatch
|
||||
function SpriteBatch:initialize(image, max)
|
||||
self._max = max
|
||||
end
|
||||
function love.graphics.newImage(path)
|
||||
if path.type == "ImageData" then
|
||||
return newImage(nil, path, true)
|
||||
function SpriteBatch:getBufferSize()
|
||||
return self._max
|
||||
end
|
||||
function SpriteBatch:setBufferSize(maxsprites)
|
||||
assert(type(maxsprites) == "number", "bad argument #1 to setBufferSize (expected number)")
|
||||
assert(maxsprites > 0, "maxsprites must be greater than 0")
|
||||
self._max = maxsprites
|
||||
end
|
||||
function SpriteBatch:add() end
|
||||
function SpriteBatch:flush() end
|
||||
function SpriteBatch:clear() end
|
||||
function love.graphics.newSpriteBatch(image, maxsprites)
|
||||
maxsprites = maxsprites or 1000
|
||||
assert(type(image) == "table" and tostring(image.class) == "class Image", "bad argument #1 to newSpriteBatch (expected Image)")
|
||||
assert(type(maxsprites) == "number", "bad argument #2 to newSpriteBatch (expected number)")
|
||||
assert(maxsprites > 0, "maxsprites must be greater than 0")
|
||||
return SpriteBatch:new(image, maxsprites, usage)
|
||||
end
|
||||
|
||||
local Image = class("Image")
|
||||
infatuated.classes.Image = Image
|
||||
function Image:initialize(a)
|
||||
if type(a) == "string" then
|
||||
infatuated.print("Loading image from %q", a)
|
||||
local image = newImage()
|
||||
a = ("/"..a):gsub("/%.%.", "/")
|
||||
image.src = "game"..a
|
||||
image.onload = function(self)
|
||||
infatuated.print("Loaded image")
|
||||
coroutine.resume(infatuated.thread)
|
||||
end
|
||||
coroutine.yield()
|
||||
self.image = image
|
||||
else
|
||||
assert(type(path) == "string", "bad argument #1 to newImage")
|
||||
return newImage(nil, path)
|
||||
infatuated.print("Loading image from ImageData")
|
||||
local image = newImage()
|
||||
image.src = "data:image/png;base64,"..a.data
|
||||
image.onload = function(self)
|
||||
infatuated.print("Loaded image")
|
||||
coroutine.resume(infatuated.thread)
|
||||
end
|
||||
coroutine.yield()
|
||||
self.image = image
|
||||
end
|
||||
end
|
||||
function Image:getWidth()
|
||||
return self.image.width
|
||||
end
|
||||
function Image:getHeight()
|
||||
return self.image.height
|
||||
end
|
||||
function love.graphics.newImage(a)
|
||||
local t = type(a)
|
||||
assert(t == "string" or (t == "table" and tostring(a.class) == "class ImageData"), "bad argument #1 to newImage (expected string or ImageData)")
|
||||
return Image:new(a)
|
||||
end
|
||||
|
||||
function love.graphics.draw(obj, x, y, r, sx, sy, ox, oy)
|
||||
if type(obj) == "table" and tostring(obj.class) == "class SpriteBatch" then return end
|
||||
assert(type(obj) == "table" and tostring(obj.class) == "class Image", "bad argument #1 to draw (expected Image)")
|
||||
r = r or 0
|
||||
ox = ox or 0
|
||||
oy = oy or 0
|
||||
|
@ -126,7 +164,7 @@ function love.graphics.draw(obj, x, y, r, sx, sy, ox, oy)
|
|||
ctx:rotate(r)
|
||||
-- color tinting looks HARD!
|
||||
ctx.globalAlpha = infatuated.color[4]
|
||||
drawImage(nil, ctx, obj, -ox, -oy)
|
||||
ctx:drawImage(obj.image, -ox, -oy)
|
||||
ctx:restore()
|
||||
end
|
||||
function love.graphics.print(text, x, y, r, sx, sy, ox, oy, kx, ky)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
love.image = {}
|
||||
function love.image.newImageData(w, h, f, d)
|
||||
if h or f or d then
|
||||
error("not implemented")
|
||||
else
|
||||
-- TODO: use an actual class
|
||||
return {
|
||||
type = "ImageData",
|
||||
content = w
|
||||
}
|
||||
end
|
||||
local ImageData = class("ImageData")
|
||||
infatuated.classes.ImageData = ImageData
|
||||
function ImageData:initialize(a)
|
||||
self.data = a.contents
|
||||
end
|
||||
function love.image.newImageData(a, b, c, d)
|
||||
assert(type(a) == "table" and tostring(a.class) == "class FileData", "bad argument #1 to newImageData (expected FileData)")
|
||||
if b or c or d then
|
||||
error("not implemented")
|
||||
end
|
||||
return ImageData:new(a)
|
||||
end
|
||||
|
|
|
@ -27,10 +27,13 @@ local platformIDs = {
|
|||
win64 = "Windows",
|
||||
wince = "Windows" -- amirite
|
||||
}
|
||||
function love.system.getOS()
|
||||
local function getOS()
|
||||
if useragent:find("android") then return "Android" end -- fucking "Linux 50m3_r4nd0m_5h1t"
|
||||
if useragent:find("iphone") then return "iOS" end -- fucking "general Mobile Device"
|
||||
return platformIDs[platform] or platform:find("mobile") and "Android" or "Windows"
|
||||
end
|
||||
love._os = love.system.getOS() -- 0.8.0 compatibility
|
||||
infatuated.print("Detected OS as %s", love._os)
|
||||
infatuated.os = getOS()
|
||||
infatuated.print("Detected OS as %s", infatuated.os)
|
||||
function love.system.getOS()
|
||||
return infatuated.os
|
||||
end
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
function infatuated.parseColor(r, g, b, a)
|
||||
if type(r) == "table" then
|
||||
return infatuated.parseColor(r[1], r[2], r[3], r[4])
|
||||
elseif type(r) == "number" then
|
||||
a = a or 1
|
||||
assert(type(g) == "number", "bad argument #2 to parseColor")
|
||||
assert(type(b) == "number", "bad argument #3 to parseColor")
|
||||
assert(type(a) == "number", "bad argument #4 to parseColor")
|
||||
return {r, g, b, a}, string.format("rgba(%f, %f, %f, %f)", r, g, b, a)
|
||||
else
|
||||
error("bad argument #1 to parseColor")
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue