| @@ -5,14 +5,7 @@ local thrusterMax = 0 | |||||
| local animationComplete = false | local animationComplete = false | ||||
| local frame = 0 | local frame = 0 | ||||
| asteroidImage = love.graphics.newImage("entities/planet/asteroid.png") | asteroidImage = love.graphics.newImage("entities/planet/asteroid.png") | ||||
| function love.keyreleased(key) | |||||
| if key == "escape" and gameStatus == "play" then | |||||
| if pauseStatus then | |||||
| pauseStatus = false | |||||
| else pauseStatus = true | |||||
| end | |||||
| end | |||||
| end | |||||
| function levelgeneral.update(dt) | function levelgeneral.update(dt) | ||||
| if not pauseStatus then | if not pauseStatus then | ||||
| if not levelLoaded then | if not levelLoaded then | ||||
| @@ -72,6 +65,8 @@ else | |||||
| camera:follow(VCAM.x, VCAM.y) | camera:follow(VCAM.x, VCAM.y) | ||||
| end | end | ||||
| levelgeneral.GUIControl() | levelgeneral.GUIControl() | ||||
| else | |||||
| settingsMenuUpdate(dt) | |||||
| end | end | ||||
| end | end | ||||
| @@ -127,7 +122,7 @@ function levelgeneral.draw() | |||||
| end | end | ||||
| if gameStatus == "setup" and not reachedGoal then | if gameStatus == "setup" and not reachedGoal then | ||||
| level.hint() | level.hint() | ||||
| elseif gameStatus == "play" then | |||||
| elseif gameStatus == "play" and not pauseStatus then | |||||
| if not reachedGoal then | if not reachedGoal then | ||||
| love.graphics.printf("[W] Thrusters: ", 0, WINDOW_HEIGHT-100, 300, "center") | love.graphics.printf("[W] Thrusters: ", 0, WINDOW_HEIGHT-100, 300, "center") | ||||
| local m = smallfont:getWidth("[W] Thrusters: ") | local m = smallfont:getWidth("[W] Thrusters: ") | ||||
| @@ -1,8 +1,10 @@ | |||||
| menu = Class{} | menu = Class{} | ||||
| menuMode = "main" | |||||
| local M = {} | local M = {} | ||||
| menuLoaded = false | menuLoaded = false | ||||
| function menu.update(dt) | function menu.update(dt) | ||||
| if not menuLoaded then | if not menuLoaded then | ||||
| firstShip.x = -100 | firstShip.x = -100 | ||||
| menuLoaded = true | menuLoaded = true | ||||
| planets = {} | planets = {} | ||||
| @@ -31,6 +33,15 @@ function menu.update(dt) | |||||
| end | end | ||||
| --print("ship is hit") | --print("ship is hit") | ||||
| end | end | ||||
| if menuMode == "settings" then | |||||
| local mx, my = love.mouse.getPosition() | |||||
| local vmx, vmy = camera:getMousePosition() | |||||
| local vmx = vmx * DIFFERENCE_X | |||||
| local vmy = vmy * DIFFERENCE_Y | |||||
| local mx = mx * DIFFERENCE_X | |||||
| local my = my * DIFFERENCE_Y | |||||
| volumeSlider:update(mx, my) | |||||
| end | |||||
| end | end | ||||
| function menu.draw(dt) | function menu.draw(dt) | ||||
| @@ -44,7 +55,19 @@ function menu.draw(dt) | |||||
| else | else | ||||
| love.graphics.setFont(titlefont) | love.graphics.setFont(titlefont) | ||||
| love.graphics.printf("NuclearGravity", 0, 20, WINDOW_WIDTH, "center") | love.graphics.printf("NuclearGravity", 0, 20, WINDOW_WIDTH, "center") | ||||
| if menuMode == "main" then | |||||
| menu:butt(buttons, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 40, WINDOW_WIDTH/3) | menu:butt(buttons, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 40, WINDOW_WIDTH/3) | ||||
| elseif menuMode == "settings" then | |||||
| menu:butt(mainsettings, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 40, WINDOW_WIDTH/3) | |||||
| love.graphics.setColor(254, 67, 101) | |||||
| love.graphics.setFont(tinyfont) | |||||
| love.graphics.printf("Sound volume:", 0, WINDOW_HEIGHT/2-140, WINDOW_WIDTH, "center") | |||||
| -- draw slider, set color and line style before calling | |||||
| volumeSlider:draw() | |||||
| else | |||||
| print("[EE]No menu found! " .. menu.mode) | |||||
| end | |||||
| love.keyboard.mouseisReleased = false | love.keyboard.mouseisReleased = false | ||||
| end | end | ||||
| end | end | ||||
| @@ -4,6 +4,7 @@ local M = {} | |||||
| local currenctScore = 0 | local currenctScore = 0 | ||||
| function practice.update(dt) | function practice.update(dt) | ||||
| if not pauseStatus then | |||||
| if not levelLoaded then | if not levelLoaded then | ||||
| shipsleft = 1 | shipsleft = 1 | ||||
| planetsleft = 10 | planetsleft = 10 | ||||
| @@ -38,6 +39,7 @@ function practice.update(dt) | |||||
| levelLoaded = true | levelLoaded = true | ||||
| end | end | ||||
| camera:update(dt) | camera:update(dt) | ||||
| --print(camera.x .. " " .. camera.y) | --print(camera.x .. " " .. camera.y) | ||||
| for i, explosion in ipairs(explosions) do | for i, explosion in ipairs(explosions) do | ||||
| explosion:update(dt) | explosion:update(dt) | ||||
| @@ -63,7 +65,7 @@ function practice.update(dt) | |||||
| planets[i]:update(dt) | planets[i]:update(dt) | ||||
| if math.sqrt((firstShip.x - planets[i].x)^2 + (firstShip.y - planets[i].y)^2) > planets[i].w/3 then | if math.sqrt((firstShip.x - planets[i].x)^2 + (firstShip.y - planets[i].y)^2) > planets[i].w/3 then | ||||
| currentScore = currentScore + math.sqrt(planets[i].attractionX^2 + planets[i].attractionY^2)*100 | currentScore = currentScore + math.sqrt(planets[i].attractionX^2 + planets[i].attractionY^2)*100 | ||||
| print(math.sqrt(planets[i].attractionX^2 + planets[i].attractionY^2)) | |||||
| --print(math.sqrt(planets[i].attractionX^2 + planets[i].attractionY^2)) | |||||
| end | end | ||||
| end | end | ||||
| for i in ipairs(cannons) do | for i in ipairs(cannons) do | ||||
| @@ -83,8 +85,9 @@ else | |||||
| camera:follow(VCAM.x, VCAM.y) | camera:follow(VCAM.x, VCAM.y) | ||||
| end | end | ||||
| practice.GUIControl() | practice.GUIControl() | ||||
| else | |||||
| settingsMenuUpdate(dt) | |||||
| end | |||||
| end | end | ||||
| function practice.draw() | function practice.draw() | ||||
| @@ -118,15 +121,17 @@ function practice.draw() | |||||
| local textW = tinyfont:getWidth("Top score: " .. math.floor(saveData.score/100)) | local textW = tinyfont:getWidth("Top score: " .. math.floor(saveData.score/100)) | ||||
| love.graphics.print("Top score: " .. math.floor(saveData.score/100), WINDOW_WIDTH/2-textW/2, 10) | love.graphics.print("Top score: " .. math.floor(saveData.score/100), WINDOW_WIDTH/2-textW/2, 10) | ||||
| practice.hint() | practice.hint() | ||||
| elseif gameStatus == "play" then | |||||
| elseif gameStatus == "play" and not pauseStatus then | |||||
| local textW = tinyfont:getWidth("Score: " .. math.floor(currentScore/100)) | local textW = tinyfont:getWidth("Score: " .. math.floor(currentScore/100)) | ||||
| love.graphics.setFont(tinyfont) | love.graphics.setFont(tinyfont) | ||||
| love.graphics.print("Score: " .. math.floor(currentScore/100), WINDOW_WIDTH/2-textW/2, 10) | love.graphics.print("Score: " .. math.floor(currentScore/100), WINDOW_WIDTH/2-textW/2, 10) | ||||
| guimenu:butt(playbutts, WINDOW_WIDTH, WINDOW_HEIGHT, 1100, WINDOW_HEIGHT-50, 40, WINDOW_WIDTH/3) | guimenu:butt(playbutts, WINDOW_WIDTH, WINDOW_HEIGHT, 1100, WINDOW_HEIGHT-50, 40, WINDOW_WIDTH/3) | ||||
| love.keyboard.mouseisReleased = false | |||||
| end | end | ||||
| if pauseStatus then | |||||
| drawPauseMenu() | |||||
| love.keyboard.mouseisReleased = false | |||||
| end | |||||
| end | end | ||||
| @@ -142,6 +147,9 @@ function practice.reset() | |||||
| firstShip:reset() | firstShip:reset() | ||||
| camera.scale = 1 | camera.scale = 1 | ||||
| projectiles = {} | projectiles = {} | ||||
| for i in ipairs(cannons) do | |||||
| cannons[i].timer = cannons[i].otimer | |||||
| end | |||||
| shipsleft = 1 | shipsleft = 1 | ||||
| if currentScore > saveData.score then | if currentScore > saveData.score then | ||||
| @@ -18,7 +18,7 @@ saveData = { | |||||
| levelsBeaten = 0, | levelsBeaten = 0, | ||||
| score = 0 | score = 0 | ||||
| } | } | ||||
| mainsettings = {} | |||||
| planets = {} | planets = {} | ||||
| buttons = {} | buttons = {} | ||||
| cannons = {} | cannons = {} | ||||
| @@ -33,7 +33,17 @@ function love.wheelmoved(x, y) | |||||
| end | end | ||||
| end | end | ||||
| end | end | ||||
| function love.keyreleased(key) | |||||
| if key == "escape" and gameStatus == "play" then | |||||
| if pauseStatus then | |||||
| pauseStatus = false | |||||
| pauseState = "main" | |||||
| else pauseStatus = true | |||||
| end | |||||
| end | |||||
| end | |||||
| function love.load() | function love.load() | ||||
| love.graphics.setLineWidth(4) | |||||
| print(love.filesystem.getAppdataDirectory()) | print(love.filesystem.getAppdataDirectory()) | ||||
| print(love.filesystem.getSaveDirectory()) | print(love.filesystem.getSaveDirectory()) | ||||
| print(love.filesystem.areSymlinksEnabled()) | print(love.filesystem.areSymlinksEnabled()) | ||||
| @@ -24,8 +24,10 @@ If you're on arch, install the prerequisites with: | |||||
| `` | `` | ||||
| Changelog: | |||||
| Changelog history: | |||||
| - Changed practice scoring system | - Changed practice scoring system | ||||
| - Fixed bug with cannon timers not resetting | - Fixed bug with cannon timers not resetting | ||||
| - Toggle music button added | - Toggle music button added | ||||
| - Added the pause menu | - Added the pause menu | ||||
| - Volume slider added | |||||
| - Made trail **wider** | |||||
| @@ -9,7 +9,7 @@ function buttonClutter() | |||||
| function() | function() | ||||
| gameState = "selectlv" | gameState = "selectlv" | ||||
| end)) | end)) | ||||
| table.insert(buttons, menu:addButton("Toggle Fullscreen", | |||||
| table.insert(mainsettings, menu:addButton("Toggle Fullscreen", | |||||
| function() | function() | ||||
| myscreen:toggle(WINDOW_HEIGHT, WINDOW_WIDTH) | myscreen:toggle(WINDOW_HEIGHT, WINDOW_WIDTH) | ||||
| DIFFERENCE_X = myscreen.c | DIFFERENCE_X = myscreen.c | ||||
| @@ -17,9 +17,13 @@ function buttonClutter() | |||||
| OFFSET_X = myscreen.e | OFFSET_X = myscreen.e | ||||
| OFFSET_Y = myscreen.f | OFFSET_Y = myscreen.f | ||||
| end)) | end)) | ||||
| table.insert(buttons, menu:addButton("Toggle Music", | |||||
| table.insert(mainsettings, menu:addButton("back", | |||||
| function() | |||||
| menuMode = "main" | |||||
| end)) | |||||
| table.insert(buttons, menu:addButton("Settings", | |||||
| function() | function() | ||||
| toggleMusic() | |||||
| menuMode = "settings" | |||||
| end | end | ||||
| )) | )) | ||||
| @@ -8,6 +8,7 @@ require 'entities/planet/planet' | |||||
| require 'src/buttonClutter' | require 'src/buttonClutter' | ||||
| require 'entities/explosion/explosion' | require 'entities/explosion/explosion' | ||||
| require 'src/GUI' | require 'src/GUI' | ||||
| require 'src/simple-slider' | |||||
| require 'src/pauseMenu' | require 'src/pauseMenu' | ||||
| require 'src/stateMachine' | require 'src/stateMachine' | ||||
| require 'entities/base/base' | require 'entities/base/base' | ||||
| @@ -1,6 +1,9 @@ | |||||
| pauseStatus = false | pauseStatus = false | ||||
| pauseState = "main" | |||||
| pauseMenu = {} | pauseMenu = {} | ||||
| settings = {} | |||||
| function pauseMake() | function pauseMake() | ||||
| volumeSlider = newSlider(WINDOW_WIDTH/2, WINDOW_HEIGHT/2-100, 300, 0.5, 0, 1, function (v) love.audio.setVolume(v) end) | |||||
| table.insert(pauseMenu, menu:addButton("Resume", | table.insert(pauseMenu, menu:addButton("Resume", | ||||
| function() | function() | ||||
| pauseStatus = false | pauseStatus = false | ||||
| @@ -12,7 +15,7 @@ function() | |||||
| goBack() | goBack() | ||||
| end | end | ||||
| )) | )) | ||||
| table.insert(pauseMenu, menu:addButton("Toggle Fullscreen", | |||||
| table.insert(settings, menu:addButton("Toggle Fullscreen", | |||||
| function() | function() | ||||
| myscreen:toggle(WINDOW_HEIGHT, WINDOW_WIDTH) | myscreen:toggle(WINDOW_HEIGHT, WINDOW_WIDTH) | ||||
| DIFFERENCE_X = myscreen.c | DIFFERENCE_X = myscreen.c | ||||
| @@ -21,9 +24,14 @@ function() | |||||
| OFFSET_Y = myscreen.f | OFFSET_Y = myscreen.f | ||||
| end | end | ||||
| )) | )) | ||||
| table.insert(pauseMenu, menu:addButton("Toggle Music", | |||||
| table.insert(settings, menu:addButton("back", | |||||
| function() | function() | ||||
| toggleMusic() | |||||
| pauseState = "main" | |||||
| end | |||||
| )) | |||||
| table.insert(pauseMenu, menu:addButton("Settings", | |||||
| function() | |||||
| pauseState = "settings" | |||||
| end | end | ||||
| )) | )) | ||||
| table.insert(pauseMenu, menu:addButton("Quit", | table.insert(pauseMenu, menu:addButton("Quit", | ||||
| @@ -34,5 +42,30 @@ end | |||||
| end | end | ||||
| function drawPauseMenu() | function drawPauseMenu() | ||||
| -- print("draw") | -- print("draw") | ||||
| if pauseState == "main" then | |||||
| menu:butt(pauseMenu, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 40, WINDOW_WIDTH/3) | menu:butt(pauseMenu, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 40, WINDOW_WIDTH/3) | ||||
| end | |||||
| end | |||||
| if pauseState == "settings" then | |||||
| menu:butt(settings, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 40, WINDOW_WIDTH/3) | |||||
| love.graphics.setLineWidth(4) | |||||
| love.graphics.setColor(254, 67, 101) | |||||
| love.graphics.setFont(tinyfont) | |||||
| love.graphics.printf("Sound volume:", 0, WINDOW_HEIGHT/2-140, WINDOW_WIDTH, "center") | |||||
| -- draw slider, set color and line style before calling | |||||
| volumeSlider:draw() | |||||
| end | |||||
| end | |||||
| function settingsMenuUpdate(dt) | |||||
| if pauseState == "settings" then | |||||
| local mx, my = love.mouse.getPosition() | |||||
| local vmx, vmy = camera:getMousePosition() | |||||
| local vmx = vmx * DIFFERENCE_X | |||||
| local vmy = vmy * DIFFERENCE_Y | |||||
| local mx = mx * DIFFERENCE_X | |||||
| local my = my * DIFFERENCE_Y | |||||
| volumeSlider:update(mx, my) | |||||
| -- print("updating") | |||||
| end | |||||
| -- print("called?") | |||||
| end | |||||
| @@ -0,0 +1,138 @@ | |||||
| --[[ | |||||
| Copyright (c) 2016 George Prosser | |||||
| 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 slider = {} | |||||
| slider.__index = slider | |||||
| function newSlider(x, y, length, value, min, max, setter, style) | |||||
| local s = {} | |||||
| s.value = (value - min) / (max - min) | |||||
| s.min = min | |||||
| s.max = max | |||||
| s.setter = setter | |||||
| s.x = x | |||||
| s.y = y | |||||
| s.length = length | |||||
| local p = style or {} | |||||
| s.width = p.width or length * 0.1 | |||||
| s.orientation = p.orientation or 'horizontal' | |||||
| s.track = p.track or 'rectangle' | |||||
| s.knob = p.knob or 'rectangle' | |||||
| s.grabbed = false | |||||
| s.wasDown = true | |||||
| s.ox = 0 | |||||
| s.oy = 0 | |||||
| return setmetatable(s, slider) | |||||
| end | |||||
| function slider:update(mouseX, mouseY, mouseDown) | |||||
| local x = mouseX or love.mouse.getX() | |||||
| local y = mouseY or love.mouse.getY() | |||||
| local down = love.mouse.isDown(1) | |||||
| if mouseDown ~= nil then | |||||
| down = mouseDown | |||||
| end | |||||
| local knobX = self.x | |||||
| local knobY = self.y | |||||
| if self.orientation == 'horizontal' then | |||||
| knobX = self.x - self.length/2 + self.length * self.value | |||||
| elseif self.orientation == 'vertical' then | |||||
| knobY = self.y + self.length/2 - self.length * self.value | |||||
| end | |||||
| local ox = x - knobX | |||||
| local oy = y - knobY | |||||
| local dx = ox - self.ox | |||||
| local dy = oy - self.oy | |||||
| if down then | |||||
| if self.grabbed then | |||||
| if self.orientation == 'horizontal' then | |||||
| self.value = self.value + dx / self.length | |||||
| elseif self.orientation == 'vertical' then | |||||
| self.value = self.value - dy / self.length | |||||
| end | |||||
| elseif (x > knobX - self.width/2 and x < knobX + self.width/2 and y > knobY - self.width/2 and y < knobY + self.width/2) and not self.wasDown then | |||||
| self.ox = ox | |||||
| self.oy = oy | |||||
| self.grabbed = true | |||||
| end | |||||
| else | |||||
| self.grabbed = false | |||||
| end | |||||
| self.value = math.max(0, math.min(1, self.value)) | |||||
| if self.setter ~= nil then | |||||
| self.setter(self.min + self.value * (self.max - self.min)) | |||||
| end | |||||
| self.wasDown = down | |||||
| end | |||||
| function slider:draw() | |||||
| if self.track == 'rectangle' then | |||||
| if self.orientation == 'horizontal' then | |||||
| love.graphics.rectangle('line', self.x - self.length/2 - self.width/2, self.y - self.width/2, self.length + self.width, self.width) | |||||
| elseif self.orientation == 'vertical' then | |||||
| love.graphics.rectangle('line', self.x - self.width/2, self.y - self.length/2 - self.width/2, self.width, self.length + self.width) | |||||
| end | |||||
| elseif self.track == 'line' then | |||||
| if self.orientation == 'horizontal' then | |||||
| love.graphics.line(self.x - self.length/2, self.y, self.x + self.length/2, self.y) | |||||
| elseif self.orientation == 'vertical' then | |||||
| love.graphics.line(self.x, self.y - self.length/2, self.x, self.y + self.length/2) | |||||
| end | |||||
| elseif self.track == 'roundrect' then | |||||
| if self.orientation == 'horizontal' then | |||||
| love.graphics.rectangle('line', self.x - self.length/2 - self.width/2, self.y - self.width/2, self.length + self.width, self.width, self.width/2, self.width) | |||||
| elseif self.orientation == 'vertical' then | |||||
| love.graphics.rectangle('line', self.x - self.width/2, self.y - self.length/2 - self.width/2, self.width, self.length + self.width, self.width, self.width/2) | |||||
| end | |||||
| end | |||||
| local knobX = self.x | |||||
| local knobY = self.y | |||||
| if self.orientation == 'horizontal' then | |||||
| knobX = self.x - self.length/2 + self.length * self.value | |||||
| elseif self.orientation == 'vertical' then | |||||
| knobY = self.y + self.length/2 - self.length * self.value | |||||
| end | |||||
| if self.knob == 'rectangle' then | |||||
| love.graphics.rectangle('fill', knobX - self.width/2, knobY - self.width/2, self.width, self.width) | |||||
| elseif self.knob == 'circle' then | |||||
| love.graphics.circle('fill', knobX, knobY, self.width/2) | |||||
| end | |||||
| end | |||||
| function slider:getValue() | |||||
| return self.min + self.value * (self.max - self.min) | |||||
| end | |||||