Code edit (1 edits merged)
Please save this source code
Code edit (19 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: nbTicksSinceEndOfWave is not defined' in or related to this line: 'nbTicksSinceEndOfWave -= 1; //On attend un peu avant de passer à la vague suivante' Line Number: 738
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 95
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 95
Code edit (6 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: ticksBeforeNextPosition is not defined' in or related to this line: 'scoreTest = "actualPIx: " + self.actualPositionIndex + " goalPIx: " + self.goalPositionIndex + " assetsToUse: " + self.assetsToUse + " seqIxToUse: " + self.sequenceIndexToUse + "\nticksBeforeNextPosition: " + ticksBeforeNextPosition;' Line Number: 114
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 96
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 96
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 96
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 96
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'length')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 94
Code edit (13 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'trajectory')' in or related to this line: 'coconutChoosen.trajectory.isStarted = true;' Line Number: 138
Code edit (1 edits merged)
Please save this source code
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'anchorX')' in or related to this line: 'monkeyAsset = self.attachAsset(newAssetId, {' Line Number: 69
Code edit (4 edits merged)
Please save this source code
/**** 
* Classes
****/ 
// Class for the Coconut
var Coconut = Container.expand(function () {
	var self = Container.call(this);
	var coconutAsset = self.attachAsset('coconut', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.isFalling = false;
	self.isBouncing = false;
	self.Xintercept = 0; //Abscisse d'interception du coconut avec le parasol
	self.Yintercept = 0; //Ordonnée d'interception du coconut avec le parasol
	self.trajectory = new Trajectory();
	// Function to change the asset
	self.changeAsset = function (newAssetId, options) {
		// Remove the existing asset
		self.removeChild(coconutAsset);
		coconutAsset.destroy();
		// Attach the new asset
		coconutAsset = self.attachAsset(newAssetId, {
			anchorX: options && options.anchorX !== undefined ? options.anchorX : 0.5,
			anchorY: options && options.anchorY !== undefined ? options.anchorY : 0.5
		});
	}; //fin changeAsset
	self.update = function () {
		if (self.trajectory.typeTrajectory == -1) {
			self.trajectory.updateStatic();
		}
		if (self.trajectory.typeTrajectory == 0) {
			self.trajectory.updateLinear();
		}
		if (self.trajectory.typeTrajectory == 1) {
			self.trajectory.updateParabol();
		}
		self.y = self.trajectory.y;
		self.x = self.trajectory.x;
		self.isFalling = self.trajectory.isFalling;
		if (self.y > 2732) {
			self.destroy();
		}
	}; //fin update
});
//<Assets used in the game will automatically appear here>
// Class for the Monkey
var Monkey = Container.expand(function () {
	var self = Container.call(this);
	var monkeyAsset = self.attachAsset('monkeyToLeft', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.assetsToRight = ['monkeyToRight', 'monkeyInterRight'];
	self.assetsToLeft = ['monkeyToLeft', 'monkeyInterLeft'];
	self.sequenceIndexToCenter = [0, 1, 0];
	self.sequenceIndexToExtreme = [0, 1, 0, 1, 0];
	self.assetsToUse = [];
	self.sequenceIndexToUse = []; //Séquence des index des assets du monkey a utiliser
	self.sequenceIndex = 0; //Index de la séquence des assets du monkey
	self.actualPositionIndex = 0; //Positions de depart : 0 (XL), 1 (XC), 2 (XR) index du tableau startPoints
	self.goalPositionIndex = 0; //Positions d'arrivée : 0 (XL), 1 (XC), 2 (XR) index du tableau startPoints
	self.ticksToGoToGoalPosition = 0;
	self.ticksBeforeNextPosition = 0; // Initialize ticksBeforeNextPosition
	self.isGoingToRight = false;
	self.isGoingToLeft = false;
	self.isMoving = false;
	self.coconutChoosen = null;
	// Function to change the asset
	self.changeAsset = function (newAssetId, options) {
		// Remove the existing asset
		self.removeChild(monkeyAsset);
		monkeyAsset.destroy();
		// Attach the new asset
		monkeyAsset = self.attachAsset(newAssetId, {
			anchorX: options && options.anchorX !== undefined ? options.anchorX : 0.5,
			anchorY: options && options.anchorY !== undefined ? options.anchorY : 0.5
		});
	};
	self.update = function () {}; //fin update
});
// Class for the Parasol
var Parasol = Container.expand(function () {
	var self = Container.call(this);
	var parasolGraphics = self.attachAsset('parasol', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.update = function () {
		// Parasol logic can be added here
	};
});
//Class for the trajectory of the coconut
//Gestion d'une trajectoire parabolique de sommet ((X1 + X2)/2, Yh)
//et de point de départ (X1, Y0) et d'arrivée (X2, Y0) avec Y0 > Yh et X1 < X2 et Yh != Y0 != 0 et X1 != X2 != 0
//la fonction de mise à jour calcule la position du point suivant en fonction de speed .
//L'equation de la trajectoire est de la forme y = a(x - X1)(x - X2) + Y0 avec a = 4(Y0 - Yh)/((X1 - X2)(X1 - X2))
//Pour la trajectoire linéaire, le point de départ est (X1, Yh) et le point d'arrivée est (X1, Y0)
//Le temps de parcours est totalTicks que se soit pour la trajectoire linéaire ou parabolique
var Trajectory = Container.expand(function () {
	var self = Container.call(this);
	var trajectoryGraphics = self.attachAsset('trajectory', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.typeTrajectory = 0; //-1: static, 0: linear, 1: parabolic
	self.X1 = 0;
	self.X2 = 0;
	self.Y0 = 0;
	self.Yh = 0;
	self.a = 0;
	self.x = 0;
	self.y = 0;
	self.totalTicks = 0; //Nombre total de ticks pour passer de X1 à X2
	self.distPerTick = 0; //Distance parcourue par tick
	self.isStarted = false; //Indique si la trajectoire a commencé
	self.setParameters = function (typeTrajectory, X1, X2, Y0, Yh, totalTicks) {
		//Initialisation des paramètres de la trajectoire
		self.typeTrajectory = typeTrajectory;
		self.X1 = X1;
		self.X2 = X2;
		self.Y0 = Y0;
		self.Yh = Yh;
		self.totalTicks = totalTicks;
		self.isStarted = false;
		if (self.typeTrajectory == -1) {
			self.x = self.X1;
			self.y = self.Y0;
		}
		if (self.typeTrajectory == 0) {
			self.x = self.X1;
			self.y = self.Yh;
			distPerTick = (self.Y0 - self.Yh) / self.totalTicks;
		}
		if (self.typeTrajectory == 1) {
			self.x = self.X1;
			self.y = self.Y0;
			self.a = 4 * (self.Y0 - self.Yh) / ((self.X1 - self.X2) * (self.X1 - self.X2));
			self.distPerTick = (self.X2 - self.X1) / self.totalTicks;
		}
		//scoreTest = "typeTrajectory: " + typeTrajectory + " X1: " + self.X1 + " X2: " + self.X2 + " Y0: " + self.Y0 + " Yh: " + self.Yh + " totalTicks: " + self.totalTicks;
	}; //fin setParameters
	self.updateStatic = function () {
		var lastY = self.y;
		self.isFalling = lastY < self.y;
	}; //fin updateStatic
	self.updateLinear = function () {
		// Trajectory logic can be added here
		var lastY = self.y;
		if (self.isStarted) {
			if (self.y < self.Y0) {
				self.y += distPerTick;
				//scoreTest = "x= " + self.x + " y= " + self.y + " distPerTick= " + self.distPerTick;
			}
		}
		self.isFalling = lastY < self.y;
	}; //fin updateLinear
	self.updateParabol = function () {
		//scoreTest += 1;
		// Trajectory logic can be added here
		var lastY = self.y;
		if (self.isStarted) {
			self.x += self.distPerTick;
			self.y = self.a * (self.x - self.X1) * (self.x - self.X2) + self.Y0;
			//scoreTest = "x= " + self.x + " y= " + self.y + " a= " + self.a + " distPerTick= " + self.distPerTick;
		}
		self.isFalling = lastY < self.y;
	}; //fin updateParabol
});
/**** 
* Initialize Game
****/ 
//fin class Trajectory
var game = new LK.Game({
	backgroundColor: 0x87CEEB // Sky blue background
});
/**** 
* Game Code
****/ 
/**** 
* GAME DESCRIPTION:
* Game Principle:
	* NAME: COCO MONKEY V1.0 by Dalhem 2024
	* -There is beach where people are enjoying the sun by the shadow of palm trees.
	* -Above them, three palm trees are growing coconuts.
	* -In the trees, a monkey is throwing coconuts from the top of the trees, thus three points of departure.
	* -The player controls a guy who holding a parasol to protect everyone from the coconuts.
	* -The coconuts are falling at a regular speed, falling in straight lines.
	* -If a coconut touches the parasol, the player earns points.
	* -If a coconut touches the ground, the player loses a life.
	* -The game is over when the player has no more lives.
* Game Areas:
	* The screen is divided into 3 main zones in the following descending order:
		1. Score area: displays the player's score.
		2. The main game area: where the game takes place, it is divided into 3 zones corresponding to the 3 points of departure of the coconuts :
			* The left zone: the coconuts fall from the left tree.
			* The center zone: the coconuts fall from the center tree.
			* The right zone: the coconuts fall from the right tree.
		3. Options area (or advertisement).
* Game Progression:
	* At the beginning of the game, the player has 0 points.
	* The player has 3 lives.
	* The player can move the parasol by dragging it.
	* The monkey throws coconuts at a regular interval randomly from the top of the trees.
	* When a coconut touches the parasol, it bounces up following a parabolic trajectory.
	* The parabolic trajectory depends on the angle of the parasol:
		* The more the parasol is inclined, the more the coconut will bounce back :
			* If the parasol is in the left zone, the coconut may bounce following a parabolic trajectory :
				* to the left, thus outside the screen.
				* to the right, thus towards the center zone.
				* to the extrem right, thus towards the right zone.
			* If the parasol is in the center zone, the coconut may bounce following a parabolic trajectory :
				* to the left, thus towards the left zone.
				* to the extrem left, thus outside the screen.
				* to the right, thus towards the right zone.
				* to the extrem right, thus outside the screen.
			* If the parasol is in the right zone, the coconut may bounce following a parabolic trajectory :
				* to the left, thus towards the center zone.
				* to the extrem left, thus towards the left zone.
				* to the right, thus outside the screen.
	* the parasol has three zones of influence:
		* The left zone: the coconut will bounce to the extrem left.
		* The center zone: the coconut will randomly bounce to the left or to the right.
		* The right zone: the coconut will bounce to the extrem right.
****/ 
/**** 
* Game zones and backgrounds
****/ 
var ScoreZone = {
	x: 0,
	y: 0,
	width: game.width,
	height: 200 * game.height / 2732
};
var MainZone = {
	x: 0,
	y: ScoreZone.height,
	width: game.width,
	height: game.height - 2 * ScoreZone.height
};
var OptionsZone = {
	x: 0,
	y: game.height - ScoreZone.height,
	width: game.width,
	height: 200 * game.height / 2732
};
setBackGroundImage('backGroundBeach', 0, 0, game.width, game.height);
/**** 
* Autres
****/ 
var monkeyLevel = 200;
var monkey = game.addChild(new Monkey());
monkey.x = 2048 / 2;
monkey.y = monkeyLevel;
game.addChild(monkey.sprite);
var parasol = game.addChild(new Parasol());
parasol.x = 2048 / 2;
parasol.y = OptionsZone.y - 400;
var coconutsInTree = []; //Tableau des coconuts dans les arbres
var coconuts = []; //Tableau des coconuts en mouvement
var nombreCoconuts = 5; //Nombre de coconuts en mouvement en même temps
var coconutChoosen = null; //Coconut choisie pour tomber
var sommetParaboleHaute = ScoreZone.height + 200;
var sommetParaboleBasse = ScoreZone.height + 400;
var nbTicksToBounceHight = 230; //Nombre de ticks pour effectuer une parabole haute
var nbTicksTobounceLow = 220; //Nombre de ticks pour effectuer une parabole basse
var nbTicksToFall = 200; //Nombre de ticks pour tomber
var nbTicksBeforeThrow = 150;
var nbTicksLeftBeforeNextThrow = 0;
var score = 0;
var scoreLast = score;
var scoreTest = 0;
var startPoints = [XL = game.width / 4, XC = game.width / 2, XR = 3 * game.width / 4]; // Define the startPoints array
var parasolLevel = OptionsZone.y - 600;
var groundLevel = OptionsZone.y - 300;
var bullesInsultes = ['heInsultes1', 'sheInsultes', 'heInsultes2'];
var wave = 1; //Nro de la vague
/**** 
* Init game
* ***/
setCocoInTree(wave);
/**** 
* Score
****/ 
var livesLeft = 3; //Nombre de vies restantes
var livesLeftGraphics = []; //Tableau des sprites 'life' représentant les vies restantes
var scoreTestText = new Text2('0', {
	size: 30,
	fill: "#000000",
	anchorX: 0.5,
	anchorY: 0
});
LK.gui.topLeft.addChild(scoreTestText);
var scoreTxt = new Text2('0', {
	size: 100,
	fill: "#ff0000",
	anchorX: 0.5,
	anchorY: 0
});
LK.gui.top.addChild(scoreTxt);
game.down = function (x, y, obj) {
	parasol.x = x;
	parasol.y = parasolLevel;
};
game.move = function (x, y, obj) {
	parasol.x = x;
	parasol.y = parasolLevel;
};
/**** 
* Functions
****/ 
//Fonction setBackGroundImage : permet de définir l'image de fond du jeu
function setBackGroundImage(image, x, y, width, height) {
	backGroundImage = LK.getAsset(image, {
		x: x,
		y: y,
		width: width,
		height: height
	});
	game.addChild(backGroundImage);
} //Fin de la fonction setBackGroundImage
function updateScoreTest(nouveauScore) {
	scoreTestText.setText(nouveauScore);
} //fin updateScoreTest
function updateScore(nouveauScore) {
	scoreTxt.setText(nouveauScore);
} //fin updateScore
function setLivesLeft() {
	//Affiche le nombre de vies restantes (sprite 'life' ) dans le coin supérieur gauche
	//Commence par effacer les vies restantes s'il y en a
	if (livesLeft != livesLeftGraphics.length) {
		for (var i = livesLeftGraphics.length - 1; i >= livesLeft; i--) {
			if (livesLeftGraphics[i]) {
				game.removeChild(livesLeftGraphics[i]);
				livesLeftGraphics[i].destroy();
				livesLeftGraphics.splice(i, 1);
			}
		}
	}
	//Crée des sprites 'life' si nécessaire (si livesLeft > livesLeftGraphics.length)
	if (livesLeft > livesLeftGraphics.length) {
		for (var i = livesLeftGraphics.length; i < livesLeft; i++) {
			var lifeGraphics = LK.getAsset('life', {
				anchorX: 0.5,
				anchorY: 0,
				scaleX: 4 - livesLeft,
				scaleY: 4 - livesLeft,
				x: ScoreZone.x + 100 + 100 * i,
				y: ScoreZone.y + 50
			});
			livesLeftGraphics.push(lifeGraphics);
		}
	}
	//Affiche les sprites 'life' dans le coin supérieur gauche
	for (var i = 0; i < livesLeft; i++) {
		game.addChild(livesLeftGraphics[i]);
	}
} //fin setLivesLeft
//Fonction setCocoInTree: crée un coconut dans un arbre
//Les coconuts sont créés au nombre de nombreCoconuts 
//puis elles réparties aléatoirement mais équitablement dans les arbres autour des trois points de départ (XL, XC, XR) + ou - 50 pixels
//Elles sont stockées dans le tableau coconutsInTree
function setCocoInTree(wave) {
	for (var i = 0; i < nombreCoconuts + wave * 5; i++) {
		var newCoconut = new Coconut();
		// Choisir aléatoirement un point de départ
		var randomIndex = Math.floor(Math.random() * startPoints.length);
		var randomDeltaX = Math.floor(Math.random() * 100) - 50;
		var randomDeltaY = Math.floor(Math.random() * 100) - 50;
		var typeTrajectory = -1; //Trajectoire statique
		var X1 = startPoints[randomIndex] + randomDeltaX;
		//var X1 = startPoints[1];
		var X2 = X1;
		var Y0 = monkeyLevel + randomDeltaY;
		var Yh = Y0;
		var totalTicks = 0;
		newCoconut.trajectory.setParameters(typeTrajectory, X1, X2, Y0, Yh, totalTicks);
		coconutsInTree.push(newCoconut);
		nbTicksBeforeThrow /= wave; //Diminue le nombre de ticks avant le prochain lancer
		LK.getSound('monkeySquirk').play();
		LK.getSound('boomBoom').play();
		LK.getSound('boomBoom').play();
	}
	//Affiche les coconuts dans les arbres
	for (var i = 0; i < coconutsInTree.length; i++) {
		game.addChild(coconutsInTree[i]);
	}
} //fin setCocoInTree
//Fonction chooseNextStartPoint: choisit aléatoirement un point de départ d'un coconut
//Renvoie un objet Coconut
function chooseNextStartPoint() {
	var newCoconut = new Coconut();
	// Choisir aléatoirement un point de départ
	var randomIndex = Math.floor(Math.random() * startPoints.length);
	var typeTrajectory = 0;
	newCoconut.isFalling = true;
	var X1 = startPoints[randomIndex];
	var X2 = X1;
	var Y0 = groundLevel;
	var Yh = monkeyLevel;
	newCoconut.trajectory.setParameters(typeTrajectory, X1, X2, Y0, Yh, nbTicksToFall);
	coconuts.push(newCoconut);
	moveMonkeyToStartPoint(X1, monkeyLevel);
	return newCoconut;
} //fin chooseNextStartPoint
//Fonction chooseNextCoconut: choisit aléatoirement un coconut dans les arbres
//Renvoie un objet Coconut
function chooseNextCoconut() {
	var randomIndex = Math.floor(Math.random() * coconutsInTree.length);
	var newCoconut = coconutsInTree[randomIndex];
	coconutsInTree.splice(randomIndex, 1);
	moveMonkeyToCoconut(newCoconut);
	var typeTrajectory = 0; //Trajectoire linéaire
	var X1 = newCoconut.x;
	var X2 = X1;
	var Y0 = groundLevel;
	var Yh = newCoconut.y;
	newCoconut.trajectory.setParameters(typeTrajectory, X1, X2, Y0, Yh, nbTicksToFall);
	coconuts.push(newCoconut);
	return newCoconut;
} //fin chooseNextCoconut
//Fonction moveMoveMonkeyToCoconut: déplace le monkey au point de depart du coconut
function moveMonkeyToCoconut(coconut) {
	//Efface le monkey de l'écran
	game.removeChild(monkey);
	var deltaIndex = checkIndexPosition(monkey) - checkIndexPosition(coconut);
	if (deltaIndex < 0) {
		//Le monkey est à gauche du coconut
		monkey.changeAsset('monkeyToRight', {
			anchorX: 0.91,
			anchorY: 0.11
		});
		if (deltaIndex > -1) {
			//Le monkey est à gauche du coconut mais pas trop
			monkey.changeAsset('monkeyInterRight', {
				anchorX: 0.5,
				anchorY: 0.5
			});
		}
	} else {
		//Le monkey est à droite du coconut
		monkey.changeAsset('monkeyToLeft', {
			anchorX: 0.09,
			anchorY: 0.11
		});
	}
	monkey.x = coconut.x;
	monkey.y = coconut.y;
	game.addChild(monkey);
	LK.setTimeout(function () {
		coconut.trajectory.isStarted = true;
	}, 500);
} //fin moveMonkeyToCoconut
//Fonction checkPosition : donne la position XL, XC, ou XR la plus proche de la position x du parasol
function checkPosition(parasol) {
	var deltaX = Math.abs(parasol.x - XL);
	var deltaY = Math.abs(parasol.x - XC);
	var deltaZ = Math.abs(parasol.x - XR);
	var Xreturn = -1;
	if (deltaX <= parasol.width / 2) {
		Xreturn = XL;
	}
	if (deltaY <= parasol.width / 2) {
		Xreturn = XC;
	}
	if (deltaZ <= parasol.width / 2) {
		Xreturn = XR;
	}
	return Xreturn;
} //fin checkPosition
//Fonction checkIndexPosition : donne l'index de la position XL, XC, ou XR la plus proche de la position x d'un objet
function checkIndexPosition(obj) {
	var deltaX = Math.abs(obj.x - XL);
	var deltaY = Math.abs(obj.x - XC);
	var deltaZ = Math.abs(obj.x - XR);
	var Xreturn = -1;
	if (deltaX <= obj.width) {
		Xreturn = 0;
	}
	if (deltaY <= obj.width) {
		Xreturn = 1;
	}
	if (deltaZ <= obj.width) {
		Xreturn = 2;
	}
	return Xreturn;
} //fin checkIndexPosition
//Fonction zoneIntersectParasol: renvoie la zone du parasol qui intersecte le coconut (0 : zone de gauche, 1 : zone centrale de gauche, 2 : zone centrale de droite, 3 : zone de droite)
//Sachant que l'ancrage du parasol est en (0.5, 0.5) et que l'ancrage du coconut est en (0.5, 0.5)
//La zone 0 est la zone de gauche, la zone 1 est la zone centrale, la zone 2 est la zone de droite
function zoneIntersectParasol(coconut) {
	var zone = -1;
	var oneThirdParasol = parasol.width / 3;
	var parasolCenter = parasol.x;
	var coconutCenter = coconut.x;
	var deltaXToCenter = parasolCenter - coconutCenter; //distance du centre du coconut par rapport au centre du parasol (positif si à gauche, négatif si à droite)
	if (deltaXToCenter > oneThirdParasol / 2) {
		//La coco se trouve dans la zone gauche au delà du tiers gauche
		zone = 0;
	}
	if (deltaXToCenter <= oneThirdParasol / 2 && deltaXToCenter >= 0) {
		//La coco se trouve dans la zone gauche entre le tiers gauche et le centre du parasol
		zone = 1;
	}
	if (deltaXToCenter >= -oneThirdParasol / 2 && deltaXToCenter <= 0) {
		//La coco se trouve dans la zone droite entre le centre du parasol et le tiers droit
		zone = 2;
	}
	if (deltaXToCenter < -oneThirdParasol / 2) {
		//La coco se trouve dans la zone droite au delà du tiers droit
		zone = 3;
	}
	return zone;
} //fin zoneIntersectParasol
//Fonction changeTrajectory: change la trajectoire d'un coconut en fonction de la position du parasol en XL, XC ou XR (position de startPoints)
//Si la position du parasol est en XL le coconut rebondit aléatoirement :
//	- vers la gauche, donc vers l'extérieur de l'écran
//	- vers la droite, donc vers la zone centrale avec une parabole de somment sommetParaboleHaute
//	- vers l'extrême droite, donc vers la zone de droite avec une parabole de somment sommetParaboleBasse
//Si la position du parasol est en XC le coconut rebondit aléatoirement :
//	- vers la gauche, donc vers la zone de gauche avec une parabole de somment sommetParaboleHaute
//	- vers l'extrême gauche, donc vers l'extérieur de l'écran
//	- vers la droite, donc vers la zone de droite avec une parabole de somment sommetParaboleHaute
//	- vers l'extrême droite, donc vers l'extérieur de l'écran
//Si la position du parasol est en XR le coconut rebondit aléatoirement :
//	- vers la droite, donc vers l'extérieur de l'écran
//	- vers la gauche, donc vers la zone centrale avec une parabole de somment sommetParaboleHaute
//	- vers l'extrême gauche, donc vers la zone de gauche avec une parabole de somment sommetParaboleBasse
function changeTrajectory(coconut, randomIndex) {
	if (randomIndex != 0 && randomIndex != 1 && randomIndex != 2 && randomIndex != 3) {
		randomIndex = Math.floor(Math.random() * 4);
	}
	var Xposition = checkPosition(parasol);
	var deltaX = Math.abs(coconut.x - Xposition);
	if (Xposition == XL) {
		if (randomIndex == 0) {
			//vers la gauche, sortie de l'écran
			coconut.trajectory.setParameters(1, coconut.x, -XL - deltaX, coconut.y, sommetParaboleBasse, nbTicksToBounceHight);
		}
		if (randomIndex == 1) {
			//vers la gauche, sortie de l'écran
			coconut.trajectory.setParameters(1, coconut.x, -XL - deltaX, coconut.y, sommetParaboleHaute, nbTicksToBounceHight);
		}
		if (randomIndex == 2) {
			//vers le centre, parabole haute
			coconut.trajectory.setParameters(1, coconut.x, XC - deltaX, coconut.y, sommetParaboleHaute, nbTicksToBounceHight);
		}
		if (randomIndex == 3) {
			//vers l'extrême droite, parabole basse
			coconut.trajectory.setParameters(1, coconut.x, XR - deltaX, coconut.y, sommetParaboleBasse, nbTicksTobounceLow);
		}
	} else if (Xposition == XC) {
		if (randomIndex == 0) {
			//vers la gauche, sortie d'ecran
			coconut.trajectory.setParameters(1, coconut.x, -XL + deltaX, coconut.y, sommetParaboleBasse, nbTicksTobounceLow);
		}
		if (randomIndex == 1) {
			//vers la gauche, parabole haute
			coconut.trajectory.setParameters(1, coconut.x, XL + deltaX, coconut.y, sommetParaboleHaute, nbTicksToBounceHight);
		}
		if (randomIndex == 2) {
			//Vers la droite, parabole haute
			coconut.trajectory.setParameters(1, coconut.x, XR - deltaX, coconut.y, sommetParaboleHaute, nbTicksToBounceHight);
		}
		if (randomIndex == 3) {
			//Vers la droite, sortie d'ecran
			coconut.trajectory.setParameters(1, coconut.x, XR + 2 * XL - deltaX, coconut.y, sommetParaboleBasse, nbTicksTobounceLow);
		}
	} else if (Xposition == XR) {
		if (randomIndex == 0) {
			//vers l'extrême gauche, parabole basse
			coconut.trajectory.setParameters(1, coconut.x, XL + deltaX, coconut.y, sommetParaboleBasse, nbTicksTobounceLow);
		}
		if (randomIndex == 1) {
			//vers le centre, parabole haute
			coconut.trajectory.setParameters(1, coconut.x, XC + deltaX, coconut.y, sommetParaboleHaute, nbTicksToBounceHight);
		}
		if (randomIndex == 2) {
			//vers la droite, sortie de l'écran
			coconut.trajectory.setParameters(1, coconut.x, XR + 2 * XL - deltaX, coconut.y, sommetParaboleHaute, nbTicksToBounceHight);
		}
		if (randomIndex == 3) {
			//vers l'extrême gauche, parabole haute
			coconut.trajectory.setParameters(1, coconut.x, XR + 2 * XL - deltaX, coconut.y, sommetParaboleBasse, nbTicksTobounceLow);
		}
	}
} //fin changeTrajectory
//Fonction placeInsultes: place une bulle d'insultes autour de la tete du personnage designé par l'index
//Retire la bulle d'insultes après un certain temps
function placeInsultes(index) {
	var insulte = LK.getAsset(bullesInsultes[index], {
		anchorX: 0.5,
		anchorY: 0.5
	});
	var positionsInsultes = [{
		x: XL - 300,
		y: groundLevel - 30
	}, {
		x: XC + 50,
		y: groundLevel
	}, {
		x: XR + 250,
		y: groundLevel - 20
	}];
	var posInsulte = positionsInsultes[index];
	insulte.x = posInsulte.x;
	insulte.y = posInsulte.y;
	game.addChild(insulte);
	LK.setTimeout(function () {
		game.removeChild(insulte);
		insulte.destroy();
	}, 2000);
} //fin placeInsultes
//Fonction letShout: fait crier le personnage designé par l'index de la position
function letShoutNInsultes(index) {
	if (index != 0 && index != 1 && index != 2) {
		LK.effects.flashScreen(0xff0000, 1000);
	}
	var shouts = ['heShout1', 'sheShout', 'heShout2'];
	var shout = shouts[index];
	LK.getSound(shout).play();
	placeInsultes(index);
} //fin letShoutNInsultes
/**** 
* Main loop
****/ 
game.update = function () {
	//Mise à jour score
	updateScoreTest(scoreTest);
	updateScore(score);
	//Vérifier si un coco a touché le sol
	for (var i = coconuts.length - 1; i >= 0; i--) {
		if (coconuts[i].y >= groundLevel / 2 && (coconuts[i].x < 0 || coconuts[i].x > game.width)) {
			//Si le coco est sorti de l'écran sur les côtés
			coconuts[i].destroy();
			coconuts.splice(i, 1);
		} else if (coconuts[i].y >= groundLevel) {
			//Si le coco est tombé au sol
			//letShoutNInsultes(checkIndexPosition(coconuts[i])); //Bug : sound doesnt play that way!
			if (checkIndexPosition(coconuts[i]) == 1) {
				LK.getSound('sheOuch').play();
				placeInsultes(1);
			} else if (checkIndexPosition(coconuts[i]) == 2) {
				LK.getSound('heOuch2').play();
				placeInsultes(2);
			} else if (checkIndexPosition(coconuts[i]) == 0) {
				LK.getSound('heOuch1').play();
				placeInsultes(0);
			} else {
				LK.effects.flashScreen(0xff0000, 1000);
			}
			coconuts[i].destroy();
			coconuts.splice(i, 1);
			livesLeft -= 1;
			if (livesLeft == 0) {
				setLivesLeft();
				LK.setTimeout(function () {
					LK.showGameOver();
				}, 2000);
			}
		}
	}
	//Check if a coconut has touched the parasol et changement de trajectoire
	for (var i = coconuts.length - 1; i >= 0; i--) {
		var deltaX = Math.abs(coconuts[i].x - parasol.x);
		var deltaY = parasol.y - coconuts[i].y;
		var isCloseEnough = deltaY > 0 && deltaY < 150;
		if (coconuts[i].intersects(parasol) && coconuts[i].isFalling && deltaX < parasol.width / 2 && isCloseEnough) {
			coconuts[i].Xintercept = parasol.x;
			coconuts[i].Yintercept = coconuts[i].y;
			score += 10;
			if (score - scoreLast >= 1000 && livesLeft < 10) {
				livesLeft += 1; //Bonus de 11 coeur tous les 1000 noix
				scoreLast = score;
			}
			coconuts[i].isFalling = false;
			var bouncingSoundList = ['bouncing1', 'bouncing2', 'bouncing3'];
			var bouncingSound = bouncingSoundList[Math.floor(Math.random() * bouncingSoundList.length)];
			LK.getSound(bouncingSound).play();
			changeTrajectory(coconuts[i], zoneIntersectParasol(coconuts[i]));
			coconuts[i].trajectory.isStarted = true;
			coconuts[i].isBouncing = true;
		}
	}
	//Autres actions à effectuer sans urgence
	if (LK.ticks % 60 == 0) {
		//Afficher les coeurs
		setLivesLeft();
		// Récupérer un coconut dans les arbres et le faire tomber si l'heure est venue
		if (coconutsInTree.length > 0 && nbTicksLeftBeforeNextThrow <= 0 && livesLeft > 0) {
			if (coconutChoosen == null) {
				coconutChoosen = chooseNextCoconut();
				game.addChild(coconutChoosen);
			} else {
				nbTicksLeftBeforeNextThrow = nbTicksBeforeThrow;
				coconutChoosen = null;
			}
		} else if (coconutsInTree.length > 0 && nbTicksLeftBeforeNextThrow > 0) {
			nbTicksLeftBeforeNextThrow -= 60;
		} else if (coconutsInTree.length == 0) {
			wave += 1;
			setCocoInTree(wave);
		}
	}
}; ===================================================================
--- original.js
+++ change.js
@@ -3,17 +3,28 @@
 ****/ 
 // Class for the Coconut
 var Coconut = Container.expand(function () {
 	var self = Container.call(this);
-	var coconutGraphics = self.attachAsset('coconut', {
+	var coconutAsset = self.attachAsset('coconut', {
 		anchorX: 0.5,
 		anchorY: 0.5
 	});
 	self.isFalling = false;
 	self.isBouncing = false;
 	self.Xintercept = 0; //Abscisse d'interception du coconut avec le parasol
 	self.Yintercept = 0; //Ordonnée d'interception du coconut avec le parasol
 	self.trajectory = new Trajectory();
+	// Function to change the asset
+	self.changeAsset = function (newAssetId, options) {
+		// Remove the existing asset
+		self.removeChild(coconutAsset);
+		coconutAsset.destroy();
+		// Attach the new asset
+		coconutAsset = self.attachAsset(newAssetId, {
+			anchorX: options && options.anchorX !== undefined ? options.anchorX : 0.5,
+			anchorY: options && options.anchorY !== undefined ? options.anchorY : 0.5
+		});
+	}; //fin changeAsset
 	self.update = function () {
 		if (self.trajectory.typeTrajectory == -1) {
 			self.trajectory.updateStatic();
 		}
@@ -247,9 +258,9 @@
 parasol.x = 2048 / 2;
 parasol.y = OptionsZone.y - 400;
 var coconutsInTree = []; //Tableau des coconuts dans les arbres
 var coconuts = []; //Tableau des coconuts en mouvement
-var nombreCoconuts = 15; //Nombre de coconuts en mouvement en même temps
+var nombreCoconuts = 5; //Nombre de coconuts en mouvement en même temps
 var coconutChoosen = null; //Coconut choisie pour tomber
 var sommetParaboleHaute = ScoreZone.height + 200;
 var sommetParaboleBasse = ScoreZone.height + 400;
 var nbTicksToBounceHight = 230; //Nombre de ticks pour effectuer une parabole haute
@@ -257,17 +268,19 @@
 var nbTicksToFall = 200; //Nombre de ticks pour tomber
 var nbTicksBeforeThrow = 150;
 var nbTicksLeftBeforeNextThrow = 0;
 var score = 0;
+var scoreLast = score;
 var scoreTest = 0;
 var startPoints = [XL = game.width / 4, XC = game.width / 2, XR = 3 * game.width / 4]; // Define the startPoints array
 var parasolLevel = OptionsZone.y - 600;
 var groundLevel = OptionsZone.y - 300;
 var bullesInsultes = ['heInsultes1', 'sheInsultes', 'heInsultes2'];
+var wave = 1; //Nro de la vague
 /**** 
 * Init game
 * ***/
-setCocoInTree();
+setCocoInTree(wave);
 /**** 
 * Score
 ****/ 
 var livesLeft = 3; //Nombre de vies restantes
@@ -279,9 +292,9 @@
 	anchorY: 0
 });
 LK.gui.topLeft.addChild(scoreTestText);
 var scoreTxt = new Text2('0', {
-	size: 150,
+	size: 100,
 	fill: "#ff0000",
 	anchorX: 0.5,
 	anchorY: 0
 });
@@ -330,12 +343,12 @@
 		for (var i = livesLeftGraphics.length; i < livesLeft; i++) {
 			var lifeGraphics = LK.getAsset('life', {
 				anchorX: 0.5,
 				anchorY: 0,
-				scaleX: 1,
-				scaleY: 1,
+				scaleX: 4 - livesLeft,
+				scaleY: 4 - livesLeft,
 				x: ScoreZone.x + 100 + 100 * i,
-				y: ScoreZone.y + 100
+				y: ScoreZone.y + 50
 			});
 			livesLeftGraphics.push(lifeGraphics);
 		}
 	}
@@ -347,10 +360,10 @@
 //Fonction setCocoInTree: crée un coconut dans un arbre
 //Les coconuts sont créés au nombre de nombreCoconuts 
 //puis elles réparties aléatoirement mais équitablement dans les arbres autour des trois points de départ (XL, XC, XR) + ou - 50 pixels
 //Elles sont stockées dans le tableau coconutsInTree
-function setCocoInTree() {
-	for (var i = 0; i < nombreCoconuts; i++) {
+function setCocoInTree(wave) {
+	for (var i = 0; i < nombreCoconuts + wave * 5; i++) {
 		var newCoconut = new Coconut();
 		// Choisir aléatoirement un point de départ
 		var randomIndex = Math.floor(Math.random() * startPoints.length);
 		var randomDeltaX = Math.floor(Math.random() * 100) - 50;
@@ -363,8 +376,12 @@
 		var Yh = Y0;
 		var totalTicks = 0;
 		newCoconut.trajectory.setParameters(typeTrajectory, X1, X2, Y0, Yh, totalTicks);
 		coconutsInTree.push(newCoconut);
+		nbTicksBeforeThrow /= wave; //Diminue le nombre de ticks avant le prochain lancer
+		LK.getSound('monkeySquirk').play();
+		LK.getSound('boomBoom').play();
+		LK.getSound('boomBoom').play();
 	}
 	//Affiche les coconuts dans les arbres
 	for (var i = 0; i < coconutsInTree.length; i++) {
 		game.addChild(coconutsInTree[i]);
@@ -457,15 +474,15 @@
 	var deltaX = Math.abs(obj.x - XL);
 	var deltaY = Math.abs(obj.x - XC);
 	var deltaZ = Math.abs(obj.x - XR);
 	var Xreturn = -1;
-	if (deltaX <= obj.width / 2) {
+	if (deltaX <= obj.width) {
 		Xreturn = 0;
 	}
-	if (deltaY <= obj.width / 2) {
+	if (deltaY <= obj.width) {
 		Xreturn = 1;
 	}
-	if (deltaZ <= obj.width / 2) {
+	if (deltaZ <= obj.width) {
 		Xreturn = 2;
 	}
 	return Xreturn;
 } //fin checkIndexPosition
@@ -576,16 +593,16 @@
 		anchorX: 0.5,
 		anchorY: 0.5
 	});
 	var positionsInsultes = [{
-		x: XL - 200,
-		y: groundLevel
+		x: XL - 300,
+		y: groundLevel - 30
 	}, {
-		x: XC + 30,
+		x: XC + 50,
 		y: groundLevel
 	}, {
-		x: XR + 100,
-		y: groundLevel
+		x: XR + 250,
+		y: groundLevel - 20
 	}];
 	var posInsulte = positionsInsultes[index];
 	insulte.x = posInsulte.x;
 	insulte.y = posInsulte.y;
@@ -594,8 +611,18 @@
 		game.removeChild(insulte);
 		insulte.destroy();
 	}, 2000);
 } //fin placeInsultes
+//Fonction letShout: fait crier le personnage designé par l'index de la position
+function letShoutNInsultes(index) {
+	if (index != 0 && index != 1 && index != 2) {
+		LK.effects.flashScreen(0xff0000, 1000);
+	}
+	var shouts = ['heShout1', 'sheShout', 'heShout2'];
+	var shout = shouts[index];
+	LK.getSound(shout).play();
+	placeInsultes(index);
+} //fin letShoutNInsultes
 /**** 
 * Main loop
 ****/ 
 game.update = function () {
@@ -609,8 +636,9 @@
 			coconuts[i].destroy();
 			coconuts.splice(i, 1);
 		} else if (coconuts[i].y >= groundLevel) {
 			//Si le coco est tombé au sol
+			//letShoutNInsultes(checkIndexPosition(coconuts[i])); //Bug : sound doesnt play that way!
 			if (checkIndexPosition(coconuts[i]) == 1) {
 				LK.getSound('sheOuch').play();
 				placeInsultes(1);
 			} else if (checkIndexPosition(coconuts[i]) == 2) {
@@ -628,9 +656,9 @@
 			if (livesLeft == 0) {
 				setLivesLeft();
 				LK.setTimeout(function () {
 					LK.showGameOver();
-				}, 200);
+				}, 2000);
 			}
 		}
 	}
 	//Check if a coconut has touched the parasol et changement de trajectoire
@@ -641,8 +669,12 @@
 		if (coconuts[i].intersects(parasol) && coconuts[i].isFalling && deltaX < parasol.width / 2 && isCloseEnough) {
 			coconuts[i].Xintercept = parasol.x;
 			coconuts[i].Yintercept = coconuts[i].y;
 			score += 10;
+			if (score - scoreLast >= 1000 && livesLeft < 10) {
+				livesLeft += 1; //Bonus de 11 coeur tous les 1000 noix
+				scoreLast = score;
+			}
 			coconuts[i].isFalling = false;
 			var bouncingSoundList = ['bouncing1', 'bouncing2', 'bouncing3'];
 			var bouncingSound = bouncingSoundList[Math.floor(Math.random() * bouncingSoundList.length)];
 			LK.getSound(bouncingSound).play();
@@ -655,17 +687,20 @@
 	if (LK.ticks % 60 == 0) {
 		//Afficher les coeurs
 		setLivesLeft();
 		// Récupérer un coconut dans les arbres et le faire tomber si l'heure est venue
-		if (coconutsInTree.length > 0 && nbTicksLeftBeforeNextThrow <= 0) {
+		if (coconutsInTree.length > 0 && nbTicksLeftBeforeNextThrow <= 0 && livesLeft > 0) {
 			if (coconutChoosen == null) {
 				coconutChoosen = chooseNextCoconut();
 				game.addChild(coconutChoosen);
 			} else {
 				nbTicksLeftBeforeNextThrow = nbTicksBeforeThrow;
 				coconutChoosen = null;
 			}
-		} else {
+		} else if (coconutsInTree.length > 0 && nbTicksLeftBeforeNextThrow > 0) {
 			nbTicksLeftBeforeNextThrow -= 60;
+		} else if (coconutsInTree.length == 0) {
+			wave += 1;
+			setCocoInTree(wave);
 		}
 	}
 };
\ No newline at end of file