diff --git a/love2d/data/map/tutorial1.ini b/love2d/data/map/tutorial1.ini new file mode 100644 index 0000000..b0f4a5e --- /dev/null +++ b/love2d/data/map/tutorial1.ini @@ -0,0 +1,28 @@ +map = { + width = 11, + height = 11, + baseX = 3, + baseY = 5, + spawn = { + { + enemyType = 1, + towerType = 7, + x = 10, + y = 10, + delay = 1, + count = 10 + }, + }, + tower = { + { + towerType = 8, + x = 1, + y = 3, + }, + + }, + random = { + }, + mass = 10, + energy = 999 +} \ No newline at end of file diff --git a/love2d/data/menu/missions1.ini b/love2d/data/menu/missions1.ini index 6d31878..502f2ef 100644 --- a/love2d/data/menu/missions1.ini +++ b/love2d/data/menu/missions1.ini @@ -1,25 +1,37 @@ missions = { { - map = "mission1", + map = "tutorial1", x = 300, y = 130, + title = "Tutorial 1", + description = "Tutorial 1.\n\nMapsize: Small", + briefingText = "These aliens seem to be carrying explosives that they want to carry into our main generator. Prevent them from doing so by building laser towers!", + button = "T", + }, + { + map = "mission1", + x = 370, + y = 190, title = "Mission 1", description = "Defeat 3 Wave lines\nwith 2 different enemies.\n\nMapsize: Small", + button = "1" }, { map = "mission2", - x = 370, - y = 190, + x = 410, + y = 260, needMission = "mission1", title = "Mission 2", description = "Defeat 3 Wave lines\nwith 2 different enemies.\n\nMapsize: Medium", + button = "2", }, { map = "mission3", - x = 420, - y = 270, + x = 410, + y = 320, needMission = "mission2", title = "Mission 3", description = "Defeat 4 Wave lines\nwith 2 different enemies.\n\nMapsize: Small", + button = "3", }, } \ No newline at end of file diff --git a/love2d/enemy.lua b/love2d/enemy.lua index 124396b..210f01e 100644 --- a/love2d/enemy.lua +++ b/love2d/enemy.lua @@ -64,6 +64,10 @@ function love.turris.newEnemy(enemyType, map, x, y, baseX, baseY) o.update = function(dt) o.ai.update(dt) end + + o.getBaseDamage = function() + return o.enemyType.baseDamage + end o.updateVelocity = function(dirX, dirY) o.xVel = dirX * o.speed @@ -137,7 +141,8 @@ function love.turris.updateEnemies(o, dt) -- TODO: destroy base (explosion!) -- TODO: after explosions have finished -> transition to game over state love.sounds.playSound("sounds/einschlag.mp3") - turMap.data[o.baseX][o.baseY].addHealth(-5) --TODO: Each creep does different damage to the base + local damage = e.getBaseDamage() + turMap.data[o.baseX][o.baseY].addHealth(-damage) --TODO: Each creep does different damage to the base, see issue #87 turGame.effectTimer = 0 gameOverEffect = 0 diff --git a/love2d/enemyType.lua b/love2d/enemyType.lua index 8ff5698..877ae56 100644 --- a/love2d/enemyType.lua +++ b/love2d/enemyType.lua @@ -4,6 +4,15 @@ function love.turris.newEnemyType(id, sheet, maxHealth, baseSpeed) o.sheet = sheet o.maxHealth = maxHealth o.baseSpeed = baseSpeed + + if o.id==1 then + o.baseDamage = 12 + elseif o.id==2 then + o.baseDamage = 30 + else + print ("warning: unknown creep id: ", o.id) + end + o.playDeathSound = function() if o.id == 1 then love.sounds.playSound("sounds/phaser_rotating.mp3") diff --git a/love2d/game.lua b/love2d/game.lua index 8a7a8d3..bdb990d 100644 --- a/love2d/game.lua +++ b/love2d/game.lua @@ -91,8 +91,8 @@ function love.turris.newGame() massTower.setMassGeneration(5) o.map.init() - - o.player.setMass(20) + o.player.setEnergy(o.map.energy or 20) + o.player.setMass(o.map.mass or 20) o.imgLaser = G.newImage("gfx/laserbeam_blue.png") o.imgLaser:setWrap("repeat", "repeat") @@ -121,6 +121,8 @@ function love.turris.newGame() o.layerGameOver = require("layer/gameover") o.layerWin = require("layer/win") o.layerCountdown = require("layer/countdown") + o.layerMissionBriefing = require("layer/missionBriefing") + o.update(0.001) end -- gameplay @@ -338,9 +340,9 @@ function love.turris.newGame() if energyCost <= o.player.energy then local e = t.determineTarget(o.enemies, distance_euclid) t.target = e --TODO just do that inside tower module - + if e then - laserVolume = laserVolume + 0.25 + laserVolume = laserVolume + 0.45 o.player.addEnergy(-energyCost) if e.health > 0.0 then e.health = e.health - t.type.damage*dt @@ -361,8 +363,8 @@ function love.turris.newGame() -- test --TODO: -> player.update --- o.player.addMass(dt*2) --- o.player.addEnergy(dt*5) + -- o.player.addMass(dt*2) + -- o.player.addEnergy(dt*5) end --------------------- drawing starts here diff --git a/love2d/layer/gameover.lua b/love2d/layer/gameover.lua index 5b266f3..47ccdd8 100644 --- a/love2d/layer/gameover.lua +++ b/love2d/layer/gameover.lua @@ -20,7 +20,6 @@ o.draw = function() G.printf("Game Over!", 0, 240, W.getWidth(), "center") G.setColor(255, 255, 255, 127) G.printf("Click to go to the main menu", 0, 320, W.getWidth(), "center") - --love.setgamestate(4) end end diff --git a/love2d/layer/missionBriefing.lua b/love2d/layer/missionBriefing.lua new file mode 100644 index 0000000..284662c --- /dev/null +++ b/love2d/layer/missionBriefing.lua @@ -0,0 +1,30 @@ +local o = {} + +o.text = "" + +o.guiMenu = love.gui.newGui() +o.init = function(mission) + o.text = mission.briefingText or mission.description + o.btnOkay = o.guiMenu.newButton(W.getWidth()/2, W.getHeight()*0.75, 66, 42, "OK") + o.mission = mission +end + +o.update = function(dt) + o.guiMenu.update(dt) + if o.btnOkay.isHit() then + love.sounds.playSound("sounds/button_pressed.wav") + love.setgamestate(14, o.mission) + o.guiMenu.flushMouse() + end +end + +o.draw = function() + G.setFont(FONT) + G.setColor(255, 127, 0, 127) + local scale = 1---(o.countdown-o.oldcountdown)/2 + G.printf(o.text, 0, 240, W.getWidth(), "center",0,scale,scale) + G.setColor(255, 255, 255, 127) + o.guiMenu.draw() +end + +return o \ No newline at end of file diff --git a/love2d/layer/win.lua b/love2d/layer/win.lua index 05ddc0e..1484649 100644 --- a/love2d/layer/win.lua +++ b/love2d/layer/win.lua @@ -20,8 +20,7 @@ o.draw = function() G.printf("Stage clear!", 0, 240, W.getWidth(), "center") G.setColor(255, 255, 255, 127) G.printf("Click to go to the main menu", 0, 320, W.getWidth(), "center") - --love.setgamestate(4) - end + end end return o \ No newline at end of file diff --git a/love2d/main.lua b/love2d/main.lua index 4bfb270..39f9340 100644 --- a/love2d/main.lua +++ b/love2d/main.lua @@ -22,6 +22,7 @@ require "util" -- states stateMainMenu = require("state/main_menu") stateIntro = require("state/intro") +stateOutro = require("state/outro") stateWorldMenu = require("state/world_menu") stateCredits = require("state/credits") stateSettings = require("state/settings_menu") @@ -49,14 +50,13 @@ function love.load() S = love.sounds FS = love.filesystem loadOptions() - --saveOptions() --TODO temporarily added for testing FONT = G.newFont(32) FONT_LARGE = G.newFont(64) FONT_SMALL = G.newFont(24) currentgamestate = 12 -- TODO: make "skip intro" an option - stateMainMenu.setVersion("v0.6.4") + stateMainMenu.setVersion("v0.6.5") end function love.getgamestate() @@ -86,18 +86,22 @@ function love.setgamestate(newgamestate, option) love.sounds.playBackground("sounds/music/Chiptune_2step_mp3.mp3", "menu") elseif newgamestate == 1 then turGame.layerGameOver.effectTimer = 0 - --love.sounds.playBackground("sounds/music/turres_music_1.mp3", "menu") + love.sounds.playBackground("sounds/music/turres_music_1.mp3", "menu") love.sounds.loopSound("sounds/weapons/laser_loop.ogg") love.sounds.setSoundVolume(0,"sounds/weapons/laser_loop.ogg") - - elseif newgamestate == 4 or newgamestate == 13 then + elseif newgamestate == 4 then turGame.layerGameOver.effectTimer = 0 love.sounds.playBackground("sounds/music/game_over_music.mp3", "game") + elseif newgamestate == 13 then + turGame.layerGameOver.effectTimer = 0 + love.sounds.playBackground("sounds/music/level_up.mp3", "game") elseif newgamestate == 11 then stateWorldMenu.init() elseif newgamestate == 14 then - love.turris.reinit(option) turGame.layerCountdown.init() + elseif newgamestate == 16 then + love.turris.reinit(option.map) + turGame.layerMissionBriefing.init(option) end if currentgamestate == 5 then @@ -135,6 +139,10 @@ function love.update(dt) turGame.layerWin.update(dt) elseif (currentgamestate == 14)then turGame.layerCountdown.update(dt) + elseif (currentgamestate == 15)then + stateOutro.update(dt) + elseif (currentgamestate == 16)then + turGame.layerMissionBriefing.update(dt) end TEsound.cleanup() --Important, Clears all the channels in TEsound end @@ -178,6 +186,11 @@ function love.draw() elseif currentgamestate == 14 then --countdown turGame.draw() turGame.layerCountdown.draw() + elseif currentgamestate == 15 then --outro + stateOutro.draw() + elseif (currentgamestate == 16)then + turGame.draw() + turGame.layerMissionBriefing.draw() end if stateSettingsVideoShaders.optionScanlines then diff --git a/love2d/map.lua b/love2d/map.lua index 7f3eb54..4384b3c 100644 --- a/love2d/map.lua +++ b/love2d/map.lua @@ -12,6 +12,8 @@ function love.turris.newMap(path) o.spawn = map.spawn o.tower = map.tower o.random = map.random + o.energy = map.energy + o.mass = map.mass if map.ground then o.groundColor = map.ground.color o.groundImg = map.ground.img or "ground01" diff --git a/love2d/player.lua b/love2d/player.lua index fb19d52..778f391 100644 --- a/love2d/player.lua +++ b/love2d/player.lua @@ -2,8 +2,8 @@ function love.turris.newPlayer() local o = {} - o.mass = 20 - o.energy = 20 + o.mass = 99999 + o.energy = 99999 o.addMass = function(mass) o.mass = o.mass + mass diff --git a/love2d/sounds/music/level_up.mp3 b/love2d/sounds/music/level_up.mp3 new file mode 100644 index 0000000..91a4661 Binary files /dev/null and b/love2d/sounds/music/level_up.mp3 differ diff --git a/love2d/state/intro.lua b/love2d/state/intro.lua index 4c53025..411e414 100644 --- a/love2d/state/intro.lua +++ b/love2d/state/intro.lua @@ -11,7 +11,7 @@ o.vertBackground0 = { o.mshBackground0 = love.graphics.newMesh(o.vertBackground0, o.imgBackground0, "fan") o.imgBackground1 = love.graphics.newImage("gfx/love_logo.png") o.imgBackground2 = love.graphics.newImage("gfx/world.png") -o.phase = 1 +o.phase = 2 o.fontTitle = love.graphics.newFont(20) @@ -25,74 +25,37 @@ o.update = function(dt) o.gui.update(dt) o.showTimer = o.showTimer + dt - if (o.phase == 1)then - if o.gui.isHit() or love.keyboard.isDown("escape") or (o.showTimer > 4) then - o.showTimer = 0 - o.phase = 2 - end - elseif o.phase == 2 then - o.effectTimer = o.effectTimer + dt - o.chromaticEffect = o.chromaticEffect + dt - if o.gui.isHit() or love.keyboard.isDown("escape") or(o.showTimer > 4) then - o.gui.flushMouse() - love.setgamestate(0) - end + o.effectTimer = o.effectTimer + dt + o.chromaticEffect = o.chromaticEffect + dt + if o.gui.isHit() or love.keyboard.isDown("escape") or(o.showTimer > 30) then + o.gui.flushMouse() + love.setgamestate(0) end end -local quoterandomizer = love.math.newRandomGenerator(os.time()*os.clock()) -for i=1,20 do -- the value 1 will be considered sufficiently random otherwise - quoterandomizer:random() -end -local quotes ={"War...war never changes.","Fallout","Always put a tower where the creeps want to go!","The Art Of Tower Defense","Haskell <3", "???", - "How about I always give you the same random number?","love.math.random()","Thou shalt not pass through my towers, foul creatures!","William S.", - "Please stand by while we think of more quotes...","the developers","Fallback quote. It's not a bug, it's a feature.", "Unknown Programmer", - "Please use data-driven development ;-)","Nicolai"} --TODO: next step is to get these from an external file -local quoteno = quoterandomizer:random(1,#quotes/2) -- The second value will always have to be as high as the amount of quotes (the random number is not perfect, though) -local quoteIndex = 1+(quoteno-1)*2 -o.quote = quotes[quoteIndex] -o.source = quotes[quoteIndex+1] +o.quote = "Commander! Can you hear me? This is Station Alpha Z-031 on Mining Colony Monaco XIV. We are under siege. I repeat: We are under siege." +o.quote = o.quote.. " The colony is being attacked by a massive fleet of alien ships. Requesting immediate backup." +o.quote = o.quote .." We don't have much time. Other stations are sending out distress calls as well. Please save us." +o.source = "" o.draw = function() - if o.phase == 1 then - o.vertBackground0 = { - { 0, 0, -o.showTimer * 0.1, -o.showTimer * 0.2, 255, 255, 255, 63 }, - { love.window.getWidth(), 0, love.window.getWidth() / o.imgBackground0:getWidth() - o.showTimer * 0.1, -o.showTimer * 0.2, 255, 255, 255, 63 }, - { love.window.getWidth(), love.window.getHeight(), love.window.getWidth() / o.imgBackground0:getWidth() - o.showTimer * 0.1, love.window.getHeight() / o.imgBackground0:getHeight() - o.showTimer * 0.2, 255, 255, 255, 127 }, - { 0, love.window.getHeight(), - o.showTimer * 0.1, love.window.getHeight() / o.imgBackground0:getHeight() - o.showTimer * 0.2, 255, 255, 255, 127 }, - } - o.mshBackground0:setVertices(o.vertBackground0) - love.graphics.setBlendMode("alpha") - love.graphics.setColor(131, 192, 240) - love.graphics.rectangle("fill", 0, 0, love.window.getWidth(), love.window.getHeight()) - love.graphics.setColor(255, 255, 255) - love.graphics.draw(o.mshBackground0) - love.graphics.setColor(255, 255, 255) - local sx = love.window.getWidth() * 0.5 - o.imgBackground1:getWidth() * 0.5 - local sy = love.window.getHeight() * 0.5 - o.imgBackground1:getHeight() * 0.5 - love.graphics.draw(o.imgBackground1, sx, sy) - love.graphics.setFont(o.fontTitle) - love.graphics.setColor(63, 63, 63) - love.graphics.printf("Created with:", 0, love.window.getHeight() * 0.5 - o.imgBackground1:getHeight() - 8, love.window.getWidth(), "center") - elseif o.phase == 2 then - love.graphics.setColor(95 + math.sin(o.effectTimer * 0.1) * 63, 191 + math.cos(o.effectTimer) * 31, 223 + math.sin(o.effectTimer) * 31, 63) - love.graphics.draw(o.imgBackground2, love.window.getWidth() * 0.5 - o.imgBackground2:getWidth() * 0.5) + love.graphics.setColor(95 + math.sin(o.effectTimer * 0.1) * 63, 191 + math.cos(o.effectTimer) * 31, 223 + math.sin(o.effectTimer) * 31, 63) + love.graphics.draw(o.imgBackground2, love.window.getWidth() * 0.5 - o.imgBackground2:getWidth() * 0.5) - love.graphics.setColor(95 + math.sin(o.effectTimer * 0.1) * 63, 191 + math.cos(o.effectTimer) * 31, 223 + math.sin(o.effectTimer) * 31, 127) - love.graphics.setFont(o.fontTitle) - love.graphics.printf(o.quote, love.window.getWidth() * 0.5 - 128, love.window.getHeight() * 0.5 - 16, love.window.getWidth() * 0.5, "left") - love.graphics.printf(o.source, love.window.getWidth() * 0.5 + 64, love.window.getHeight() * 0.5 + 16, love.window.getWidth() * 0.5, "left") + love.graphics.setColor(95 + math.sin(o.effectTimer * 0.1) * 63, 191 + math.cos(o.effectTimer) * 31, 223 + math.sin(o.effectTimer) * 31, 127) + love.graphics.setFont(o.fontTitle) + love.graphics.printf(o.quote, love.window.getWidth() * 0.5 - 128, love.window.getHeight() * 0.5 - 16, love.window.getWidth() * 0.5, "left") + love.graphics.printf(o.source, love.window.getWidth() * 0.5 + 64, love.window.getHeight() * 0.5 + 16, love.window.getWidth() * 0.5, "left") - if math.random(0, love.timer.getFPS() * 8) == 0 then - o.chromaticEffect = math.random(0, 5) * 0.1 - end + if math.random(0, love.timer.getFPS() * 8) == 0 then + o.chromaticEffect = math.random(0, 5) * 0.1 + end - if o.chromaticEffect < 1.0 then - local colorAberration1 = math.sin(love.timer.getTime() * 10.0) * (1.0 - o.chromaticEffect) * 2.0 - local colorAberration2 = math.cos(love.timer.getTime() * 10.0) * (1.0 - o.chromaticEffect) * 2.0 + if o.chromaticEffect < 1.0 then + local colorAberration1 = math.sin(love.timer.getTime() * 10.0) * (1.0 - o.chromaticEffect) * 2.0 + local colorAberration2 = math.cos(love.timer.getTime() * 10.0) * (1.0 - o.chromaticEffect) * 2.0 - love.postshader.addEffect("chromatic", colorAberration1, colorAberration2, colorAberration2, -colorAberration1, colorAberration1, -colorAberration2) - end + love.postshader.addEffect("chromatic", colorAberration1, colorAberration2, colorAberration2, -colorAberration1, colorAberration1, -colorAberration2) end end diff --git a/love2d/state/main_menu.lua b/love2d/state/main_menu.lua index ba4d4e5..d7109f9 100644 --- a/love2d/state/main_menu.lua +++ b/love2d/state/main_menu.lua @@ -51,7 +51,7 @@ o.update = function(dt) if o.btnQuit.isHit() then love.sounds.playSound("sounds/button_pressed.wav") - love.event.quit() + love.setgamestate(15) end end diff --git a/love2d/state/outro.lua b/love2d/state/outro.lua new file mode 100644 index 0000000..564acac --- /dev/null +++ b/love2d/state/outro.lua @@ -0,0 +1,57 @@ +local o = {} + +o.imgBackground0 = love.graphics.newImage("gfx/love_bg.png") +o.imgBackground0:setWrap("repeat", "repeat") +o.vertBackground0 = { + { 0, 0, 0, 0, 255, 255, 255, 63 }, + { love.window.getWidth(), 0, love.window.getWidth() / o.imgBackground0:getWidth(), 0, 255, 255, 255, 63 }, + { love.window.getWidth(), love.window.getHeight(), love.window.getWidth() / o.imgBackground0:getWidth(), love.window.getHeight() / o.imgBackground0:getHeight(), 255, 255, 255, 127 }, + { 0, love.window.getHeight(), 0, love.window.getHeight() / o.imgBackground0:getHeight(), 255, 255, 255, 127 }, +} +o.mshBackground0 = love.graphics.newMesh(o.vertBackground0, o.imgBackground0, "fan") +o.imgBackground1 = love.graphics.newImage("gfx/love_logo.png") +o.imgBackground2 = love.graphics.newImage("gfx/world.png") +o.phase = 1 + +o.fontTitle = love.graphics.newFont(20) + +o.effectTimer = 0 +o.chromaticEffect = 0 +o.showTimer = 0 + +o.gui = love.gui.newGui() + +o.update = function(dt) + o.gui.update(dt) + + o.showTimer = o.showTimer + dt + if o.gui.isHit() or love.keyboard.isDown("escape") or (o.showTimer > 4) then + o.showTimer = 0 + love.event.quit() + end +end + + +o.draw = function() + o.vertBackground0 = { + { 0, 0, -o.showTimer * 0.1, -o.showTimer * 0.2, 255, 255, 255, 63 }, + { love.window.getWidth(), 0, love.window.getWidth() / o.imgBackground0:getWidth() - o.showTimer * 0.1, -o.showTimer * 0.2, 255, 255, 255, 63 }, + { love.window.getWidth(), love.window.getHeight(), love.window.getWidth() / o.imgBackground0:getWidth() - o.showTimer * 0.1, love.window.getHeight() / o.imgBackground0:getHeight() - o.showTimer * 0.2, 255, 255, 255, 127 }, + { 0, love.window.getHeight(), - o.showTimer * 0.1, love.window.getHeight() / o.imgBackground0:getHeight() - o.showTimer * 0.2, 255, 255, 255, 127 }, + } + o.mshBackground0:setVertices(o.vertBackground0) + love.graphics.setBlendMode("alpha") + love.graphics.setColor(131, 192, 240) + love.graphics.rectangle("fill", 0, 0, love.window.getWidth(), love.window.getHeight()) + love.graphics.setColor(255, 255, 255) + love.graphics.draw(o.mshBackground0) + love.graphics.setColor(255, 255, 255) + local sx = love.window.getWidth() * 0.5 - o.imgBackground1:getWidth() * 0.5 + local sy = love.window.getHeight() * 0.5 - o.imgBackground1:getHeight() * 0.5 + love.graphics.draw(o.imgBackground1, sx, sy) + love.graphics.setFont(o.fontTitle) + love.graphics.setColor(63, 63, 63) + love.graphics.printf("Created with:", 0, love.window.getHeight() * 0.5 - o.imgBackground1:getHeight() - 8, love.window.getWidth(), "center") +end + +return o \ No newline at end of file diff --git a/love2d/state/world_menu.lua b/love2d/state/world_menu.lua index ac845d1..4f0ac21 100644 --- a/love2d/state/world_menu.lua +++ b/love2d/state/world_menu.lua @@ -30,7 +30,7 @@ o.init = function() o.description = {} for i = 1, #missions do - o.btnStage[i] = o.guiMenu.newButton(o.startx + missions[i].x, missions[i].y, 34, 34, i) + o.btnStage[i] = o.guiMenu.newButton(o.startx + missions[i].x, missions[i].y, 34, 34, missions[i].button or "") o.description[i] = {missions[i].title, missions[i].description} local locked = true @@ -64,7 +64,7 @@ o.update = function(dt) for i = 1, #o.btnStage do if o.btnStage[i].isHit() then love.sounds.playSound("sounds/button_pressed.wav") - love.setgamestate(14, missions[i].map) + love.setgamestate(16, missions[i]) o.guiMenu.flushMouse() end end diff --git a/love2d/world.lua b/love2d/world.lua index 924b7a8..3ec12b1 100644 --- a/love2d/world.lua +++ b/love2d/world.lua @@ -21,14 +21,12 @@ function love.turris.checkleftclick(clickx,clicky) currentgstate = love.getgamestate() if currentgstate == 1 then --ingame if turGame.layerHud.guiGame.hover then - --love.setgamestate(0) local clickedfieldx, clickedfieldy = getclickedfield(clickx, clicky) turGame.addTower(clickedfieldx, clickedfieldy, love.turris.selectedtower) end elseif currentgstate == 4 or currentgstate == 13 then --game over love.turris.gameoverstate() elseif currentgstate == 5 then --credits - --love.setgamestate(0) end end