woo more stuff
- custom button support WIP - logging
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
local debug = true
|
||||
|
||||
function love.conf(t)
|
||||
t.identity = "rgb"
|
||||
t.version = "0.9.1"
|
||||
--t.author = "Guard13007"
|
||||
--t.console = true
|
||||
if debug then t.console = true end
|
||||
|
||||
t.window = {}
|
||||
t.window.title = "RGB - The Color Chooser"
|
||||
@@ -16,3 +18,5 @@ function love.conf(t)
|
||||
t.modules.joystick = false
|
||||
t.modules.physics = false
|
||||
end
|
||||
|
||||
return debug
|
||||
|
@@ -1,5 +1,7 @@
|
||||
love.math.setRandomSeed(os.time())
|
||||
|
||||
local input = require "util.input"
|
||||
|
||||
-- Gamestates
|
||||
--local won = require "gamestates.won" --TODO MAKE THIS
|
||||
local lost = require "gamestates.lost"
|
||||
@@ -12,7 +14,7 @@ local game = {}
|
||||
local boxes = {}
|
||||
local score, totalScore = 0, 0
|
||||
local level, time, startingTime = 0, 0, 0
|
||||
local previousState, gameSettings
|
||||
local previousState, gameSettings, controls
|
||||
--these are defined on each entry to this gamestate
|
||||
local screenWidth, screenHeight --defines where things are rendered
|
||||
local boxColumns, boxRows --defines how many boxes
|
||||
@@ -20,6 +22,8 @@ local boxColumns, boxRows --defines how many boxes
|
||||
local boxSize, colorStep, timeLimit = 20, 80, 60 --default values just in case
|
||||
|
||||
local function nextLevel()
|
||||
log("Creating the next level!")
|
||||
|
||||
totalScore = totalScore + score
|
||||
score = 0
|
||||
level = level + 1
|
||||
@@ -43,6 +47,8 @@ local function nextLevel()
|
||||
boxes[x][y][2] = boxes[x][y][2] - boxes[x][y][2] % colorStep
|
||||
boxes[x][y][3] = boxes[x][y][3] - boxes[x][y][3] % colorStep
|
||||
end
|
||||
|
||||
log("Done!")
|
||||
end
|
||||
|
||||
local function colorsEqual(A, B)
|
||||
@@ -56,7 +62,8 @@ local function copyColor(A)
|
||||
return {A[1], A[2], A[3]}
|
||||
end
|
||||
|
||||
function game:enter(previous, settings)
|
||||
function game:enter(previous, settings, gameControls)
|
||||
log("Entering game...")
|
||||
-- save the state we came from
|
||||
previousState = previous
|
||||
-- set locals based on screen size
|
||||
@@ -66,6 +73,7 @@ function game:enter(previous, settings)
|
||||
boxRows = math.floor(screenHeight / boxSize) - 5
|
||||
-- save the settings for later use
|
||||
gameSettings = settings or gameSettings
|
||||
controls = gameControls or controls
|
||||
-- set how to play the game based on settings
|
||||
boxSize = gameSettings.boxSize
|
||||
colorStep = gameSettings.colorStep
|
||||
@@ -165,19 +173,19 @@ function game:mousepressed(x, y, button)
|
||||
-- check if we are actually over a box first
|
||||
if boxes[nx][ny] then
|
||||
-- left, red
|
||||
if button == "l" then
|
||||
if input(button, controls.red) then
|
||||
boxes[nx][ny][1] = boxes[nx][ny][1] + colorStep
|
||||
if boxes[nx][ny][1] > 255 then
|
||||
boxes[nx][ny][1] = 0
|
||||
end
|
||||
-- middle, green
|
||||
elseif button == "m" or button == "wu" or button == "wd" then
|
||||
elseif input(button, controls.green) then
|
||||
boxes[nx][ny][2] = boxes[nx][ny][2] + colorStep
|
||||
if boxes[nx][ny][2] > 255 then
|
||||
boxes[nx][ny][2] = 0
|
||||
end
|
||||
-- right, blue
|
||||
elseif button == "r" then
|
||||
elseif input(button, controls.blue) then
|
||||
boxes[nx][ny][3] = boxes[nx][ny][3] + colorStep
|
||||
if boxes[nx][ny][3] > 255 then
|
||||
boxes[nx][ny][3] = 0
|
||||
@@ -186,6 +194,20 @@ function game:mousepressed(x, y, button)
|
||||
end
|
||||
end
|
||||
|
||||
function game:keypressed(key, unicode)
|
||||
if input(key, controls.back) then
|
||||
Gamestate.switch(previousState)
|
||||
elseif input(key, controls.pause) then
|
||||
Gamestate.push(paused, love.graphics.newScreenshot())
|
||||
end
|
||||
end
|
||||
|
||||
function game:focus(isFocused)
|
||||
if not isFocused then
|
||||
Gamestate.push(paused, love.graphics.newScreenshot())
|
||||
end
|
||||
end
|
||||
|
||||
function game:leave()
|
||||
--double check the correctness of this
|
||||
level = 0
|
||||
@@ -195,18 +217,4 @@ function game:leave()
|
||||
startingTime = 0
|
||||
end
|
||||
|
||||
function game:keypressed(key, unicode)
|
||||
if key == " " then
|
||||
Gamestate.push(paused, love.graphics.newScreenshot())
|
||||
elseif key == "escape" then
|
||||
Gamestate.switch(previousState)
|
||||
end
|
||||
end
|
||||
|
||||
function game:focus(isFocused)
|
||||
if not isFocused then
|
||||
Gamestate.push(paused, love.graphics.newScreenshot())
|
||||
end
|
||||
end
|
||||
|
||||
return game
|
||||
|
@@ -1,11 +1,82 @@
|
||||
local ser = require "lib.ser"
|
||||
local input = require "util.input"
|
||||
|
||||
local Gamestate = require "lib.gamestate"
|
||||
local game = require "gamestates.game"
|
||||
|
||||
local menu = {}
|
||||
|
||||
local screenWidth, screenHeight
|
||||
local settings, controls
|
||||
|
||||
function menu:init()
|
||||
log("Initializing menu...")
|
||||
-- load or create settings
|
||||
if love.filesystem.isFile("settings.ini") then
|
||||
log("Loading settings (again)...")
|
||||
settings = inifile.parse("settings.ini")
|
||||
else
|
||||
log("Creating settings...")
|
||||
settings = {
|
||||
display = {
|
||||
width = love.graphics.getWidth(),
|
||||
height = love.graphics.getHeight(),
|
||||
fullscreen = false,
|
||||
borderless = true,
|
||||
},
|
||||
gamejolt = {
|
||||
username = false,
|
||||
usertoken = false
|
||||
},
|
||||
sound = {
|
||||
music = 0,
|
||||
sfx = 0
|
||||
},
|
||||
difficulty = {
|
||||
preset = "normal",
|
||||
timeLimit = 60,
|
||||
colorStep = 80,
|
||||
boxSize = 20
|
||||
}
|
||||
}
|
||||
end
|
||||
-- load or create controls
|
||||
if love.filesystem.isFile("controls.lua") then
|
||||
log("Loading controls...")
|
||||
controls = require "controls"
|
||||
else
|
||||
log("Creating controls...")
|
||||
controls = {
|
||||
select = {
|
||||
clicks = {"l"},
|
||||
buttons = {}
|
||||
},
|
||||
back = {
|
||||
clicks = {},
|
||||
buttons = {"escape"}
|
||||
},
|
||||
pause = {
|
||||
clicks = {},
|
||||
buttons = {" ", "escape"}
|
||||
},
|
||||
red = {
|
||||
clicks = {"l"},
|
||||
buttons = {}
|
||||
},
|
||||
green = {
|
||||
clicks = {"wd", "wu", "m"},
|
||||
buttons = {}
|
||||
},
|
||||
blue = {
|
||||
clicks = {"r"},
|
||||
buttons = {}
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function menu:enter()
|
||||
log("Entering menu...")
|
||||
screenWidth = love.graphics.getWidth()
|
||||
screenHeight = love.graphics.getHeight()
|
||||
end
|
||||
@@ -22,14 +93,14 @@ function menu:draw()
|
||||
end
|
||||
|
||||
function menu:mousepressed(x, y, button)
|
||||
if button == "l" then
|
||||
-- TODO replace constructed settings object with actual loaded settings
|
||||
Gamestate.switch(game, {boxSize = 20, colorStep = 80, timeLimit = 10})
|
||||
if input(button, controls.select) then
|
||||
Gamestate.switch(game, {boxSize = settings.difficulty.boxSize, colorStep = settings.difficulty.colorStep, timeLimit = settings.difficulty.timeLimit}, controls)
|
||||
end
|
||||
end
|
||||
|
||||
function menu:keypressed(key, unicode)
|
||||
if key == "escape" then
|
||||
if input(key, controls.back) then
|
||||
log("Quitting.")
|
||||
love.event.quit()
|
||||
end
|
||||
end
|
||||
|
122
src/lib/ser.lua
Normal file
122
src/lib/ser.lua
Normal file
@@ -0,0 +1,122 @@
|
||||
local pairs, ipairs, tostring, type, concat, dump, floor = pairs, ipairs, tostring, type, table.concat, string.dump, math.floor
|
||||
|
||||
local function getchr(c)
|
||||
return "\\" .. c:byte()
|
||||
end
|
||||
|
||||
local function make_safe(text)
|
||||
return ("%q"):format(text):gsub('\n', 'n'):gsub("[\128-\255]", getchr)
|
||||
end
|
||||
|
||||
local oddvals = {[tostring(1/0)] = '1/0', [tostring(-1/0)] = '-1/0', [tostring(0/0)] = '0/0'}
|
||||
local function write(t, memo, rev_memo)
|
||||
local ty = type(t)
|
||||
if ty == 'number' or ty == 'boolean' or ty == 'nil' then
|
||||
t = tostring(t)
|
||||
return oddvals[t] or t
|
||||
elseif ty == 'string' then
|
||||
return make_safe(t)
|
||||
elseif ty == 'table' or ty == 'function' then
|
||||
if not memo[t] then
|
||||
local index = #rev_memo + 1
|
||||
memo[t] = index
|
||||
rev_memo[index] = t
|
||||
end
|
||||
return '_[' .. memo[t] .. ']'
|
||||
else
|
||||
error("Trying to serialize unsupported type " .. ty)
|
||||
end
|
||||
end
|
||||
|
||||
local kw = {['and'] = true, ['break'] = true, ['do'] = true, ['else'] = true,
|
||||
['elseif'] = true, ['end'] = true, ['false'] = true, ['for'] = true,
|
||||
['function'] = true, ['goto'] = true, ['if'] = true, ['in'] = true,
|
||||
['local'] = true, ['nil'] = true, ['not'] = true, ['or'] = true,
|
||||
['repeat'] = true, ['return'] = true, ['then'] = true, ['true'] = true,
|
||||
['until'] = true, ['while'] = true}
|
||||
local function write_key_value_pair(k, v, memo, rev_memo, name)
|
||||
if type(k) == 'string' and k:match '^[_%a][_%w]*$' and not kw[k] then
|
||||
return (name and name .. '.' or '') .. k ..' = ' .. write(v, memo, rev_memo)
|
||||
else
|
||||
return (name or '') .. '[' .. write(k, memo, rev_memo) .. '] = ' .. write(v, memo, rev_memo)
|
||||
end
|
||||
end
|
||||
|
||||
-- fun fact: this function is not perfect
|
||||
-- it has a few false positives sometimes
|
||||
-- but no false negatives, so that's good
|
||||
local function is_cyclic(memo, sub, super)
|
||||
local m = memo[sub]
|
||||
local p = memo[super]
|
||||
return m and p and m < p
|
||||
end
|
||||
|
||||
local function write_table_ex(t, memo, rev_memo, srefs, name)
|
||||
if type(t) == 'function' then
|
||||
return '_[' .. name .. '] = loadstring ' .. make_safe(dump(t))
|
||||
end
|
||||
local m = {'_[', name, '] = {'}
|
||||
local mi = 3
|
||||
for i = 1, #t do -- don't use ipairs here, we need the gaps
|
||||
local v = t[i]
|
||||
if v == t or is_cyclic(memo, v, t) then
|
||||
srefs[#srefs + 1] = {name, i, v}
|
||||
m[mi + 1] = 'nil, '
|
||||
mi = mi + 1
|
||||
else
|
||||
m[mi + 1] = write(v, memo, rev_memo)
|
||||
m[mi + 2] = ', '
|
||||
mi = mi + 2
|
||||
end
|
||||
end
|
||||
for k,v in pairs(t) do
|
||||
if type(k) ~= 'number' or floor(k) ~= k or k < 1 or k > #t then
|
||||
if v == t or k == t or is_cyclic(memo, v, t) or is_cyclic(memo, k, t) then
|
||||
srefs[#srefs + 1] = {name, k, v}
|
||||
else
|
||||
m[mi + 1] = write_key_value_pair(k, v, memo, rev_memo)
|
||||
m[mi + 2] = ', '
|
||||
mi = mi + 2
|
||||
end
|
||||
end
|
||||
end
|
||||
m[mi > 3 and mi or mi + 1] = '}'
|
||||
return concat(m)
|
||||
end
|
||||
|
||||
return function(t)
|
||||
local memo = {[t] = 0}
|
||||
local rev_memo = {[0] = t}
|
||||
local srefs = {}
|
||||
local result = {}
|
||||
|
||||
-- phase 1: recursively descend the table structure
|
||||
local n = 0
|
||||
while rev_memo[n] do
|
||||
result[n + 1] = write_table_ex(rev_memo[n], memo, rev_memo, srefs, n)
|
||||
n = n + 1
|
||||
end
|
||||
|
||||
-- phase 2: reverse order
|
||||
for i = 1, n*.5 do
|
||||
local j = n - i + 1
|
||||
result[i], result[j] = result[j], result[i]
|
||||
end
|
||||
|
||||
-- phase 3: add all the tricky cyclic stuff
|
||||
for i, v in ipairs(srefs) do
|
||||
n = n + 1
|
||||
result[n] = write_key_value_pair(v[2], v[3], memo, rev_memo, '_[' .. v[1] .. ']')
|
||||
end
|
||||
|
||||
-- phase 4: add something about returning the main table
|
||||
if result[n]:sub(1, 5) == '_[0] ' then
|
||||
result[n] = 'return' .. result[n]:sub(7)
|
||||
else
|
||||
result[n + 1] = 'return _[0]'
|
||||
end
|
||||
|
||||
-- phase 5: just concatenate everything
|
||||
result = concat(result, '\n')
|
||||
return n > 1 and 'local _ = {}\n' .. result or result
|
||||
end
|
61
src/main.lua
61
src/main.lua
@@ -1,49 +1,90 @@
|
||||
Gamestate = require "lib.gamestate"
|
||||
Gamejolt = require "lib.gamejolt"
|
||||
GameJolt = require "lib.gamejolt"
|
||||
debug = require "conf" -- a bit redundant but makes it obvious what is global
|
||||
|
||||
local startDate = os.date("*t", os.time())
|
||||
local logFile = "logs/" .. startDate.year .. "." .. startDate.month .. "." .. startDate.day .. "-" .. startDate.hour .. "." .. startDate.min .. ".log"
|
||||
function log(...)
|
||||
--[[
|
||||
local strings = ""
|
||||
if type(arg) == "table" then
|
||||
for _,v in pairs(arg) do
|
||||
strings = strings .. v
|
||||
end
|
||||
else
|
||||
strings = arg
|
||||
end
|
||||
if love.filesystem.exists("logs") then
|
||||
if not love.filesystem.isDirectory("logs") then
|
||||
love.filesystem.remove()
|
||||
love.filesystem.createDirectory("logs")
|
||||
end
|
||||
else
|
||||
love.filesystem.createDirectory("logs")
|
||||
end
|
||||
local success, errorMsg = love.filesystem.append(logFile, strings)
|
||||
if not success then
|
||||
print("Failed to write to log file.", errorMsg)
|
||||
end
|
||||
--]]
|
||||
if debug then print(...) end
|
||||
end
|
||||
|
||||
local inifile = require "lib.inifile"
|
||||
|
||||
local menu = require "gamestates.menu"
|
||||
|
||||
function love.load()
|
||||
log("Loading...")
|
||||
-- set custom window icon
|
||||
local icon = love.image.newImageData("icon.png")
|
||||
love.window.setIcon(icon)
|
||||
log("Window icon set.")
|
||||
|
||||
-- initialize Game Jolt
|
||||
Gamejolt.init(48728, "b8e4a0eae1509d3edef3d8451bae1842")
|
||||
local initSuccess = GameJolt.init(48728, "b8e4a0eae1509d3edef3d8451bae1842")
|
||||
if initSuccess then log("Game Jolt initialized.") end
|
||||
|
||||
-- load settings and change if needed
|
||||
local gamejoltSessionOpen = false --set true if we get a session open
|
||||
if love.filesystem.isFile("settings.ini") then
|
||||
log("Loading settings...")
|
||||
local settings = inifile.parse("settings.ini")
|
||||
love.window.setMode(settings.display.width, settings.display.height, {fullscreen = settings.display.fullscreen, borderless = settings.display.borderless})
|
||||
-- login if we have the data to do so
|
||||
if settings.gamejolt.username and settings.gamejolt.usertoken then
|
||||
local authSuccess = Gamejolt.authUser(settings.gamejolt.username, settings.gamejolt.usertoken)
|
||||
log("Logging in to Game Jolt.")
|
||||
local authSuccess = GameJolt.authUser(settings.gamejolt.username, settings.gamejolt.usertoken)
|
||||
if authSuccess then
|
||||
-- check if the player has been banned
|
||||
local userInfo = Gamejolt.fetchUserByName(settings.gamejolt.username)
|
||||
local userInfo = GameJolt.fetchUserByName(settings.gamejolt.username)
|
||||
if userInfo.status == "Banned" then
|
||||
log("Player has been banned from Game Jolt.")
|
||||
settings.gamejolt.username = false
|
||||
settings.gamejolt.usertoken = false
|
||||
inifile.save("settings.ini", settings)
|
||||
error("You have been banned from Game Jolt. Your login data has been deleted, re-open RGB to continue playing without Game Jolt account integration.")
|
||||
end
|
||||
local sessionSuccess = Gamejolt.openSession() -- tell Game Jolt the user is playing
|
||||
gamejoltSessionOpen = GameJolt.openSession() -- tell Game Jolt the user is playing
|
||||
if sessionSuccess then
|
||||
local idleSuccess = Gamejolt.pingSession(false)
|
||||
log("Game Jolt session opened.")
|
||||
local idleSuccess = GameJolt.pingSession(false)
|
||||
if not idleSuccess then
|
||||
print("Couldn't ping Gamejolt session. Session may close.") --this is lazy but I don't care
|
||||
-- TODO make a better system for checking this
|
||||
log("Couldn't ping Game Jolt session. Session may close.") --this is lazy but I don't care
|
||||
end
|
||||
else
|
||||
print("Couldn't open a session with Game Jolt.")
|
||||
-- TODO make this known to user
|
||||
log("Couldn't open a session with Game Jolt.")
|
||||
end
|
||||
else
|
||||
print("Failed to log into Game Jolt. Please report this error (with a screenshot) to: paul.liverman.iii@gmail.com")
|
||||
-- TODO make this better, also detect if online somehow
|
||||
log("Failed to log into Game Jolt. Please report this error (with a screenshot) to: paul.liverman.iii@gmail.com")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gamestate.registerEvents()
|
||||
Gamestate.switch(menu)
|
||||
log("Loaded, switching to main menu...")
|
||||
Gamestate.switch(menu, gamejoltSessionOpen)
|
||||
end
|
||||
|
10
src/util/input.lua
Normal file
10
src/util/input.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
return function(inValue, acceptableValues)
|
||||
local isValid = false
|
||||
for i=1,#acceptableValues.clicks do
|
||||
if inValue == acceptableValues.clicks[i] then isValid = true end
|
||||
end
|
||||
for i=1,#acceptableValues.buttons do
|
||||
if inValue == acceptableValues.buttons[i] then isValid = true end
|
||||
end
|
||||
return isValid
|
||||
end
|
Reference in New Issue
Block a user