summaryrefslogtreecommitdiffhomepage
path: root/not
diff options
context:
space:
mode:
authorAki <nthirtyone@gmail.com>2017-04-07 03:24:40 +0200
committerAki <nthirtyone@gmail.com>2017-04-07 03:24:40 +0200
commitd1a19fea50aefc9d7fb52568a5bdcfb56d75eccf (patch)
treed86118b2bae5125f6cecd28a5a7b6f46739f30a9 /not
parent54e85dd188af15cd5f3f5e08f5d3e69088a909b1 (diff)
downloadroflnauts-d1a19fea50aefc9d7fb52568a5bdcfb56d75eccf.zip
roflnauts-d1a19fea50aefc9d7fb52568a5bdcfb56d75eccf.tar.gz
roflnauts-d1a19fea50aefc9d7fb52568a5bdcfb56d75eccf.tar.bz2
Moved menu elements to /not/
Diffstat (limited to 'not')
-rw-r--r--not/Button.lua76
-rw-r--r--not/Element.lua50
-rw-r--r--not/Header.lua48
-rw-r--r--not/Selector.lua290
4 files changed, 464 insertions, 0 deletions
diff --git a/not/Button.lua b/not/Button.lua
new file mode 100644
index 0000000..91aca45
--- /dev/null
+++ b/not/Button.lua
@@ -0,0 +1,76 @@
+--- `Button`
+-- Menu element that can be activated by user.
+Button = {
+ parent = --[[not.Menu]]nil,
+ x = 0,
+ y = 0,
+ text = "",
+ focused = false,
+ sprite,
+ quads,
+ delay = 2,
+ parent,
+}
+
+-- `Button` is a child of `Element`.
+require "not.Element"
+Button.__index = Button
+setmetatable(Button, Element)
+
+function Button:new (parent)
+ local o = setmetatable({}, self)
+ o.parent = parent
+ o.sprite, o.quads = parent:getSheet()
+ return o
+end
+
+function Button:setText (text)
+ self.text = text or ""
+ return self
+end
+
+function Button:focus(next)
+ self.focused = true
+ return true
+end
+function Button:blur ()
+ self.focused = false
+end
+
+function Button:active () end
+function Button:isEnabled ()
+ return true
+end
+
+function Button:draw (scale)
+ local x,y = self:getPosition()
+ local quad = self.quads
+ local sprite = self.sprite
+ if self:isEnabled() then
+ love.graphics.setColor(255, 255, 255, 255)
+ else
+ love.graphics.setColor(140, 140, 140, 255)
+ end
+ love.graphics.draw(sprite, quad.button.normal, x*scale, y*scale, 0, scale, scale)
+ if self.focused then
+ love.graphics.draw(sprite, quad.arrow_l, (x+54+math.floor(self.delay))*scale, (y+5)*scale, 0, scale, scale)
+ love.graphics.draw(sprite, quad.arrow_r, (x-2-math.floor(self.delay))*scale, (y+5)*scale, 0, scale, scale)
+ end
+ love.graphics.setFont(Font)
+ love.graphics.printf(self.text, (x+2)*scale, (y+4)*scale, 54, "center", 0, scale, scale)
+end
+
+function Button:update (dt)
+ self.delay = self.delay + dt
+ if self.delay > Button.delay then -- Button.delay is initial
+ self.delay = self.delay - Button.delay
+ end
+end
+
+function Button:controlpressed (set, action, key)
+ if action == "attack" and self.focused and self:isEnabled() then
+ self:active()
+ end
+end
+
+return Button
diff --git a/not/Element.lua b/not/Element.lua
new file mode 100644
index 0000000..e6d91da
--- /dev/null
+++ b/not/Element.lua
@@ -0,0 +1,50 @@
+--- `Element`
+-- Empty element used inside `Menu`.
+Element = {
+ parent = --[[not.Menu]]nil,
+ x = 0,
+ y = 0
+}
+
+Element.__index = Element
+
+function Element:new (parent)
+ local o = setmetatable({}, self)
+ o.parent = parent
+ return o
+end
+
+function Element:delete () end -- deletes Element
+
+function Element:getPosition ()
+ return self.x, self.y
+end
+function Element:setPosition (x, y)
+ self.x = x or 0
+ self.y = y or 0
+ return self
+end
+
+function Element:set (name, func)
+ if type(name) == "string" and func ~= nil then
+ self[name] = func
+ end
+ return self
+end
+
+-- Called when menu tries to focus on this element.
+-- If it will return false then menu will skip element and go to next in list.
+function Element:focus ()
+ return false
+end
+function Element:blur () end -- Called when Element loses focus.
+
+-- LÖVE2D callbacks
+function Element:draw (scale) end
+function Element:update (dt) end
+
+-- Controller callbacks
+function Element:controlpressed (set, action, key) end
+function Element:controlreleased (set, action, key) end
+
+return Element
diff --git a/not/Header.lua b/not/Header.lua
new file mode 100644
index 0000000..a563ab2
--- /dev/null
+++ b/not/Header.lua
@@ -0,0 +1,48 @@
+--- `Header`
+-- Swinging title.
+Header = {
+ parent = --[[not.Menu]]nil,
+ x = 0,
+ y = 0,
+ text = "",
+ bounce = 2,
+}
+
+-- `Header` is a child of `Element`.
+require "not.Element"
+Header.__index = Header
+setmetatable(Header, Element)
+
+function Header:new (parent)
+ local o = setmetatable({}, self)
+ o.parent = parent
+ return o
+end
+
+function Header:setText (text)
+ self.text = text or ""
+ return self
+end
+
+function Header:getBounce (f)
+ local f = f or 1
+ return math.sin(self.bounce*f*math.pi)
+end
+
+-- LÖVE2D callbacks
+function Header:draw (scale)
+ local angle = self:getBounce(2)
+ local dy = self:getBounce()*4
+ local x,y = self:getPosition()
+ love.graphics.setColor(255,255,255,255)
+ love.graphics.setFont(Bold)
+ love.graphics.printf(string.upper(self.text),x*scale,(y+dy)*scale,400,"center",(angle*5)*math.pi/180,scale,scale,200,12)
+end
+function Header:update (dt)
+ self.bounce = self.bounce + dt*0.7
+ if self.bounce > Header.bounce then -- Header.bounce is initial
+ self.bounce = self.bounce - Header.bounce
+ end
+end
+
+return Header
diff --git a/not/Selector.lua b/not/Selector.lua
new file mode 100644
index 0000000..8e03457
--- /dev/null
+++ b/not/Selector.lua
@@ -0,0 +1,290 @@
+--- `Selector`
+-- Used in Menu for selecting various things from list. Works for each Controller set or globally.
+--[[
+How to use `Selector` in `Menu` config file?
+selector:new(menu)
+ :setPosition(x, y)
+ :setMargin(8) -- each block has marigin on both sides; they do stack
+ :setSize(32, 32) -- size of single graphics frame
+ :set("list", require "nautslist")
+ :set("icons_i", love.graphics.newImage("assets/portraits.png"))
+ :set("icons_q", require "portraits")
+ :set("global", false) -- true: single selector; false: selector for each controller set present
+ :init()
+]]
+Selector = {
+ parent = --[[not.Menu]]nil,
+ x = 0,
+ y = 0,
+ width = 0,
+ height = 0,
+ margin = 0,
+ focused = false,
+ global = false,
+ delay = 2,
+ first = false,
+ list,
+ sets,
+ locks,
+ selections,
+ shape = "portrait",
+ sprite,
+ quads,
+ icons_i,
+ icons_q
+}
+
+-- `Selector` is a child of `Element`.
+require "not.Element"
+Selector.__index = Selector
+setmetatable(Selector, Element)
+
+-- Constructor
+function Selector:new (parent)
+ local o = setmetatable({}, self)
+ o.parent = parent
+ o.sprite, o.quads = parent:getSheet()
+ return o
+end
+
+-- Size of single block
+function Selector:getSize ()
+ return self.width, self.height
+end
+function Selector:setSize (width, height)
+ self.width, self.height = width, height
+ return self
+end
+
+-- Spacing between two blocks
+function Selector:getMargin ()
+ return self.margin
+end
+function Selector:setMargin (margin)
+ self.margin = margin
+ return self
+end
+
+-- Initialize Selector with current settings.
+function Selector:init ()
+ -- Make sure that there is list present
+ if self.list == nil then
+ self.list = {}
+ end
+ -- Initialize global Selector
+ if self.global then
+ self.sets = {}
+ self.locks = {false}
+ self.selections = {1}
+ -- Initialize Selector for Controllers
+ else
+ self.sets = Controller.getSets()
+ self.locks = {}
+ self.selections = {}
+ for n=1,#self.sets do
+ self.locks[n] = false
+ self.selections[n] = 1
+ end
+ end
+ return self
+end
+
+-- Cycle through list on given number
+function Selector:next (n)
+ local current = self.selections[n]
+ self:setSelection(n, current + 1)
+end
+function Selector:previous (n)
+ local current = self.selections[n]
+ self:setSelection(n, current - 1)
+end
+
+-- Get number associated with a given set
+function Selector:checkNumber (set)
+ if self.global then return 1 end -- For global Selector
+ for n,check in pairs(self.sets) do
+ if check == set then return n end
+ end
+end
+
+-- Check if given number is locked
+function Selector:isLocked (n)
+ local n = n or 1
+ return self.locks[n]
+end
+
+-- Sets value of selection of given number. Returns old.
+function Selector:setSelection (n, new)
+ -- Functception. It sounds like fun but it isn't.
+ local function limit(new, total)
+ if new > total then
+ return limit(new - total, total)
+ elseif new < 1 then
+ return limit(total + new, total)
+ else
+ return new
+ end
+ end
+ local n = n or 1
+ local old = self.selections[n]
+ self.selections[n] = limit(new, #self.list)
+ return old
+end
+
+-- Get value of selection of given number
+function Selector:getSelection (n)
+ local n = n or 1
+ return self.selections[n]
+end
+
+-- Get value from list by selection
+function Selector:getListValue (i)
+ return self.list[i]
+end
+
+-- Checks if selection of given number is unique within Selector scope.
+function Selector:isUnique (n)
+ local selection = self:getSelection(n)
+ for fn,v in pairs(self.selections) do
+ if fn ~= n and self:isLocked(fn) and v == selection then
+ return false
+ end
+ end
+ return true
+end
+
+-- Get list of selections, checks if not locked are allowed.
+function Selector:getFullSelection (allowed)
+ local allowed = allowed
+ if allowed == nil then allowed = false end
+ local t = {}
+ for n,v in pairs(self.selections) do
+ local name = self:getListValue(self:getSelection(n))
+ local locked = self:isLocked(n)
+ if locked or allowed then
+ local a = {name}
+ if self.sets[n] then table.insert(a, self.sets[n]) end
+ table.insert(t, a)
+ end
+ end
+ return t
+end
+
+-- Rolls and returns random selection from list that is not locked.
+function Selector:rollRandom (avoids)
+ -- Me: You should make it simpler.
+ -- Inner me: Nah, it works. Leave it.
+ -- Me: Ok, let's leave it as it is.
+ local avoids = avoids or {}
+ local total = #self.list
+ local random = love.math.random(1, total)
+ local eligible = true
+ for _,avoid in ipairs(avoids) do
+ if random == avoid then
+ eligible = false
+ break
+ end
+ end
+ if not eligible or self:isLocked(random) then
+ table.insert(avoids, random)
+ return self:rollRandom(avoid)
+ else
+ return random
+ end
+end
+
+-- Draw single block of Selector
+function Selector:drawBlock (n, x, y, scale)
+ if self.quads == nil or self.sprite == nil then return end
+ local x, y = x or 0, y or 0
+ local name = self:getListValue(self:getSelection(n))
+ local locked = self:isLocked(n)
+ local sprite = self.sprite
+ local quad = self.quads
+ local icon = self.icons_i
+ local iconq = self.icons_q[name]
+ local w,h = self:getSize()
+ local unique = self:isUnique(n)
+ if unique then
+ love.graphics.setColor(255, 255, 255, 255)
+ else
+ love.graphics.setColor(140, 140, 140, 255)
+ end
+ if not locked then
+ love.graphics.draw(sprite, quad[self.shape].normal, x*scale, y*scale, 0, scale, scale)
+ else
+ love.graphics.draw(sprite, quad[self.shape].active, x*scale, y*scale, 0, scale, scale)
+ end
+ love.graphics.draw(icon, iconq, (x+2)*scale, (y+3)*scale, 0, scale, scale)
+ if self.focused then
+ local dy = (h-6)/2
+ if not locked then
+ love.graphics.draw(sprite, quad.arrow_l, (x+0-2-math.floor(self.delay))* scale, (y+dy)*scale, 0, scale, scale)
+ love.graphics.draw(sprite, quad.arrow_r, (x+w-4+math.floor(self.delay))*scale, (y+dy)*scale, 0, scale, scale)
+ else
+ love.graphics.draw(sprite, quad.arrow_r, (x+0-2-math.floor(self.delay))* scale, (y+dy)*scale, 0, scale, scale)
+ love.graphics.draw(sprite, quad.arrow_l, (x+w-4+math.floor(self.delay))*scale, (y+dy)*scale, 0, scale, scale)
+ end
+ end
+ if (self:getSelection(n) ~= 1 or self.first) then
+ love.graphics.setFont(Font)
+ love.graphics.setColor(255, 255, 255, 255)
+ love.graphics.printf(string.upper(name), (x-w)*scale, (y+h+1)*scale, w*3, "center", 0, scale, scale)
+ end
+end
+
+-- Menu callbacks
+function Selector:focus () -- Called when Element gains focus
+ self.focused = true
+ return true
+end
+function Selector:blur () -- Called when Element loses focus
+ self.focused = false
+end
+
+-- LÖVE2D callbacks
+function Selector:draw (scale)
+ local x,y = self:getPosition()
+ local margin = self:getMargin()
+ local width = self:getSize()
+ x = x - #self.selections*0.5*(margin+margin+width)
+ for n=1,#self.selections do
+ self:drawBlock(n, x+(margin+width)*(n-1)+margin*n, y, scale)
+ end
+end
+function Selector:update (dt)
+ self.delay = self.delay + dt
+ if self.delay > Selector.delay then -- Selector.delay is initial
+ self.delay = self.delay - Selector.delay
+ end
+end
+
+-- Controller callbacks
+-- TODO: Add action to perform when key is pressed and selector is locked in e.g. to move into character selection from map selection.
+function Selector:controlpressed (set, action, key)
+ if set and self.focused then
+ local n = self:checkNumber(set)
+ local locked = self:isLocked(n)
+ if action == "left" and not locked then self:previous(n) end
+ if action == "right" and not locked then self:next(n) end
+ if action == "attack" then
+ local name = self:getListValue(self:getSelection(n))
+ if name == "random" then
+ self:setSelection(n, self:rollRandom({1,2})) -- avoid empty naut
+ self.locks[n] = true
+ else
+ -- If not empty or if first is allowed. Additionaly must be unique selection.
+ if (self:getSelection(n) ~= 1 or self.first) and self:isUnique(n) then
+ self.locks[n] = true
+ end
+ end
+ end
+ if action == "jump" then
+ if locked then
+ self.locks[n] = false
+ end
+ end
+ end
+end
+
+return Selector