components and new tower
This commit is contained in:
parent
87aea4bd6f
commit
c00dacd4cb
389
index.js
389
index.js
@ -6,6 +6,9 @@ window.onload = function () {
|
|||||||
* I use Object.assign to copy objects in order to eliminate references when spawning enemies
|
* I use Object.assign to copy objects in order to eliminate references when spawning enemies
|
||||||
and to get the ability to modify them individually
|
and to get the ability to modify them individually
|
||||||
* Components such as buttons or selections within the canvas are classes
|
* Components such as buttons or selections within the canvas are classes
|
||||||
|
* if, function and else have spaces between both '(' and '{'
|
||||||
|
`if (thing) {}` not `if(thing){}`
|
||||||
|
* Keep all variables local to their scope (in other words, use `let` instead of `var`)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let canvas = document.getElementById('canvas')
|
let canvas = document.getElementById('canvas')
|
||||||
@ -36,6 +39,7 @@ window.onload = function () {
|
|||||||
waveTimer: 0,
|
waveTimer: 0,
|
||||||
tower: 'simple',
|
tower: 'simple',
|
||||||
towerSel: null,
|
towerSel: null,
|
||||||
|
debug: false,
|
||||||
sellRatio: .8
|
sellRatio: .8
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +71,7 @@ window.onload = function () {
|
|||||||
tough: {
|
tough: {
|
||||||
speed: 5,
|
speed: 5,
|
||||||
node: 1,
|
node: 1,
|
||||||
health: 100,
|
health: 150,
|
||||||
reward: 20,
|
reward: 20,
|
||||||
frequency: 1000,
|
frequency: 1000,
|
||||||
icon: '#f40'
|
icon: '#f40'
|
||||||
@ -80,30 +84,44 @@ window.onload = function () {
|
|||||||
damage: 15, // damage to deal to enemies when hit
|
damage: 15, // damage to deal to enemies when hit
|
||||||
rate: 20, // rate of fire, higher - slower
|
rate: 20, // rate of fire, higher - slower
|
||||||
name: 'Simple', // name of the tower
|
name: 'Simple', // name of the tower
|
||||||
description: 'Basic tower',
|
description: 'Medium rate and damage',
|
||||||
speed: 30, // bullet speed, higher - faster
|
speed: 30, // bullet speed, higher - faster
|
||||||
cost: 50, // cost to place
|
cost: 50, // cost to place
|
||||||
icon: '#333' // currently color
|
icon: '#333', // currently color
|
||||||
|
bullet: 1 // The type of bullet. 1: damage, 2: slow down by damage, 3: instant kill
|
||||||
},
|
},
|
||||||
rapid: {
|
rapid: {
|
||||||
range: 3,
|
range: 3,
|
||||||
damage: 5,
|
damage: 5,
|
||||||
rate: 5,
|
rate: 5,
|
||||||
name: 'Rapid',
|
name: 'Rapid',
|
||||||
description: 'Rapid-firing tower',
|
description: 'Rapid-firing but low damage',
|
||||||
speed: 30,
|
speed: 30,
|
||||||
cost: 250,
|
cost: 250,
|
||||||
icon: '#303'
|
icon: '#303',
|
||||||
|
bullet: 1
|
||||||
},
|
},
|
||||||
snipe: {
|
sticky: {
|
||||||
range: 5,
|
range: 3,
|
||||||
damage: 150,
|
damage: 10,
|
||||||
rate: 100,
|
rate: 30,
|
||||||
name: 'Sniper',
|
name: 'Sticky',
|
||||||
description: 'Slow but powerful shots',
|
description: 'Slow down enemies by damage',
|
||||||
speed: 50,
|
speed: 50,
|
||||||
cost: 500,
|
cost: 500,
|
||||||
icon: '#4f3'
|
icon: '#4f3',
|
||||||
|
bullet: 2
|
||||||
|
},
|
||||||
|
snipe: {
|
||||||
|
range: 10,
|
||||||
|
damage: 1500,
|
||||||
|
rate: 100,
|
||||||
|
name: 'Sniper',
|
||||||
|
description: 'Slow firing but always kills',
|
||||||
|
speed: 50,
|
||||||
|
cost: 1000,
|
||||||
|
icon: '#4f3',
|
||||||
|
bullet: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,12 +175,114 @@ window.onload = function () {
|
|||||||
class Component {
|
class Component {
|
||||||
constructor (x, y) {
|
constructor (x, y) {
|
||||||
this.visible = true
|
this.visible = true
|
||||||
|
this.elements = []
|
||||||
this.x = x
|
this.x = x
|
||||||
this.y = y
|
this.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
draw () {}
|
elDraw() {
|
||||||
update() {}
|
for (let i in this.elements) {
|
||||||
|
let elem = this.elements[i]
|
||||||
|
if (elem instanceof Component) {
|
||||||
|
elem.draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
elUpdate() {
|
||||||
|
for (let i in this.elements) {
|
||||||
|
let elem = this.elements[i]
|
||||||
|
if (elem instanceof Component) {
|
||||||
|
elem.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addElement (el) {
|
||||||
|
if (!(el instanceof Component)) return
|
||||||
|
this.elements.push(el)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw () {
|
||||||
|
this.elDraw()
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.elUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tooltip extends Component {
|
||||||
|
constructor () {
|
||||||
|
super(0, 0)
|
||||||
|
this.font = '20px Helvetica'
|
||||||
|
this.text = ''
|
||||||
|
this.w = 0
|
||||||
|
this.h = 24
|
||||||
|
this.components = []
|
||||||
|
this.visible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
static assign (tooltip, component, text) {
|
||||||
|
tooltip.addComponent(component, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
setText (str) {
|
||||||
|
if (this.text === str) return
|
||||||
|
this.text = str
|
||||||
|
if (this.font) ctx.font = this.font
|
||||||
|
this.w = ctx.measureText(this.text).width + this.h
|
||||||
|
}
|
||||||
|
|
||||||
|
draw () {
|
||||||
|
if (!this.visible) return
|
||||||
|
if (this.text === '') return
|
||||||
|
if (this.font) ctx.font = this.font
|
||||||
|
|
||||||
|
let aX = this.x
|
||||||
|
let aY = this.y
|
||||||
|
|
||||||
|
if (aX + this.w > canvas.width) {
|
||||||
|
aX -= this.w + 5
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)'
|
||||||
|
ctx.fillRect(aX, aY, this.w, this.h)
|
||||||
|
|
||||||
|
ctx.fillStyle = '#000'
|
||||||
|
ctx.fillText(this.text, aX + this.h / 2, aY + this.h / 2 + 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition (x, y) {
|
||||||
|
this.x = x
|
||||||
|
this.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
update () {
|
||||||
|
if (this.components.length) {
|
||||||
|
let cmps = false
|
||||||
|
for (let i in this.components) {
|
||||||
|
let cmp = this.components[i]
|
||||||
|
if (mXr > cmp.x && mYr > cmp.y &&
|
||||||
|
mXr < cmp.x + cmp.w && mYr < cmp.y + cmp.h) {
|
||||||
|
this.setPosition(mXr, mYr)
|
||||||
|
this.setText(cmp.text)
|
||||||
|
cmps = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.visible = cmps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addComponent (component, text) {
|
||||||
|
this.components.push({
|
||||||
|
x: component.x,
|
||||||
|
y: component.y,
|
||||||
|
w: component.w,
|
||||||
|
h: component.h,
|
||||||
|
text: text
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ButtonComponent extends Component {
|
class ButtonComponent extends Component {
|
||||||
@ -197,9 +317,19 @@ window.onload = function () {
|
|||||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.45)'
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.45)'
|
||||||
ctx.fillRect(this.x, this.y, this.w, this.h)
|
ctx.fillRect(this.x, this.y, this.w, this.h)
|
||||||
} else if (this.hovered) {
|
} else if (this.hovered) {
|
||||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.25)'
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.15)'
|
||||||
ctx.fillRect(this.x, this.y, this.w, this.h)
|
ctx.fillRect(this.x, this.y, this.w, this.h)
|
||||||
}
|
}
|
||||||
|
this.elDraw()
|
||||||
|
}
|
||||||
|
|
||||||
|
update () {
|
||||||
|
if (!this.visible || this.disabled) return
|
||||||
|
if (mXr > this.x && mYr > this.y && mXr < this.x + this.w && mYr < this.y + this.h) {
|
||||||
|
this.hovered = true
|
||||||
|
} else if (this.hovered) {
|
||||||
|
this.hovered = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setDisabled (disable) {
|
setDisabled (disable) {
|
||||||
@ -222,13 +352,23 @@ window.onload = function () {
|
|||||||
this.textColor = '#fff'
|
this.textColor = '#fff'
|
||||||
this.color = '#995522'
|
this.color = '#995522'
|
||||||
this.fn = this.select
|
this.fn = this.select
|
||||||
this.font = '14px Helvetica'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select () {
|
select () {
|
||||||
Game.tower = this.tower
|
Game.tower = this.tower
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addTooltip () {
|
||||||
|
Tooltip.assign(Components.tooltip, this, this.towerObj.description)
|
||||||
|
}
|
||||||
|
|
||||||
|
update () {
|
||||||
|
super.update()
|
||||||
|
this.disabled = this.towerObj.cost > Game.money
|
||||||
|
this.active = Game.tower === this.tower
|
||||||
|
this.elUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
draw () {
|
draw () {
|
||||||
if (!this.visible) return
|
if (!this.visible) return
|
||||||
if (this.active) {
|
if (this.active) {
|
||||||
@ -261,26 +401,113 @@ window.onload = function () {
|
|||||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.45)'
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.45)'
|
||||||
ctx.fillRect(this.x, this.y, this.w, this.h)
|
ctx.fillRect(this.x, this.y, this.w, this.h)
|
||||||
} else if (this.hovered) {
|
} else if (this.hovered) {
|
||||||
ctx.fillStyle = 'rgba(255, 255, 255, 0.25)'
|
ctx.fillStyle = 'rgba(255, 255, 255, 0.15)'
|
||||||
ctx.fillRect(this.x, this.y, this.w, this.h)
|
ctx.fillRect(this.x, this.y, this.w, this.h)
|
||||||
}
|
}
|
||||||
|
this.elDraw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickBtn () {
|
class InfoDialog extends Component {
|
||||||
|
constructor () {
|
||||||
|
super()
|
||||||
|
this.x = 0
|
||||||
|
this.y = (Maps.height - 5) * Maps.tile
|
||||||
|
this.w = Maps.width * Maps.tile
|
||||||
|
this.h = 5 * Maps.tile
|
||||||
|
this.createButton()
|
||||||
|
}
|
||||||
|
|
||||||
|
createButton () {
|
||||||
|
let btn = new ButtonComponent('Sell Tower', '#fff', '#f11', 490, 590, 140, 40, () => {
|
||||||
|
if (Game.towerSel) {
|
||||||
|
sellTower(Game.towerSel.x, Game.towerSel.y)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
btn.update = function () {
|
||||||
|
this.visible = Game.towerSel !== null
|
||||||
|
if (!this.visible) return
|
||||||
|
if (mXr > this.x && mYr > this.y && mXr < this.x + this.w && mYr < this.y + this.h) {
|
||||||
|
this.hovered = true
|
||||||
|
} else if (this.hovered) {
|
||||||
|
this.hovered = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addElement(btn)
|
||||||
|
}
|
||||||
|
|
||||||
|
draw () {
|
||||||
|
if (Game.towerSel) {
|
||||||
|
let ts = Game.towerSel
|
||||||
|
|
||||||
|
ctx.fillStyle = 'rgba(0, 0, 0, 0.45)'
|
||||||
|
ctx.fillRect(this.x, this.y, this.w, this.h)
|
||||||
|
|
||||||
|
ctx.fillStyle = '#fff'
|
||||||
|
ctx.font = '25px Helvetica'
|
||||||
|
ctx.fillText(ts.name + ' Tower', 5, this.y + 25)
|
||||||
|
|
||||||
|
ctx.font = '15px Helvetica'
|
||||||
|
ctx.fillText(ts.description, 5, this.y + 42)
|
||||||
|
|
||||||
|
ctx.fillText('Range: ' + ts.range + ' tiles', 5, this.y + 70)
|
||||||
|
ctx.fillText('Damage: ' + ts.damage + ' HP', 5, this.y + 85)
|
||||||
|
ctx.fillText('Fire Rate: ' + ts.rate, 5, this.y + 100)
|
||||||
|
ctx.fillText('Kills: ' + ts.killcount, 5, this.y + 115)
|
||||||
|
ctx.fillText('Fired ' + ts.fires + ' times', 5, this.y + 130)
|
||||||
|
}
|
||||||
|
this.elDraw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickBtn (cmp) {
|
||||||
let click = false
|
let click = false
|
||||||
for (let i in Components) {
|
let compList = cmp != null && cmp instanceof Component ? cmp.elements : null
|
||||||
let btn = Components[i]
|
if (cmp == null && compList == null) {
|
||||||
if (!(btn instanceof ButtonComponent)) continue
|
compList = Components
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in compList) {
|
||||||
|
let btn = compList[i]
|
||||||
|
|
||||||
|
if (!(btn instanceof ButtonComponent)) {
|
||||||
|
// Loop through sub-components of components
|
||||||
|
if (btn.elements.length) {
|
||||||
|
click = clickBtn(btn)
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Click the button if its in bounds, visible and not disabled
|
||||||
if (btn.disabled || !btn.visible) continue
|
if (btn.disabled || !btn.visible) continue
|
||||||
if (mXr > btn.x && mYr > btn.y && mXr < btn.x + btn.w && mYr < btn.y + btn.h) {
|
if (mXr > btn.x && mYr > btn.y && mXr < btn.x + btn.w && mYr < btn.y + btn.h && btn) {
|
||||||
btn.fn()
|
btn.fn()
|
||||||
click = true
|
click = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return click
|
return click
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateComponents (cmp) {
|
||||||
|
// Determine which object of components to update
|
||||||
|
let compList = cmp != null && cmp instanceof Component ? cmp.elements : null
|
||||||
|
if (cmp == null && compList == null) {
|
||||||
|
compList = Components
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in compList) {
|
||||||
|
let component = compList[i]
|
||||||
|
component.update()
|
||||||
|
|
||||||
|
if (component.elements.length) {
|
||||||
|
updateComponents(component)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use this function to spawn enemies depending on round
|
// Use this function to spawn enemies depending on round
|
||||||
function nextWave () {
|
function nextWave () {
|
||||||
Game.wave++
|
Game.wave++
|
||||||
@ -303,7 +530,7 @@ window.onload = function () {
|
|||||||
// Use this function to modify the enemies spawned each round
|
// Use this function to modify the enemies spawned each round
|
||||||
function waveEnemyModifer (enemy, round) {
|
function waveEnemyModifer (enemy, round) {
|
||||||
// Reduce the time between enemy spawns
|
// Reduce the time between enemy spawns
|
||||||
let fr = enemy.frequency - 2 * round
|
let fr = enemy.frequency - 5 * round
|
||||||
if (fr < 100) {
|
if (fr < 100) {
|
||||||
fr = 100
|
fr = 100
|
||||||
}
|
}
|
||||||
@ -400,6 +627,8 @@ window.onload = function () {
|
|||||||
target = enemiesProxima[enemiesProxima.length - 1]
|
target = enemiesProxima[enemiesProxima.length - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tower.fires++
|
||||||
|
|
||||||
Game.particles.push({
|
Game.particles.push({
|
||||||
x: tower.x,
|
x: tower.x,
|
||||||
y: tower.y,
|
y: tower.y,
|
||||||
@ -408,9 +637,9 @@ window.onload = function () {
|
|||||||
velY: (target.y - tower.y) / target.dist * 1.24,
|
velY: (target.y - tower.y) / target.dist * 1.24,
|
||||||
dmg: tower.damage,
|
dmg: tower.damage,
|
||||||
speed: tower.speed,
|
speed: tower.speed,
|
||||||
life: 100
|
type: tower.bullet || 1,
|
||||||
|
life: 30
|
||||||
})
|
})
|
||||||
tower.fires++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function tickTowers () {
|
function tickTowers () {
|
||||||
@ -446,6 +675,7 @@ window.onload = function () {
|
|||||||
if (parti.x >= enemy.x - 0.25 && parti.y >= enemy.y - 0.25 &&
|
if (parti.x >= enemy.x - 0.25 && parti.y >= enemy.y - 0.25 &&
|
||||||
parti.x <= enemy.x + 0.5 && parti.y <= enemy.y + 0.5) {
|
parti.x <= enemy.x + 0.5 && parti.y <= enemy.y + 0.5) {
|
||||||
// damage enemy
|
// damage enemy
|
||||||
|
if (parti.type === 1) {
|
||||||
enemy.dmg -= parti.dmg
|
enemy.dmg -= parti.dmg
|
||||||
|
|
||||||
if (enemy.dmg <= 0) {
|
if (enemy.dmg <= 0) {
|
||||||
@ -457,6 +687,12 @@ window.onload = function () {
|
|||||||
tower.killcount++
|
tower.killcount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (parti.type === 2) {
|
||||||
|
enemy.speed -= parti.dmg
|
||||||
|
if (enemy.speed < 2) {
|
||||||
|
enemy.speed = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// remove particle
|
// remove particle
|
||||||
Game.particles.splice(i, 1)
|
Game.particles.splice(i, 1)
|
||||||
@ -576,7 +812,7 @@ window.onload = function () {
|
|||||||
|
|
||||||
function sellTower (x, y) {
|
function sellTower (x, y) {
|
||||||
let tower = getTowerAt(x, y)
|
let tower = getTowerAt(x, y)
|
||||||
if(tower) {
|
if (tower) {
|
||||||
let amount = tower.cost * Game.sellRatio
|
let amount = tower.cost * Game.sellRatio
|
||||||
Game.money += amount
|
Game.money += amount
|
||||||
Game.selltext.push({
|
Game.selltext.push({
|
||||||
@ -591,12 +827,13 @@ window.onload = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Game.towers.splice(Game.towers.indexOf(tower), 1)
|
return Game.towers.splice(Game.towers.indexOf(tower), 1)
|
||||||
}else{
|
} else {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function update (dt) {
|
function update (dt) {
|
||||||
|
// Update FPS count for drawing (Don't render a new number every frame, it changes too fast)
|
||||||
fpsCount++
|
fpsCount++
|
||||||
fpsCount %= 20
|
fpsCount %= 20
|
||||||
if (fpsCount === 0) {
|
if (fpsCount === 0) {
|
||||||
@ -608,32 +845,25 @@ window.onload = function () {
|
|||||||
tickTowers()
|
tickTowers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move enemies
|
||||||
updateEnemyMovements()
|
updateEnemyMovements()
|
||||||
|
|
||||||
|
// Move bullets
|
||||||
tickParticles()
|
tickParticles()
|
||||||
|
|
||||||
|
// Move sell texts
|
||||||
tickSellText()
|
tickSellText()
|
||||||
|
|
||||||
for (let i in Components) {
|
// Update all components (eg buttons)
|
||||||
let btn = Components[i]
|
updateComponents()
|
||||||
if (btn instanceof ButtonComponent) {
|
|
||||||
if (mXr > btn.x && mYr > btn.y && mXr < btn.x + btn.w && mYr < btn.y + btn.h) {
|
|
||||||
btn.hovered = true
|
|
||||||
} else if (btn.hovered) {
|
|
||||||
btn.hovered = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (btn instanceof TowerButton) {
|
|
||||||
btn.disabled = btn.towerObj.cost > Game.money
|
|
||||||
btn.active = Game.tower === i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Set the state
|
||||||
updateGameState()
|
updateGameState()
|
||||||
|
|
||||||
|
// Increment game clock
|
||||||
if (Game.state === 1) {
|
if (Game.state === 1) {
|
||||||
Game.waveTimer++
|
Game.waveTimer++
|
||||||
}
|
}
|
||||||
|
|
||||||
Components.sell.visible = Game.towerSel !== null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function render () {
|
function render () {
|
||||||
@ -641,6 +871,7 @@ window.onload = function () {
|
|||||||
ctx.fillStyle = '#0fa'
|
ctx.fillStyle = '#0fa'
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||||
|
|
||||||
|
// Draw the map
|
||||||
for (let i in Game.map.tiles) {
|
for (let i in Game.map.tiles) {
|
||||||
let tile = Game.map.tiles[i]
|
let tile = Game.map.tiles[i]
|
||||||
let index = parseInt(i)
|
let index = parseInt(i)
|
||||||
@ -658,28 +889,34 @@ window.onload = function () {
|
|||||||
draw_tile = false
|
draw_tile = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if(draw_tile) {
|
if (draw_tile) {
|
||||||
ctx.fillRect(x * mt, y * mt, mt, mt)
|
ctx.fillRect(x * mt, y * mt, mt, mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Game.state == 2 && tile == 0 && !getTowerAt(x, y) && !canPlaceTowerAt(x, y)) {
|
// Draw obstructed tiles
|
||||||
|
if (Game.state == 2 && tile == 0 && !getTowerAt(x, y) && !canPlaceTowerAt(x, y)) {
|
||||||
ctx.fillStyle = 'rgba(255, 0, 0, 0.45)'
|
ctx.fillStyle = 'rgba(255, 0, 0, 0.45)'
|
||||||
ctx.fillRect(x * mt, y * mt, mt, mt)
|
ctx.fillRect(x * mt, y * mt, mt, mt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
|
// Show the enemy movement path
|
||||||
|
if (Game.debug) {
|
||||||
for (let i in Game.map.pathgen) {
|
for (let i in Game.map.pathgen) {
|
||||||
let node = Game.map.pathgen[i]
|
let node = Game.map.pathgen[i]
|
||||||
ctx.fillStyle = '#00f'
|
ctx.fillStyle = '#00f'
|
||||||
ctx.fillRect((node.x * mt) + mt / 3, (node.y * mt) + mt / 3, 8, 8)
|
ctx.fillRect((node.x * mt) + mt / 3, (node.y * mt) + mt / 3, 8, 8)
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
// Draw towers
|
||||||
for (let i in Game.towers) {
|
for (let i in Game.towers) {
|
||||||
let tower = Game.towers[i]
|
let tower = Game.towers[i]
|
||||||
ctx.fillStyle = tower.icon
|
ctx.fillStyle = tower.icon
|
||||||
ctx.fillRect(tower.x * mt + 2, tower.y * mt + 2, 28, 28)
|
ctx.fillRect(tower.x * mt + 2, tower.y * mt + 2, 28, 28)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw enemies
|
||||||
for (let i in Game.enemies) {
|
for (let i in Game.enemies) {
|
||||||
let enemy = Game.enemies[i]
|
let enemy = Game.enemies[i]
|
||||||
let rx = (enemy.x * mt) + mt / 8
|
let rx = (enemy.x * mt) + mt / 8
|
||||||
@ -697,13 +934,14 @@ window.onload = function () {
|
|||||||
ctx.fillRect(hx, hy, (16 + 12) * enemy.dmg / enemy.health, 5)
|
ctx.fillRect(hx, hy, (16 + 12) * enemy.dmg / enemy.health, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw bullets
|
||||||
for (let i in Game.particles) {
|
for (let i in Game.particles) {
|
||||||
let tower = Game.particles[i]
|
let tower = Game.particles[i]
|
||||||
ctx.fillStyle = '#f33'
|
ctx.fillStyle = '#f33'
|
||||||
ctx.fillRect(tower.x * mt + mt / 16, tower.y * mt + mt / 16, 8, 8)
|
ctx.fillRect(tower.x * mt + mt / 16, tower.y * mt + mt / 16, 8, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tower range visualization
|
// Tower range visualization
|
||||||
let towerData = Towers[Game.tower]
|
let towerData = Towers[Game.tower]
|
||||||
let vX = null
|
let vX = null
|
||||||
let vY = null
|
let vY = null
|
||||||
@ -730,6 +968,7 @@ window.onload = function () {
|
|||||||
ctx.closePath()
|
ctx.closePath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render sell text
|
||||||
for (let i in Game.selltext) {
|
for (let i in Game.selltext) {
|
||||||
let txt = Game.selltext[i]
|
let txt = Game.selltext[i]
|
||||||
ctx.font = '12px Helvetica'
|
ctx.font = '12px Helvetica'
|
||||||
@ -737,9 +976,11 @@ window.onload = function () {
|
|||||||
ctx.fillText('+ $' + txt.amount, txt.x * mt, txt.y * mt)
|
ctx.fillText('+ $' + txt.amount, txt.x * mt, txt.y * mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render sidebar background
|
||||||
ctx.fillStyle = '#996633'
|
ctx.fillStyle = '#996633'
|
||||||
ctx.fillRect(640, 0, 240, 640)
|
ctx.fillRect(640, 0, 240, 640)
|
||||||
|
|
||||||
|
// Render sidebar text
|
||||||
ctx.font = '20px Helvetica'
|
ctx.font = '20px Helvetica'
|
||||||
ctx.fillStyle = '#fff'
|
ctx.fillStyle = '#fff'
|
||||||
ctx.fillText('FPS: ' + fpsDraw.toFixed(2), 0, 20)
|
ctx.fillText('FPS: ' + fpsDraw.toFixed(2), 0, 20)
|
||||||
@ -747,43 +988,24 @@ window.onload = function () {
|
|||||||
ctx.fillText('Health: ' + Game.health, 645, 45)
|
ctx.fillText('Health: ' + Game.health, 645, 45)
|
||||||
ctx.fillText('Money: ' + Game.money, 645, 65)
|
ctx.fillText('Money: ' + Game.money, 645, 65)
|
||||||
|
|
||||||
|
// Game Over text
|
||||||
if (Game.state === -1) {
|
if (Game.state === -1) {
|
||||||
ctx.font = '80px Helvetica'
|
ctx.font = '80px Helvetica'
|
||||||
ctx.fillStyle = '#f00'
|
ctx.fillStyle = '#f00'
|
||||||
ctx.fillText('Game Over', 100, canvas.height / 2 - 80 / 2)
|
ctx.fillText('Game Over', 100, canvas.height / 2 - 80 / 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw mouse cursor
|
||||||
if (mX < Maps.width && mY < Maps.height) {
|
if (mX < Maps.width && mY < Maps.height) {
|
||||||
ctx.fillStyle = 'rgba(255, 0, 0, 0.24)'
|
ctx.fillStyle = 'rgba(255, 0, 0, 0.24)'
|
||||||
ctx.fillRect(mX * mt, mY * mt, mt, mt)
|
ctx.fillRect(mX * mt, mY * mt, mt, mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render a selection information box
|
// Draw all components
|
||||||
// TODO: component
|
|
||||||
if (Game.towerSel) {
|
|
||||||
let by = (Maps.height - 5) * Maps.tile
|
|
||||||
let ts = Game.towerSel
|
|
||||||
|
|
||||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.45)'
|
|
||||||
ctx.fillRect(0, by, Maps.width * Maps.tile, 5 * Maps.tile)
|
|
||||||
|
|
||||||
ctx.fillStyle = '#fff'
|
|
||||||
ctx.font = '25px Helvetica'
|
|
||||||
ctx.fillText(ts.name + ' Tower', 5, by + 25)
|
|
||||||
|
|
||||||
ctx.font = '15px Helvetica'
|
|
||||||
ctx.fillText(ts.description, 5, by + 42)
|
|
||||||
|
|
||||||
ctx.fillText('Range: ' + ts.range + ' tiles', 5, by + 70)
|
|
||||||
ctx.fillText('Damage: ' + ts.damage + ' HP', 5, by + 85)
|
|
||||||
ctx.fillText('Fire Rate: ' + ts.rate, 5, by + 100)
|
|
||||||
ctx.fillText('Kills: ' + ts.killcount, 5, by + 115)
|
|
||||||
ctx.fillText('Fired ' + ts.fires + ' times', 5, by + 130)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i in Components) {
|
for (let i in Components) {
|
||||||
let btn = Components[i]
|
let cmp = Components[i]
|
||||||
btn.draw()
|
if (!(cmp) instanceof Component) continue
|
||||||
|
cmp.draw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,6 +1017,7 @@ window.onload = function () {
|
|||||||
update()
|
update()
|
||||||
render()
|
render()
|
||||||
|
|
||||||
|
// Update FPS
|
||||||
let cfps = 1000 / ((now = new Date) - lastTime)
|
let cfps = 1000 / ((now = new Date) - lastTime)
|
||||||
if (now != lastTime) {
|
if (now != lastTime) {
|
||||||
fps += (cfps - fps) / fpsRes
|
fps += (cfps - fps) / fpsRes
|
||||||
@ -812,19 +1035,25 @@ window.onload = function () {
|
|||||||
updateGameState(1)
|
updateGameState(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Tower sell button
|
// Tower information box
|
||||||
Components.sell = new ButtonComponent('Sell Tower', '#fff', '#f11', 490, 590, 140, 40, () => {
|
Components.info = new InfoDialog()
|
||||||
if (Game.towerSel) {
|
|
||||||
sellTower(Game.towerSel.x, Game.towerSel.y)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
// Add buy buttons to every tower
|
||||||
let index = 0
|
let index = 0
|
||||||
for (let i in Towers) {
|
for (let i in Towers) {
|
||||||
Components[i] = new TowerButton(i, index)
|
Components[i] = new TowerButton(i, index)
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tooltip
|
||||||
|
Components.tooltip = new Tooltip()
|
||||||
|
for (let i in Towers) {
|
||||||
|
let cmp = Components[i]
|
||||||
|
if (!cmp) continue
|
||||||
|
Components.tooltip.addComponent(cmp, cmp.towerObj.description)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the game
|
||||||
gameLoop()
|
gameLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user