diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | assets/backgrounds/menu.png | bin | 0 -> 13640 bytes | |||
-rw-r--r-- | assets/menu.png | bin | 0 -> 599 bytes | |||
-rw-r--r-- | assets/music/menu.ogg (renamed from assets/music/ROFLmenu.ogg) | bin | 1041812 -> 1041812 bytes | |||
-rw-r--r-- | assets/placeholder-map-icon.png | bin | 0 -> 6850 bytes | |||
-rw-r--r-- | button.lua | 78 | ||||
-rw-r--r-- | conf.lua | 3 | ||||
-rw-r--r-- | config/menucredits.lua | 24 | ||||
-rw-r--r-- | config/menuhost.lua | 42 | ||||
-rw-r--r-- | config/menumain.lua | 58 | ||||
-rw-r--r-- | config/menuselect.lua | 73 | ||||
-rw-r--r-- | config/menusettings.lua | 107 | ||||
-rw-r--r-- | controller.lua | 23 | ||||
-rw-r--r-- | element.lua | 42 | ||||
-rw-r--r-- | header.lua | 57 | ||||
-rw-r--r-- | main.lua | 18 | ||||
-rw-r--r-- | mapicons.lua | 8 | ||||
-rw-r--r-- | menu.lua | 244 | ||||
-rw-r--r-- | nautsicons.lua | 46 | ||||
-rw-r--r-- | player.lua | 2 | ||||
-rw-r--r-- | selector.lua | 311 | ||||
-rw-r--r-- | settings.default | 6 | ||||
-rw-r--r-- | settings.lua | 63 | ||||
-rw-r--r-- | world.lua | 13 |
24 files changed, 948 insertions, 276 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5eee011 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +all: + zip not-nautz maps/*.lua config/*.lua assets/*.png assets/sounds/*.ogg assets/platforms/*.png assets/nauts/*.png assets/music/*.ogg assets/decorations/*.png assets/backgrounds/*.png *.lua gamecontrollerdb.txt settings.default + mv not-nautz.zip ../not-nautz.love + +clean: + $(RM) ../not-nautz.love
\ No newline at end of file diff --git a/assets/backgrounds/menu.png b/assets/backgrounds/menu.png Binary files differnew file mode 100644 index 0000000..9be3233 --- /dev/null +++ b/assets/backgrounds/menu.png diff --git a/assets/menu.png b/assets/menu.png Binary files differnew file mode 100644 index 0000000..8088c23 --- /dev/null +++ b/assets/menu.png diff --git a/assets/music/ROFLmenu.ogg b/assets/music/menu.ogg Binary files differindex 07bcb89..07bcb89 100644 --- a/assets/music/ROFLmenu.ogg +++ b/assets/music/menu.ogg diff --git a/assets/placeholder-map-icon.png b/assets/placeholder-map-icon.png Binary files differnew file mode 100644 index 0000000..3d54e18 --- /dev/null +++ b/assets/placeholder-map-icon.png diff --git a/button.lua b/button.lua new file mode 100644 index 0000000..c5681b2 --- /dev/null +++ b/button.lua @@ -0,0 +1,78 @@ +-- `Button` +-- Button used in `Menu` + +Button = { + text = "", + focused = false, + x = 0, + y = 0, + sprite, + quads, + delay = 2, + parent, +} + +function Button:new(parent) + local o = {} + setmetatable(o, self) + self.__index = 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:setPosition(x, y) + self.x = x or 0 + self.y = y or 0 + return self +end +function Button:getPosition() return self.x,self.y 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:set(name, func) + if type(name) == "string" and type(func) == "function" then + self[name] = func + end + return self +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 +function Button:controlreleased(set, action, key) end + +return Button
\ No newline at end of file @@ -5,7 +5,8 @@ function love.conf(t) -- t.window.width = 320*3 -- t.window.height = 180*3 -- t.window.borderless = true + t.identity = "not-nautz" t.window.fullscreentype = "desktop" t.window.fullscreen = true t.console = false -end
\ No newline at end of file +end diff --git a/config/menucredits.lua b/config/menucredits.lua new file mode 100644 index 0000000..9d38da4 --- /dev/null +++ b/config/menucredits.lua @@ -0,0 +1,24 @@ +local menu = ... + +local button = require "button" +local element = require "element" + +local width, height = love.graphics.getWidth()/getRealScale(), love.graphics.getHeight()/getRealScale() +local bx = width/2-29 + +return { + button:new(menu) + :setText("Go back") + :setPosition(bx,144) + :set("active", function (self) + self.parent:load("menumain") + end) + , + element:new(menu) + :setPosition(width/2, 30) + :set("draw", function (self, scale) + local x,y = self:getPosition() + love.graphics.printf("A game by the Awesomenauts community including:\nSeltzy, PlasmaWisp, ParaDoX, MilkingChicken, Burningdillo, Bronkey and Aki.\n\n04font was used.\n\nBased on a game by Jan Willem Nijman, Paul Veer and Bits_Beats XOXO.\n\nAwesomenauts is property of Ronimo Games.", (x-110)*scale, (y+10)*scale, 220, "left", 0, scale, scale) + end) + , +}
\ No newline at end of file diff --git a/config/menuhost.lua b/config/menuhost.lua new file mode 100644 index 0000000..710839d --- /dev/null +++ b/config/menuhost.lua @@ -0,0 +1,42 @@ +local menu = ... + +local button = require "button" +local selector = require "selector" + +local width, height = love.graphics.getWidth()/getScale(), love.graphics.getHeight()/getScale() +local bx = width/2-29 + +local map_selector = selector:new(menu) + +return { + map_selector + :setPosition(width/2, 40) + :setSize(80, 42) + :setMargin(0) + :set("global", true) + :set("first", true) + :set("list", require "maplist") + :set("icons_i", love.graphics.newImage("assets/placeholder-map-icon.png")) + :set("icons_q", require "mapicons") + :set("shape", "panorama") + :init() + , + button:new(menu) + :setText("Next") + :setPosition(bx,101) + :set("isEnabled", function () + return map_selector:isLocked() + end) + :set("active", function (self) + MAP = map_selector:getFullSelection(true)[1][1] -- please, don't kill me for this, kek + self.parent:load("menuselect") + end) + , + button:new(menu) + :setText("Go back") + :setPosition(bx,117) + :set("active", function (self) + self.parent:load("menumain") + end) + , +}
\ No newline at end of file diff --git a/config/menumain.lua b/config/menumain.lua new file mode 100644 index 0000000..e312b51 --- /dev/null +++ b/config/menumain.lua @@ -0,0 +1,58 @@ +local menu = ... + +local button = require "button" +local header = require "header" +local element = require "element" + +local width, height = love.graphics.getWidth()/getScale(), love.graphics.getHeight()/getScale() +local bx = width/2-29 + +return { + button:new(menu) + :setText("Start") + :setPosition(bx, 80) + :set("active", function (self) + self.parent:load("menuhost") + end) + , + button:new(menu) + :setText("Join") + :setPosition(bx, 96) + :set("isEnabled", function (self) + return false + end) + , + button:new(menu) + :setText("Settings") + :setPosition(bx, 112) + :set("active", function (self) + self.parent:load("menusettings") + end) + , + button:new(menu) + :setText("Credits") + :setPosition(bx, 128) + :set("active", function (self) + self.parent:load("menucredits") + end) + , + button:new(menu) + :setText("Exit") + :setPosition(bx, 144) + :set("active", love.event.quit) + , + element:new(menu) + :setPosition(width/2, 15) + :set("draw", function (self, scale) + local x,y = self:getPosition() + love.graphics.setColor(255, 255, 255, 255) + love.graphics.setFont(Bold) + love.graphics.print("1", (x-17)*scale, y*scale, 0, scale*2, scale*2, 12) + love.graphics.print("1", (x+13)*scale, y*scale, 0, scale*2, scale*2, 12) + end) + , + header:new(menu) + :setText("Roflnauts") + :setPosition(width/2,40) + , +}
\ No newline at end of file diff --git a/config/menuselect.lua b/config/menuselect.lua new file mode 100644 index 0000000..19f46ab --- /dev/null +++ b/config/menuselect.lua @@ -0,0 +1,73 @@ +local menu = ... + +local button = require "button" +local selector = require "selector" +local element = require "element" + +local width, height = love.graphics.getWidth()/getScale(), love.graphics.getHeight()/getScale() +local bx = width/2-29 + +local naut_selector = selector:new(menu) +local start_button = button:new(menu) + +return { + naut_selector + :setPosition(width/2,60) + :setMargin(8) + :setSize(32, 32) + :set("list", require "nautslist") + :set("global", false) + :set("icons_i", love.graphics.newImage("assets/portraits.png")) + :set("icons_q", require "nautsicons") + :init() + , + start_button + :setText("Force start") + :setPosition(bx,134) + :set("isEnabled", function () + if #naut_selector:getFullSelection(false) > 1 then + return true + end + return false + end) + :set("active", function (self) + local nauts = naut_selector:getFullSelection(false) + if #nauts > 1 then + changeScene(World:new(MAP, nauts)) + end + end) + , + button:new(menu) + :setText("Go back") + :setPosition(bx,150) + :set("active", function (self) + self.parent:load("menuhost") + end) + , + element:new(menu) + :setPosition(bx, 101) + :set("the_final_countdown", 9) + :set("draw", function (self, scale) + if self.the_final_countdown ~= 9 then + local x,y = self:getPosition() + local countdown = math.max(1, math.ceil(self.the_final_countdown)) + love.graphics.setColor(255, 255, 255, 255) + love.graphics.setFont(Font) + love.graphics.print("Autostart in:", (x-16)*scale, (y+10)*scale, 0, scale, scale) + love.graphics.setFont(Bold) + love.graphics.printf(countdown, (x+40)*scale, (y)*scale, 36, "center", 0, scale, scale) + end + end) + :set("update", function (self, dt) + local total = #naut_selector:getFullSelection(false) + if total > 1 then + self.the_final_countdown = self.the_final_countdown - dt + else + self.the_final_countdown = 9 + end + if self.the_final_countdown < 0 then + start_button:active() + end + end) + , +}
\ No newline at end of file diff --git a/config/menusettings.lua b/config/menusettings.lua new file mode 100644 index 0000000..1b19e84 --- /dev/null +++ b/config/menusettings.lua @@ -0,0 +1,107 @@ +local menu = ... + +local button = require "button" +local selector = require "selector" +local element = require "element" + +local width, height = love.graphics.getWidth()/getRealScale(), love.graphics.getHeight()/getRealScale() +local bx = width/2-29 + +local keys = {"Left", "Right", "Up", "Down", "Attack", "Jump"} + +local dimmer = element:new(menu) + :setPosition(width/2, 15) + :set("visible", false) + :set("currentControl", "Left") + :set("draw", function (self, scale) + if self.visible then + love.graphics.setColor(0, 0, 0, 210) + love.graphics.rectangle("fill",0,0,width*getRealScale(),height*getRealScale()) + love.graphics.setColor(120, 255, 120, 255) + love.graphics.printf("Press new key for: \n> " .. self.currentControl .. " <", (width/2-110)*scale, (height/2-4)*scale, 220, "center", 0, scale, scale) + love.graphics.setColor(255, 255, 255, 255) + end + end) + +-- CHANGER functions +local isEnabled = function (self) + if Controller.getSets()[self.setNumber()] and not self.inProgress then + return true + else + return false + end +end +local startChange = function (self) + dimmer:set("visible", true):set("currentControl", "Left") + self.parent.allowMove = false + self.inProgress = true + self.currentKey = 0 + self.newSet = {} +end +local controlreleased = function(self, set, action, key) + if self.inProgress then + if self.currentKey > 0 and self.currentKey < 7 then + table.insert(self.newSet, key) + dimmer:set("currentControl", keys[self.currentKey+1]) + end + if self.currentKey > 5 then + dimmer:set("visible", false) + self.parent.allowMove = true + self.inProgress = false + table.insert(self.newSet, Controller.sets[self.setNumber()][7]) + print(self.newSet[7]) + Settings.change(self.setNumber(), self.newSet[1], self.newSet[2], self.newSet[3], self.newSet[4], self.newSet[5], self.newSet[6], self.newSet[7]) + else + self.currentKey = self.currentKey + 1 + end + end +end + +local a = { + button:new(menu) + :setText("Keyboard 1") + :setPosition(bx,80) + :set("setNumber", function () return 1 end) + :set("isEnabled", isEnabled) + :set("controlreleased", controlreleased) + :set("stopChange", stopChange) + :set("active", startChange) + , + button:new(menu) + :setText("Keyboard 2") + :setPosition(bx,96) + :set("setNumber", function () return 2 end) + :set("isEnabled", isEnabled) + :set("controlreleased", controlreleased) + :set("stopChange", stopChange) + :set("active", startChange) + , + button:new(menu) + :setText("Gamepad 1") + :setPosition(bx,112) + :set("setNumber", function () return 3 end) + :set("isEnabled", isEnabled) + :set("controlreleased", controlreleased) + :set("stopChange", stopChange) + :set("active", startChange) + , + button:new(menu) + :setText("Gamepad 2") + :setPosition(bx,128) + :set("setNumber", function () return 4 end) + :set("isEnabled", isEnabled) + :set("controlreleased", controlreleased) + :set("stopChange", stopChange) + :set("active", startChange) + , + button:new(menu) + :setText("Go back") + :setPosition(bx,144) + :set("active", function (self) + self.parent:load("menumain") + end) + , + dimmer +} + +return a
\ No newline at end of file diff --git a/controller.lua b/controller.lua index 513af45..e435d63 100644 --- a/controller.lua +++ b/controller.lua @@ -16,6 +16,7 @@ function Controller.controlreleased(set, action, key) end -- Create new controls set. function Controller.registerSet(left, right, up, down, attack, jump, joystick) + if not Controller.isJoystickUnique(joystick) then return end local set = {} set.left = left or "left" set.right = right or "right" @@ -29,6 +30,21 @@ function Controller.registerSet(left, right, up, down, attack, jump, joystick) return set end +-- Get table of controls sets. +function Controller.getSets() + return Controller.sets +end + +-- Checks if given joystick is unique in current set of Controller sets +function Controller.isJoystickUnique(joystick) + if joystick ~= nil then + for _,set in pairs(Controller.sets) do + if set.joystick == joystick then return false end + end + end + return true +end + -- Tests all sets if they have control assigned to given key and joystick. function Controller.testSets(key, joystick) for i,set in pairs(Controller.sets) do @@ -144,13 +160,6 @@ end -- Load gamepad mappings from db file and init module function Controller.load() love.joystick.loadGamepadMappings("gamecontrollerdb.txt") - Controller.registerSet("left", "right", "up", "down", "return", "rshift") - Controller.registerSet("a", "d", "w", "s", "g", "h") -end - --- Create new sets when new joystick is added -function Controller.joystickadded(joystick) - Controller.registerSet("axis:leftx-", "axis:leftx+", "axis:lefty-", "axis:lefty+", "a", "b", joystick) end -- Gamepad input callbacks diff --git a/element.lua b/element.lua new file mode 100644 index 0000000..f9d1c3d --- /dev/null +++ b/element.lua @@ -0,0 +1,42 @@ +-- `Element` +-- Empty element for `Menu` creation. Can be anything. +Element = { + x = 0, + y = 0, + parent +} +function Element:new(parent) + local o = {} + setmetatable(o, self) + self.__index = self + o.parent = parent + return o +end +function Element:delete() end -- deletes Element +function Element:getPosition() return self.x, self.y end -- gives x,y of Element +function Element:setPosition(x,y) + self.x, self.y = x, y + return self +end +function Element:set(name, func) + if type(name) == "string" and func ~= nil then + self[name] = func + end + return self +end + +-- Menu callbacks +function Element:focus() -- Called when Element gains 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
\ No newline at end of file diff --git a/header.lua b/header.lua new file mode 100644 index 0000000..d67e582 --- /dev/null +++ b/header.lua @@ -0,0 +1,57 @@ +-- `Header` +-- It dances! + +Header = { + x = 0, + y = 0, + text = "", + parent, + bounce = 2, +} +function Header:new(parent) + local o = {} + setmetatable(o, self) + self.__index = self + o.parent = parent + return o +end +function Header:setText(text) + self.text = text or "" + return self +end +function Header:setPosition(x, y) + self.x = x or 0 + self.y = y or 0 + return self +end +function Header:getBounce(f) + local f = f or 1 + return math.sin(self.bounce*f*math.pi) +end +function Header:getPosition() return self.x,self.y end -- gives x,y of Element +function Header:focus() + return false +end +function Header:blur() end -- Called when Element loses focus + +-- 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 + +-- Controller callbacks +function Header:controlpressed(set, action, key) end +function Header:controlreleased(set, action, key) end + +return Header
\ No newline at end of file @@ -39,12 +39,12 @@ require "camera" require "menu" require "controller" require "music" +require "settings" -- Temporary debug debug = false -- LÖVE2D callbacks --- Load function love.load() -- Graphics love.graphics.setBackgroundColor(90, 90, 90) @@ -54,28 +54,30 @@ function love.load() Bold = love.graphics.newImageFont("assets/font-big.png", " 0123456789AEFILNORSTUW", -2) Font:setLineHeight(9/16) love.graphics.setFont(Font) - -- Controller + -- Modules Controller.load() + Settings.load() -- Scene Scene = Menu:new() end --- Update function love.update(dt) Scene:update(dt) end --- Draw function love.draw() Scene:draw() if debug then local scale = getScale() + love.graphics.setFont(Font) love.graphics.setColor(255, 0, 0, 255) love.graphics.print("Debug ON", 10, 10, 0, scale, scale) love.graphics.setColor(255, 255, 255, 255) love.graphics.print("Current FPS: "..tostring(love.timer.getFPS()), 10, 10+9*scale, 0, scale, scale) end end +function love.quit() + Settings.save() +end -- Pass input to Controller -function love.joystickadded(joystick) Controller.joystickadded(joystick) end function love.gamepadaxis(joystick, axis, value) Controller.gamepadaxis(joystick, axis, value) end function love.gamepadpressed(joystick, key) Controller.gamepadpressed(joystick, key) end function love.gamepadreleased(joystick, key) Controller.gamepadreleased(joystick, key) end @@ -87,7 +89,7 @@ function Controller.controlpressed(set, action, key) -- pass to current Scene Scene:controlpressed(set, action, key) -- globals - if key == "escape" or key == "f1" then + if key == "escape" then love.event.quit() end if key == "f5" then @@ -97,6 +99,4 @@ end function Controller.controlreleased(set, action, key) -- pass to current Scene Scene:controlreleased(set, action, key) -end - - +end
\ No newline at end of file diff --git a/mapicons.lua b/mapicons.lua new file mode 100644 index 0000000..40ba589 --- /dev/null +++ b/mapicons.lua @@ -0,0 +1,8 @@ +local w, h = 80, 210 +return { + default = love.graphics.newQuad(2, 3,76,37,w,h), + rill = love.graphics.newQuad(2, 45,76,37,w,h), + ribbit = love.graphics.newQuad(2, 87,76,37,w,h), + starstorm = love.graphics.newQuad(2,129,76,37,w,h), + aiguillon = love.graphics.newQuad(2,171,76,37,w,h), +}
\ No newline at end of file @@ -1,215 +1,115 @@ --- `Menu` --- It is one of the last things I will need to mess around with. I'm happy and surprised everything works so far. --- For sure I have learnt a lot about lua during this journey. Still a lot ahead. I will continue writing in the same style though, to not make it even worse. +-- `Menu` (Scene) +-- It creates single screen of a menu +-- I do know that model I used here and in `World` loading configuration files is not flawless but I did not want to rewrite `World`s one but wanted to keep things similar at least in project scope. --- WHOLE CODE HAS FLAG OF "need a cleanup" +require "music" -require "selector" - --- Metatable of `Menu` +-- Here it begins Menu = { - -- move selectors to one table; make functions to retrieve selectors w or w/o controller - selectors = nil, - nauts = require "nautslist", - portrait_sprite = nil, - portrait_sheet = require "portraits", scale = getScale(), - countdown = 10, - maplist = require "maplist", - map = 1, - header_move = 0 + elements, --table + active = 1, + music, + sprite, + background, + allowMove = true, + quads = { + button = { + normal = love.graphics.newQuad(0, 0, 58,15, 80,130), + active = love.graphics.newQuad(0, 0, 58,15, 80,130) + }, + portrait = { + normal = love.graphics.newQuad( 0, 15, 32,32, 80,130), + active = love.graphics.newQuad(32, 15, 32,32, 80,130) + }, + panorama = { + normal = love.graphics.newQuad(0,47, 80,42, 80,130), + active = love.graphics.newQuad(0,88, 80,42, 80,130) + }, + arrow_l = love.graphics.newQuad(68, 0, 6, 6, 80,130), + arrow_r = love.graphics.newQuad(74, 0, 6, 6, 80,130), + } } - --- Constructor of `Menu` -function Menu:new() - -- Meta +function Menu:new(name) local o = {} setmetatable(o, self) self.__index = self - -- initialize - o.selectors = {} - o.portrait_sprite = love.graphics.newImage("assets/portraits.png") - -- selectors - for i=0,3 do - o:newSelector() - end - -- music - o.music = Music:new("ROFLmenu.ogg") + self.sprite = love.graphics.newImage("assets/menu.png") + self.background = love.graphics.newImage("assets/backgrounds/menu.png") + o.elements = {} + o:load(name) + o.music = Music:new("menu.ogg") return o end - --- Destructor function Menu:delete() self.music:delete() end --- Naut selector -function Menu:newSelector() - local selector = Selector:new(self) - local w, h = love.graphics.getWidth()/self.scale, love.graphics.getHeight()/self.scale - local n = #self.selectors - 1 - table.insert(self.selectors, selector) - local x = (w-76)/2+n*44 - local y = h/2-8 - selector:setPosition(x, y) +-- Load menu from file +function Menu:load(name) + local name = "config/" .. (name or "menumain") .. ".lua" + local menu = love.filesystem.load(name) + self.active = 1 + self.elements = menu(self) + self.elements[self.active]:focus() end --- Selectors tables getters --- all of them -function Menu:getSelectors() - return self.selectors -end --- with control set -function Menu:getSelectorsActive() - local t = {} - for _,selector in pairs(self.selectors) do - if selector:getState() ~= 0 then - table.insert(t, selector) - end - end - return t -end --- without control set -function Menu:getSelectorsInactive() - local t = {} - for _,selector in pairs(self.selectors) do - if selector:getState() == 0 then - table.insert(t, selector) - end - end - return t -end --- with locked character -function Menu:getSelectorsLocked() - local t = {} - for _,selector in pairs(self.selectors) do - if selector:getState() == 2 then - table.insert(t, selector) - end - end - return t +-- Return reference to quads table and menu sprite +function Menu:getSheet() + return self.sprite, self.quads end --- Tests if Control set is assigned to any selector (1.) and if it is locked (2.) -function Menu:isSetUsed(set) - for k,selector in pairs(self:getSelectorsActive()) do - if selector:getControlSet() == set then - if selector:getState() == 2 then - return true, true - else - return true, false - end - end +-- Cycle elements +function Menu:next() + self.elements[self.active]:blur() + self.active = (self.active%#self.elements)+1 + if not self.elements[self.active]:focus() then + self:next() end - return false, false -end - --- Header get bounce move -function Menu:getBounce(f) - local f = f or 1 - return math.sin(self.header_move*f*math.pi) end - --- Speed up countdown -function Menu:countdownJump() - if self.countdown ~= Menu.countdown then -- Menu.countdown is initial - self.countdown = self.countdown - 1 +function Menu:previous() + self.elements[self.active]:blur() + if self.active == 1 then + self.active = #self.elements + else + self.active = self.active - 1 end -end - --- Get table of nauts currently selected by locked selectors -function Menu:getNauts() - local nauts = {} - for _,selector in pairs(self:getSelectorsLocked()) do - table.insert(nauts, {selector:getSelectionName(), selector:getControlSet()}) + if not self.elements[self.active]:focus() then + self:previous() end - return nauts -end - --- WARUDO -function Menu:startGame() - local world = World:new(self.maplist[self.map], self:getNauts()) - changeScene(world) end -- LÖVE2D callbacks --- Update function Menu:update(dt) - if #self:getSelectorsLocked() > 1 then - self.countdown = self.countdown - dt - else - self.countdown = Menu.countdown -- Menu.countdown is initial - end - if self.countdown < 0 then - self:startGame() - end - -- Bounce header - self.header_move = self.header_move + dt - if self.header_move > 2 then - self.header_move = self.header_move - 2 + for _,element in pairs(self.elements) do + element:update(dt) end end --- Draw function Menu:draw() - -- locals - local w, h = love.graphics.getWidth()/self.scale, love.graphics.getHeight()/self.scale local scale = self.scale - -- map selection - love.graphics.setFont(Font) - love.graphics.printf("Map: " .. self.maplist[self.map], (w/2)*scale, (h/2-22)*scale, 150, "center", 0, scale, scale, 75, 4) - -- character selection - for _,selector in pairs(self:getSelectors()) do - selector:draw() - end - -- header - love.graphics.setFont(Bold) - local angle = self:getBounce(2) - local dy = self:getBounce()*4 - love.graphics.printf("ROFLNAUTS2",(w/2)*scale,(32+dy)*scale,336,"center",(angle*5)*math.pi/180,scale,scale,168,12) - -- footer + love.graphics.draw(self.background, 0, 0, 0, getRealScale(), getRealScale()) love.graphics.setFont(Font) - love.graphics.printf("Use W,S,A,D,G,H or Arrows,Enter,Rshift or Gamepad\n\nA game by the Awesomenauts community\nSeltzy, PlasmaWisp, ParaDoX, MilkingChicken, Burningdillo, Bronkey, Aki, 04font\nBased on a game by Jan Willem Nijman, Paul Veer and Bits_Beats XOXO", (w/2)*scale, (h-42)*scale, 336, "center", 0, scale, scale, 168, 4) - -- countdown - local countdown = math.floor(self.countdown) - if self.countdown < Menu.countdown then -- Menu.countdown is initial - love.graphics.setFont(Bold) - love.graphics.print(countdown,(w/2-6.5)*self.scale,(h/2+30)*self.scale,0,self.scale,self.scale) + for _,element in pairs(self.elements) do + element:draw(scale) end end -- Controller callbacks function Menu:controlpressed(set, action, key) - local used, locked = self:isSetUsed(set) - -- Pass to active selectors - for k,selector in pairs(self:getSelectorsActive()) do - selector:controlpressed(set, action, key) - end - if not used then - if action == "attack" then - self:getSelectorsInactive()[1]:assignControlSet(set) + if self.allowMove then + if action == "down" then + self:next() end - -- map selection chaos! - if action == "left" then - if self.map ~= 1 then - self.map = self.map - 1 - else - self.map = #self.maplist - end - end - if action == "right" then - if self.map ~= #self.maplist then - self.map = self.map + 1 - else - self.map = 1 - end + if action == "up" then + self:previous() end end - -- speed up the countdown - if action ~= "jump" then - if set == nil or locked then - self:countdownJump() -- that's funny isn't it? if not jump then jump - end + for _,element in pairs(self.elements) do + element:controlpressed(set, action, key) end end function Menu:controlreleased(set, action, key) + for _,element in pairs(self.elements) do + element:controlreleased(set, action, key) + end end
\ No newline at end of file diff --git a/nautsicons.lua b/nautsicons.lua new file mode 100644 index 0000000..f0cd9c2 --- /dev/null +++ b/nautsicons.lua @@ -0,0 +1,46 @@ +-- Spritesheet for character portraits +-- Original size: 331x265 (say what?) +-- Single size: 32x32 1px border merged between +local w, h = 331, 265 +return { + -- EMPTY + empty = love.graphics.newQuad(300,136,28,28,w,h), + -- 1. ROW + froggo = love.graphics.newQuad( 3, 4,28,27,w,h), + cowboy = love.graphics.newQuad( 36, 4,28,27,w,h), + honic = love.graphics.newQuad( 69, 4,28,27,w,h), + gelato = love.graphics.newQuad(102, 4,28,27,w,h), + veno = love.graphics.newQuad(135, 4,28,27,w,h), + lady = love.graphics.newQuad(168, 4,28,27,w,h), + girl = love.graphics.newQuad(201, 4,28,27,w,h), + megoman = love.graphics.newQuad(234, 4,28,27,w,h), + brainos = love.graphics.newQuad(267, 4,28,27,w,h), + -- 2. ROW + woman = love.graphics.newQuad( 3, 70,28,27,w,h), + bison = love.graphics.newQuad( 36, 70,28,27,w,h), + bobito = love.graphics.newQuad( 69, 70,28,27,w,h), + slugzor = love.graphics.newQuad(102, 70,28,27,w,h), + capone = love.graphics.newQuad(135, 70,28,27,w,h), + bug = love.graphics.newQuad(168, 70,28,27,w,h), + calamari = love.graphics.newQuad(201, 70,28,27,w,h), + quack = love.graphics.newQuad(234, 70,28,27,w,h), + scissors = love.graphics.newQuad(267, 70,28,27,w,h), + -- 3. ROW + marine = love.graphics.newQuad( 3, 136,28,27,w,h), + scooter = love.graphics.newQuad( 36, 136,28,27,w,h), + phonebooth = love.graphics.newQuad( 69, 136,28,27,w,h), + weed = love.graphics.newQuad(102, 136,28,27,w,h), + gummybear = love.graphics.newQuad(135, 136,28,27,w,h), + gramps = love.graphics.newQuad(168, 136,28,27,w,h), + biker = love.graphics.newQuad(201, 136,28,27,w,h), + vrooom = love.graphics.newQuad(234, 136,28,27,w,h), + link = love.graphics.newQuad(267, 136,28,27,w,h), + -- 4. ROW + gorilla = love.graphics.newQuad( 3,202,28,27,w,h), + nemo = love.graphics.newQuad( 36,202,28,27,w,h), + rock = love.graphics.newQuad( 69,202,28,27,w,h), + boss = love.graphics.newQuad(102,202,28,27,w,h), + -- ARROWS + arrow_left = love.graphics.newQuad(298,1,4,6,w,h), + arrow_right = love.graphics.newQuad(303,1,4,6,w,h) +} @@ -286,6 +286,8 @@ end -- Draw of `Player` function Player:draw(offset_x, offset_y, scale, debug) + -- draw only alive + if not self.alive then return end -- locals local offset_x = offset_x or 0 local offset_y = offset_y or 0 diff --git a/selector.lua b/selector.lua index afdfed7..de20699 100644 --- a/selector.lua +++ b/selector.lua @@ -1,112 +1,269 @@ --- `Selector` --- Used in menu; selecting nauts? +-- `Selector` (Element) +-- 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 = { - naut = 1, + parent, x = 0, y = 0, - parent = nil, - controlset = nil, - locked = false + 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 } -function Selector:new(menu) + +-- Constructor +function Selector:new(parent) local o = {} setmetatable(o, self) self.__index = self - o.parent = menu + o.parent = parent + o.sprite, o.quads = parent:getSheet() return o end + -- Position -function Selector:setPosition(x,y) - self.x = x - self.y = y -end function Selector:getPosition() return self.x, self.y end --- Control Sets -function Selector:assignControlSet(set) - self.controlset = set - self.naut = 2 +function Selector:setPosition(x,y) + self.x, self.y = x, y + return self +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:getControlSet() - if self.controlset ~= nil then - return self.controlset +function Selector:setMargin(margin) + self.margin = margin + return self +end + +-- General setter for Menu configuration files +function Selector:set(name, func) + if type(name) == "string" and func ~= nil then + self[name] = func end + return self end --- States -function Selector:getState() - if self:getControlSet() ~= nil then - if self.locked then - return 2 -- has controls and locked + +-- 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 - return 1 -- has controls but not locked end - return 0 -- no controls and not locked + return self end -function Selector:clear() - self.controlset = nil - self.naut = 1 - self.locked = false + +-- Cycle through list on given number +function Selector:next(n) + local total = #self.list + local current = self.selections[n] + local locked = self:isLocked(n) + if not locked then + self.selections[n] = (current % total) + 1 + end end -function Selector:getSelectionName() - return self.parent.nauts[self.naut] +function Selector:previous(n) + local total = #self.list + local current = self.selections[n] + local locked = self:isLocked(n) + if not locked then + if current == 1 then + self.selections[n] = total + else + self.selections[n] = current - 1 + end + end end --- LÖVE2D callbacks -function Selector:draw() - -- portrait, sprite - local name = self.parent.nauts[self.naut] - local p = self.parent.portrait_sheet[name] - local sprite = self.parent.portrait_sprite - -- scale, position - local scale = self.parent.scale - local x,y = self:getPosition() - -- arrows - local arrowl = self.parent.portrait_sheet.arrow_left - local arrowr = self.parent.portrait_sheet.arrow_right - if not self.locked then - love.graphics.draw(sprite, p.normal, x*scale, y*scale, 0, scale, scale) - if self.controlset ~= nil then - love.graphics.draw(sprite, arrowl, (x-2)* scale, (y+13)*scale, 0, scale, scale) - love.graphics.draw(sprite, arrowr, (x+30)*scale, (y+13)*scale, 0, scale, scale) +-- 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 + +-- 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 + +-- 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.draw(sprite, p.active, x*scale, y*scale, 0, scale, scale) + love.graphics.setColor(140, 140, 140, 255) end - if self.naut ~= 1 then - love.graphics.printf(string.upper(name), (x-8)*scale, (y+33)*scale, 48, "center", 0, scale, scale) + 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 function Selector:controlpressed(set, action, key) - -- locals - local n = #self.parent.nauts - if set == self:getControlSet() then - if action == "left" and not self.locked then - if self.naut == 2 or self.naut == 1 then - self.naut = n - else - self.naut = self.naut - 1 - end - elseif action == "right" and not self.locked then - if self.naut == n then - self.naut = 2 - else - self.naut = self.naut + 1 + 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 + if (self:getSelection(n) ~= 1 or self.first) and self:isUnique(n) then + self.locks[n] = true end - elseif action == "attack" then - if self.naut ~= 1 then - self.locked = true - end - elseif action == "jump" then - if self.locked == true then - self.locked = false - else - self:clear() + end + if action == "jump" then + if locked then + self.locks[n] = false end end end end -function Selector:controlreleased(set, action, key) -end
\ No newline at end of file +function Selector:controlreleased(set, action, key) end + +return Selector
\ No newline at end of file diff --git a/settings.default b/settings.default new file mode 100644 index 0000000..6816116 --- /dev/null +++ b/settings.default @@ -0,0 +1,6 @@ +return { + {"left", "right", "up", "down", "return", "rshift", false}, + {"a", "d", "w", "s", "g", "h", false}, + {"axis:leftx-", "axis:leftx+", "axis:lefty-", "axis:lefty+", "a", "b", true}, + {"axis:leftx-", "axis:leftx+", "axis:lefty-", "axis:lefty+", "a", "b", true}, +} diff --git a/settings.lua b/settings.lua new file mode 100644 index 0000000..ad8b8e5 --- /dev/null +++ b/settings.lua @@ -0,0 +1,63 @@ +Settings = {} +Settings.current = {} +function Settings.load() + if Controller then + if not love.filesystem.exists("settings") then + local def = love.filesystem.newFile("settings.default") + local new = love.filesystem.newFile("settings") + new:open("w") def:open("r") + new:write(def:read()) + new:close() def:close() + end + local getSettings = love.filesystem.load("settings") + Settings.current = getSettings() + local joysticksList = love.joystick.getJoysticks() -- local list for editing + for _,set in pairs(Settings.current) do + local isJoystick = set[7] + local joystick + if isJoystick then + -- take and remove first joystick from list + joystick = joysticksList[1] + table.remove(joysticksList, 1) + end + if not isJoystick or joystick then + Controller.registerSet(set[1], set[2], set[3], set[4], set[5], set[6], joystick) + end + end + end +end +function Settings.save() + local new = love.filesystem.newFile("settings") + local sets = Settings.current + local string = "return {\n" + for i,set in pairs(sets) do + string = string .. "\t{" + for j,word in pairs(set) do + if j ~= 7 then + string = string .. "\"" .. word .. "\", " + else + if word then + string = string .. "true" + else + string = string .. "false" + end + end + end + string = string .. "},\n" + end + string = string .. "}" + new:open("w") + new:write(string) + new:close() +end +function Settings.change(n, left, right, up, down, attack, jump, joystick) + local bool + if joystick then + bool = true + else + bool = false + end + Settings.current[n] = {left, right, up, down, attack, jump, bool} + table.remove(Controller.sets, n) + Controller.registerSet(left, right, up, down, attack, jump, joystick) +end
\ No newline at end of file @@ -36,7 +36,7 @@ World = { } -- Constructor of `World` ZA WARUDO! -function World:new(map, ...) +function World:new(map, nauts) -- Meta local o = {} setmetatable(o, self) @@ -64,7 +64,7 @@ function World:new(map, ...) local map = map or "default" o:loadMap(map) -- Nauts - o:spawnNauts(...) + o:spawnNauts(nauts) -- Create camera o.camera = Camera:new(o) -- Play music @@ -110,14 +110,7 @@ function World:loadMap(name) end -- Spawn all the nauts for the round -function World:spawnNauts(...) - local params = {...} - local nauts = nil - if type(params[1][1]) == "table" then - nauts = params[1] - else - nauts = params - end +function World:spawnNauts(nauts) for _,naut in pairs(nauts) do local x,y = self:getSpawnPosition() local spawn = self:createNaut(x, y, naut[1]) |