| @@ -5,14 +5,7 @@ local thrusterMax = 0 | |||
| local animationComplete = false | |||
| local frame = 0 | |||
| 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) | |||
| if not pauseStatus then | |||
| if not levelLoaded then | |||
| @@ -72,6 +65,8 @@ else | |||
| camera:follow(VCAM.x, VCAM.y) | |||
| end | |||
| levelgeneral.GUIControl() | |||
| else | |||
| settingsMenuUpdate(dt) | |||
| end | |||
| end | |||
| @@ -127,7 +122,7 @@ function levelgeneral.draw() | |||
| end | |||
| if gameStatus == "setup" and not reachedGoal then | |||
| level.hint() | |||
| elseif gameStatus == "play" then | |||
| elseif gameStatus == "play" and not pauseStatus then | |||
| if not reachedGoal then | |||
| love.graphics.printf("[W] Thrusters: ", 0, WINDOW_HEIGHT-100, 300, "center") | |||
| local m = smallfont:getWidth("[W] Thrusters: ") | |||
| @@ -1,8 +1,10 @@ | |||
| menu = Class{} | |||
| menuMode = "main" | |||
| local M = {} | |||
| menuLoaded = false | |||
| function menu.update(dt) | |||
| if not menuLoaded then | |||
| firstShip.x = -100 | |||
| menuLoaded = true | |||
| planets = {} | |||
| @@ -31,6 +33,15 @@ function menu.update(dt) | |||
| end | |||
| --print("ship is hit") | |||
| 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 | |||
| function menu.draw(dt) | |||
| @@ -44,7 +55,19 @@ function menu.draw(dt) | |||
| else | |||
| love.graphics.setFont(titlefont) | |||
| 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) | |||
| 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 | |||
| end | |||
| end | |||
| @@ -4,6 +4,7 @@ local M = {} | |||
| local currenctScore = 0 | |||
| function practice.update(dt) | |||
| if not pauseStatus then | |||
| if not levelLoaded then | |||
| shipsleft = 1 | |||
| planetsleft = 10 | |||
| @@ -38,6 +39,7 @@ function practice.update(dt) | |||
| levelLoaded = true | |||
| end | |||
| camera:update(dt) | |||
| --print(camera.x .. " " .. camera.y) | |||
| for i, explosion in ipairs(explosions) do | |||
| explosion:update(dt) | |||
| @@ -63,7 +65,7 @@ function practice.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 | |||
| 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 | |||
| for i in ipairs(cannons) do | |||
| @@ -83,8 +85,9 @@ else | |||
| camera:follow(VCAM.x, VCAM.y) | |||
| end | |||
| practice.GUIControl() | |||
| else | |||
| settingsMenuUpdate(dt) | |||
| end | |||
| end | |||
| function practice.draw() | |||
| @@ -118,15 +121,17 @@ function practice.draw() | |||
| 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) | |||
| practice.hint() | |||
| elseif gameStatus == "play" then | |||
| elseif gameStatus == "play" and not pauseStatus then | |||
| local textW = tinyfont:getWidth("Score: " .. math.floor(currentScore/100)) | |||
| love.graphics.setFont(tinyfont) | |||
| 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) | |||
| love.keyboard.mouseisReleased = false | |||
| end | |||
| if pauseStatus then | |||
| drawPauseMenu() | |||
| love.keyboard.mouseisReleased = false | |||
| end | |||
| end | |||
| @@ -142,6 +147,9 @@ function practice.reset() | |||
| firstShip:reset() | |||
| camera.scale = 1 | |||
| projectiles = {} | |||
| for i in ipairs(cannons) do | |||
| cannons[i].timer = cannons[i].otimer | |||
| end | |||
| shipsleft = 1 | |||
| if currentScore > saveData.score then | |||
| @@ -18,7 +18,7 @@ saveData = { | |||
| levelsBeaten = 0, | |||
| score = 0 | |||
| } | |||
| mainsettings = {} | |||
| planets = {} | |||
| buttons = {} | |||
| cannons = {} | |||
| @@ -33,7 +33,17 @@ function love.wheelmoved(x, y) | |||
| 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() | |||
| love.graphics.setLineWidth(4) | |||
| print(love.filesystem.getAppdataDirectory()) | |||
| print(love.filesystem.getSaveDirectory()) | |||
| print(love.filesystem.areSymlinksEnabled()) | |||
| @@ -24,8 +24,10 @@ If you're on arch, install the prerequisites with: | |||
| `` | |||
| Changelog: | |||
| Changelog history: | |||
| - Changed practice scoring system | |||
| - Fixed bug with cannon timers not resetting | |||
| - Toggle music button added | |||
| - Added the pause menu | |||
| - Volume slider added | |||
| - Made trail **wider** | |||
| @@ -9,7 +9,7 @@ function buttonClutter() | |||
| function() | |||
| gameState = "selectlv" | |||
| end)) | |||
| table.insert(buttons, menu:addButton("Toggle Fullscreen", | |||
| table.insert(mainsettings, menu:addButton("Toggle Fullscreen", | |||
| function() | |||
| myscreen:toggle(WINDOW_HEIGHT, WINDOW_WIDTH) | |||
| DIFFERENCE_X = myscreen.c | |||
| @@ -17,9 +17,13 @@ function buttonClutter() | |||
| OFFSET_X = myscreen.e | |||
| OFFSET_Y = myscreen.f | |||
| 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() | |||
| toggleMusic() | |||
| menuMode = "settings" | |||
| end | |||
| )) | |||
| @@ -8,6 +8,7 @@ require 'entities/planet/planet' | |||
| require 'src/buttonClutter' | |||
| require 'entities/explosion/explosion' | |||
| require 'src/GUI' | |||
| require 'src/simple-slider' | |||
| require 'src/pauseMenu' | |||
| require 'src/stateMachine' | |||
| require 'entities/base/base' | |||
| @@ -1,6 +1,9 @@ | |||
| pauseStatus = false | |||
| pauseState = "main" | |||
| pauseMenu = {} | |||
| settings = {} | |||
| 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", | |||
| function() | |||
| pauseStatus = false | |||
| @@ -12,7 +15,7 @@ function() | |||
| goBack() | |||
| end | |||
| )) | |||
| table.insert(pauseMenu, menu:addButton("Toggle Fullscreen", | |||
| table.insert(settings, menu:addButton("Toggle Fullscreen", | |||
| function() | |||
| myscreen:toggle(WINDOW_HEIGHT, WINDOW_WIDTH) | |||
| DIFFERENCE_X = myscreen.c | |||
| @@ -21,9 +24,14 @@ function() | |||
| OFFSET_Y = myscreen.f | |||
| end | |||
| )) | |||
| table.insert(pauseMenu, menu:addButton("Toggle Music", | |||
| table.insert(settings, menu:addButton("back", | |||
| function() | |||
| toggleMusic() | |||
| pauseState = "main" | |||
| end | |||
| )) | |||
| table.insert(pauseMenu, menu:addButton("Settings", | |||
| function() | |||
| pauseState = "settings" | |||
| end | |||
| )) | |||
| table.insert(pauseMenu, menu:addButton("Quit", | |||
| @@ -34,5 +42,30 @@ end | |||
| end | |||
| function drawPauseMenu() | |||
| -- print("draw") | |||
| if pauseState == "main" then | |||
| 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 | |||