Commit cec1e0b0 authored by babyjeans's avatar babyjeans

Moved to git.rou.sr

parents
MIT License
Copyright (c) 2016 babyjeans
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.
# BrewWitch
BrewWitch is an **UNFINISHED** game written for love2d in Lua. It was originally going to be my entry
for [GBJAM 5](itch.io/jam/gbjam-5) but I wasn't able to finish it on time... so I decided to
post it so maybe something useful can come of it!
Currently, you can press the arrow keys, and 'X' to open the Brew Menu. Z / X and Arrows to manipulate the menu.
The menu alternates between 'success' and 'failed' for animation states and that's it. Pressing up in front of the
stairs will climb the stairs, ladder too!
I'm hoping maybe someone will get some use out of it as an example program / demo, or just a 'use case' to study.
There's the capability for it to extend to multiple 'screens.' I disabled it while working on it for the jam, should
bue trivial to turn it back on.
![BrewWitch-Demo](https://zippy.gfycat.com/VioletBadBaleenwhale.gif)
## Credit
### Things used
* [30log](https://github.com/Yonaba/30log)
* [tween.lua](https://github.com/kikito/tween.lua)
* [04b-03](http://www.dafont.com/04b-03.font)
[Top]
[Top]: #user-content-brewwitch
{
"Early Gameboy": {
"ttf": "EarlyGameboy.ttf",
"url": "http://www.dafont.com/early-gameboy.font?text=BREW"
},
}
\ No newline at end of file
function love.conf(t)
t.identity = nil -- The name of the save directory (string)
t.version = "0.10.1" -- The LÖVE version this game was made for (string)
t.console = true -- Attach a console (boolean, Windows only)
t.accelerometerjoystick = true -- Enable the accelerometer on iOS and Android by exposing it as a Joystick (boolean)
t.externalstorage = false -- True to save files (and read from the save directory) in external storage on Android (boolean)
t.gammacorrect = true -- Enable gamma-correct rendering, when supported by the system (boolean)
t.window.title = "BrewWitch" -- The window title (string)
t.window.icon = nil -- Filepath to an image to use as the window's icon (string)
t.window.width = 640 -- The window width (number)
t.window.height = 576 -- The window height (number)
t.window.borderless = false -- Remove all border visuals from the window (boolean)
t.window.resizable = false -- Let the window be user-resizable (boolean)
t.window.minwidth = 1 -- Minimum window width if the window is resizable (number)
t.window.minheight = 1 -- Minimum window height if the window is resizable (number)
t.window.fullscreen = false -- Enable fullscreen (boolean)
t.window.fullscreentype = "desktop" -- Choose between "desktop" fullscreen or "exclusive" fullscreen mode (string)
t.window.vsync = true -- Enable vertical sync (boolean)
t.window.msaa = 0 -- The number of samples to use with multi-sampled antialiasing (number)
t.window.display = 1 -- Index of the monitor to show the window in (number)
t.window.highdpi = false -- Enable high-dpi mode for the window on a Retina display (boolean)
t.window.x = 640 -- The x-coordinate of the window's position in the specified display (number)
t.window.y = 80 -- The y-coordinate of the window's position in the specified display (number)
t.modules.audio = true -- Enable the audio module (boolean)
t.modules.event = true -- Enable the event module (boolean)
t.modules.graphics = true -- Enable the graphics module (boolean)
t.modules.image = true -- Enable the image module (boolean)
t.modules.joystick = true -- Enable the joystick module (boolean)
t.modules.keyboard = true -- Enable the keyboard module (boolean)
t.modules.math = true -- Enable the math module (boolean)
t.modules.mouse = true -- Enable the mouse module (boolean)
t.modules.physics = true -- Enable the physics module (boolean)
t.modules.sound = true -- Enable the sound module (boolean)
t.modules.system = true -- Enable the system module (boolean)
t.modules.timer = true -- Enable the timer module (boolean), Disabling it will result 0 delta time in love.update
t.modules.touch = true -- Enable the touch module (boolean)
t.modules.video = true -- Enable the video module (boolean)
t.modules.window = true -- Enable the window module (boolean)
t.modules.thread = true -- Enable the thread module (boolean)
end
\ No newline at end of file
local class = {
_DESCRIPTION = '30 lines library for object orientation in Lua',
_VERSION = '30log v1.2.0',
_URL = 'http://github.com/Yonaba/30log',
_LICENSE = 'MIT LICENSE <http://www.opensource.org/licenses/mit-license.php>',
}
local next = next
local assert = assert
local pairs = pairs
local type = type
local tostring = tostring
local setmetatable = setmetatable
local _class
local baseMt = {}
local _instances = setmetatable({},{__mode = 'k'})
local _classes = setmetatable({},{__mode = 'k'})
local function assert_call_from_class(class, method)
assert(_classes[class], ('Wrong method call. Expected class:%s.'):format(method))
end
local function assert_call_from_instance(instance, method)
assert(_instances[instance], ('Wrong method call. Expected instance:%s.'):format(method))
end
local default_filter = function() return true end
local function deep_copy(t, dest, aType)
t = t or {}
local r = dest or {}
for k,v in pairs(t) do
if aType ~= nil and type(v) == aType then
r[k] = (type(v) == 'table')
and ((_classes[v] or _instances[v]) and v or deep_copy(v))
or v
elseif aType == nil then
r[k] = (type(v) == 'table')
and k~= '__index' and ((_classes[v] or _instances[v]) and v or deep_copy(v))
or v
end
end
return r
end
local function instantiate(self,...)
assert_call_from_class(self, 'new(...) or class(...)')
local instance = {class = self}
_instances[instance] = tostring(instance)
deep_copy(self, instance, 'table')
instance.__index = nil
instance.mixins = nil
instance.__subclasses = nil
instance.__instances = nil
setmetatable(instance,self)
if self.init then
if type(self.init) == 'table' then
deep_copy(self.init, instance)
else
self.init(instance, ...)
end
end
return instance
end
local function extend(self, name, extra_params)
assert_call_from_class(self, 'extend(...)')
local heir = {}
_classes[heir] = tostring(heir)
self.__subclasses[heir] = true
deep_copy(extra_params, deep_copy(self, heir))
heir.name = extra_params and extra_params.name or name
heir.__index = heir
heir.super = self
heir.mixins = {}
return setmetatable(heir,self)
end
baseMt = {
__call = function (self,...) return self:new(...) end,
__tostring = function(self,...)
if _instances[self] then
return ("instance of '%s' (%s)"):format(rawget(self.class,'name')
or '?', _instances[self])
end
return _classes[self]
and ("class '%s' (%s)"):format(rawget(self,'name')
or '?',
_classes[self]) or self
end
}
_classes[baseMt] = tostring(baseMt)
setmetatable(baseMt, {__tostring = baseMt.__tostring})
class.isClass = function(t) return not not _classes[t] end
class.isInstance = function(t) return not not _instances[t] end
_class = function(name, attr)
local c = deep_copy(attr)
_classes[c] = tostring(c)
c.name = name or c.name
c.__tostring = baseMt.__tostring
c.__call = baseMt.__call
c.new = instantiate
c.extend = extend
c.__index = c
c.mixins = setmetatable({},{__mode = 'k'})
c.__instances = setmetatable({},{__mode = 'k'})
c.__subclasses = setmetatable({},{__mode = 'k'})
c.subclasses = function(self, filter, ...)
assert_call_from_class(self, 'subclasses(class)')
filter = filter or default_filter
local subclasses = {}
for class in pairs(_classes) do
if class ~= baseMt and class:subclassOf(self) and filter(class,...) then
subclasses[#subclasses + 1] = class
end
end
return subclasses
end
c.instances = function(self, filter, ...)
assert_call_from_class(self, 'instances(class)')
filter = filter or default_filter
local instances = {}
for instance in pairs(_instances) do
if instance:instanceOf(self) and filter(instance, ...) then
instances[#instances + 1] = instance
end
end
return instances
end
c.subclassOf = function(self, superclass)
assert_call_from_class(self, 'subclassOf(superclass)')
assert(class.isClass(superclass), 'Wrong argument given to method "subclassOf()". Expected a class.')
local super = self.super
while super do
if super == superclass then return true end
super = super.super
end
return false
end
c.classOf = function(self, subclass)
assert_call_from_class(self, 'classOf(subclass)')
assert(class.isClass(subclass), 'Wrong argument given to method "classOf()". Expected a class.')
return subclass:subclassOf(self)
end
c.instanceOf = function(self, fromclass)
assert_call_from_instance(self, 'instanceOf(class)')
assert(class.isClass(fromclass), 'Wrong argument given to method "instanceOf()". Expected a class.')
return ((self.class == fromclass) or (self.class:subclassOf(fromclass)))
end
c.cast = function(self, toclass)
assert_call_from_instance(self, 'instanceOf(class)')
assert(class.isClass(toclass), 'Wrong argument given to method "cast()". Expected a class.')
setmetatable(self, toclass)
self.class = toclass
return self
end
c.with = function(self,...)
assert_call_from_class(self, 'with(mixin)')
for _, mixin in ipairs({...}) do
assert(self.mixins[mixin] ~= true, ('Attempted to include a mixin which was already included in %s'):format(tostring(self)))
self.mixins[mixin] = true
deep_copy(mixin, self, 'function')
end
return self
end
c.includes = function(self, mixin)
assert_call_from_class(self,'includes(mixin)')
return not not (self.mixins[mixin] or (self.super and self.super:includes(mixin)))
end
c.without = function(self, ...)
assert_call_from_class(self, 'without(mixin)')
for _, mixin in ipairs({...}) do
assert(self.mixins[mixin] == true, ('Attempted to remove a mixin which is not included in %s'):format(tostring(self)))
local classes = self:subclasses()
classes[#classes + 1] = self
for _, class in ipairs(classes) do
for method_name, method in pairs(mixin) do
if type(method) == 'function' then
class[method_name] = nil
end
end
end
self.mixins[mixin] = nil
end
return self
end
return setmetatable(c, baseMt)
end
return setmetatable(class,{__call = function(_,...) return _class(...) end })
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
-- brew witch
-- a game wonderfully created by babyjeans for #GBJAM-5
-- http://babyjeans.rou.sr
-- http://www.twitter.com/babyj3ans
---
-- external types / core
class = require('ext/30log-clean')
Tween = require('ext/tween')
-- types
vector = require('script/core/vector')
Vector2 = require('script/core/vector2')
AppUtil = require('script/core/apputil')
coreApp = { }
coreInput = require('script/core/input')
coreDebug = require('script/core/debug')
-- game specific
require('gamedata')
-- app definition
local App = require('script/core/app')
AppUtil.addTableHelpers()
coreApp = App({
load = function(self)
Resources = require('script/core/resources')
initGameData()
coreInput:updateControlMap(GameSettings.Controls)
self:setScreen(GameSettings.Screen)
self:addState('mainMenu', require('script/mainmenu'))
self:addState('game', require('script/game'))
self:setState('mainMenu')
end,
update = function(self, dt)
end,
draw = function(self)
end,
})
\ No newline at end of file
-- app.lua
-- babyjeans
--
-- convenience class for handling app stuff, keeping it out of love namespace
---
local App = class('coreApp')
-- types
GameState = require('script/core/gamestate')
Rectangle = require('script/core/rectangle')
Circle = require('script/core/circle')
-- global systems
Timers = { }
Resources = { }
Audio = { }
function App:init(appFunctions)
App.appInstance = self
if love then
love.load = App.load
love.update = App.update
love.draw = App.draw
end
self.states = { }
AppUtil.addHook(self, 'update')
self.currentState = GameState()
love.graphics.setDefaultFilter('nearest', 'nearest')
--love.mouse.setGrabbed(true)
self.appFunctions = {
load = appFunctions.load or function() end,
update = appFunctions.update or function(dt) end,
draw = appFunctions.draw or function() end
}
-- setup input
coreInput:hookPressed(function(key, scancode, isrepeat)
App.appInstance:keyPressed(key, scancode, isrepeat)
end)
coreInput:hookReleased(function(key, scancode)
App.appInstance:keyReleased(key)
end)
end
---
-- state management
--
function App:addState(name, state)
self.states[name] = state
end
function App:setState(state)
state = self.states[state]
if state == self.currentState then
return
end
if self.currentState then
self.currentState:exit()
end
self.currentState = state
if self.currentState then
self.currentState:enter()
end
end
function App:setScreen(screen)
self.screen = screen
-- create the render target for the target resolution
self.renderCanvas = love.graphics.newCanvas(self.screen.Resolution.w, self.screen.Resolution.h)
end
---
--
--
function App.load()
self = App.appInstance
Timers = require('script/core/timers')
Tweens = require('script/core/tweens')
Audio = require('script/core/audio')
self.appFunctions.load(self)
end
function App.draw()
self = App.appInstance
self.renderCanvas:renderTo(function()
self.appFunctions.draw(self, dt)
self.currentState:draw()
end)
-- draw the canvas now
love.graphics.setColor(255, 255, 255, 255)
love.graphics.draw(self.renderCanvas, 0, 0, 0, self.screen.Scale, self.screen.Scale)
-- draw debug data
coreDebug:draw()
end
function App.update(dt)
self = App.appInstance
self.appFunctions.update(self, dt)
self.currentState:update(dt)
for i, updateHook in ipairs(self.updateHooks.contents) do
updateHook[2](updateHook[1], dt)
end
coreDebug:update()
end
function App:keyReleased(key)
self.currentState:onKeyReleased(key)
if key == '\\' then
coreDebug.showWatches = not coreDebug.showWatches
end
end
function App:keyPressed(key)
self.currentState:onKeyPressed(key)
end
return App
\ No newline at end of file
-- apputil.lua
-- babyjeans
--
---
return {
----
--- addHook(self, hookName)
--- simple listener / sync system to be attached to any object for convenience
--- pass it an instance object and name to refer hooks with.
-- adds
-- * self.[hookName]Hooks vector
-- * hook[hookName] / unhook[hookname] - add / remove a function call
-- * call[hookname] - will return from the call if a hook function returns true
---
addHook = function(self, hookName)
local hookVec = vector()
self[hookName .. 'Hooks'] = hookVec
self['hook' .. hookName] = function(self, hook) hookVec:addUnique(hook) ; return hook end
self['unhook' .. hookName] = function(self, hook) return hookVec:remove(hook) end
self['call' .. hookName] = function(self, ...) for i, func in ipairs(hookVec.contents) do if func(...) then return end end end
end,
----
--- addTableHelpers()
--- table helpers
--- adds functionality to the table Lua object for convenience
--
-- findIndex(t, elem) - return index of elem in t
-- removeIndexedMatching(t, matchFunc, (opt)removeMultiple) - iterate over t, calling matchFunc on each e. removes anything func returns true for
-- removeIndexedElem(t, elem, (opt)removeMultiple) - remove 'elem' from the array t
-- clone(dst, srt) - attempt at deep copy of src into dst
-- cloneR(dst, src) - attempt at deep copy of src into dst, using recursion as opposed to a list
--
addTableHelpers = function()
table.findIndex = function(t, elem)
for i, e in ipairs(t) do if elem == e then return i end end
end
table.removeIndexedMatching = function(t, matchFunc, removeMultiple)
local r = { }