From 2209ae983408f0c43005e00ea2d7a5122a1607be Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:31:14 -0800 Subject: [PATCH 01/65] Update index.html --- index.html | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/index.html b/index.html index 29a9360..b83b732 100644 --- a/index.html +++ b/index.html @@ -1105,16 +1105,6 @@ var extension = Modernizr.audio.ogg ? 'ogg' : 'mp3'; - var audio_files = [ - ["start", root + "audio/opening_song." + extension], - ["die", root + "audio/die." + extension], - ["eatghost", root + "audio/eatghost." + extension], - ["eatpill", root + "audio/eatpill." + extension], - ["eating", root + "audio/eating.short." + extension], - ["eating2", root + "audio/eating.short." + extension] - ]; - - load(audio_files, function() { loaded(); }); }; function load(arr, callback) { From 06d38c13aecc375c1740f74d577367589770990b Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:33:51 -0800 Subject: [PATCH 02/65] Create tetris.html --- tetris.html | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 tetris.html diff --git a/tetris.html b/tetris.html new file mode 100644 index 0000000..fd8cb85 --- /dev/null +++ b/tetris.html @@ -0,0 +1,319 @@ + + + + Basic Tetris HTML Game + + + + + + + + From 1bbcfe92d6faa87ba906d514a738ae5509b43b22 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:35:44 -0800 Subject: [PATCH 03/65] Rename index.html to pacman.html --- index.html => pacman.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename index.html => pacman.html (100%) diff --git a/index.html b/pacman.html similarity index 100% rename from index.html rename to pacman.html From 48cf960d36b2f897372ae305a827a2dc068eba77 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:36:19 -0800 Subject: [PATCH 04/65] Create index.html --- index.html | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000..f55e3a0 --- /dev/null +++ b/index.html @@ -0,0 +1,56 @@ + + +
+

HTML Unlocked

+ + + + +
+ + Mainpage + + + + Play Tetrisr + + +
 + +
+ + Mainpage + + + + Play Pacman + + +
 +
 From 051b2a142f1657031fddf01e8f532e329f7a5563 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:38:17 -0800 Subject: [PATCH 05/65] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index f55e3a0..a7f819c 100644 --- a/index.html +++ b/index.html @@ -25,7 +25,7 @@

HTML Unlocked

- Play Tetrisr + Play Tetris 
 From d10fc188c8935b108c47f00384deeafe0d33c030 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:40:50 -0800 Subject: [PATCH 06/65] Update pacman.html --- pacman.html | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pacman.html b/pacman.html index b83b732..ed8b6bc 100644 --- a/pacman.html +++ b/pacman.html @@ -1105,6 +1105,16 @@ var extension = Modernizr.audio.ogg ? 'ogg' : 'mp3'; + var audio_files = [ + ["start", root + "audio/opening_song." + extension], + ["die", root + "audio/die." + extension], + ["eatghost", root + "audio/eatghost." + extension], + ["eatpill", root + "audio/eatpill." + extension], + ["eating", root + "audio/eating.short." + extension], + ["eating2", root + "audio/eating.short." + extension] + ]; + + load(audio_files, function() { loaded(); }); }; function load(arr, callback) { @@ -1322,3 +1332,4 @@ + From 670885ebb3aa05cf0654afc2b8fe24d89f0f2bf1 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:42:40 -0800 Subject: [PATCH 07/65] Update pacman.html --- pacman.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pacman.html b/pacman.html index ed8b6bc..0dc5126 100644 --- a/pacman.html +++ b/pacman.html @@ -1,7 +1,7 @@ - Consume + Maintenance - Moota.co + + + + + + + + + From 65f4d3793ffc4ad0ac0a291879516ee970a72c24 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:44:41 -0800 Subject: [PATCH 10/65] Create snake.html --- snake.html | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 snake.html diff --git a/snake.html b/snake.html new file mode 100644 index 0000000..5e79edf --- /dev/null +++ b/snake.html @@ -0,0 +1,169 @@ + + + + Basic Snake HTML Game + + + + + + + + From 8c2b1b6f517f46edcd68946e5e1571b81417b6e5 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:44:54 -0800 Subject: [PATCH 11/65] Rename breakout to breakout.html --- breakout => breakout.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename breakout => breakout.html (100%) diff --git a/breakout b/breakout.html similarity index 100% rename from breakout rename to breakout.html From 60cc19c200d66f6e9f2273da61273b85c0e5aae9 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:46:34 -0800 Subject: [PATCH 12/65] Create README.md --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ea700e6 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# I do not own any of these assest and sound files, they are being used for education reasons to learn about HTML5. Thank you From e14b0280b75ac20d620183c91106f8832e85f56e Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:47:58 -0800 Subject: [PATCH 13/65] Update index.html --- index.html | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/index.html b/index.html index a7f819c..b28f11c 100644 --- a/index.html +++ b/index.html @@ -54,3 +54,51 @@

HTML Unlocked


 
 + +
+ + Mainpage + + + + Play Snake + + + + + +
+ + Mainpage + + + + Play Breakout + + From 4ee73a63725727d93117a33c94cbc6352f817694 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 17 Dec 2021 12:51:15 -0800 Subject: [PATCH 14/65] Update breakout.html --- breakout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/breakout.html b/breakout.html index 0fb846d..1930c7a 100644 --- a/breakout.html +++ b/breakout.html @@ -1,7 +1,7 @@ - Gamedev Canvas Workshop - lesson 10: finishing up + Breakout From 5fa9938f3eac63cf11a55e47f159c7dcbbf51f4e Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Sun, 19 Dec 2021 12:09:07 -0800 Subject: [PATCH 15/65] Update breakout.html --- breakout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/breakout.html b/breakout.html index 1930c7a..361e5ec 100644 --- a/breakout.html +++ b/breakout.html @@ -6,7 +6,7 @@ - + + + +
+ + +
+ +
+
+ Loopy + Backtrack + Dash +
+ +
+

A fully featured tower defense game built with <canvas>.

+ +

Instructions

+

Build and upgrade turrets (which costs money and increases score) to kill creeps (which generates money and increases score). Experiment with the turrets; each has a special ability when fully upgraded.

+ +

Shortcuts

+
+
1
+
Build Laser / Upgrade damage
+ +
2
+
Build Missile / Upgrade rate
+ +
3
+
Build Tazer / Upgrade range
+ +
4
+
Build Mortar / Move
+ +
*
+
Sell
+ +
=
+
Fast forward
+ +
Esc
+
Deselect / Cancel / Pause
+ +
Enter
+
Send wave
+
+ + +
+
+ +
+

Loopy

+

Backtrack

+

Dash

+ +
    +
      +
        + +
          +
            +
              + + +
              + +
              +

              Canvas TD was originally created for 10k Apart 2010, a challenge to build a web app in 10 KiB or less. Finished in less than twelve days, it failed to receive any prizes, but was ranked high in community voting and generated a significant amount of Twitter activity. While lacking much in the way of instructions, it was fully featured and quite enjoyable, and can still be played here.

              + +

              After the contest ended, work was started on a rewrite. Completed in June 2011, it featured far better code, many UI improvements, new gameplay elements, and some real instructions. Technologies used include <canvas>, @font-face, the Twitter Search API, Web Storage, and many other HTML5/CSS3/ES5 features.

              + +

              The endless, increasingly difficult gameplay (and many other core elements) is inspired by Onslaught TD. The retro look is heavily based on the excellent BIT.TRIP games and Vector TD. I'd also like to thank Alex K. and David S. for their plentiful ideas, testing, feedback, and motivation.

              + + + + +
              +
              + +
              +
              + + +
              + + + + Move
              $90
              + +
              +
              + +
              + Game over! You scored .

              + Play again or view scores + (maybe tweet yours?) +
              +
              + +
              +
              + + +
              + +
              + Cash $35
              + Lives 10
              + Wave #1 +
              + +
              + 60FPS
              + Pause
              + Reset +
              +
              +
              + + + + + + + diff --git a/canvas-td-master/canvas-td-master/legacy.html b/canvas-td-master/canvas-td-master/legacy.html new file mode 100644 index 0000000..926612f --- /dev/null +++ b/canvas-td-master/canvas-td-master/legacy.html @@ -0,0 +1,4 @@ + + +Canvas TD +
              Choose map:
              Place and upgrade turrets (which cost money) to kill creeps (which give you money).
              FPS 60

              20s
              Cash $35
              Lives 10
              Wave #1
              Loading tweets...
              \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/defs.js b/canvas-td-master/canvas-td-master/scripts/defs.js new file mode 100644 index 0000000..941ad72 --- /dev/null +++ b/canvas-td-master/canvas-td-master/scripts/defs.js @@ -0,0 +1,269 @@ +var Defs = {}; + + +/////////////////////////////////////////////////////////////////////////////// +// Maps +/////////////////////////////////////////////////////////////////////////////// +Defs.maps = { + Loopy: [ + { x: 0, y: 70 }, + { x: 730, y: 70 }, + { x: 730, y: 430 }, + { x: 70, y: 430 }, + { x: 70, y: 160 }, + { x: 640, y: 160 }, + { x: 640, y: 340 }, + { x: 160, y: 340 }, + { x: 160, y: 250 }, + { x: 800, y: 250 } + ], + + Backtrack: [ + { x: 0, y: 170 }, + { x: 120, y: 170 }, + { x: 120, y: 415 }, + { x: 460, y: 415 }, + { x: 460, y: 185 }, + { x: 230, y: 185 }, + { x: 230, y: 70 }, + { x: 345, y: 70 }, + { x: 345, y: 300 }, + { x: 700, y: 300 }, + { x: 700, y: 0 } + ], + + Dash: [ + { x: 0, y: 250 }, + { x: 800, y: 250 } + ] +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Turrets +/////////////////////////////////////////////////////////////////////////////// +Defs.turrets = {}; + +Defs.turrets.upgrades = [25, 40, 75, 150, 250, 400, 500, 700, 900, 1000]; + +Defs.turrets.Laser = { + cost: 15, + damage: 10, + rate: 40, + range: 80, + upgrades: [ + { damage: 15, rate: 38, range: 85 }, + { damage: 25, rate: 36, range: 90 }, + { damage: 50, rate: 34, range: 95 }, + { damage: 75, rate: 32, range: 100 }, + { damage: 100, rate: 30, range: 105 }, + { damage: 150, rate: 28, range: 110 }, + { damage: 200, rate: 26, range: 120 }, + { damage: 400, rate: 25, range: 130 }, + { damage: 600, rate: 24, range: 140 }, + { damage: 1000, rate: 22, range: 160 } + ], + shoot: function (creeps) { + var creep = creeps[0]; + var _hp = creep.hp; + var turret = this; + + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + + if (turret.levels.full && Math.rand(9) === 0) { + var start = game.map[0]; + creep.x = start.x; + creep.y = start.y; + creep.nextpoint = 0; + } + + game.run.push({ what: function () { + canvas.lineCap = "round"; + canvas.lineWidth = 2; + canvas.strokeStyle = "#EE82EE"; + canvas.beginPath(); + canvas.moveTo(turret.x, turret.y); + canvas.lineTo(creep.x, creep.y); + canvas.stroke(); + }, until: 6 }); + } +}; + +Defs.turrets.Missile = { + cost: 25, + damage: 15, + rate: 60, + range: 120, + upgrades: [ + { damage: 20, rate: 57, range: 125 }, + { damage: 30, rate: 54, range: 130 }, + { damage: 40, rate: 51, range: 135 }, + { damage: 80, rate: 48, range: 140 }, + { damage: 120, rate: 45, range: 145 }, + { damage: 220, rate: 42, range: 150 }, + { damage: 320, rate: 40, range: 160 }, + { damage: 450, rate: 38, range: 170 }, + { damage: 600, rate: 36, range: 180 }, + { damage: 800, rate: 33, range: 200 } + ], + cell: 0, + shoot: function (creeps) { + var creep = creeps[Math.rand(creeps.length - 1)]; + var cell = this.cell % 4; + var missile = { x: this.x + (cell % 2 === 0 ? -5 : 5), y: this.y + (cell < 2 ? -5 : 5) }; + var turret = this; + + game.run.push({ what: function () { + if (creep.hp <= 0) { + var creeps = game.creeps.filter(function () { return true; }); + + if (creeps.length) { + creep = creeps[Math.rand(creeps.length - 1)]; + } else { + return false; + } + } + + if (Math.move(missile, creep, 3)) { + if (turret.levels.full) { + game.creeps.forEach(function (c) { + if (Math.inRadius(creep, c, 20)) { + var _hp = c.hp; + if ((c.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + } + }); + + game.run.push({ what: function () { + canvas.fillStyle = "#FF0"; + canvas.beginPath(); + canvas.moveTo(creep.x, creep.y); + canvas.arc(creep.x, creep.y, 20, 0, Math.PI * 2, true); + canvas.fill(); + }, until: 3 }); + } else { + var _hp = creep.hp; + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + } + + return false; + } else { + canvas.fillStyle = "#FFF"; + canvas.fillRect(missile.x - 2, missile.y - 2, 4, 4); + } + }, until: Infinity }); + + turret.cell++; + } +}; + +Defs.turrets.Tazer = { + cost: 40, + damage: 1, + rate: 40, + range: 60, + upgrades: [ + { damage: 5, rate: 38, range: 62 }, + { damage: 10, rate: 36, range: 64 }, + { damage: 15, rate: 34, range: 66 }, + { damage: 25, rate: 32, range: 68 }, + { damage: 50, rate: 30, range: 70 }, + { damage: 100, rate: 29, range: 75 }, + { damage: 200, rate: 28, range: 80 }, + { damage: 300, rate: 27, range: 85 }, + { damage: 400, rate: 26, range: 90 }, + { damage: 500, rate: 24, range: 100 } + ], + shoot: function (creeps) { + var creep = creeps.sort(function (a, b) { return b.speed - a.speed; })[0]; + var _hp = creep.hp; + var turret = this; + var speed = 0.9 - (turret.damage / 1000); + var slowfor = 60 + turret.damage; + + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + + creep.speed = creep.speed > speed ? speed : creep.speed; + creep.slowfor = turret.levels.full ? Infinity : (creep.slowfor < slowfor ? slowfor : creep.slowfor); + + game.run.push({ what: function () { + canvas.lineCap = "round"; + canvas.lineWidth = 3; + canvas.strokeStyle = "#00F"; + canvas.beginPath(); + canvas.moveTo(turret.x, turret.y); + canvas.lineTo(creep.x, creep.y); + canvas.stroke(); + canvas.strokeStyle = "#FFF"; + canvas.lineWidth = 2; + canvas.beginPath(); + canvas.moveTo(turret.x, turret.y); + canvas.lineTo(creep.x, creep.y); + canvas.stroke(); + }, until: 6 }); + } +}; + +Defs.turrets.Mortar = { + cost: 60, + damage: 50, + rate: 120, + range: 200, + upgrades: [ + { damage: 75, rate: 115, range: 205 }, + { damage: 100, rate: 110, range: 210 }, + { damage: 150, rate: 105, range: 215 }, + { damage: 250, rate: 100, range: 220 }, + { damage: 400, rate: 96, range: 225 }, + { damage: 600, rate: 92, range: 230 }, + { damage: 800, rate: 88, range: 235 }, + { damage: 1000, rate: 84, range: 240 }, + { damage: 1200, rate: 80, range: 245 }, + { damage: 1500, rate: 75, range: 250 } + ], + shoot: function (creeps) { + var creep = creeps[0]; + var turret = this; + var target = { x: creep.x / 1, y: creep.y / 1 }; + var shell = { x: turret.x / 1, y: turret.y / 1 }; + var radius = 25 + (turret.damage / 150); + + game.run.push({ what: function () { + if (Math.move(shell, target, 1.5)) { + game.creeps.forEach(function (creep) { + if (Math.inRadius(creep, target, radius)) { + var _hp = creep.hp; + + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + + if (turret.levels.full && !creep.burning) { + creep.burning = turret; + } + } + }); + + game.run.push({ what: function () { + canvas.fillStyle = "#FF0"; + canvas.beginPath(); + canvas.moveTo(target.x, target.y); + canvas.arc(target.x, target.y, radius, 0, Math.PI * 2, true); + canvas.fill(); + }, until: 3 }); + + return false; + } else { + canvas.fillStyle = "#808080"; + canvas.fillRect(shell.x - 3, shell.y - 3, 6, 6); + } + }, until: Infinity }); + } +}; \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/game.js b/canvas-td-master/canvas-td-master/scripts/game.js new file mode 100644 index 0000000..13530d5 --- /dev/null +++ b/canvas-td-master/canvas-td-master/scripts/game.js @@ -0,0 +1,230 @@ +var game = { + ticks: 0, + _ticks: 0, + _tick: 0, + ticker: -1, + run: [], + fast: false, + paused: true, + + wave: 0, + _wave: 0, + + creeps: [], + hp: 1, + hpinc: 1.3, + lives: 10, + + turrets: [], + spent: 0, + kills: 0, + cash: 35, + selection: false, + + tiles: {}, + + tick: function () { + /////////////////////////////////////////////////////////////////////////////// + // fps + /////////////////////////////////////////////////////////////////////////////// + if (game.ticks - game._ticks === 60) { + ui.fps.textContent = Math.round(60000 / (Date.now() - game._tick)); + game._tick = Date.now(); + game._ticks = game.ticks; + } + + + /////////////////////////////////////////////////////////////////////////////// + // wave + /////////////////////////////////////////////////////////////////////////////// + if ((game.ticks - game._wave) % 30 === 29) { + ui.timer.style.opacity = 1 - (((game.ticks - game._wave) / 60) * 0.05); + } + + if (game._wave + 1200 === game.ticks) { + ui.wave.textContent = ++game.wave; + + game.hpinc = { 10: 1.2, 25: 1.1, 50: 1.06, 100: 1.04, 150: 1.02, 200: 1.01 }[game.wave] || game.hpinc; + game.hp *= game.hpinc; + + for (var i = 1; i <= 10; i++) { + game.creeps.push({ + x: -(i * 20) - 10, + y: game.map[0].y, + offset: Math.rand(14), + nextpoint: 0, + speed: 1, + slowfor: 0, + hp: game.hp, + _hp: game.hp, + burning: false, + cash: game.wave + }); + } + + game._wave = game.ticks; + } + + + /////////////////////////////////////////////////////////////////////////////// + // map + /////////////////////////////////////////////////////////////////////////////// + canvas.fillStyle = "#000"; + canvas.fillRect(0, 0, 800, 500); + + var map = game.map.slice(1), start = game.map[0]; + canvas.lineWidth = 40; + canvas.strokeStyle = "#00F"; + canvas.beginPath(); + canvas.moveTo(start.x, start.y); + map.forEach(function (cur, i) { + canvas.lineTo(cur.x, cur.y); + }); + canvas.stroke(); + canvas.lineWidth = 30; + canvas.strokeStyle = "#004"; + canvas.beginPath(); + canvas.moveTo(start.x, start.y); + map.forEach(function (cur, i) { + canvas.lineTo(cur.x, cur.y); + }); + canvas.stroke(); + + + /////////////////////////////////////////////////////////////////////////////// + // creeps + /////////////////////////////////////////////////////////////////////////////// + game.creeps.forEach(function (creep, i, a) { + var _hp = creep.hp; + var burning = creep.burning; + + if (burning) { + creep.hp -= 30; + } + + if (creep.hp <= 0) { + if (_hp > 0) { + burning.kills++; + } + + game.kills++; + game.cash += creep.cash; + + delete a[i]; + + ui.action.refresh(); + } else if (creep.nextpoint === game.map.length) { + delete a[i]; + + ui.lives.textContent = --game.lives; + + if (!game.lives) { + game.end(); + } + } else { + if (--creep.slowfor <= 0) { + creep.speed = 1; + } + + var waypoint = game.map[creep.nextpoint]; + var hue = (creep.speed < 1 || burning) ? (burning ? (creep.speed < 1 ? 300 : 33) : 240) : 0; + var sat = 100 * (creep.hp / creep._hp); + + if (Math.move(creep, { x: waypoint.x - 7 + creep.offset, y: waypoint.y - 7 + creep.offset }, creep.speed)) { + creep.nextpoint++; + } + + canvas.fillStyle = "hsl(" + hue + "," + sat + "%,50%)"; + canvas.fillRect(creep.x - 5, creep.y - 5, 10, 10); + } + }); + + + /////////////////////////////////////////////////////////////////////////////// + // turrets + /////////////////////////////////////////////////////////////////////////////// + game.turrets.forEach(function (turret) { + if (turret.lastshot + turret.rate <= game.ticks) { + var creeps = game.creeps.filter(function (creep) { + return Math.inRadius(creep, turret, turret.range); + }); + + if (creeps.length > 0) { + turret.shoot(creeps); + turret.lastshot = game.ticks; + } + } + + canvas.drawImage(turret.img, turret.x - 12.5, turret.y - 12.5); + }); + + var selection = game.selection; + var turret = selection.turret; + if (selection) { + canvas.beginPath(); + canvas.fillStyle = selection.status === "selected" || selection.placeable ? "rgba(255, 255, 255, .3)" : "rgba(255, 0, 0, .3)"; + canvas.arc(turret.x, turret.y, turret.range, 0, Math.PI * 2, true); + canvas.fill(); + + canvas.drawImage(turret.img, turret.x - 12.5, turret.y - 12.5); + } + + + /////////////////////////////////////////////////////////////////////////////// + // finish + /////////////////////////////////////////////////////////////////////////////// + game.run.forEach(function (something, i, a) { + if (something.what() === false || --something.until === 0) { + delete a[i]; + } + }); + + game.ticks++; + }, + start: function () { + game._ticks = game.ticks; + game._tick = Date.now(); + game.ticker = window.setInterval(game.tick, 1000 / (game.fast ? 180 : 60)); + game.paused = false; + game.tick(); + }, + pause: function () { + window.clearInterval(game.ticker); + game.paused = true; + }, + end: function () { + game.pause(); + document.removeEventListener("keydown", ui.handleshortcuts, false); + window.removeEventListener("beforeunload", ui.handleunload, false); + + var map = game.map.name; + var kills = game.kills; + var spent = game.spent; + var score = kills * spent; + var text = score + " (" + kills + " kills, $" + spent + " spent)"; + var top = JSON.parse(localStorage.scores || '{"Loopy":[],"Backtrack":[],"Dash":[]}'); + var topmap = top[map]; + + if (score > (topmap.length === 5 && topmap[4].score)) { + topmap.splice(4, 1); + topmap.push({ score: score, kills: kills, spent: spent, date: Date.now() }); + topmap.sort(function (a, b) { return b.score - a.score; }); + localStorage.scores = JSON.stringify(top); + ui.action.scores(); + } + + $("control-score-text").textContent = text; + $("control-score-tweet").setAttribute("href", + "https://twitter.com/?status=" + window.encodeURIComponent("I scored " + text + " on " + map + " in #canvastd http://canvas-td.tkaz.ec/")); + + ui.panel("score"); + $("pages-overlay").style.display = "block"; + + _gaq.push(["_trackEvent", "Game", "End", map]); + _gaq.push(["_trackEvent", "Game", "Creeps killed", map, kills]); + _gaq.push(["_trackEvent", "Game", "Money spent", map, spent]); + _gaq.push(["_trackEvent", "Game", "Money available", map, game.cash]); + _gaq.push(["_trackEvent", "Game", "Turrets placed", map, game.turrets.length]); + _gaq.push(["_trackEvent", "Game", "Last FPS", map, Number(ui.fps.textContent)]); + } +}; \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/ui.js b/canvas-td-master/canvas-td-master/scripts/ui.js new file mode 100644 index 0000000..bc52be8 --- /dev/null +++ b/canvas-td-master/canvas-td-master/scripts/ui.js @@ -0,0 +1,429 @@ +/////////////////////////////////////////////////////////////////////////////// +// Global +/////////////////////////////////////////////////////////////////////////////// +document.addEventListener("dragstart", function (evt) { + if (evt.target.tagName === "IMG") { + evt.preventDefault(); + } +}, false); + +ui.bind("click", document.querySelectorAll("[data-page]"), function (evt) { + ui.page(this.getAttribute("data-page")); +}); + +ui.handleshortcuts = function (evt) { + if (!game.paused) { + switch (evt.keyCode) { + case 49: { + if (game.selection) { + ui.action.upgrade("damage"); + } else { + ui.action.build("Laser"); + } + break; + } + case 50: { + if (game.selection) { + ui.action.upgrade("rate"); + } else { + ui.action.build("Missile"); + } + break; + } + case 51: { + if (game.selection) { + ui.action.upgrade("range"); + } else { + ui.action.build("Tazer"); + } + break; + } + case 52: { + if (game.selection) { + ui.action.move(); + } else { + ui.action.build("Mortar"); + } + break; + } + case 56: { + if (evt.shiftKey && game.selection) { + ui.action.sell(); + } + break; + } + case 187: { + $("control-fast").click(); + break; + } + case 27: { + if (game.selection) { + ui.action.deselect(); + } else { + $("control-pause").click(); + } + break; + } + case 13: { + game._wave = game.ticks - 1200; + break; + } + } + } else { + if (evt.keyCode === 27) { + $("control-pause").click(); + } + } +}; + +ui.handleunload = function (e) { + return "A game is currently running, are you sure you want to close it?"; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Actions +/////////////////////////////////////////////////////////////////////////////// +ui.action.scores = function () { + var list = JSON.parse(localStorage.scores || "{}"); + + for (var map in list) { + var out = ""; + + list[map].forEach(function (r) { + out += '
            • ' + + '' + new Date(r.date).toDateString() + ' ' + + r.score + ' ☠' + r.kills + ' $' + r.spent + + '
            • '; + }); + + $("pages-scores-local-" + map.toLowerCase()).innerHTML = out; + } +}; + +ui.action.build = function (type) { + var tdata = Defs.turrets[type]; + var turret = { + x: -1000, + y: -1000, + levels: { + range: 0, + rate: 0, + damage: 0, + full: false + }, + kills: 0, + lastshot: 0, + img: document.querySelector("#control-turrets [data-name=" + type + "] img"), + id: game.turrets.length + }; + + for (var k in tdata) { + turret[k] = tdata[k]; + } + + game.selection = game.cash - tdata.cost >= 0 ? { + status: "placing", + turret: turret, + placeable: false + } : false; +}; + +ui.action.upgrade = function (stat) { + var turret = game.selection.turret; + var levels = turret.levels; + var level = levels[stat]; + var cost = Defs.turrets.upgrades[level]; + + if (game.selection.status === "selected" && cost && game.cash - cost >= 0) { + levels[stat]++; + turret[stat] = turret.upgrades[level][stat]; + levels.full = levels.damage === 10 && levels.rate === 10 && levels.range === 10; + turret.cost += cost; + game.cash -= cost; + game.spent += cost; + ui.action.refresh(); + } +}; + +ui.action.move = function () { + if (game.selection.status === "selected" && game.cash - 90 >= 0) { + var turret = game.selection.turret; + + game.selection = { + status: "moving", + turret: turret, + placeable: true + }; + + turret._x = turret.x; + turret._y = turret.y; + + var tx = (turret._x + 2.5) / 5, ty = (turret._y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = false; + } + } + + delete game.turrets[turret.id]; + } +}; + +ui.action.sell = function () { + var turret = game.selection.turret, value = Math.round(turret.cost * 0.7); + game.cash += value; + game.spent -= value; + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = false; + } + } + + ui.panel("turrets"); + game.selection = false; + delete game.turrets[turret.id]; + ui.action.refresh(); +}; + +ui.action.refresh = function () { + ui.cash.textContent = game.cash; + + if (game.selection) { + var turret = game.selection.turret; + var levels = turret.levels; + var costs = Defs.turrets.upgrades; + + ["Damage", "Rate", "Range"].forEach(function (proper) { + var id = proper.toLowerCase(); + var level = levels[id]; + var cost = costs[level] || ""; + $("control-manage-" + id).innerHTML = proper + " (" + level + ")
              " + (cost && "$" + cost); + }); + + $("control-manage-sell").innerHTML = "Sell
              $" + Math.round(turret.cost * 0.7); + + $("control-manage-stats").innerHTML = turret.kills + " kills
              " + (((turret.kills / game.kills) || 0) * 100).toFixed(2) + "% of ∑"; + } +}; + +ui.action.deselect = function () { + if (game.selection.status === "moving") { + var turret = game.selection.turret; + game.turrets[turret.id] = turret; + + turret.x = turret._x; + turret.y = turret._y; + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; + } + } + } + + game.selection = false; + + ui.panel("turrets"); +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Canvas +/////////////////////////////////////////////////////////////////////////////// +var canvas = $("pages-canvas").getContext("2d"); + +$("pages-canvas").addEventListener("mousemove", function (evt) { + var selection = game.selection; + var turret = selection.turret; + + if (selection && selection.status !== "selected") { + var tx = Math.ceil((evt.pageX - this.offsetLeft) / 5); + var ty = Math.ceil((evt.pageY - this.offsetTop) / 5); + + turret.x = (tx * 5) - 2.5; + turret.y = (ty * 5) - 2.5; + selection.placeable = tx >= 3 && tx <= 158 && ty >= 3 && ty <= 98; + + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + if (game.tiles[(tx + i - 2) + "," + (ty + ii - 2)]) { + selection.placeable = false; + return; + } + } + } + } +}, false); + +$("pages-canvas").addEventListener("click", function (evt) { + var selection = game.selection; + var turret = selection.turret; + var tile = game.tiles[Math.ceil((evt.pageX - this.offsetLeft) / 5) + "," + Math.ceil((evt.pageY - this.offsetTop) / 5)]; + + if (selection.status === "moving") { + if (selection.placeable && game.cash - 90 >= 0) { + game.cash -= 90; + game.turrets[turret.id] = turret; + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; + } + } + + ui.panel("turrets"); + game.selection = false; + ui.action.refresh(); + } + } else if (selection.status === "placing") { + if (selection.placeable) { + game.cash -= turret.cost; + game.spent += turret.cost; + game.turrets.push(turret); + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; + } + } + + game.selection = false; + ui.action.refresh(); + } + } else if (typeof tile === "object") { + game.selection = { + status: "selected", + turret: tile + }; + + ui.action.refresh(); + ui.panel("manage"); + } else { + ui.action.deselect(); + } +}, false); + + +/////////////////////////////////////////////////////////////////////////////// +// Control panel +/////////////////////////////////////////////////////////////////////////////// +$("control").addEventListener("click", function (evt) { + if (evt.target.id === "control") { + ui.action.deselect(); + } +}, false); + +ui.bind("click", $("control-turrets").children, function (evt) { + if (!game.paused) { + ui.action.build(this.getAttribute("data-name")); + } +}); + +ui.bind("click", $("control-manage").getElementsByTagName("a"), function (evt) { + var action = evt.target.id.split("-")[2]; + + if (!game.paused) { + (ui.action[action] || ui.action.upgrade)(action); + } +}); + +$("control-timer").addEventListener("click", function (evt) { + if (!game.paused) { + game._wave = game.ticks - 1200; + } +}, false); + +$("control-fast").addEventListener("click", function (evt) { + if (!game.paused) { + this.style.backgroundColor = (game.fast = !game.fast) ? "#97D164" : "#85ADE6"; + game.pause(); + game.start(); + } +}, false); + +$("control-pause").addEventListener("click", function (evt) { + this.textContent = game.paused ? (game.start(), "Pause") : (game.pause(), "Start"); +}, false); + + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +ui.bind("click", $("pages-start-maps").children, function (evt) { + var name = this.textContent; + game.map = Defs.maps[name]; + game.map.name = name; + + game.map.map(function (p) { + return { x: p.x, y: p.y }; + }).forEach(function (cur, i, a) { + var next = a[i + 1] || cur, dx = next.x - cur.x, dy = next.y - cur.y; + + if (Math.abs(dx) > Math.abs(dy)) { + cur.x += dx < 0 ? 21 : -16; + var m = dy / dx, b = cur.y - m*cur.x; + dx = dx < 0 ? -1 : 1; + + while (cur.x !== next.x) { + cur.x += dx; + + for (var i = -3; i <= 4; i++) { + game.tiles[Math.round(cur.x / 5) + "," + ((Math.round(m*cur.x + b) / 5) + i)] = true; + } + } + } else if (dy !== 0) { + cur.y += dy < 0 ? 21 : -16; + var m = dx / dy, b = cur.x - m*cur.y; + dy = dy < 0 ? -1 : 1; + + while (cur.y !== next.y) { + cur.y += dy; + + for (var i = -3; i <= 4; i++) { + game.tiles[((Math.round(m*cur.y + b) / 5) + i) + "," + Math.round(cur.y / 5)] = true; + } + } + } + }); + + document.addEventListener("keydown", ui.handleshortcuts, false); + window.addEventListener("beforeunload", ui.handleunload, false); + + game.start(); + ui.panel("turrets"); + ui.page("canvas"); + + _gaq.push(["_trackEvent", "Game", "Start", name]); +}); + +ui.handletweets = function (data) { + var maps = { + loopy: $("pages-scores-twitter-loopy"), + backtrack: $("pages-scores-twitter-backtrack"), + dash: $("pages-scores-twitter-dash") + }; + + data.results.forEach(function (tweet) { + var m = tweet.text.match(/I scored (\d+) \((\d+) kills, \$(\d+) spent\) on (Loopy|Backtrack|Dash) in #canvastd/i); + + if (m) { + var map = maps[m[4].toLowerCase()]; + + if (m[1] == m[2] * m[3] && map.children.length < 31) { + var url = "https://twitter.com/" + tweet.from_user + "/status/" + tweet.id_str, + title = "@" + tweet.from_user + " on " + tweet.created_at, + a = '@' + tweet.from_user + ' '; + + map.innerHTML += '
            • ' + a + m[1] + ' ☠' + m[2] + ' $' + m[3] + '
            • '; + } + } + }); +}; + +ui.action.scores(); \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/utils.js b/canvas-td-master/canvas-td-master/scripts/utils.js new file mode 100644 index 0000000..3912179 --- /dev/null +++ b/canvas-td-master/canvas-td-master/scripts/utils.js @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////// +// Math +/////////////////////////////////////////////////////////////////////////////// +Math.inRadius = function (target, obj, rad) { + return (obj.x - target.x)*(obj.x - target.x) + (obj.y - target.y)*(obj.y - target.y) < rad*rad; +}; + +Math.move = function (obj, target, speed) { + var distx = target.x - obj.x; + var disty = target.y - obj.y; + var angle = Math.atan2(disty, distx); + + obj.x += speed * Math.cos(angle); + obj.y += speed * Math.sin(angle); + + return (distx < 0 ? -distx : distx) + (disty < 0 ? -disty : disty) < 2; +}; + +Math.rand = function (max) { + return Math.floor(Math.random() * (max + 1)); +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Elements +/////////////////////////////////////////////////////////////////////////////// +var $ = function (id) { + return document.getElementById(id); +}; + +window.ui = { + timer: $("control-timer"), + cash: $("control-cash"), + lives: $("control-lives"), + wave: $("control-wave"), + fps: $("control-fps"), + + nav: ["start"], + action: {}, + + bind: function (evt, elems, fn) { + Array.prototype.slice.call(elems).forEach(function (elem) { + elem.addEventListener(evt, fn, false); + }); + }, + page: function (name) { + if (name) { + ui.nav.unshift(name); + } else { + ui.page(ui.nav[1]); + return; + } + + Array.prototype.slice.call($("pages").children).forEach(function (elem) { + if (elem.id !== "pages-overlay") { + elem.style.display = "none"; + } + }); + + $("pages-" + name).style.display = "block"; + + _gaq.push(["_trackPageview", "/" + name]); + }, + panel: function (name) { + Array.prototype.slice.call($("control-left").children).forEach(function (elem) { + elem.style.display = "none"; + }); + + $("control-" + name).style.display = "block"; + } +}; \ No newline at end of file From c66451715cfd8940b0765e60412629c2edfc892e Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:45:23 -0800 Subject: [PATCH 28/65] Rename index.html to td.html --- canvas-td-master/canvas-td-master/{index.html => td.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename canvas-td-master/canvas-td-master/{index.html => td.html} (100%) diff --git a/canvas-td-master/canvas-td-master/index.html b/canvas-td-master/canvas-td-master/td.html similarity index 100% rename from canvas-td-master/canvas-td-master/index.html rename to canvas-td-master/canvas-td-master/td.html From ffa1ce45af0ff5a19beabb65783880d87f1ca614 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:46:07 -0800 Subject: [PATCH 29/65] Update index.html --- index.html | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/index.html b/index.html index b28f11c..7ac2f98 100644 --- a/index.html +++ b/index.html @@ -102,3 +102,27 @@

              HTML Unlocked

              Play Breakout + + +
              + + Mainpage + + + + Play Tower Defense + + From 3684a958afd1a890a4d03b2921e9421ebb9a0010 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:48:08 -0800 Subject: [PATCH 30/65] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 7ac2f98..4884bbd 100644 --- a/index.html +++ b/index.html @@ -123,6 +123,6 @@

              HTML Unlocked

              - Play Tower Defense + Play Tower Defense From 5c3d97a338adf31d77c49d53ba3dfe147f21bdc5 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:49:30 -0800 Subject: [PATCH 31/65] Create td.html --- td.html | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 td.html diff --git a/td.html b/td.html new file mode 100644 index 0000000..10a92b4 --- /dev/null +++ b/td.html @@ -0,0 +1,155 @@ + + + + + Canvas TD + + + + + +
              + + +
              + +
              +
              + Loopy + Backtrack + Dash +
              + +
              +

              A fully featured tower defense game built with <canvas>.

              + +

              Instructions

              +

              Build and upgrade turrets (which costs money and increases score) to kill creeps (which generates money and increases score). Experiment with the turrets; each has a special ability when fully upgraded.

              + +

              Shortcuts

              +
              +
              1
              +
              Build Laser / Upgrade damage
              + +
              2
              +
              Build Missile / Upgrade rate
              + +
              3
              +
              Build Tazer / Upgrade range
              + +
              4
              +
              Build Mortar / Move
              + +
              *
              +
              Sell
              + +
              =
              +
              Fast forward
              + +
              Esc
              +
              Deselect / Cancel / Pause
              + +
              Enter
              +
              Send wave
              +
              + + +
              +
              + +
              +

              Loopy

              +

              Backtrack

              +

              Dash

              + +
                +
                  +
                    + +
                      +
                        +
                          + + +
                          + +
                          +

                          Canvas TD was originally created for 10k Apart 2010, a challenge to build a web app in 10 KiB or less. Finished in less than twelve days, it failed to receive any prizes, but was ranked high in community voting and generated a significant amount of Twitter activity. While lacking much in the way of instructions, it was fully featured and quite enjoyable, and can still be played here.

                          + +

                          After the contest ended, work was started on a rewrite. Completed in June 2011, it featured far better code, many UI improvements, new gameplay elements, and some real instructions. Technologies used include <canvas>, @font-face, the Twitter Search API, Web Storage, and many other HTML5/CSS3/ES5 features.

                          + +

                          The endless, increasingly difficult gameplay (and many other core elements) is inspired by Onslaught TD. The retro look is heavily based on the excellent BIT.TRIP games and Vector TD. I'd also like to thank Alex K. and David S. for their plentiful ideas, testing, feedback, and motivation.

                          + + + + +
                          +
                          + +
                          +
                          + + +
                          + + + + Move
                          $90
                          + +
                          +
                          + +
                          + Game over! You scored .

                          + Play again or view scores + (maybe tweet yours?) +
                          +
                          + +
                          +
                          + + +
                          + +
                          + Cash $35
                          + Lives 10
                          + Wave #1 +
                          + +
                          + 60FPS
                          + Pause
                          + Reset +
                          +
                          +
                          + + + + + + + From 2bc5f812111e31a9d9cbfea1c58c0f93f74f64c2 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:50:15 -0800 Subject: [PATCH 32/65] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 4884bbd..7ac2f98 100644 --- a/index.html +++ b/index.html @@ -123,6 +123,6 @@

                          HTML Unlocked

                          - Play Tower Defense + Play Tower Defense From bb650a285cc13842f88bc41d15471133f0914db8 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:53:18 -0800 Subject: [PATCH 33/65] Add files via upload --- LICENSE | 21 ++ README.md | 6 +- TODO.md | 8 + build.sh | 23 ++ future/logo-handmade.svg | 18 ++ future/logo-text.svg | 119 +++++++++ future/logo.svg | 108 ++++++++ future/maps/random.svg | 67 +++++ future/mathrandom.js | 10 + future/server/README.md | 41 +++ future/server/creep.py | 21 ++ future/server/game.py | 100 +++++++ future/server/mathext.py | 37 +++ future/server/server.py | 14 + future/server/turrets.py | 166 ++++++++++++ future/turrets/laser-shoot.sfs | Bin 0 -> 105 bytes future/turrets/missile-hit.sfs | Bin 0 -> 105 bytes future/turrets/missile-shoot.sfs | Bin 0 -> 105 bytes future/turrets/mortar-hit.sfs | Bin 0 -> 105 bytes future/turrets/mortar-shoot.sfs | Bin 0 -> 105 bytes future/turrets/tazer-shoot.sfs | Bin 0 -> 105 bytes images/favicon.ico | Bin 0 -> 318 bytes images/logo.png | Bin 0 -> 1777 bytes images/maps/backtrack.png | Bin 0 -> 271 bytes images/maps/dash.png | Bin 0 -> 220 bytes images/maps/loopy.png | Bin 0 -> 302 bytes images/turrets/laser.png | Bin 0 -> 124 bytes images/turrets/missile.png | Bin 0 -> 127 bytes images/turrets/mortar.png | Bin 0 -> 130 bytes images/turrets/tazer.png | Bin 0 -> 124 bytes index.css | 256 ++++++++++++++++++ legacy.html | 4 + scripts/defs.js | 269 +++++++++++++++++++ scripts/game.js | 230 +++++++++++++++++ scripts/ui.js | 429 +++++++++++++++++++++++++++++++ scripts/utils.js | 71 +++++ 36 files changed, 2017 insertions(+), 1 deletion(-) create mode 100644 LICENSE create mode 100644 TODO.md create mode 100644 build.sh create mode 100644 future/logo-handmade.svg create mode 100644 future/logo-text.svg create mode 100644 future/logo.svg create mode 100644 future/maps/random.svg create mode 100644 future/mathrandom.js create mode 100644 future/server/README.md create mode 100644 future/server/creep.py create mode 100644 future/server/game.py create mode 100644 future/server/mathext.py create mode 100644 future/server/server.py create mode 100644 future/server/turrets.py create mode 100644 future/turrets/laser-shoot.sfs create mode 100644 future/turrets/missile-hit.sfs create mode 100644 future/turrets/missile-shoot.sfs create mode 100644 future/turrets/mortar-hit.sfs create mode 100644 future/turrets/mortar-shoot.sfs create mode 100644 future/turrets/tazer-shoot.sfs create mode 100644 images/favicon.ico create mode 100644 images/logo.png create mode 100644 images/maps/backtrack.png create mode 100644 images/maps/dash.png create mode 100644 images/maps/loopy.png create mode 100644 images/turrets/laser.png create mode 100644 images/turrets/missile.png create mode 100644 images/turrets/mortar.png create mode 100644 images/turrets/tazer.png create mode 100644 index.css create mode 100644 legacy.html create mode 100644 scripts/defs.js create mode 100644 scripts/game.js create mode 100644 scripts/ui.js create mode 100644 scripts/utils.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1c4172e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Teddy Cross + +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. diff --git a/README.md b/README.md index ea700e6..444f9c9 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# I do not own any of these assest and sound files, they are being used for education reasons to learn about HTML5. Thank you +A fully featured tower defense game built with <canvas>. https://canvas-td.teddy.io + +--- + +© 2017 [Teddy Cross](https://teddy.io), shared under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..bd5dfe9 --- /dev/null +++ b/TODO.md @@ -0,0 +1,8 @@ +* Redo turret targeting. +* Confirm selling turrets. +* Optimize collision detection/tiling, e.g. only check edges, + more. +* Better icon and promo graphics. +* Audio effects. +* Random map generator. +* Canvas TD Server. +* Offline support. diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..13c55d6 --- /dev/null +++ b/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# $ bash build.sh outdir ga-id + +SRCDIR="$( cd "$( dirname "$0" )" && pwd )" +OUTDIR=$1 +GAID=$2 + +rm -rf $OUTDIR +cp -R $SRCDIR $OUTDIR +cd $OUTDIR + +mv images/favicon.ico favicon.ico + +sed -i '' -e "s/##GAID##/$GAID/" index.html +sed -i '' -e '/\.js"><\/script>/d' -e 's/ \ No newline at end of file diff --git a/scripts/defs.js b/scripts/defs.js new file mode 100644 index 0000000..941ad72 --- /dev/null +++ b/scripts/defs.js @@ -0,0 +1,269 @@ +var Defs = {}; + + +/////////////////////////////////////////////////////////////////////////////// +// Maps +/////////////////////////////////////////////////////////////////////////////// +Defs.maps = { + Loopy: [ + { x: 0, y: 70 }, + { x: 730, y: 70 }, + { x: 730, y: 430 }, + { x: 70, y: 430 }, + { x: 70, y: 160 }, + { x: 640, y: 160 }, + { x: 640, y: 340 }, + { x: 160, y: 340 }, + { x: 160, y: 250 }, + { x: 800, y: 250 } + ], + + Backtrack: [ + { x: 0, y: 170 }, + { x: 120, y: 170 }, + { x: 120, y: 415 }, + { x: 460, y: 415 }, + { x: 460, y: 185 }, + { x: 230, y: 185 }, + { x: 230, y: 70 }, + { x: 345, y: 70 }, + { x: 345, y: 300 }, + { x: 700, y: 300 }, + { x: 700, y: 0 } + ], + + Dash: [ + { x: 0, y: 250 }, + { x: 800, y: 250 } + ] +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Turrets +/////////////////////////////////////////////////////////////////////////////// +Defs.turrets = {}; + +Defs.turrets.upgrades = [25, 40, 75, 150, 250, 400, 500, 700, 900, 1000]; + +Defs.turrets.Laser = { + cost: 15, + damage: 10, + rate: 40, + range: 80, + upgrades: [ + { damage: 15, rate: 38, range: 85 }, + { damage: 25, rate: 36, range: 90 }, + { damage: 50, rate: 34, range: 95 }, + { damage: 75, rate: 32, range: 100 }, + { damage: 100, rate: 30, range: 105 }, + { damage: 150, rate: 28, range: 110 }, + { damage: 200, rate: 26, range: 120 }, + { damage: 400, rate: 25, range: 130 }, + { damage: 600, rate: 24, range: 140 }, + { damage: 1000, rate: 22, range: 160 } + ], + shoot: function (creeps) { + var creep = creeps[0]; + var _hp = creep.hp; + var turret = this; + + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + + if (turret.levels.full && Math.rand(9) === 0) { + var start = game.map[0]; + creep.x = start.x; + creep.y = start.y; + creep.nextpoint = 0; + } + + game.run.push({ what: function () { + canvas.lineCap = "round"; + canvas.lineWidth = 2; + canvas.strokeStyle = "#EE82EE"; + canvas.beginPath(); + canvas.moveTo(turret.x, turret.y); + canvas.lineTo(creep.x, creep.y); + canvas.stroke(); + }, until: 6 }); + } +}; + +Defs.turrets.Missile = { + cost: 25, + damage: 15, + rate: 60, + range: 120, + upgrades: [ + { damage: 20, rate: 57, range: 125 }, + { damage: 30, rate: 54, range: 130 }, + { damage: 40, rate: 51, range: 135 }, + { damage: 80, rate: 48, range: 140 }, + { damage: 120, rate: 45, range: 145 }, + { damage: 220, rate: 42, range: 150 }, + { damage: 320, rate: 40, range: 160 }, + { damage: 450, rate: 38, range: 170 }, + { damage: 600, rate: 36, range: 180 }, + { damage: 800, rate: 33, range: 200 } + ], + cell: 0, + shoot: function (creeps) { + var creep = creeps[Math.rand(creeps.length - 1)]; + var cell = this.cell % 4; + var missile = { x: this.x + (cell % 2 === 0 ? -5 : 5), y: this.y + (cell < 2 ? -5 : 5) }; + var turret = this; + + game.run.push({ what: function () { + if (creep.hp <= 0) { + var creeps = game.creeps.filter(function () { return true; }); + + if (creeps.length) { + creep = creeps[Math.rand(creeps.length - 1)]; + } else { + return false; + } + } + + if (Math.move(missile, creep, 3)) { + if (turret.levels.full) { + game.creeps.forEach(function (c) { + if (Math.inRadius(creep, c, 20)) { + var _hp = c.hp; + if ((c.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + } + }); + + game.run.push({ what: function () { + canvas.fillStyle = "#FF0"; + canvas.beginPath(); + canvas.moveTo(creep.x, creep.y); + canvas.arc(creep.x, creep.y, 20, 0, Math.PI * 2, true); + canvas.fill(); + }, until: 3 }); + } else { + var _hp = creep.hp; + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + } + + return false; + } else { + canvas.fillStyle = "#FFF"; + canvas.fillRect(missile.x - 2, missile.y - 2, 4, 4); + } + }, until: Infinity }); + + turret.cell++; + } +}; + +Defs.turrets.Tazer = { + cost: 40, + damage: 1, + rate: 40, + range: 60, + upgrades: [ + { damage: 5, rate: 38, range: 62 }, + { damage: 10, rate: 36, range: 64 }, + { damage: 15, rate: 34, range: 66 }, + { damage: 25, rate: 32, range: 68 }, + { damage: 50, rate: 30, range: 70 }, + { damage: 100, rate: 29, range: 75 }, + { damage: 200, rate: 28, range: 80 }, + { damage: 300, rate: 27, range: 85 }, + { damage: 400, rate: 26, range: 90 }, + { damage: 500, rate: 24, range: 100 } + ], + shoot: function (creeps) { + var creep = creeps.sort(function (a, b) { return b.speed - a.speed; })[0]; + var _hp = creep.hp; + var turret = this; + var speed = 0.9 - (turret.damage / 1000); + var slowfor = 60 + turret.damage; + + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + + creep.speed = creep.speed > speed ? speed : creep.speed; + creep.slowfor = turret.levels.full ? Infinity : (creep.slowfor < slowfor ? slowfor : creep.slowfor); + + game.run.push({ what: function () { + canvas.lineCap = "round"; + canvas.lineWidth = 3; + canvas.strokeStyle = "#00F"; + canvas.beginPath(); + canvas.moveTo(turret.x, turret.y); + canvas.lineTo(creep.x, creep.y); + canvas.stroke(); + canvas.strokeStyle = "#FFF"; + canvas.lineWidth = 2; + canvas.beginPath(); + canvas.moveTo(turret.x, turret.y); + canvas.lineTo(creep.x, creep.y); + canvas.stroke(); + }, until: 6 }); + } +}; + +Defs.turrets.Mortar = { + cost: 60, + damage: 50, + rate: 120, + range: 200, + upgrades: [ + { damage: 75, rate: 115, range: 205 }, + { damage: 100, rate: 110, range: 210 }, + { damage: 150, rate: 105, range: 215 }, + { damage: 250, rate: 100, range: 220 }, + { damage: 400, rate: 96, range: 225 }, + { damage: 600, rate: 92, range: 230 }, + { damage: 800, rate: 88, range: 235 }, + { damage: 1000, rate: 84, range: 240 }, + { damage: 1200, rate: 80, range: 245 }, + { damage: 1500, rate: 75, range: 250 } + ], + shoot: function (creeps) { + var creep = creeps[0]; + var turret = this; + var target = { x: creep.x / 1, y: creep.y / 1 }; + var shell = { x: turret.x / 1, y: turret.y / 1 }; + var radius = 25 + (turret.damage / 150); + + game.run.push({ what: function () { + if (Math.move(shell, target, 1.5)) { + game.creeps.forEach(function (creep) { + if (Math.inRadius(creep, target, radius)) { + var _hp = creep.hp; + + if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { + turret.kills++; + } + + if (turret.levels.full && !creep.burning) { + creep.burning = turret; + } + } + }); + + game.run.push({ what: function () { + canvas.fillStyle = "#FF0"; + canvas.beginPath(); + canvas.moveTo(target.x, target.y); + canvas.arc(target.x, target.y, radius, 0, Math.PI * 2, true); + canvas.fill(); + }, until: 3 }); + + return false; + } else { + canvas.fillStyle = "#808080"; + canvas.fillRect(shell.x - 3, shell.y - 3, 6, 6); + } + }, until: Infinity }); + } +}; \ No newline at end of file diff --git a/scripts/game.js b/scripts/game.js new file mode 100644 index 0000000..13530d5 --- /dev/null +++ b/scripts/game.js @@ -0,0 +1,230 @@ +var game = { + ticks: 0, + _ticks: 0, + _tick: 0, + ticker: -1, + run: [], + fast: false, + paused: true, + + wave: 0, + _wave: 0, + + creeps: [], + hp: 1, + hpinc: 1.3, + lives: 10, + + turrets: [], + spent: 0, + kills: 0, + cash: 35, + selection: false, + + tiles: {}, + + tick: function () { + /////////////////////////////////////////////////////////////////////////////// + // fps + /////////////////////////////////////////////////////////////////////////////// + if (game.ticks - game._ticks === 60) { + ui.fps.textContent = Math.round(60000 / (Date.now() - game._tick)); + game._tick = Date.now(); + game._ticks = game.ticks; + } + + + /////////////////////////////////////////////////////////////////////////////// + // wave + /////////////////////////////////////////////////////////////////////////////// + if ((game.ticks - game._wave) % 30 === 29) { + ui.timer.style.opacity = 1 - (((game.ticks - game._wave) / 60) * 0.05); + } + + if (game._wave + 1200 === game.ticks) { + ui.wave.textContent = ++game.wave; + + game.hpinc = { 10: 1.2, 25: 1.1, 50: 1.06, 100: 1.04, 150: 1.02, 200: 1.01 }[game.wave] || game.hpinc; + game.hp *= game.hpinc; + + for (var i = 1; i <= 10; i++) { + game.creeps.push({ + x: -(i * 20) - 10, + y: game.map[0].y, + offset: Math.rand(14), + nextpoint: 0, + speed: 1, + slowfor: 0, + hp: game.hp, + _hp: game.hp, + burning: false, + cash: game.wave + }); + } + + game._wave = game.ticks; + } + + + /////////////////////////////////////////////////////////////////////////////// + // map + /////////////////////////////////////////////////////////////////////////////// + canvas.fillStyle = "#000"; + canvas.fillRect(0, 0, 800, 500); + + var map = game.map.slice(1), start = game.map[0]; + canvas.lineWidth = 40; + canvas.strokeStyle = "#00F"; + canvas.beginPath(); + canvas.moveTo(start.x, start.y); + map.forEach(function (cur, i) { + canvas.lineTo(cur.x, cur.y); + }); + canvas.stroke(); + canvas.lineWidth = 30; + canvas.strokeStyle = "#004"; + canvas.beginPath(); + canvas.moveTo(start.x, start.y); + map.forEach(function (cur, i) { + canvas.lineTo(cur.x, cur.y); + }); + canvas.stroke(); + + + /////////////////////////////////////////////////////////////////////////////// + // creeps + /////////////////////////////////////////////////////////////////////////////// + game.creeps.forEach(function (creep, i, a) { + var _hp = creep.hp; + var burning = creep.burning; + + if (burning) { + creep.hp -= 30; + } + + if (creep.hp <= 0) { + if (_hp > 0) { + burning.kills++; + } + + game.kills++; + game.cash += creep.cash; + + delete a[i]; + + ui.action.refresh(); + } else if (creep.nextpoint === game.map.length) { + delete a[i]; + + ui.lives.textContent = --game.lives; + + if (!game.lives) { + game.end(); + } + } else { + if (--creep.slowfor <= 0) { + creep.speed = 1; + } + + var waypoint = game.map[creep.nextpoint]; + var hue = (creep.speed < 1 || burning) ? (burning ? (creep.speed < 1 ? 300 : 33) : 240) : 0; + var sat = 100 * (creep.hp / creep._hp); + + if (Math.move(creep, { x: waypoint.x - 7 + creep.offset, y: waypoint.y - 7 + creep.offset }, creep.speed)) { + creep.nextpoint++; + } + + canvas.fillStyle = "hsl(" + hue + "," + sat + "%,50%)"; + canvas.fillRect(creep.x - 5, creep.y - 5, 10, 10); + } + }); + + + /////////////////////////////////////////////////////////////////////////////// + // turrets + /////////////////////////////////////////////////////////////////////////////// + game.turrets.forEach(function (turret) { + if (turret.lastshot + turret.rate <= game.ticks) { + var creeps = game.creeps.filter(function (creep) { + return Math.inRadius(creep, turret, turret.range); + }); + + if (creeps.length > 0) { + turret.shoot(creeps); + turret.lastshot = game.ticks; + } + } + + canvas.drawImage(turret.img, turret.x - 12.5, turret.y - 12.5); + }); + + var selection = game.selection; + var turret = selection.turret; + if (selection) { + canvas.beginPath(); + canvas.fillStyle = selection.status === "selected" || selection.placeable ? "rgba(255, 255, 255, .3)" : "rgba(255, 0, 0, .3)"; + canvas.arc(turret.x, turret.y, turret.range, 0, Math.PI * 2, true); + canvas.fill(); + + canvas.drawImage(turret.img, turret.x - 12.5, turret.y - 12.5); + } + + + /////////////////////////////////////////////////////////////////////////////// + // finish + /////////////////////////////////////////////////////////////////////////////// + game.run.forEach(function (something, i, a) { + if (something.what() === false || --something.until === 0) { + delete a[i]; + } + }); + + game.ticks++; + }, + start: function () { + game._ticks = game.ticks; + game._tick = Date.now(); + game.ticker = window.setInterval(game.tick, 1000 / (game.fast ? 180 : 60)); + game.paused = false; + game.tick(); + }, + pause: function () { + window.clearInterval(game.ticker); + game.paused = true; + }, + end: function () { + game.pause(); + document.removeEventListener("keydown", ui.handleshortcuts, false); + window.removeEventListener("beforeunload", ui.handleunload, false); + + var map = game.map.name; + var kills = game.kills; + var spent = game.spent; + var score = kills * spent; + var text = score + " (" + kills + " kills, $" + spent + " spent)"; + var top = JSON.parse(localStorage.scores || '{"Loopy":[],"Backtrack":[],"Dash":[]}'); + var topmap = top[map]; + + if (score > (topmap.length === 5 && topmap[4].score)) { + topmap.splice(4, 1); + topmap.push({ score: score, kills: kills, spent: spent, date: Date.now() }); + topmap.sort(function (a, b) { return b.score - a.score; }); + localStorage.scores = JSON.stringify(top); + ui.action.scores(); + } + + $("control-score-text").textContent = text; + $("control-score-tweet").setAttribute("href", + "https://twitter.com/?status=" + window.encodeURIComponent("I scored " + text + " on " + map + " in #canvastd http://canvas-td.tkaz.ec/")); + + ui.panel("score"); + $("pages-overlay").style.display = "block"; + + _gaq.push(["_trackEvent", "Game", "End", map]); + _gaq.push(["_trackEvent", "Game", "Creeps killed", map, kills]); + _gaq.push(["_trackEvent", "Game", "Money spent", map, spent]); + _gaq.push(["_trackEvent", "Game", "Money available", map, game.cash]); + _gaq.push(["_trackEvent", "Game", "Turrets placed", map, game.turrets.length]); + _gaq.push(["_trackEvent", "Game", "Last FPS", map, Number(ui.fps.textContent)]); + } +}; \ No newline at end of file diff --git a/scripts/ui.js b/scripts/ui.js new file mode 100644 index 0000000..bc52be8 --- /dev/null +++ b/scripts/ui.js @@ -0,0 +1,429 @@ +/////////////////////////////////////////////////////////////////////////////// +// Global +/////////////////////////////////////////////////////////////////////////////// +document.addEventListener("dragstart", function (evt) { + if (evt.target.tagName === "IMG") { + evt.preventDefault(); + } +}, false); + +ui.bind("click", document.querySelectorAll("[data-page]"), function (evt) { + ui.page(this.getAttribute("data-page")); +}); + +ui.handleshortcuts = function (evt) { + if (!game.paused) { + switch (evt.keyCode) { + case 49: { + if (game.selection) { + ui.action.upgrade("damage"); + } else { + ui.action.build("Laser"); + } + break; + } + case 50: { + if (game.selection) { + ui.action.upgrade("rate"); + } else { + ui.action.build("Missile"); + } + break; + } + case 51: { + if (game.selection) { + ui.action.upgrade("range"); + } else { + ui.action.build("Tazer"); + } + break; + } + case 52: { + if (game.selection) { + ui.action.move(); + } else { + ui.action.build("Mortar"); + } + break; + } + case 56: { + if (evt.shiftKey && game.selection) { + ui.action.sell(); + } + break; + } + case 187: { + $("control-fast").click(); + break; + } + case 27: { + if (game.selection) { + ui.action.deselect(); + } else { + $("control-pause").click(); + } + break; + } + case 13: { + game._wave = game.ticks - 1200; + break; + } + } + } else { + if (evt.keyCode === 27) { + $("control-pause").click(); + } + } +}; + +ui.handleunload = function (e) { + return "A game is currently running, are you sure you want to close it?"; +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Actions +/////////////////////////////////////////////////////////////////////////////// +ui.action.scores = function () { + var list = JSON.parse(localStorage.scores || "{}"); + + for (var map in list) { + var out = ""; + + list[map].forEach(function (r) { + out += '
                        • ' + + '' + new Date(r.date).toDateString() + ' ' + + r.score + ' ☠' + r.kills + ' $' + r.spent + + '
                        • '; + }); + + $("pages-scores-local-" + map.toLowerCase()).innerHTML = out; + } +}; + +ui.action.build = function (type) { + var tdata = Defs.turrets[type]; + var turret = { + x: -1000, + y: -1000, + levels: { + range: 0, + rate: 0, + damage: 0, + full: false + }, + kills: 0, + lastshot: 0, + img: document.querySelector("#control-turrets [data-name=" + type + "] img"), + id: game.turrets.length + }; + + for (var k in tdata) { + turret[k] = tdata[k]; + } + + game.selection = game.cash - tdata.cost >= 0 ? { + status: "placing", + turret: turret, + placeable: false + } : false; +}; + +ui.action.upgrade = function (stat) { + var turret = game.selection.turret; + var levels = turret.levels; + var level = levels[stat]; + var cost = Defs.turrets.upgrades[level]; + + if (game.selection.status === "selected" && cost && game.cash - cost >= 0) { + levels[stat]++; + turret[stat] = turret.upgrades[level][stat]; + levels.full = levels.damage === 10 && levels.rate === 10 && levels.range === 10; + turret.cost += cost; + game.cash -= cost; + game.spent += cost; + ui.action.refresh(); + } +}; + +ui.action.move = function () { + if (game.selection.status === "selected" && game.cash - 90 >= 0) { + var turret = game.selection.turret; + + game.selection = { + status: "moving", + turret: turret, + placeable: true + }; + + turret._x = turret.x; + turret._y = turret.y; + + var tx = (turret._x + 2.5) / 5, ty = (turret._y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = false; + } + } + + delete game.turrets[turret.id]; + } +}; + +ui.action.sell = function () { + var turret = game.selection.turret, value = Math.round(turret.cost * 0.7); + game.cash += value; + game.spent -= value; + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = false; + } + } + + ui.panel("turrets"); + game.selection = false; + delete game.turrets[turret.id]; + ui.action.refresh(); +}; + +ui.action.refresh = function () { + ui.cash.textContent = game.cash; + + if (game.selection) { + var turret = game.selection.turret; + var levels = turret.levels; + var costs = Defs.turrets.upgrades; + + ["Damage", "Rate", "Range"].forEach(function (proper) { + var id = proper.toLowerCase(); + var level = levels[id]; + var cost = costs[level] || ""; + $("control-manage-" + id).innerHTML = proper + " (" + level + ")
                          " + (cost && "$" + cost); + }); + + $("control-manage-sell").innerHTML = "Sell
                          $" + Math.round(turret.cost * 0.7); + + $("control-manage-stats").innerHTML = turret.kills + " kills
                          " + (((turret.kills / game.kills) || 0) * 100).toFixed(2) + "% of ∑"; + } +}; + +ui.action.deselect = function () { + if (game.selection.status === "moving") { + var turret = game.selection.turret; + game.turrets[turret.id] = turret; + + turret.x = turret._x; + turret.y = turret._y; + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; + } + } + } + + game.selection = false; + + ui.panel("turrets"); +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Canvas +/////////////////////////////////////////////////////////////////////////////// +var canvas = $("pages-canvas").getContext("2d"); + +$("pages-canvas").addEventListener("mousemove", function (evt) { + var selection = game.selection; + var turret = selection.turret; + + if (selection && selection.status !== "selected") { + var tx = Math.ceil((evt.pageX - this.offsetLeft) / 5); + var ty = Math.ceil((evt.pageY - this.offsetTop) / 5); + + turret.x = (tx * 5) - 2.5; + turret.y = (ty * 5) - 2.5; + selection.placeable = tx >= 3 && tx <= 158 && ty >= 3 && ty <= 98; + + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + if (game.tiles[(tx + i - 2) + "," + (ty + ii - 2)]) { + selection.placeable = false; + return; + } + } + } + } +}, false); + +$("pages-canvas").addEventListener("click", function (evt) { + var selection = game.selection; + var turret = selection.turret; + var tile = game.tiles[Math.ceil((evt.pageX - this.offsetLeft) / 5) + "," + Math.ceil((evt.pageY - this.offsetTop) / 5)]; + + if (selection.status === "moving") { + if (selection.placeable && game.cash - 90 >= 0) { + game.cash -= 90; + game.turrets[turret.id] = turret; + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; + } + } + + ui.panel("turrets"); + game.selection = false; + ui.action.refresh(); + } + } else if (selection.status === "placing") { + if (selection.placeable) { + game.cash -= turret.cost; + game.spent += turret.cost; + game.turrets.push(turret); + + var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; + for (var i = 5; i--;) { + for (var ii = 5; ii--;) { + game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; + } + } + + game.selection = false; + ui.action.refresh(); + } + } else if (typeof tile === "object") { + game.selection = { + status: "selected", + turret: tile + }; + + ui.action.refresh(); + ui.panel("manage"); + } else { + ui.action.deselect(); + } +}, false); + + +/////////////////////////////////////////////////////////////////////////////// +// Control panel +/////////////////////////////////////////////////////////////////////////////// +$("control").addEventListener("click", function (evt) { + if (evt.target.id === "control") { + ui.action.deselect(); + } +}, false); + +ui.bind("click", $("control-turrets").children, function (evt) { + if (!game.paused) { + ui.action.build(this.getAttribute("data-name")); + } +}); + +ui.bind("click", $("control-manage").getElementsByTagName("a"), function (evt) { + var action = evt.target.id.split("-")[2]; + + if (!game.paused) { + (ui.action[action] || ui.action.upgrade)(action); + } +}); + +$("control-timer").addEventListener("click", function (evt) { + if (!game.paused) { + game._wave = game.ticks - 1200; + } +}, false); + +$("control-fast").addEventListener("click", function (evt) { + if (!game.paused) { + this.style.backgroundColor = (game.fast = !game.fast) ? "#97D164" : "#85ADE6"; + game.pause(); + game.start(); + } +}, false); + +$("control-pause").addEventListener("click", function (evt) { + this.textContent = game.paused ? (game.start(), "Pause") : (game.pause(), "Start"); +}, false); + + +/////////////////////////////////////////////////////////////////////////////// +// Init +/////////////////////////////////////////////////////////////////////////////// +ui.bind("click", $("pages-start-maps").children, function (evt) { + var name = this.textContent; + game.map = Defs.maps[name]; + game.map.name = name; + + game.map.map(function (p) { + return { x: p.x, y: p.y }; + }).forEach(function (cur, i, a) { + var next = a[i + 1] || cur, dx = next.x - cur.x, dy = next.y - cur.y; + + if (Math.abs(dx) > Math.abs(dy)) { + cur.x += dx < 0 ? 21 : -16; + var m = dy / dx, b = cur.y - m*cur.x; + dx = dx < 0 ? -1 : 1; + + while (cur.x !== next.x) { + cur.x += dx; + + for (var i = -3; i <= 4; i++) { + game.tiles[Math.round(cur.x / 5) + "," + ((Math.round(m*cur.x + b) / 5) + i)] = true; + } + } + } else if (dy !== 0) { + cur.y += dy < 0 ? 21 : -16; + var m = dx / dy, b = cur.x - m*cur.y; + dy = dy < 0 ? -1 : 1; + + while (cur.y !== next.y) { + cur.y += dy; + + for (var i = -3; i <= 4; i++) { + game.tiles[((Math.round(m*cur.y + b) / 5) + i) + "," + Math.round(cur.y / 5)] = true; + } + } + } + }); + + document.addEventListener("keydown", ui.handleshortcuts, false); + window.addEventListener("beforeunload", ui.handleunload, false); + + game.start(); + ui.panel("turrets"); + ui.page("canvas"); + + _gaq.push(["_trackEvent", "Game", "Start", name]); +}); + +ui.handletweets = function (data) { + var maps = { + loopy: $("pages-scores-twitter-loopy"), + backtrack: $("pages-scores-twitter-backtrack"), + dash: $("pages-scores-twitter-dash") + }; + + data.results.forEach(function (tweet) { + var m = tweet.text.match(/I scored (\d+) \((\d+) kills, \$(\d+) spent\) on (Loopy|Backtrack|Dash) in #canvastd/i); + + if (m) { + var map = maps[m[4].toLowerCase()]; + + if (m[1] == m[2] * m[3] && map.children.length < 31) { + var url = "https://twitter.com/" + tweet.from_user + "/status/" + tweet.id_str, + title = "@" + tweet.from_user + " on " + tweet.created_at, + a = '@' + tweet.from_user + ' '; + + map.innerHTML += '
                        • ' + a + m[1] + ' ☠' + m[2] + ' $' + m[3] + '
                        • '; + } + } + }); +}; + +ui.action.scores(); \ No newline at end of file diff --git a/scripts/utils.js b/scripts/utils.js new file mode 100644 index 0000000..3912179 --- /dev/null +++ b/scripts/utils.js @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////// +// Math +/////////////////////////////////////////////////////////////////////////////// +Math.inRadius = function (target, obj, rad) { + return (obj.x - target.x)*(obj.x - target.x) + (obj.y - target.y)*(obj.y - target.y) < rad*rad; +}; + +Math.move = function (obj, target, speed) { + var distx = target.x - obj.x; + var disty = target.y - obj.y; + var angle = Math.atan2(disty, distx); + + obj.x += speed * Math.cos(angle); + obj.y += speed * Math.sin(angle); + + return (distx < 0 ? -distx : distx) + (disty < 0 ? -disty : disty) < 2; +}; + +Math.rand = function (max) { + return Math.floor(Math.random() * (max + 1)); +}; + + +/////////////////////////////////////////////////////////////////////////////// +// Elements +/////////////////////////////////////////////////////////////////////////////// +var $ = function (id) { + return document.getElementById(id); +}; + +window.ui = { + timer: $("control-timer"), + cash: $("control-cash"), + lives: $("control-lives"), + wave: $("control-wave"), + fps: $("control-fps"), + + nav: ["start"], + action: {}, + + bind: function (evt, elems, fn) { + Array.prototype.slice.call(elems).forEach(function (elem) { + elem.addEventListener(evt, fn, false); + }); + }, + page: function (name) { + if (name) { + ui.nav.unshift(name); + } else { + ui.page(ui.nav[1]); + return; + } + + Array.prototype.slice.call($("pages").children).forEach(function (elem) { + if (elem.id !== "pages-overlay") { + elem.style.display = "none"; + } + }); + + $("pages-" + name).style.display = "block"; + + _gaq.push(["_trackPageview", "/" + name]); + }, + panel: function (name) { + Array.prototype.slice.call($("control-left").children).forEach(function (elem) { + elem.style.display = "none"; + }); + + $("control-" + name).style.display = "block"; + } +}; \ No newline at end of file From 3cc5317db20e7575cf765c02fb1bf14d831020dc Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Fri, 14 Jan 2022 19:53:50 -0800 Subject: [PATCH 34/65] Delete canvas-td-master/canvas-td-master directory --- canvas-td-master/canvas-td-master/LICENSE | 21 - canvas-td-master/canvas-td-master/README.md | 5 - canvas-td-master/canvas-td-master/TODO.md | 8 - canvas-td-master/canvas-td-master/build.sh | 23 - .../canvas-td-master/future/logo-handmade.svg | 18 - .../canvas-td-master/future/logo-text.svg | 119 ----- .../canvas-td-master/future/logo.svg | 108 ----- .../canvas-td-master/future/maps/random.svg | 67 --- .../canvas-td-master/future/mathrandom.js | 10 - .../canvas-td-master/future/server/README.md | 41 -- .../canvas-td-master/future/server/creep.py | 21 - .../canvas-td-master/future/server/game.py | 100 ---- .../canvas-td-master/future/server/mathext.py | 37 -- .../canvas-td-master/future/server/server.py | 14 - .../canvas-td-master/future/server/turrets.py | 166 ------- .../future/turrets/laser-shoot.sfs | Bin 105 -> 0 bytes .../future/turrets/missile-hit.sfs | Bin 105 -> 0 bytes .../future/turrets/missile-shoot.sfs | Bin 105 -> 0 bytes .../future/turrets/mortar-hit.sfs | Bin 105 -> 0 bytes .../future/turrets/mortar-shoot.sfs | Bin 105 -> 0 bytes .../future/turrets/tazer-shoot.sfs | Bin 105 -> 0 bytes .../canvas-td-master/images/favicon.ico | Bin 318 -> 0 bytes .../canvas-td-master/images/logo.png | Bin 1777 -> 0 bytes .../images/maps/backtrack.png | Bin 271 -> 0 bytes .../canvas-td-master/images/maps/dash.png | Bin 220 -> 0 bytes .../canvas-td-master/images/maps/loopy.png | Bin 302 -> 0 bytes .../canvas-td-master/images/turrets/laser.png | Bin 124 -> 0 bytes .../images/turrets/missile.png | Bin 127 -> 0 bytes .../images/turrets/mortar.png | Bin 130 -> 0 bytes .../canvas-td-master/images/turrets/tazer.png | Bin 124 -> 0 bytes canvas-td-master/canvas-td-master/index.css | 256 ----------- canvas-td-master/canvas-td-master/legacy.html | 4 - .../canvas-td-master/scripts/defs.js | 269 ----------- .../canvas-td-master/scripts/game.js | 230 ---------- .../canvas-td-master/scripts/ui.js | 429 ------------------ .../canvas-td-master/scripts/utils.js | 71 --- canvas-td-master/canvas-td-master/td.html | 155 ------- 37 files changed, 2172 deletions(-) delete mode 100644 canvas-td-master/canvas-td-master/LICENSE delete mode 100644 canvas-td-master/canvas-td-master/README.md delete mode 100644 canvas-td-master/canvas-td-master/TODO.md delete mode 100644 canvas-td-master/canvas-td-master/build.sh delete mode 100644 canvas-td-master/canvas-td-master/future/logo-handmade.svg delete mode 100644 canvas-td-master/canvas-td-master/future/logo-text.svg delete mode 100644 canvas-td-master/canvas-td-master/future/logo.svg delete mode 100644 canvas-td-master/canvas-td-master/future/maps/random.svg delete mode 100644 canvas-td-master/canvas-td-master/future/mathrandom.js delete mode 100644 canvas-td-master/canvas-td-master/future/server/README.md delete mode 100644 canvas-td-master/canvas-td-master/future/server/creep.py delete mode 100644 canvas-td-master/canvas-td-master/future/server/game.py delete mode 100644 canvas-td-master/canvas-td-master/future/server/mathext.py delete mode 100644 canvas-td-master/canvas-td-master/future/server/server.py delete mode 100644 canvas-td-master/canvas-td-master/future/server/turrets.py delete mode 100644 canvas-td-master/canvas-td-master/future/turrets/laser-shoot.sfs delete mode 100644 canvas-td-master/canvas-td-master/future/turrets/missile-hit.sfs delete mode 100644 canvas-td-master/canvas-td-master/future/turrets/missile-shoot.sfs delete mode 100644 canvas-td-master/canvas-td-master/future/turrets/mortar-hit.sfs delete mode 100644 canvas-td-master/canvas-td-master/future/turrets/mortar-shoot.sfs delete mode 100644 canvas-td-master/canvas-td-master/future/turrets/tazer-shoot.sfs delete mode 100644 canvas-td-master/canvas-td-master/images/favicon.ico delete mode 100644 canvas-td-master/canvas-td-master/images/logo.png delete mode 100644 canvas-td-master/canvas-td-master/images/maps/backtrack.png delete mode 100644 canvas-td-master/canvas-td-master/images/maps/dash.png delete mode 100644 canvas-td-master/canvas-td-master/images/maps/loopy.png delete mode 100644 canvas-td-master/canvas-td-master/images/turrets/laser.png delete mode 100644 canvas-td-master/canvas-td-master/images/turrets/missile.png delete mode 100644 canvas-td-master/canvas-td-master/images/turrets/mortar.png delete mode 100644 canvas-td-master/canvas-td-master/images/turrets/tazer.png delete mode 100644 canvas-td-master/canvas-td-master/index.css delete mode 100644 canvas-td-master/canvas-td-master/legacy.html delete mode 100644 canvas-td-master/canvas-td-master/scripts/defs.js delete mode 100644 canvas-td-master/canvas-td-master/scripts/game.js delete mode 100644 canvas-td-master/canvas-td-master/scripts/ui.js delete mode 100644 canvas-td-master/canvas-td-master/scripts/utils.js delete mode 100644 canvas-td-master/canvas-td-master/td.html diff --git a/canvas-td-master/canvas-td-master/LICENSE b/canvas-td-master/canvas-td-master/LICENSE deleted file mode 100644 index 1c4172e..0000000 --- a/canvas-td-master/canvas-td-master/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Teddy Cross - -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. diff --git a/canvas-td-master/canvas-td-master/README.md b/canvas-td-master/canvas-td-master/README.md deleted file mode 100644 index 444f9c9..0000000 --- a/canvas-td-master/canvas-td-master/README.md +++ /dev/null @@ -1,5 +0,0 @@ -A fully featured tower defense game built with <canvas>. https://canvas-td.teddy.io - ---- - -© 2017 [Teddy Cross](https://teddy.io), shared under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/canvas-td-master/canvas-td-master/TODO.md b/canvas-td-master/canvas-td-master/TODO.md deleted file mode 100644 index bd5dfe9..0000000 --- a/canvas-td-master/canvas-td-master/TODO.md +++ /dev/null @@ -1,8 +0,0 @@ -* Redo turret targeting. -* Confirm selling turrets. -* Optimize collision detection/tiling, e.g. only check edges, + more. -* Better icon and promo graphics. -* Audio effects. -* Random map generator. -* Canvas TD Server. -* Offline support. diff --git a/canvas-td-master/canvas-td-master/build.sh b/canvas-td-master/canvas-td-master/build.sh deleted file mode 100644 index 13c55d6..0000000 --- a/canvas-td-master/canvas-td-master/build.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# $ bash build.sh outdir ga-id - -SRCDIR="$( cd "$( dirname "$0" )" && pwd )" -OUTDIR=$1 -GAID=$2 - -rm -rf $OUTDIR -cp -R $SRCDIR $OUTDIR -cd $OUTDIR - -mv images/favicon.ico favicon.ico - -sed -i '' -e "s/##GAID##/$GAID/" index.html -sed -i '' -e '/\.js"><\/script>/d' -e 's/ \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/defs.js b/canvas-td-master/canvas-td-master/scripts/defs.js deleted file mode 100644 index 941ad72..0000000 --- a/canvas-td-master/canvas-td-master/scripts/defs.js +++ /dev/null @@ -1,269 +0,0 @@ -var Defs = {}; - - -/////////////////////////////////////////////////////////////////////////////// -// Maps -/////////////////////////////////////////////////////////////////////////////// -Defs.maps = { - Loopy: [ - { x: 0, y: 70 }, - { x: 730, y: 70 }, - { x: 730, y: 430 }, - { x: 70, y: 430 }, - { x: 70, y: 160 }, - { x: 640, y: 160 }, - { x: 640, y: 340 }, - { x: 160, y: 340 }, - { x: 160, y: 250 }, - { x: 800, y: 250 } - ], - - Backtrack: [ - { x: 0, y: 170 }, - { x: 120, y: 170 }, - { x: 120, y: 415 }, - { x: 460, y: 415 }, - { x: 460, y: 185 }, - { x: 230, y: 185 }, - { x: 230, y: 70 }, - { x: 345, y: 70 }, - { x: 345, y: 300 }, - { x: 700, y: 300 }, - { x: 700, y: 0 } - ], - - Dash: [ - { x: 0, y: 250 }, - { x: 800, y: 250 } - ] -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Turrets -/////////////////////////////////////////////////////////////////////////////// -Defs.turrets = {}; - -Defs.turrets.upgrades = [25, 40, 75, 150, 250, 400, 500, 700, 900, 1000]; - -Defs.turrets.Laser = { - cost: 15, - damage: 10, - rate: 40, - range: 80, - upgrades: [ - { damage: 15, rate: 38, range: 85 }, - { damage: 25, rate: 36, range: 90 }, - { damage: 50, rate: 34, range: 95 }, - { damage: 75, rate: 32, range: 100 }, - { damage: 100, rate: 30, range: 105 }, - { damage: 150, rate: 28, range: 110 }, - { damage: 200, rate: 26, range: 120 }, - { damage: 400, rate: 25, range: 130 }, - { damage: 600, rate: 24, range: 140 }, - { damage: 1000, rate: 22, range: 160 } - ], - shoot: function (creeps) { - var creep = creeps[0]; - var _hp = creep.hp; - var turret = this; - - if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { - turret.kills++; - } - - if (turret.levels.full && Math.rand(9) === 0) { - var start = game.map[0]; - creep.x = start.x; - creep.y = start.y; - creep.nextpoint = 0; - } - - game.run.push({ what: function () { - canvas.lineCap = "round"; - canvas.lineWidth = 2; - canvas.strokeStyle = "#EE82EE"; - canvas.beginPath(); - canvas.moveTo(turret.x, turret.y); - canvas.lineTo(creep.x, creep.y); - canvas.stroke(); - }, until: 6 }); - } -}; - -Defs.turrets.Missile = { - cost: 25, - damage: 15, - rate: 60, - range: 120, - upgrades: [ - { damage: 20, rate: 57, range: 125 }, - { damage: 30, rate: 54, range: 130 }, - { damage: 40, rate: 51, range: 135 }, - { damage: 80, rate: 48, range: 140 }, - { damage: 120, rate: 45, range: 145 }, - { damage: 220, rate: 42, range: 150 }, - { damage: 320, rate: 40, range: 160 }, - { damage: 450, rate: 38, range: 170 }, - { damage: 600, rate: 36, range: 180 }, - { damage: 800, rate: 33, range: 200 } - ], - cell: 0, - shoot: function (creeps) { - var creep = creeps[Math.rand(creeps.length - 1)]; - var cell = this.cell % 4; - var missile = { x: this.x + (cell % 2 === 0 ? -5 : 5), y: this.y + (cell < 2 ? -5 : 5) }; - var turret = this; - - game.run.push({ what: function () { - if (creep.hp <= 0) { - var creeps = game.creeps.filter(function () { return true; }); - - if (creeps.length) { - creep = creeps[Math.rand(creeps.length - 1)]; - } else { - return false; - } - } - - if (Math.move(missile, creep, 3)) { - if (turret.levels.full) { - game.creeps.forEach(function (c) { - if (Math.inRadius(creep, c, 20)) { - var _hp = c.hp; - if ((c.hp -= turret.damage) <= 0 && _hp > 0) { - turret.kills++; - } - } - }); - - game.run.push({ what: function () { - canvas.fillStyle = "#FF0"; - canvas.beginPath(); - canvas.moveTo(creep.x, creep.y); - canvas.arc(creep.x, creep.y, 20, 0, Math.PI * 2, true); - canvas.fill(); - }, until: 3 }); - } else { - var _hp = creep.hp; - if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { - turret.kills++; - } - } - - return false; - } else { - canvas.fillStyle = "#FFF"; - canvas.fillRect(missile.x - 2, missile.y - 2, 4, 4); - } - }, until: Infinity }); - - turret.cell++; - } -}; - -Defs.turrets.Tazer = { - cost: 40, - damage: 1, - rate: 40, - range: 60, - upgrades: [ - { damage: 5, rate: 38, range: 62 }, - { damage: 10, rate: 36, range: 64 }, - { damage: 15, rate: 34, range: 66 }, - { damage: 25, rate: 32, range: 68 }, - { damage: 50, rate: 30, range: 70 }, - { damage: 100, rate: 29, range: 75 }, - { damage: 200, rate: 28, range: 80 }, - { damage: 300, rate: 27, range: 85 }, - { damage: 400, rate: 26, range: 90 }, - { damage: 500, rate: 24, range: 100 } - ], - shoot: function (creeps) { - var creep = creeps.sort(function (a, b) { return b.speed - a.speed; })[0]; - var _hp = creep.hp; - var turret = this; - var speed = 0.9 - (turret.damage / 1000); - var slowfor = 60 + turret.damage; - - if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { - turret.kills++; - } - - creep.speed = creep.speed > speed ? speed : creep.speed; - creep.slowfor = turret.levels.full ? Infinity : (creep.slowfor < slowfor ? slowfor : creep.slowfor); - - game.run.push({ what: function () { - canvas.lineCap = "round"; - canvas.lineWidth = 3; - canvas.strokeStyle = "#00F"; - canvas.beginPath(); - canvas.moveTo(turret.x, turret.y); - canvas.lineTo(creep.x, creep.y); - canvas.stroke(); - canvas.strokeStyle = "#FFF"; - canvas.lineWidth = 2; - canvas.beginPath(); - canvas.moveTo(turret.x, turret.y); - canvas.lineTo(creep.x, creep.y); - canvas.stroke(); - }, until: 6 }); - } -}; - -Defs.turrets.Mortar = { - cost: 60, - damage: 50, - rate: 120, - range: 200, - upgrades: [ - { damage: 75, rate: 115, range: 205 }, - { damage: 100, rate: 110, range: 210 }, - { damage: 150, rate: 105, range: 215 }, - { damage: 250, rate: 100, range: 220 }, - { damage: 400, rate: 96, range: 225 }, - { damage: 600, rate: 92, range: 230 }, - { damage: 800, rate: 88, range: 235 }, - { damage: 1000, rate: 84, range: 240 }, - { damage: 1200, rate: 80, range: 245 }, - { damage: 1500, rate: 75, range: 250 } - ], - shoot: function (creeps) { - var creep = creeps[0]; - var turret = this; - var target = { x: creep.x / 1, y: creep.y / 1 }; - var shell = { x: turret.x / 1, y: turret.y / 1 }; - var radius = 25 + (turret.damage / 150); - - game.run.push({ what: function () { - if (Math.move(shell, target, 1.5)) { - game.creeps.forEach(function (creep) { - if (Math.inRadius(creep, target, radius)) { - var _hp = creep.hp; - - if ((creep.hp -= turret.damage) <= 0 && _hp > 0) { - turret.kills++; - } - - if (turret.levels.full && !creep.burning) { - creep.burning = turret; - } - } - }); - - game.run.push({ what: function () { - canvas.fillStyle = "#FF0"; - canvas.beginPath(); - canvas.moveTo(target.x, target.y); - canvas.arc(target.x, target.y, radius, 0, Math.PI * 2, true); - canvas.fill(); - }, until: 3 }); - - return false; - } else { - canvas.fillStyle = "#808080"; - canvas.fillRect(shell.x - 3, shell.y - 3, 6, 6); - } - }, until: Infinity }); - } -}; \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/game.js b/canvas-td-master/canvas-td-master/scripts/game.js deleted file mode 100644 index 13530d5..0000000 --- a/canvas-td-master/canvas-td-master/scripts/game.js +++ /dev/null @@ -1,230 +0,0 @@ -var game = { - ticks: 0, - _ticks: 0, - _tick: 0, - ticker: -1, - run: [], - fast: false, - paused: true, - - wave: 0, - _wave: 0, - - creeps: [], - hp: 1, - hpinc: 1.3, - lives: 10, - - turrets: [], - spent: 0, - kills: 0, - cash: 35, - selection: false, - - tiles: {}, - - tick: function () { - /////////////////////////////////////////////////////////////////////////////// - // fps - /////////////////////////////////////////////////////////////////////////////// - if (game.ticks - game._ticks === 60) { - ui.fps.textContent = Math.round(60000 / (Date.now() - game._tick)); - game._tick = Date.now(); - game._ticks = game.ticks; - } - - - /////////////////////////////////////////////////////////////////////////////// - // wave - /////////////////////////////////////////////////////////////////////////////// - if ((game.ticks - game._wave) % 30 === 29) { - ui.timer.style.opacity = 1 - (((game.ticks - game._wave) / 60) * 0.05); - } - - if (game._wave + 1200 === game.ticks) { - ui.wave.textContent = ++game.wave; - - game.hpinc = { 10: 1.2, 25: 1.1, 50: 1.06, 100: 1.04, 150: 1.02, 200: 1.01 }[game.wave] || game.hpinc; - game.hp *= game.hpinc; - - for (var i = 1; i <= 10; i++) { - game.creeps.push({ - x: -(i * 20) - 10, - y: game.map[0].y, - offset: Math.rand(14), - nextpoint: 0, - speed: 1, - slowfor: 0, - hp: game.hp, - _hp: game.hp, - burning: false, - cash: game.wave - }); - } - - game._wave = game.ticks; - } - - - /////////////////////////////////////////////////////////////////////////////// - // map - /////////////////////////////////////////////////////////////////////////////// - canvas.fillStyle = "#000"; - canvas.fillRect(0, 0, 800, 500); - - var map = game.map.slice(1), start = game.map[0]; - canvas.lineWidth = 40; - canvas.strokeStyle = "#00F"; - canvas.beginPath(); - canvas.moveTo(start.x, start.y); - map.forEach(function (cur, i) { - canvas.lineTo(cur.x, cur.y); - }); - canvas.stroke(); - canvas.lineWidth = 30; - canvas.strokeStyle = "#004"; - canvas.beginPath(); - canvas.moveTo(start.x, start.y); - map.forEach(function (cur, i) { - canvas.lineTo(cur.x, cur.y); - }); - canvas.stroke(); - - - /////////////////////////////////////////////////////////////////////////////// - // creeps - /////////////////////////////////////////////////////////////////////////////// - game.creeps.forEach(function (creep, i, a) { - var _hp = creep.hp; - var burning = creep.burning; - - if (burning) { - creep.hp -= 30; - } - - if (creep.hp <= 0) { - if (_hp > 0) { - burning.kills++; - } - - game.kills++; - game.cash += creep.cash; - - delete a[i]; - - ui.action.refresh(); - } else if (creep.nextpoint === game.map.length) { - delete a[i]; - - ui.lives.textContent = --game.lives; - - if (!game.lives) { - game.end(); - } - } else { - if (--creep.slowfor <= 0) { - creep.speed = 1; - } - - var waypoint = game.map[creep.nextpoint]; - var hue = (creep.speed < 1 || burning) ? (burning ? (creep.speed < 1 ? 300 : 33) : 240) : 0; - var sat = 100 * (creep.hp / creep._hp); - - if (Math.move(creep, { x: waypoint.x - 7 + creep.offset, y: waypoint.y - 7 + creep.offset }, creep.speed)) { - creep.nextpoint++; - } - - canvas.fillStyle = "hsl(" + hue + "," + sat + "%,50%)"; - canvas.fillRect(creep.x - 5, creep.y - 5, 10, 10); - } - }); - - - /////////////////////////////////////////////////////////////////////////////// - // turrets - /////////////////////////////////////////////////////////////////////////////// - game.turrets.forEach(function (turret) { - if (turret.lastshot + turret.rate <= game.ticks) { - var creeps = game.creeps.filter(function (creep) { - return Math.inRadius(creep, turret, turret.range); - }); - - if (creeps.length > 0) { - turret.shoot(creeps); - turret.lastshot = game.ticks; - } - } - - canvas.drawImage(turret.img, turret.x - 12.5, turret.y - 12.5); - }); - - var selection = game.selection; - var turret = selection.turret; - if (selection) { - canvas.beginPath(); - canvas.fillStyle = selection.status === "selected" || selection.placeable ? "rgba(255, 255, 255, .3)" : "rgba(255, 0, 0, .3)"; - canvas.arc(turret.x, turret.y, turret.range, 0, Math.PI * 2, true); - canvas.fill(); - - canvas.drawImage(turret.img, turret.x - 12.5, turret.y - 12.5); - } - - - /////////////////////////////////////////////////////////////////////////////// - // finish - /////////////////////////////////////////////////////////////////////////////// - game.run.forEach(function (something, i, a) { - if (something.what() === false || --something.until === 0) { - delete a[i]; - } - }); - - game.ticks++; - }, - start: function () { - game._ticks = game.ticks; - game._tick = Date.now(); - game.ticker = window.setInterval(game.tick, 1000 / (game.fast ? 180 : 60)); - game.paused = false; - game.tick(); - }, - pause: function () { - window.clearInterval(game.ticker); - game.paused = true; - }, - end: function () { - game.pause(); - document.removeEventListener("keydown", ui.handleshortcuts, false); - window.removeEventListener("beforeunload", ui.handleunload, false); - - var map = game.map.name; - var kills = game.kills; - var spent = game.spent; - var score = kills * spent; - var text = score + " (" + kills + " kills, $" + spent + " spent)"; - var top = JSON.parse(localStorage.scores || '{"Loopy":[],"Backtrack":[],"Dash":[]}'); - var topmap = top[map]; - - if (score > (topmap.length === 5 && topmap[4].score)) { - topmap.splice(4, 1); - topmap.push({ score: score, kills: kills, spent: spent, date: Date.now() }); - topmap.sort(function (a, b) { return b.score - a.score; }); - localStorage.scores = JSON.stringify(top); - ui.action.scores(); - } - - $("control-score-text").textContent = text; - $("control-score-tweet").setAttribute("href", - "https://twitter.com/?status=" + window.encodeURIComponent("I scored " + text + " on " + map + " in #canvastd http://canvas-td.tkaz.ec/")); - - ui.panel("score"); - $("pages-overlay").style.display = "block"; - - _gaq.push(["_trackEvent", "Game", "End", map]); - _gaq.push(["_trackEvent", "Game", "Creeps killed", map, kills]); - _gaq.push(["_trackEvent", "Game", "Money spent", map, spent]); - _gaq.push(["_trackEvent", "Game", "Money available", map, game.cash]); - _gaq.push(["_trackEvent", "Game", "Turrets placed", map, game.turrets.length]); - _gaq.push(["_trackEvent", "Game", "Last FPS", map, Number(ui.fps.textContent)]); - } -}; \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/ui.js b/canvas-td-master/canvas-td-master/scripts/ui.js deleted file mode 100644 index bc52be8..0000000 --- a/canvas-td-master/canvas-td-master/scripts/ui.js +++ /dev/null @@ -1,429 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Global -/////////////////////////////////////////////////////////////////////////////// -document.addEventListener("dragstart", function (evt) { - if (evt.target.tagName === "IMG") { - evt.preventDefault(); - } -}, false); - -ui.bind("click", document.querySelectorAll("[data-page]"), function (evt) { - ui.page(this.getAttribute("data-page")); -}); - -ui.handleshortcuts = function (evt) { - if (!game.paused) { - switch (evt.keyCode) { - case 49: { - if (game.selection) { - ui.action.upgrade("damage"); - } else { - ui.action.build("Laser"); - } - break; - } - case 50: { - if (game.selection) { - ui.action.upgrade("rate"); - } else { - ui.action.build("Missile"); - } - break; - } - case 51: { - if (game.selection) { - ui.action.upgrade("range"); - } else { - ui.action.build("Tazer"); - } - break; - } - case 52: { - if (game.selection) { - ui.action.move(); - } else { - ui.action.build("Mortar"); - } - break; - } - case 56: { - if (evt.shiftKey && game.selection) { - ui.action.sell(); - } - break; - } - case 187: { - $("control-fast").click(); - break; - } - case 27: { - if (game.selection) { - ui.action.deselect(); - } else { - $("control-pause").click(); - } - break; - } - case 13: { - game._wave = game.ticks - 1200; - break; - } - } - } else { - if (evt.keyCode === 27) { - $("control-pause").click(); - } - } -}; - -ui.handleunload = function (e) { - return "A game is currently running, are you sure you want to close it?"; -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Actions -/////////////////////////////////////////////////////////////////////////////// -ui.action.scores = function () { - var list = JSON.parse(localStorage.scores || "{}"); - - for (var map in list) { - var out = ""; - - list[map].forEach(function (r) { - out += '
                        • ' + - '' + new Date(r.date).toDateString() + ' ' + - r.score + ' ☠' + r.kills + ' $' + r.spent + - '
                        • '; - }); - - $("pages-scores-local-" + map.toLowerCase()).innerHTML = out; - } -}; - -ui.action.build = function (type) { - var tdata = Defs.turrets[type]; - var turret = { - x: -1000, - y: -1000, - levels: { - range: 0, - rate: 0, - damage: 0, - full: false - }, - kills: 0, - lastshot: 0, - img: document.querySelector("#control-turrets [data-name=" + type + "] img"), - id: game.turrets.length - }; - - for (var k in tdata) { - turret[k] = tdata[k]; - } - - game.selection = game.cash - tdata.cost >= 0 ? { - status: "placing", - turret: turret, - placeable: false - } : false; -}; - -ui.action.upgrade = function (stat) { - var turret = game.selection.turret; - var levels = turret.levels; - var level = levels[stat]; - var cost = Defs.turrets.upgrades[level]; - - if (game.selection.status === "selected" && cost && game.cash - cost >= 0) { - levels[stat]++; - turret[stat] = turret.upgrades[level][stat]; - levels.full = levels.damage === 10 && levels.rate === 10 && levels.range === 10; - turret.cost += cost; - game.cash -= cost; - game.spent += cost; - ui.action.refresh(); - } -}; - -ui.action.move = function () { - if (game.selection.status === "selected" && game.cash - 90 >= 0) { - var turret = game.selection.turret; - - game.selection = { - status: "moving", - turret: turret, - placeable: true - }; - - turret._x = turret.x; - turret._y = turret.y; - - var tx = (turret._x + 2.5) / 5, ty = (turret._y + 2.5) / 5; - for (var i = 5; i--;) { - for (var ii = 5; ii--;) { - game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = false; - } - } - - delete game.turrets[turret.id]; - } -}; - -ui.action.sell = function () { - var turret = game.selection.turret, value = Math.round(turret.cost * 0.7); - game.cash += value; - game.spent -= value; - - var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; - for (var i = 5; i--;) { - for (var ii = 5; ii--;) { - game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = false; - } - } - - ui.panel("turrets"); - game.selection = false; - delete game.turrets[turret.id]; - ui.action.refresh(); -}; - -ui.action.refresh = function () { - ui.cash.textContent = game.cash; - - if (game.selection) { - var turret = game.selection.turret; - var levels = turret.levels; - var costs = Defs.turrets.upgrades; - - ["Damage", "Rate", "Range"].forEach(function (proper) { - var id = proper.toLowerCase(); - var level = levels[id]; - var cost = costs[level] || ""; - $("control-manage-" + id).innerHTML = proper + " (" + level + ")
                          " + (cost && "$" + cost); - }); - - $("control-manage-sell").innerHTML = "Sell
                          $" + Math.round(turret.cost * 0.7); - - $("control-manage-stats").innerHTML = turret.kills + " kills
                          " + (((turret.kills / game.kills) || 0) * 100).toFixed(2) + "% of ∑"; - } -}; - -ui.action.deselect = function () { - if (game.selection.status === "moving") { - var turret = game.selection.turret; - game.turrets[turret.id] = turret; - - turret.x = turret._x; - turret.y = turret._y; - - var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; - for (var i = 5; i--;) { - for (var ii = 5; ii--;) { - game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; - } - } - } - - game.selection = false; - - ui.panel("turrets"); -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Canvas -/////////////////////////////////////////////////////////////////////////////// -var canvas = $("pages-canvas").getContext("2d"); - -$("pages-canvas").addEventListener("mousemove", function (evt) { - var selection = game.selection; - var turret = selection.turret; - - if (selection && selection.status !== "selected") { - var tx = Math.ceil((evt.pageX - this.offsetLeft) / 5); - var ty = Math.ceil((evt.pageY - this.offsetTop) / 5); - - turret.x = (tx * 5) - 2.5; - turret.y = (ty * 5) - 2.5; - selection.placeable = tx >= 3 && tx <= 158 && ty >= 3 && ty <= 98; - - for (var i = 5; i--;) { - for (var ii = 5; ii--;) { - if (game.tiles[(tx + i - 2) + "," + (ty + ii - 2)]) { - selection.placeable = false; - return; - } - } - } - } -}, false); - -$("pages-canvas").addEventListener("click", function (evt) { - var selection = game.selection; - var turret = selection.turret; - var tile = game.tiles[Math.ceil((evt.pageX - this.offsetLeft) / 5) + "," + Math.ceil((evt.pageY - this.offsetTop) / 5)]; - - if (selection.status === "moving") { - if (selection.placeable && game.cash - 90 >= 0) { - game.cash -= 90; - game.turrets[turret.id] = turret; - - var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; - for (var i = 5; i--;) { - for (var ii = 5; ii--;) { - game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; - } - } - - ui.panel("turrets"); - game.selection = false; - ui.action.refresh(); - } - } else if (selection.status === "placing") { - if (selection.placeable) { - game.cash -= turret.cost; - game.spent += turret.cost; - game.turrets.push(turret); - - var tx = (turret.x + 2.5) / 5, ty = (turret.y + 2.5) / 5; - for (var i = 5; i--;) { - for (var ii = 5; ii--;) { - game.tiles[(tx + i - 2) + "," + (ty + ii - 2)] = turret; - } - } - - game.selection = false; - ui.action.refresh(); - } - } else if (typeof tile === "object") { - game.selection = { - status: "selected", - turret: tile - }; - - ui.action.refresh(); - ui.panel("manage"); - } else { - ui.action.deselect(); - } -}, false); - - -/////////////////////////////////////////////////////////////////////////////// -// Control panel -/////////////////////////////////////////////////////////////////////////////// -$("control").addEventListener("click", function (evt) { - if (evt.target.id === "control") { - ui.action.deselect(); - } -}, false); - -ui.bind("click", $("control-turrets").children, function (evt) { - if (!game.paused) { - ui.action.build(this.getAttribute("data-name")); - } -}); - -ui.bind("click", $("control-manage").getElementsByTagName("a"), function (evt) { - var action = evt.target.id.split("-")[2]; - - if (!game.paused) { - (ui.action[action] || ui.action.upgrade)(action); - } -}); - -$("control-timer").addEventListener("click", function (evt) { - if (!game.paused) { - game._wave = game.ticks - 1200; - } -}, false); - -$("control-fast").addEventListener("click", function (evt) { - if (!game.paused) { - this.style.backgroundColor = (game.fast = !game.fast) ? "#97D164" : "#85ADE6"; - game.pause(); - game.start(); - } -}, false); - -$("control-pause").addEventListener("click", function (evt) { - this.textContent = game.paused ? (game.start(), "Pause") : (game.pause(), "Start"); -}, false); - - -/////////////////////////////////////////////////////////////////////////////// -// Init -/////////////////////////////////////////////////////////////////////////////// -ui.bind("click", $("pages-start-maps").children, function (evt) { - var name = this.textContent; - game.map = Defs.maps[name]; - game.map.name = name; - - game.map.map(function (p) { - return { x: p.x, y: p.y }; - }).forEach(function (cur, i, a) { - var next = a[i + 1] || cur, dx = next.x - cur.x, dy = next.y - cur.y; - - if (Math.abs(dx) > Math.abs(dy)) { - cur.x += dx < 0 ? 21 : -16; - var m = dy / dx, b = cur.y - m*cur.x; - dx = dx < 0 ? -1 : 1; - - while (cur.x !== next.x) { - cur.x += dx; - - for (var i = -3; i <= 4; i++) { - game.tiles[Math.round(cur.x / 5) + "," + ((Math.round(m*cur.x + b) / 5) + i)] = true; - } - } - } else if (dy !== 0) { - cur.y += dy < 0 ? 21 : -16; - var m = dx / dy, b = cur.x - m*cur.y; - dy = dy < 0 ? -1 : 1; - - while (cur.y !== next.y) { - cur.y += dy; - - for (var i = -3; i <= 4; i++) { - game.tiles[((Math.round(m*cur.y + b) / 5) + i) + "," + Math.round(cur.y / 5)] = true; - } - } - } - }); - - document.addEventListener("keydown", ui.handleshortcuts, false); - window.addEventListener("beforeunload", ui.handleunload, false); - - game.start(); - ui.panel("turrets"); - ui.page("canvas"); - - _gaq.push(["_trackEvent", "Game", "Start", name]); -}); - -ui.handletweets = function (data) { - var maps = { - loopy: $("pages-scores-twitter-loopy"), - backtrack: $("pages-scores-twitter-backtrack"), - dash: $("pages-scores-twitter-dash") - }; - - data.results.forEach(function (tweet) { - var m = tweet.text.match(/I scored (\d+) \((\d+) kills, \$(\d+) spent\) on (Loopy|Backtrack|Dash) in #canvastd/i); - - if (m) { - var map = maps[m[4].toLowerCase()]; - - if (m[1] == m[2] * m[3] && map.children.length < 31) { - var url = "https://twitter.com/" + tweet.from_user + "/status/" + tweet.id_str, - title = "@" + tweet.from_user + " on " + tweet.created_at, - a = '@' + tweet.from_user + ' '; - - map.innerHTML += '
                        • ' + a + m[1] + ' ☠' + m[2] + ' $' + m[3] + '
                        • '; - } - } - }); -}; - -ui.action.scores(); \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/scripts/utils.js b/canvas-td-master/canvas-td-master/scripts/utils.js deleted file mode 100644 index 3912179..0000000 --- a/canvas-td-master/canvas-td-master/scripts/utils.js +++ /dev/null @@ -1,71 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Math -/////////////////////////////////////////////////////////////////////////////// -Math.inRadius = function (target, obj, rad) { - return (obj.x - target.x)*(obj.x - target.x) + (obj.y - target.y)*(obj.y - target.y) < rad*rad; -}; - -Math.move = function (obj, target, speed) { - var distx = target.x - obj.x; - var disty = target.y - obj.y; - var angle = Math.atan2(disty, distx); - - obj.x += speed * Math.cos(angle); - obj.y += speed * Math.sin(angle); - - return (distx < 0 ? -distx : distx) + (disty < 0 ? -disty : disty) < 2; -}; - -Math.rand = function (max) { - return Math.floor(Math.random() * (max + 1)); -}; - - -/////////////////////////////////////////////////////////////////////////////// -// Elements -/////////////////////////////////////////////////////////////////////////////// -var $ = function (id) { - return document.getElementById(id); -}; - -window.ui = { - timer: $("control-timer"), - cash: $("control-cash"), - lives: $("control-lives"), - wave: $("control-wave"), - fps: $("control-fps"), - - nav: ["start"], - action: {}, - - bind: function (evt, elems, fn) { - Array.prototype.slice.call(elems).forEach(function (elem) { - elem.addEventListener(evt, fn, false); - }); - }, - page: function (name) { - if (name) { - ui.nav.unshift(name); - } else { - ui.page(ui.nav[1]); - return; - } - - Array.prototype.slice.call($("pages").children).forEach(function (elem) { - if (elem.id !== "pages-overlay") { - elem.style.display = "none"; - } - }); - - $("pages-" + name).style.display = "block"; - - _gaq.push(["_trackPageview", "/" + name]); - }, - panel: function (name) { - Array.prototype.slice.call($("control-left").children).forEach(function (elem) { - elem.style.display = "none"; - }); - - $("control-" + name).style.display = "block"; - } -}; \ No newline at end of file diff --git a/canvas-td-master/canvas-td-master/td.html b/canvas-td-master/canvas-td-master/td.html deleted file mode 100644 index 10a92b4..0000000 --- a/canvas-td-master/canvas-td-master/td.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - Canvas TD - - - - - -
                          - - -
                          - -
                          -
                          - Loopy - Backtrack - Dash -
                          - -
                          -

                          A fully featured tower defense game built with <canvas>.

                          - -

                          Instructions

                          -

                          Build and upgrade turrets (which costs money and increases score) to kill creeps (which generates money and increases score). Experiment with the turrets; each has a special ability when fully upgraded.

                          - -

                          Shortcuts

                          -
                          -
                          1
                          -
                          Build Laser / Upgrade damage
                          - -
                          2
                          -
                          Build Missile / Upgrade rate
                          - -
                          3
                          -
                          Build Tazer / Upgrade range
                          - -
                          4
                          -
                          Build Mortar / Move
                          - -
                          *
                          -
                          Sell
                          - -
                          =
                          -
                          Fast forward
                          - -
                          Esc
                          -
                          Deselect / Cancel / Pause
                          - -
                          Enter
                          -
                          Send wave
                          -
                          - - -
                          -
                          - -
                          -

                          Loopy

                          -

                          Backtrack

                          -

                          Dash

                          - -
                            -
                              -
                                - -
                                  -
                                    -
                                      - - -
                                      - -
                                      -

                                      Canvas TD was originally created for 10k Apart 2010, a challenge to build a web app in 10 KiB or less. Finished in less than twelve days, it failed to receive any prizes, but was ranked high in community voting and generated a significant amount of Twitter activity. While lacking much in the way of instructions, it was fully featured and quite enjoyable, and can still be played here.

                                      - -

                                      After the contest ended, work was started on a rewrite. Completed in June 2011, it featured far better code, many UI improvements, new gameplay elements, and some real instructions. Technologies used include <canvas>, @font-face, the Twitter Search API, Web Storage, and many other HTML5/CSS3/ES5 features.

                                      - -

                                      The endless, increasingly difficult gameplay (and many other core elements) is inspired by Onslaught TD. The retro look is heavily based on the excellent BIT.TRIP games and Vector TD. I'd also like to thank Alex K. and David S. for their plentiful ideas, testing, feedback, and motivation.

                                      - - - - -
                                      -
                                      - -
                                      -
                                      - - -
                                      - - - - Move
                                      $90
                                      - -
                                      -
                                      - -
                                      - Game over! You scored .

                                      - Play again or view scores - (maybe tweet yours?) -
                                      -
                                      - -
                                      -
                                      - - -
                                      - -
                                      - Cash $35
                                      - Lives 10
                                      - Wave #1 -
                                      - -
                                      - 60FPS
                                      - Pause
                                      - Reset -
                                      -
                                      -
                                      - - - - - - - From 636c7c57e0cba94da35a72a5576b9a16b22d16e8 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 12:37:19 -0800 Subject: [PATCH 35/65] Update index.html --- index.html | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/index.html b/index.html index 7ac2f98..1c0c879 100644 --- a/index.html +++ b/index.html @@ -126,3 +126,27 @@

                                      HTML Unlocked

                                      Play Tower Defense + + +
                                      + + Mainpage + + + + Play 2048 + + From 043b1c00c2dfb06a615fd43e072b114f618fae80 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 12:37:46 -0800 Subject: [PATCH 36/65] Update 2048.html --- 2048.html | 1 - 1 file changed, 1 deletion(-) diff --git a/2048.html b/2048.html index a076b76..aa109cb 100644 --- a/2048.html +++ b/2048.html @@ -1,2 +1 @@ - From 2810dd1fbee4dbd7d1c5e4fe3c73ece101733c3b Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 12:38:24 -0800 Subject: [PATCH 37/65] Update 2048.html --- 2048.html | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/2048.html b/2048.html index aa109cb..078e3a1 100644 --- a/2048.html +++ b/2048.html @@ -1 +1,22 @@ + + + Mainpage + + + Go Home + + From a647d8a62223ea32c69229a570d8906644227725 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 12:42:25 -0800 Subject: [PATCH 38/65] Update 2048.html --- 2048.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/2048.html b/2048.html index 078e3a1..99f1c9a 100644 --- a/2048.html +++ b/2048.html @@ -19,4 +19,6 @@ Go Home - + + + From 573c78a3b3875992c1f6996124b5f3ae3ec47355 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 13:01:56 -0800 Subject: [PATCH 39/65] Update breakout.html --- breakout.html | 180 +------------------------------------------------- 1 file changed, 2 insertions(+), 178 deletions(-) diff --git a/breakout.html b/breakout.html index 6ec1ae0..b46efe8 100644 --- a/breakout.html +++ b/breakout.html @@ -21,181 +21,5 @@ Go Home - - - - - - - - - - - - + + From 72129001169bacf13063e940a37778b485f067bf Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 13:02:23 -0800 Subject: [PATCH 40/65] Delete legacy.html --- legacy.html | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 legacy.html diff --git a/legacy.html b/legacy.html deleted file mode 100644 index 926612f..0000000 --- a/legacy.html +++ /dev/null @@ -1,4 +0,0 @@ - - -Canvas TD -
                                      Choose map:
                                      Place and upgrade turrets (which cost money) to kill creeps (which give you money).
                                      FPS 60

                                      20s
                                      Cash $35
                                      Lives 10
                                      Wave #1
                                      Loading tweets...
                                      \ No newline at end of file From 44a6c924338a4648eb53650ec1a8a4ee6302acd8 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 13:06:12 -0800 Subject: [PATCH 41/65] Update breakout.html --- breakout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/breakout.html b/breakout.html index b46efe8..0eb1741 100644 --- a/breakout.html +++ b/breakout.html @@ -22,4 +22,4 @@ Go Home - + From 547da8382d3dfce12a9eafd24c044c2906f6ccf9 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 13:08:16 -0800 Subject: [PATCH 42/65] Delete breakout.html --- breakout.html | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 breakout.html diff --git a/breakout.html b/breakout.html deleted file mode 100644 index 0eb1741..0000000 --- a/breakout.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - Mainpage - - - Go Home - - - From aa093b56d73a0deaf667fa7c49569bac3e0851b6 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 13:08:37 -0800 Subject: [PATCH 43/65] Update index.html --- index.html | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/index.html b/index.html index 1c0c879..7a8e16c 100644 --- a/index.html +++ b/index.html @@ -78,31 +78,6 @@

                                      HTML Unlocked

                                      - - -
                                      - - Mainpage - - - - Play Breakout - - -
                                      From 557f8c6a7683d212156aae7ff76ee48c6bac02bc Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 14:46:52 -0800 Subject: [PATCH 44/65] Update index.html --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 7a8e16c..c8ca58c 100644 --- a/index.html +++ b/index.html @@ -74,7 +74,7 @@

                                      HTML Unlocked

                                      - Play Snake + Play Speed Snake From def785250315be2cdca2c6fea1d1d947cb18e8b7 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 14:52:19 -0800 Subject: [PATCH 45/65] Create CNAME --- CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..bc224d0 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +xenongaming.xyz \ No newline at end of file From 1f11352c9685558621013183de6fa2ffa000216d Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 14:54:28 -0800 Subject: [PATCH 46/65] Update CNAME --- CNAME | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CNAME b/CNAME index bc224d0..38d787d 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -xenongaming.xyz \ No newline at end of file +http://www.xenongaming.xyz From 4c87417703475a81f39e861671d1f2a607608f3b Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 14:57:50 -0800 Subject: [PATCH 47/65] Update CNAME --- CNAME | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CNAME b/CNAME index 38d787d..b435fbd 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -http://www.xenongaming.xyz +www.xenongaming.xyz From a3fd1fb57ff282881fd64e1d4196593a33338cad Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:55:17 -0800 Subject: [PATCH 48/65] Create pong.html --- pong.html | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 pong.html diff --git a/pong.html b/pong.html new file mode 100644 index 0000000..befdd14 --- /dev/null +++ b/pong.html @@ -0,0 +1,198 @@ + + + + Pong + + + + + + + + From 66412b8f08d2adf5397e98f30cb7e150d3840f54 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:56:15 -0800 Subject: [PATCH 49/65] Create breakout.html --- breakout.html | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 breakout.html diff --git a/breakout.html b/breakout.html new file mode 100644 index 0000000..6b4933d --- /dev/null +++ b/breakout.html @@ -0,0 +1,245 @@ + + + + Basic Breakout HTML Game + + + + + + + + From 4d821add9593613d9f4949116758998c34779f76 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:56:54 -0800 Subject: [PATCH 50/65] Update index.html --- index.html | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/index.html b/index.html index c8ca58c..008073d 100644 --- a/index.html +++ b/index.html @@ -125,3 +125,52 @@

                                      HTML Unlocked

                                      Play 2048 + + +
                                      + + Mainpage + + + + Play Breakout + + + + +
                                      + + Mainpage + + + + Play Pong + + + From 762896e49184a2092a7227ceb9934658630a868d Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:59:03 -0800 Subject: [PATCH 51/65] Update pong.html --- pong.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pong.html b/pong.html index befdd14..783c431 100644 --- a/pong.html +++ b/pong.html @@ -1,4 +1,7 @@ + + WASD for player 1, Arrow keys for player2 + Pong From e3c24c1a15d4ce22c885bc06e5b76e6d6224b289 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Wed, 26 Jan 2022 16:00:01 -0800 Subject: [PATCH 52/65] Update pong.html --- pong.html | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pong.html b/pong.html index 783c431..1e05704 100644 --- a/pong.html +++ b/pong.html @@ -1,5 +1,26 @@ + + + Mainpage + + + Go Home + + WASD for player 1, Arrow keys for player2 From fb502b75cbef046f8af4413cec7cfd754559df49 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 27 Jan 2022 12:49:24 -0800 Subject: [PATCH 53/65] Create PapaGame.html --- PapaGame.html | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 PapaGame.html diff --git a/PapaGame.html b/PapaGame.html new file mode 100644 index 0000000..115fbac --- /dev/null +++ b/PapaGame.html @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + +
                                      + + + +

                                      Papa's Games

                                      +

                                      Note: If it says flash player is disabled, copy and paste "chrome://settings/content/flash" into a tab and click the button next to "block flash"

                                      + +
                                      + + + + + + + + + + + + + + + + + + + + + + Date: Thu, 27 Jan 2022 12:53:24 -0800 Subject: [PATCH 54/65] Delete PapaGame.html --- PapaGame.html | 69 --------------------------------------------------- 1 file changed, 69 deletions(-) delete mode 100644 PapaGame.html diff --git a/PapaGame.html b/PapaGame.html deleted file mode 100644 index 115fbac..0000000 --- a/PapaGame.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - -
                                      - - - -

                                      Papa's Games

                                      -

                                      Note: If it says flash player is disabled, copy and paste "chrome://settings/content/flash" into a tab and click the button next to "block flash"

                                      - -

                                      Papa's Bakeria

                                      Papa's Burgeria

                                      Papa's Cheeseria

                                      Papa's Cupcakeria

                                      Papa's Donuteria

                                      Papa's Freezeria

                                      Papa's Hot Doggeria

                                      Papa's Pancakeria

                                      Papa's Pastaria

                                      Papa's Pizzeria

                                      Papa's Scooperia

                                      Papa's Sushiria

                                      Papa's Taco Mia

                                      Papa's Wingeria

                                      Papa Louie

                                      - - - - - - - - - - - - - - - - - - - - - - Date: Thu, 27 Jan 2022 12:55:16 -0800 Subject: [PATCH 55/65] Create papas.html --- papas.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 papas.html diff --git a/papas.html b/papas.html new file mode 100644 index 0000000..168b4dc --- /dev/null +++ b/papas.html @@ -0,0 +1 @@ +
                                      Play more games at Flipline Studios From 3d260401c4becd1d3e64071cc7b3e096f62a7e9a Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Thu, 27 Jan 2022 17:05:17 -0800 Subject: [PATCH 56/65] Create mario.html --- mario.html | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 mario.html diff --git a/mario.html b/mario.html new file mode 100644 index 0000000..3f5e89e --- /dev/null +++ b/mario.html @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + +

                                      Papa's Bakeria

                                      Papa's Burgeria

                                      Papa's Cheeseria

                                      Papa's Cupcakeria

                                      Papa's Donuteria

                                      Papa's Freezeria

                                      Papa's Hot Doggeria

                                      Papa's Pancakeria

                                      Papa's Pastaria

                                      Papa's Pizzeria

                                      Papa's Scooperia

                                      Papa's Sushiria

                                      Papa's Taco Mia

                                      Papa's Wingeria

                                      Papa Louie

                                      SCORE
                                      0
                                      COINS
                                      0
                                      WORLD
                                      1-1
                                      TIME
                                      283
                                      LIVES
                                      2

                                      super

                                      MARIO HTML5

                                      Arrow/WASD keys move
                                      Shift to fire/sprint
                                      P/M to pause/mute

                                      From 749cdca6e90ffccc38663ebf30cb396ea92cc6f6 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Mon, 31 Jan 2022 12:48:00 -0800 Subject: [PATCH 57/65] Create space.html --- space.html | 1643 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1643 insertions(+) create mode 100644 space.html diff --git a/space.html b/space.html new file mode 100644 index 0000000..ab4e808 --- /dev/null +++ b/space.html @@ -0,0 +1,1643 @@ + + + + Space Invaders + + + + + +
                                      + + From b0b82c92bee63fc4eee293a18fe3f4f8aebe2aa3 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Mon, 31 Jan 2022 12:52:04 -0800 Subject: [PATCH 58/65] Update index.html --- index.html | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/index.html b/index.html index 008073d..cd9f972 100644 --- a/index.html +++ b/index.html @@ -174,3 +174,26 @@

                                      HTML Unlocked

                                      + +
                                      + + Mainpage + + + + Play Space Invaders + + From 1dc6259a2b403a55e7be90682d100820474c29fd Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Mon, 31 Jan 2022 12:55:06 -0800 Subject: [PATCH 59/65] Update snake.html --- snake.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snake.html b/snake.html index 4b95a65..2889dab 100644 --- a/snake.html +++ b/snake.html @@ -80,7 +80,7 @@ requestAnimationFrame(loop); // slow game loop to 15 fps instead of 60 (60/15 = 4) - if (++count < 4) { + if (60/15 = 4) { return; } From d4dcf491eb2bbba51b8f00efbdfefcd566ee559e Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Mon, 31 Jan 2022 12:59:51 -0800 Subject: [PATCH 60/65] Update snake.html --- snake.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snake.html b/snake.html index 2889dab..cce472c 100644 --- a/snake.html +++ b/snake.html @@ -80,7 +80,7 @@ requestAnimationFrame(loop); // slow game loop to 15 fps instead of 60 (60/15 = 4) - if (60/15 = 4) { + if (60/15 < 15) { return; } From dc39eced2c954d7ec47407332901ec03f5601164 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Mon, 31 Jan 2022 13:02:06 -0800 Subject: [PATCH 61/65] Update snake.html --- snake.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snake.html b/snake.html index cce472c..2889dab 100644 --- a/snake.html +++ b/snake.html @@ -80,7 +80,7 @@ requestAnimationFrame(loop); // slow game loop to 15 fps instead of 60 (60/15 = 4) - if (60/15 < 15) { + if (60/15 = 4) { return; } From dab7b59f180d43ba2d996e1d3040dd0a7781bba0 Mon Sep 17 00:00:00 2001 From: ExplodingCB <80976683+ExplodingCB@users.noreply.github.com> Date: Mon, 31 Jan 2022 13:05:37 -0800 Subject: [PATCH 62/65] Update snake.html --- snake.html | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/snake.html b/snake.html index 2889dab..5e79edf 100644 --- a/snake.html +++ b/snake.html @@ -1,28 +1,7 @@ - - - - Mainpage - - - Go Home - - + Basic Snake HTML Game