@@ -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 |