// Level config
|
|
FoodChain.buildLevels = [
|
|
{ size: 2, time: 2 }, // Level 1
|
|
{ size: 3, time: 5 }, // Level 2
|
|
{ size: 3, time: 3 }, // Level 3
|
|
{ size: 3, time: 2 }, // Level 4
|
|
{ size: 4, time: 5 }, // Level 5
|
|
{ size: 4, time: 3 }, // Level 6
|
|
{ size: 5, time: 3 } // Level 7
|
|
];
|
|
|
|
// Build Game class
|
|
enyo.kind({
|
|
name: "FoodChain.BuildGame",
|
|
kind: enyo.Control,
|
|
published: {level: 1},
|
|
classes: "board",
|
|
components: [
|
|
{ name: "cards", components: [
|
|
// Level - Score - Time bar
|
|
{ components: [
|
|
{ classes: "level-zone", components: [
|
|
{ name: "textlevel", classes: "title level-value" },
|
|
{ name: "level", content: "0", classes: "title level-value" }
|
|
]},
|
|
{ classes: "score-zone", components: [
|
|
{ name: "textscore", classes: "title score-text" },
|
|
{ name: "score", content: "0000", classes: "title score-value" },
|
|
{ name: "timercount", content: "0:0,0", classes: "title timer-value" }
|
|
]}
|
|
]},
|
|
|
|
// Board zone
|
|
{ name: "gamebox", classes: "box", ontap: "unselect", ondrop: "drop", ondragover: "dragover", components: [] },
|
|
|
|
// Buttons bar
|
|
{ name: "validate", kind: "ShadowButton", img: "validate", classes: "validate", ontap: "controlOrder" },
|
|
{ name: "play", kind: "ShadowButton", img: "play", classes: "play", ontap: "play" },
|
|
{ name: "pause", kind: "ShadowButton", img: "pause", classes: "play", ontap: "pause" },
|
|
{ name: "restart", kind: "ShadowButton", img: "restart", classes: "restart", ontap: "restart" },
|
|
{ name: "forward", kind: "ShadowButton", img: "forward", classes: "restart", ontap: "next" },
|
|
{ name: "home", kind: "ShadowButton", img: "home", classes: "home", ontap: "home" },
|
|
|
|
// End of sound event
|
|
{kind: "enyo.Signals", onEndOfSound: "endSound"}
|
|
]}
|
|
],
|
|
|
|
// Constructor
|
|
create: function() {
|
|
this.inherited(arguments);
|
|
this.previous = null;
|
|
this.mixed = null;
|
|
this.createComponent({ name: "timer", kind: "Timer", paused: true, onTriggered: "updateTimer" }, {owner: this});
|
|
this.setLocale();
|
|
this.$.score.setContent(String("0000"+FoodChain.context.score).slice(-4));
|
|
FoodChain.context.game = this.kindName;
|
|
this.levelChanged();
|
|
},
|
|
|
|
// Localization changed, update cards and string resource
|
|
setLocale: function() {
|
|
// Update string resources
|
|
this.$.textlevel.setContent(__$FC("level"));
|
|
this.$.textscore.setContent(__$FC("score"));
|
|
|
|
// Update cards
|
|
enyo.forEach(this.$.gamebox.getControls(), function(card) {
|
|
card.setLocale();
|
|
});
|
|
},
|
|
|
|
// Level changed, init board then start game
|
|
levelChanged: function() {
|
|
// Delete current cards on board
|
|
FoodChain.context.level = this.level;
|
|
var cards = [];
|
|
enyo.forEach(this.$.gamebox.getControls(), function(card) {
|
|
cards.push(card);
|
|
});
|
|
for (var i = 0 ; i < cards.length ; i++) {
|
|
cards[i].destroy();
|
|
}
|
|
|
|
// Compute the start chain
|
|
if (this.mixed == null) {
|
|
var same;
|
|
do {
|
|
// Pick a random chain and ensure it's not the same that the previous one
|
|
this.chain = FoodChain.randomChain(FoodChain.buildLevels[this.level-1].size);
|
|
if (this.previous == null || this.previous.length != this.chain.length) {
|
|
same = false;
|
|
} else {
|
|
same = true;
|
|
for (var i = 0 ; same && i < this.chain.length ; i++ ) {
|
|
if (this.previous[i] != this.chain[i])
|
|
same = false;
|
|
}
|
|
}
|
|
} while (same);
|
|
this.mixed = FoodChain.mix(this.chain);
|
|
}
|
|
|
|
// Display cards
|
|
var step = 99/this.mixed.length;
|
|
var x = 5-this.mixed.length, y = 8;
|
|
this.cards = [];
|
|
for (var i = 0 ; i < this.mixed.length ; i++) {
|
|
var autoplay = (i == 0) ? true: false;
|
|
this.cards.push(this.$.gamebox.createComponent({ kind: "FoodChain.Card", cardname: this.mixed[i], x: x+"%", y: y, ontap: "taped", ondragstart: "dragstart", ondragfinish: "dragfinish"}, {owner: this}));
|
|
if (i == 0) {
|
|
FoodChain.sound.play(this.cards[i].sound);
|
|
} else {
|
|
this.cards[i].hide();
|
|
}
|
|
x = x + step;
|
|
}
|
|
|
|
// Box handling
|
|
this.dragobject = null;
|
|
this.selectedobject = null;
|
|
this.zmax = 0;
|
|
this.$.gamebox.removeClass("box-win");
|
|
this.$.gamebox.removeClass("box-lost");
|
|
|
|
// Saving context
|
|
FoodChain.saveContext();
|
|
|
|
// Button handling
|
|
this.$.play.hide();
|
|
this.$.pause.show();
|
|
this.$.validate.show();
|
|
this.$.restart.hide();
|
|
this.$.forward.hide();
|
|
this.$.home.hide();
|
|
|
|
// Timer and level init
|
|
this.$.level.setContent(" "+this.level);
|
|
this.timecount = {mins:0, secs:0, tenth:0};
|
|
this.$.timercount.removeClass("timer-overtime");
|
|
this.displayTimer();
|
|
this.$.timer.pause();
|
|
|
|
this.render();
|
|
},
|
|
|
|
// Sound ended, play next card if any
|
|
endSound: function(e, s) {
|
|
// All is already displayed
|
|
if (this.cards == null)
|
|
return;
|
|
|
|
// Display next card
|
|
for (var i = 0 ; i < this.cards.length ; i++ ) {
|
|
if (this.cards[i] != null && FoodChain.soundMatch(this.cards[i].sound,s.sound)) {
|
|
this.cards[i] = null;
|
|
if (i+1 < this.cards.length) {
|
|
this.cards[i+1].show();
|
|
FoodChain.sound.play(this.cards[i+1].sound);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// All card displayed, start timer
|
|
this.cards = null;
|
|
this.$.timer.resume();
|
|
},
|
|
|
|
// Display timer value
|
|
displayTimer: function() {
|
|
this.$.timercount.setContent(this.timecount.mins+":"+String("00"+this.timecount.secs).slice(-2)+","+this.timecount.tenth);
|
|
},
|
|
|
|
// Update timer
|
|
updateTimer: function(s, e) {
|
|
this.timecount.tenth = this.timecount.tenth + 1;
|
|
if (this.timecount.tenth == 10) {
|
|
this.timecount.tenth = 0;
|
|
this.timecount.secs = this.timecount.secs + 1;
|
|
var currentcount = this.timecount.mins * 60 + this.timecount.secs;
|
|
if (currentcount >= FoodChain.buildLevels[this.level-1].time) {
|
|
this.$.timercount.addClass("timer-overtime");
|
|
}
|
|
if (this.timecount.secs == 60) {
|
|
this.timecount.secs = 0;
|
|
this.timecount.mins = this.timecount.mins + 1;
|
|
}
|
|
}
|
|
this.displayTimer();
|
|
},
|
|
|
|
// Play sound when card taped, set card as selected (avoid need of drag&drop)
|
|
taped: function(s, e) {
|
|
if (this.$.timer.paused)
|
|
return true;
|
|
FoodChain.log(s.cardname+" taped");
|
|
|
|
// Use selection to avoid drag&drop
|
|
if (this.selectedobject == null) {
|
|
// No selection, set card as selected, play sound
|
|
this.selectedobject = s;
|
|
s.addClass("card-dragged");
|
|
FoodChain.sound.play(s.sound);
|
|
this.toTop(s);
|
|
return true;
|
|
} else if (s != this.selectedobject) {
|
|
// A card is already selected, swap the 2 card
|
|
var startx = this.selectedobject.getX(), starty = this.selectedobject.getY();
|
|
var endx = s.getX(), endy = s.getY();
|
|
this.selectedobject.moveTo(endx, endy);
|
|
s.moveTo(startx, starty);
|
|
this.selectedobject.removeClass("card-dragged");
|
|
this.selectedobject = null;
|
|
return true;
|
|
}
|
|
},
|
|
|
|
// Tap on the board unselect current card
|
|
unselect: function() {
|
|
if (this.selectedobject != null) {
|
|
this.selectedobject.removeClass("card-dragged");
|
|
this.selectedobject = null;
|
|
}
|
|
},
|
|
|
|
// Card drag start, change style to dragged
|
|
dragstart: function(s, e) {
|
|
if (this.$.timer.paused)
|
|
return true;
|
|
s.addClass("card-dragged");
|
|
this.$.gamebox.addClass("box-dragging");
|
|
FoodChain.sound.play(s.sound);
|
|
this.dragobject = s;
|
|
this.selectedobject = null;
|
|
this.dragx = 0;
|
|
this.dragy = e.clientY-s.y;
|
|
this.toTop(this.dragobject);
|
|
},
|
|
|
|
// Card drag end, change style to not dragged
|
|
dragfinish: function(s, e) {
|
|
s.removeClass("card-dragged");
|
|
this.$.gamebox.removeClass("box-dragging");
|
|
},
|
|
|
|
// Drag over the box, allow dragging
|
|
dragover: function(s, e) {
|
|
if (this.dragobject == null)
|
|
return true;
|
|
e.preventDefault();
|
|
return false;
|
|
},
|
|
|
|
// Dropped in the box, change card parent
|
|
drop: function(s, e) {
|
|
if (this.dragobject == null || this.$.timer.paused)
|
|
return true;
|
|
e.preventDefault();
|
|
this.dragobject.moveTo((e.clientX/window.innerWidth)*100+"%", e.clientY-this.dragy);
|
|
this.dragobject = null;
|
|
},
|
|
|
|
// Set the card to top of the stack
|
|
toTop: function(card) {
|
|
this.zmax = this.zmax + 1;
|
|
card.applyStyle("z-index", this.zmax)
|
|
},
|
|
|
|
// Validate cards order
|
|
controlOrder: function() {
|
|
// Stop timer
|
|
this.$.timer.pause();
|
|
|
|
// Hide button
|
|
this.$.play.hide();
|
|
this.$.pause.hide();
|
|
this.$.validate.hide();
|
|
|
|
// Get cards
|
|
var cards = [];
|
|
enyo.forEach(this.$.gamebox.getControls(), function(card) {
|
|
cards.push(card);
|
|
});
|
|
|
|
// Sort using x card position
|
|
cards = cards.sort(function (c1, c2) { return c1.x.replace("%","") - c2.x.replace("%",""); });
|
|
|
|
// Check order
|
|
var win = true;
|
|
for (var i = 0 ; win && i < this.chain.length ; i++) {
|
|
if (cards[i].cardname != this.chain[i])
|
|
win = false;
|
|
}
|
|
|
|
// Play win or loose sound
|
|
if (win) {
|
|
FoodChain.sound.play("audio/applause");
|
|
this.$.gamebox.addClass("box-win");
|
|
this.computeScore();
|
|
this.$.home.show();
|
|
if (this.level != FoodChain.buildLevels.length)
|
|
this.$.forward.show();
|
|
}
|
|
else {
|
|
FoodChain.sound.play("audio/disappointed");
|
|
this.$.gamebox.addClass("box-lost");
|
|
this.$.home.show();
|
|
this.$.restart.show();
|
|
}
|
|
},
|
|
|
|
// Compute score
|
|
computeScore: function() {
|
|
var score = 10;
|
|
var currentcount = this.timecount.mins * 60 + this.timecount.secs;
|
|
if (currentcount < FoodChain.buildLevels[this.level-1].time) {
|
|
score += (FoodChain.buildLevels[this.level-1].time - currentcount);
|
|
}
|
|
FoodChain.context.score += score;
|
|
this.$.score.setContent(String("0000"+FoodChain.context.score).slice(-4));
|
|
},
|
|
|
|
// Resume game
|
|
play: function() {
|
|
// Show cards
|
|
enyo.forEach(this.$.gamebox.getControls(), function(card) {
|
|
card.show();
|
|
});
|
|
|
|
// Show pause button, hide play button
|
|
this.$.timer.resume();
|
|
this.$.play.hide();
|
|
this.$.pause.show();
|
|
this.$.home.hide();
|
|
},
|
|
|
|
// Pause game
|
|
pause: function() {
|
|
// Hide cards
|
|
enyo.forEach(this.$.gamebox.getControls(), function(card) {
|
|
card.hide();
|
|
});
|
|
|
|
// Show play button, hide pause button
|
|
this.$.timer.pause();
|
|
this.$.pause.hide();
|
|
this.$.play.show();
|
|
this.$.home.show();
|
|
},
|
|
|
|
// Restart the current level
|
|
restart: function() {
|
|
this.levelChanged();
|
|
},
|
|
|
|
// Go to the next level
|
|
next: function() {
|
|
this.level = this.level + 1;
|
|
this.previous = this.chain;
|
|
this.mixed = null;
|
|
this.levelChanged();
|
|
},
|
|
|
|
// Go to the home page of the app
|
|
home: function() {
|
|
this.$.timer.stop();
|
|
FoodChain.goHome();
|
|
}
|
|
});
|