not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

495 lines
14 KiB

// Play class
enyo.kind({
name: "TankOp.Play",
kind: enyo.Control,
classes: "board",
published: { level: 0 },
components: [
// Playing zone
{name: "gamebox", classes: "game-box", ontap: "gameClick", components: [
]},
// Status and score
{classes: "status-line", components: [
{name: "wavetext", classes: "wave-text no-select-content"},
{name: "wave", content: "1", classes: "wave-value no-select-content"},
{name: "scoretext", classes: "score-text no-select-content"},
{name: "score", content: "0000", classes: "score-value no-select-content"}
]},
// Home button
{kind: "Image", classes: "home-button no-select-content", src: "images/gohome.png", ontap: "goHome"},
// LCD counter and Keyboard
{name: "keyboard", classes: "keyboard-set no-select-content", components: [
{classes: "display-line", components: [
{name: "lcd", kind: "LcdDisplay", classes: "lcd-value", size: 3, value: ""}
]},
{classes: "keyboard-line", components: [
{kind: "Image", src: "images/key_1.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_2.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_3.svg", classes: "keyboard", ontap: "virtkeyPressed"}
]},
{classes: "keyboard_line", components: [
{kind: "Image", src: "images/key_4.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_5.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_6.svg", classes: "keyboard", ontap: "virtkeyPressed"}
]},
{classes: "keyboard_line", components: [
{kind: "Image", src: "images/key_7.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_8.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_9.svg", classes: "keyboard", ontap: "virtkeyPressed"}
]},
{classes: "keyboard_line", components: [
{kind: "Image", src: "images/key_0.svg", classes: "keyboard", ontap: "virtkeyPressed"},
{kind: "Image", src: "images/key_fire.svg", classes: "keyboard", ontap: "virtkeyPressed"}
]}
]},
// Key handling
{kind: "Signals", onkeypress: "keyPressed"},
// Image cache
{kind: "ImageCache", showing: false, onCacheLoaded: "cacheLoaded"}
],
// Constructor
create: function() {
this.inherited(arguments);
play = this;
this.imagesToLoad++;
this.endOfGame = false;
this.pausedGame = true;
this.initializedGame = false;
this.waitForClick = false;
// Init canvas
var wsize = document.body.clientWidth;
if (wsize <= 480) {
this.zoom = 0.4;
} else if (wsize <= 640) {
this.zoom = 0.55;
} else if (wsize <= 768) {
this.zoom = 0.62;
} else if (wsize <= 854) {
this.zoom = 0.65;
} else if (wsize <= 960) {
this.zoom = 0.75;
} else if (wsize <= 1024) {
this.zoom = 0.88;
} else {
this.zoom = 1;
}
this.$.gamebox.setStyle("max-height: "+(this.zoom*constant.areaHeight)+"px;");
this.canvas = this.$.gamebox.createComponent({kind: "Canvas", id: "acanvas", name: "canvas", attributes: {width: constant.areaWidth, height: constant.areaHeight}});
// Start game loop
this.loopTimer = window.setInterval(enyo.bind(this, "gameLoopTick"), constant.loopInterval);
},
// Init game
initGame: function() {
// Game init
var level = this.currentlevel = preferences.levels[this.level];
var settings_map = level.map;
var settings_hq = level.defense[0];
var settings_soldier = level.defense[1];
var settings_tank = level.defense[2];
var settings_canon = level.defense[3];
var settings_helo = level.defense[4];
// Init board
this.initializedGame = true;
this.game = util.createMap(preferences.gameMap(settings_map));
this.targetpos = {x: 7, y: 4};
this.$.wavetext.setContent(l10n.get("Wave"));
this.$.scoretext.setContent(l10n.get("Score"));
// Init units
var width = constant.boardWidth, height = constant.boardHeight;
var goodEngine = enyo.bind(this, "goodEngine");
this.units = []
// Set HQ
var step = constant.boardHeight/(settings_hq+1);
var hqs = [];
for (var i = 0 ; i < settings_hq ; i++) {
var hq = util.createUnit({type: "hq", color: "blue", x: 0, y: Math.floor((i+1)*step), engine: null});
this.units.push(hq);
hqs.push(hq);
}
// Create defending units
var defense = [];
for(var i = 0 ; i < settings_helo ; i++)
defense.push({type: "helo", color: "blue", engine: goodEngine});
for(var i = 0 ; i < settings_canon ; i++)
defense.push({type: "canon", color: "blue", engine: goodEngine});
for(var i = 0 ; i < settings_tank ; i++)
defense.push({type: "tank", color: "blue", engine: goodEngine});
for(var i = 0 ; i < settings_soldier ; i++)
defense.push({type: "soldier", color: "blue", engine: goodEngine});
// Set defense around hq
if (defense.length > 0) {
var hqindex = 0;
var defenselength = Math.min(defense.length, 1+hqs.length*2);
for (var i = 0 ; i < defenselength ; i++) {
var position = {};
do {
var arounds = [{dx: 1, dy: 0}, {dx: 0, dy: -1}, {dx: 0, dy: 1}];
for (j = 0 ; j < arounds.length ; j++) {
position = {x: hqs[hqindex].x+arounds[j].dx, y: hqs[hqindex].y+arounds[j].dy};
if (util.lookForUnit(position) == null)
break;
else
position = {x: -1, y: -1};
}
hqindex = (hqindex + 1) % hqs.length;
} while (position.x == -1);
defense[i].x = position.x;
defense[i].y = position.y;
this.units.push(util.createUnit(defense[i]));
}
}
// Prepare bad units arrival
this.score = 0;
this.wave = 1;
this.enemyCount = level.attack;
this.enemyWaveSize = constant.waveInitSize;
this.enemyNextWaveCount = constant.waveInitSize;
this.enemyWaveCount = 0;
this.enemyArrivalTurn = constant.startArrival;
// Let's Go !
this.pausedGame = false;
},
// Render
rendered: function() {
// Init game
if (!this.initializedGame) {
// Init context
this.initGame();
// Set zoom
this.canvas.hasNode().style.MozTransform = "scale("+this.zoom+")";
this.canvas.hasNode().style.MozTransformOrigin = "0 0";
this.canvas.hasNode().style.zoom = this.zoom;
}
},
cacheLoaded: function() {
},
// Draw
draw: function() {
// Clear all
var ctx = this.canvas.hasNode().getContext('2d');
ctx.clearRect(0, 0, this.canvas.attributes.width, this.canvas.attributes.height);
// Draw board
var grass = document.getElementById("grass");
var trees = document.getElementById("trees");
var mountain = document.getElementById("mountain");
var water = document.getElementById("water");
for (var i = 0 ; i < constant.boardHeight ; i++ ) {
for (var j = 0 ; j < constant.boardWidth ; j++ ) {
ctx.save();
ctx.translate(j*constant.tileSize, i*constant.tileSize);
ctx.drawImage(grass, 0, 0);
var tileType = this.game[i][j];
if (tileType == constant.tileTrees)
ctx.drawImage(trees, 0, 0);
else if (tileType == constant.tileMountain)
ctx.drawImage(mountain, 0, 0);
else if (tileType == constant.tileWater)
ctx.drawImage(water, 0, 0);
ctx.restore();
}
}
// Draw tanks
if (!this.endOfGame) {
for (var i = 0 ; i < this.units.length ; i++)
this.units[i].draw(ctx);
// Draw target
var target = document.getElementById("target");
ctx.save();
ctx.translate(this.targetpos.x*constant.tileSize, this.targetpos.y*constant.tileSize);
ctx.drawImage(target, 0, 0);
ctx.restore();
}
// End of game
else {
// Draw end of game screen
var endscreen = this.win ? document.getElementById("endgame_victory") : document.getElementById("endgame_defeat");
ctx.save();
ctx.translate((constant.areaWidth-constant.endGameWidth)/2, (constant.areaHeight-constant.endGameHeight)/2);
ctx.drawImage(endscreen, 0, 0);
ctx.restore();
// Play end of game sound
if (!this.waitForClick) {
sound.play(this.win ? "audio/mission_completed" : "audio/mission_failed", true);
this.waitForClick = true;
}
}
},
// A key was pressed
keyPressed: function(s, e) {
var key = e.charCode;
if (this.endOfGame)
return;
// Digit key
if (key >= 48 && key <= 57) {
// Add digit to string
var value = this.$.lcd.getValue();
if (value.length == this.$.lcd.getSize())
value = value.substr(1);
value += String.fromCharCode(key);
this.$.lcd.setValue(value);
}
// Dash key
else if (key == 45) {
this.$.lcd.setValue("-");
}
// Fire key
else if (key == 32) {
// Look for unit with the value
var units = util.lookForValue(this.$.lcd.getValue().replace(/ /g,''));
if (units.length != 0) {
for (var i = 0 ; i < units.length ; i++) {
util.processFight(null, units[i], constant.userPower);
this.targetpos.x = units[i].x;
this.targetpos.y = units[i].y;
}
}
else
sound.play("audio/missed");
this.$.lcd.setValue("");
}
},
// A virtual key is pressed
virtkeyPressed: function(s) {
var classes = s.getSrc().replace(".svg", "");
var value = classes.substr("images/key_".length,classes.indexOf("key_"));
if (value == "fire")
this.keyPressed(null, {charCode: 32});
else
this.keyPressed(null, {charCode: 48+parseInt(value)});
},
goHome: function() {
// Click at the end of game
if (this.waitForClick) {
this.gameClick();
return;
}
// Stop game loop
window.clearInterval(this.loopTimer);
// Back to app
app.init();
app.playTheme()
app.renderInto(document.getElementById("board"));
},
// A tap occur on the game
gameClick: function() {
// At end of game, quit
if (this.endOfGame) {
// Stop game loop
window.clearInterval(this.loopTimer);
// Set mission result
if (this.win) {
preferences.levels[this.level].completed = true;
app.nextMission();
app.save();
}
app.init();
// Back to app
app.renderInto(document.getElementById("board"));
}
// Compute direction
var screen_width = document.documentElement.clientWidth;
var screen_height = document.documentElement.clientHeight;
var center_x = Math.floor(screen_width/2.0);
var center_y = Math.floor((screen_height+constant.pubHeight)/2.0);
var diffx = mouse.position.x-center_x, diffy = mouse.position.y-center_y;
var absdiffx = Math.abs(diffx);
var absdiffy = Math.abs(diffy);
if (absdiffx >= 0 && absdiffx < constant.fireZoneWidth && absdiffy >= 0 && absdiffy < constant.fireZoneHeight) {
var targetunit = util.lookForUnit(this.targetpos);
if (targetunit != null)
util.processFight(null, targetunit);
return;
} else if (absdiffx > absdiffy) {
dx = diffx > 0 ? 1 : -1;
dy = 0;
} else {
dx = 0;
dy = diffy > 0 ? 1 : -1;
}
// Move target
var newX = this.targetpos.x + dx;
var newY = this.targetpos.y + dy;
if (newX < 0 || newX == constant.boardWidth || newY < 0 || newY == constant.boardHeight)
return;
this.targetpos.x = newX;
this.targetpos.y = newY;
},
// Tick for game loop
gameLoopTick: function() {
if (this.pausedGame)
return;
// Sanitize: clean dead units and compute victory/defeat conditions
var alives = [];
var hqs = [];
var livingHq = 0;
var livingEnemy = 0;
for (var i = 0 ; i < this.units.length ; i++) {
var unit = this.units[i];
var isRed = unit.getCurrentImage().indexOf("red") != -1;
if (unit.power > 0) {
alives.push(unit);
} else {
if (isRed) {
this.enemyNextWaveCount--;
this.score += util.unitPowers[util.getUnitType(unit)];
}
continue;
}
if (util.getUnitType(unit) == 0) {
hqs[livingHq++] = unit;
}
if (isRed)
livingEnemy++;
}
this.units = alives;
this.endOfGame = (livingHq == 0 || (livingEnemy == 0 && this.enemyCount == 0));
this.win = (livingHq > 0);
// Game play
if (!this.endOfGame) {
// Next wave
if (this.enemyNextWaveCount == 0) {
this.wave++;
this.enemyWaveSize += 2;
this.enemyWaveCount = 0;
this.enemyNextWaveCount = this.enemyWaveSize;
this.enemyArrivalTurn = constant.startArrival;
}
// Enemy arrival
else if (this.enemyWaveCount != this.enemyWaveSize) {
if (this.enemyArrivalTurn == 0 && this.enemyCount > 0) {
var badEngine = enyo.bind(this, "badEngine");
var unit = util.createUnit({
type: util.randomUnit(this.currentlevel.stats),
color: "red",
heading: 0,
engine: badEngine,
x: constant.boardWidth-1,
y: util.random(constant.boardHeight)
});
unit.value = this.currentlevel.generator();
this.units.push(unit);
this.enemyCount = this.enemyCount-1;
this.enemyWaveCount++;
this.enemyArrivalTurn = constant.startArrival;
} else {
this.enemyArrivalTurn = this.enemyArrivalTurn - 1;
}
}
// Launch engine for each unit
for (var i = 0 ; i < this.units.length ; i++) {
var engine = this.units[i].engine;
if (engine != null)
engine(this.units[i], hqs);
}
}
// Draw
this.draw();
// HACK: On Android, force redraw of canvas
if (enyo.platform.android && document.location.protocol.substr(0,4) != "http") {
document.getElementById('acanvas').style.display='none';
document.getElementById('acanvas').offsetHeight;
document.getElementById('acanvas').style.display='block';
}
// Draw score
this.$.wave.setContent(String("0000"+this.wave).slice(-4))
this.$.score.setContent(String("0000"+this.score).slice(-4))
},
// Engine for good tank moves
goodEngine: function(that, hqs) {
// Look for enemy unit
var opponent = util.lookForOpponent(that);
if (opponent != null) {
// Change heading toward opponent
that.heading = opponent.heading;
// Fight
util.processFight(that, opponent.unit);
return;
}
},
// Engine for bad tank moves
badEngine: function(that, hqs) {
// Look for enemy unit around
var opponent = util.lookForOpponent(that);
if (opponent != null) {
// Change heading toward opponent
that.heading = opponent.heading;
// Fight
util.processFight(that, opponent.unit);
return;
}
// Change heading to go toward the nearest HQ
var nearestHQ = util.nearestUnit(that, hqs);
if (nearestHQ != null) {
var dx = that.x - nearestHQ.x;
var dy = that.y - nearestHQ.y;
if (Math.abs(dx) > Math.abs(dy))
that.heading = dx > 0 ? 0 : 2;
else
that.heading = dy > 0 ? 1 : 3;
}
// Is it a valid position ?
var next = util.nextPositionOnHeading(that);
while (!util.isValidPosition(next, that)) {
// No, try a random heading
that.heading = util.random(4);
next = util.nextPositionOnHeading(that);
}
next = util.nextPositionOnHeading(that);
that.x = next.x;
that.y = next.y;
}
});