User prompt
Make the game easy
User prompt
Add more lives
User prompt
Make the chicken jump higher
User prompt
Please add touch control
Code edit (1 edits merged)
Please save this source code
User prompt
Chicken Face Jump
Initial prompt
Please help me make a face game where you use your face to make a chicken jump over obstacles
/**** 
* Plugins
****/ 
var facekit = LK.import("@upit/facekit.v1");
var tween = LK.import("@upit/tween.v1");
/**** 
* Classes
****/ 
// Chicken class
var Chicken = Container.expand(function () {
	var self = Container.call(this);
	// Chicken body
	var chickenBody = self.attachAsset('chicken', {
		anchorX: 0.5,
		anchorY: 1
	});
	// Chicken shadow
	var shadow = self.attachAsset('shadow', {
		anchorX: 0.5,
		anchorY: 0.5,
		y: 20
	});
	// Physics
	self.groundY = 0; // Set after adding to game
	self.velY = 0;
	self.isJumping = false;
	self.jumpPower = -82; // Even higher jump for easier play
	self.gravity = 5.2;
	self.jumpCooldown = 0; // Prevents double jumps
	// Jump method
	self.jump = function () {
		if (!self.isJumping && self.jumpCooldown <= 0) {
			self.velY = self.jumpPower;
			self.isJumping = true;
			self.jumpCooldown = 12; // ~0.2s lockout
			LK.getSound('jump').play();
			// Animate chicken up
			tween(self, {
				scaleX: 1.08,
				scaleY: 0.92
			}, {
				duration: 120,
				easing: tween.easeOut
			});
			tween(shadow, {
				scaleX: 0.7,
				scaleY: 0.7
			}, {
				duration: 120,
				easing: tween.easeOut
			});
		}
	};
	// Update method
	self.update = function () {
		// Cooldown
		if (self.jumpCooldown > 0) self.jumpCooldown--;
		// Gravity
		if (self.isJumping) {
			self.y += self.velY;
			self.velY += self.gravity;
			// Land
			if (self.y >= self.groundY) {
				self.y = self.groundY;
				self.velY = 0;
				self.isJumping = false;
				// Animate squash
				tween(self, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 120,
					easing: tween.easeOut
				});
				tween(shadow, {
					scaleX: 1,
					scaleY: 1
				}, {
					duration: 120,
					easing: tween.easeOut
				});
			}
		}
	};
	return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
	var self = Container.call(this);
	var obs = self.attachAsset('obstacle', {
		anchorX: 0.5,
		anchorY: 1
	});
	self.speed = 0; // Set by game
	self.passed = false; // For scoring
	self.update = function () {
		self.x -= self.speed;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0xb3e0ff // Light blue sky
});
/**** 
* Game Code
****/ 
// Tween plugin
// Facekit plugin
// Hit sound
// Jump sound
// Shadow
// Ground
// Obstacle (box)
// Chicken (player)
// Game constants
var GROUND_Y = 2300;
var CHICKEN_X = 500;
var OBSTACLE_MIN_GAP = 950; // Wider minimum gap
var OBSTACLE_MAX_GAP = 1450; // Wider maximum gap
var OBSTACLE_MIN_HEIGHT = 140; // Lower minimum height
var OBSTACLE_MAX_HEIGHT = 220; // Lower maximum height
var OBSTACLE_WIDTH = 120;
var OBSTACLE_SPEED_START = 16; // Slower start speed for easier play
var OBSTACLE_SPEED_INC = 0.006; // Slower speed increase
var OBSTACLE_MAX_SPEED = 28; // Lower max speed
// Game state
var chicken;
var ground;
var obstacles = [];
var score = 0;
var distance = 0;
var gameSpeed = OBSTACLE_SPEED_START;
var lastObstacleX = 0;
var isGameOver = false;
var jumpTriggered = false;
var scoreTxt;
var distTxt;
var dragNode = null;
var lives = 6; // Number of lives (increased for easier gameplay)
var livesTxt; // Text2 for lives
// Add ground
ground = LK.getAsset('ground', {
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: GROUND_Y + 60
});
game.addChild(ground);
// Add chicken
chicken = new Chicken();
chicken.x = CHICKEN_X;
chicken.groundY = GROUND_Y;
chicken.y = GROUND_Y;
game.addChild(chicken);
// Score text
scoreTxt = new Text2('0', {
	size: 120,
	fill: 0xFFF700
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Lives text (top right)
livesTxt = new Text2('❤ x' + lives, {
	size: 90,
	fill: 0xFF4444
});
livesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(livesTxt);
// Distance text (bottom center)
distTxt = new Text2('0m', {
	size: 70,
	fill: 0xFFFFFF
});
distTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(distTxt);
// Helper: spawn obstacle
function spawnObstacle() {
	var obs = new Obstacle();
	obs.speed = gameSpeed;
	obs.x = 2048 + OBSTACLE_WIDTH;
	obs.y = GROUND_Y;
	// Randomize height
	var h = OBSTACLE_MIN_HEIGHT + Math.floor(Math.random() * (OBSTACLE_MAX_HEIGHT - OBSTACLE_MIN_HEIGHT));
	obs.children[0].height = h;
	obs.children[0].y = 0; // AnchorY=1, so bottom at y=0
	obstacles.push(obs);
	game.addChild(obs);
	lastObstacleX = obs.x;
}
// Helper: reset game state
function resetGame() {
	// Remove obstacles
	for (var i = 0; i < obstacles.length; ++i) {
		obstacles[i].destroy();
	}
	obstacles = [];
	score = 0;
	distance = 0;
	gameSpeed = OBSTACLE_SPEED_START;
	lastObstacleX = 0;
	isGameOver = false;
	lives = 3;
	if (livesTxt) livesTxt.setText('❤ x' + lives);
	chicken.x = CHICKEN_X;
	chicken.y = GROUND_Y;
	chicken.velY = 0;
	chicken.isJumping = false;
	chicken.jumpCooldown = 0;
	scoreTxt.setText('0');
	distTxt.setText('0m');
}
// Face control: triggers jump if mouth opens or head moves up
function shouldJump() {
	// If mouth open
	if (facekit.mouthOpen) return true;
	// If head moves up (nose tip y decreases quickly)
	// We'll use a simple delta check
	if (typeof shouldJump.lastNoseY === 'undefined') {
		shouldJump.lastNoseY = facekit.noseTip ? facekit.noseTip.y : 0;
		return false;
	}
	var currY = facekit.noseTip ? facekit.noseTip.y : 0;
	var delta = shouldJump.lastNoseY - currY;
	shouldJump.lastNoseY = currY;
	if (delta > 22) return true; // Quick upward nod
	return false;
}
// Main update loop
game.update = function () {
	if (isGameOver) return;
	// Chicken update
	chicken.update();
	// Facekit: check for jump
	if (shouldJump() && !jumpTriggered) {
		chicken.jump();
		jumpTriggered = true;
	}
	if (!facekit.mouthOpen && !shouldJump()) {
		jumpTriggered = false;
	}
	// Obstacles update
	for (var i = obstacles.length - 1; i >= 0; --i) {
		var obs = obstacles[i];
		obs.speed = gameSpeed;
		obs.update();
		// Remove if off screen
		if (obs.x < -OBSTACLE_WIDTH) {
			obs.destroy();
			obstacles.splice(i, 1);
			continue;
		}
		// Collision
		if (!isGameOver && chicken.y + 10 > obs.y - obs.children[0].height + 30) {
			// Chicken feet near ground
			// Simple AABB
			var cLeft = chicken.x - chicken.children[0].width / 2 + 30;
			var cRight = chicken.x + chicken.children[0].width / 2 - 30;
			var oLeft = obs.x - OBSTACLE_WIDTH / 2;
			var oRight = obs.x + OBSTACLE_WIDTH / 2;
			if (cRight > oLeft && cLeft < oRight) {
				// Hit!
				lives--;
				livesTxt.setText('❤ x' + lives);
				LK.getSound('hit').play();
				LK.effects.flashScreen(0xff0000, 800);
				tween(chicken, {
					rotation: 0.7
				}, {
					duration: 300,
					easing: tween.easeOut
				});
				if (lives <= 0) {
					isGameOver = true;
					LK.setTimeout(function () {
						LK.showGameOver();
					}, 900);
					return;
				} else {
					// Remove the obstacle and reset chicken position for next life
					obs.destroy();
					obstacles.splice(i, 1);
					chicken.x = CHICKEN_X;
					chicken.y = GROUND_Y;
					chicken.velY = 0;
					chicken.isJumping = false;
					chicken.jumpCooldown = 0;
					tween(chicken, {
						rotation: 0
					}, {
						duration: 200,
						easing: tween.easeOut
					});
					// Brief invulnerability (skip further collision this frame)
					break;
				}
			}
		}
		// Score: passed obstacle
		if (!obs.passed && obs.x + OBSTACLE_WIDTH / 2 < chicken.x - chicken.children[0].width / 2) {
			obs.passed = true;
			score++;
			scoreTxt.setText(score);
		}
	}
	// Distance
	distance += gameSpeed / 8;
	distTxt.setText(Math.floor(distance) + "m");
	// Spawn new obstacle
	if (obstacles.length === 0 || 2048 - lastObstacleX > OBSTACLE_MIN_GAP + Math.random() * (OBSTACLE_MAX_GAP - OBSTACLE_MIN_GAP)) {
		spawnObstacle();
	}
	// Increase speed
	if (gameSpeed < OBSTACLE_MAX_SPEED) {
		gameSpeed += OBSTACLE_SPEED_INC;
	}
};
// Touch control: tap anywhere to jump (always enabled)
game.down = function (x, y, obj) {
	if (!isGameOver && !chicken.isJumping && chicken.jumpCooldown <= 0) {
		chicken.jump();
	}
	// Drag chicken for debug/touch (optional, for mobile fallback)
	if (!facekit.mouthOpen && !facekit.noseTip) {
		if (x > chicken.x - 120 && x < chicken.x + 120 && y > chicken.y - 180 && y < chicken.y) {
			dragNode = chicken;
		}
	}
};
game.move = function (x, y, obj) {
	if (dragNode) {
		dragNode.y = Math.max(Math.min(y, GROUND_Y), GROUND_Y - 400);
	}
};
game.up = function (x, y, obj) {
	dragNode = null;
};
// Reset game on showGameOver
LK.on('gameover', function () {
	resetGame();
});
// Reset game on showYouWin (not used, but for completeness)
LK.on('youwin', function () {
	resetGame();
}); ===================================================================
--- original.js
+++ change.js
@@ -24,9 +24,9 @@
 	// Physics
 	self.groundY = 0; // Set after adding to game
 	self.velY = 0;
 	self.isJumping = false;
-	self.jumpPower = -68; // Negative = up (higher jump)
+	self.jumpPower = -82; // Even higher jump for easier play
 	self.gravity = 5.2;
 	self.jumpCooldown = 0; // Prevents double jumps
 	// Jump method
 	self.jump = function () {
@@ -120,16 +120,16 @@
 // Chicken (player)
 // Game constants
 var GROUND_Y = 2300;
 var CHICKEN_X = 500;
-var OBSTACLE_MIN_GAP = 700;
-var OBSTACLE_MAX_GAP = 1100;
-var OBSTACLE_MIN_HEIGHT = 180;
-var OBSTACLE_MAX_HEIGHT = 320;
+var OBSTACLE_MIN_GAP = 950; // Wider minimum gap
+var OBSTACLE_MAX_GAP = 1450; // Wider maximum gap
+var OBSTACLE_MIN_HEIGHT = 140; // Lower minimum height
+var OBSTACLE_MAX_HEIGHT = 220; // Lower maximum height
 var OBSTACLE_WIDTH = 120;
-var OBSTACLE_SPEED_START = 22;
-var OBSTACLE_SPEED_INC = 0.012; // Per tick
-var OBSTACLE_MAX_SPEED = 38;
+var OBSTACLE_SPEED_START = 16; // Slower start speed for easier play
+var OBSTACLE_SPEED_INC = 0.006; // Slower speed increase
+var OBSTACLE_MAX_SPEED = 28; // Lower max speed
 // Game state
 var chicken;
 var ground;
 var obstacles = [];
@@ -141,9 +141,9 @@
 var jumpTriggered = false;
 var scoreTxt;
 var distTxt;
 var dragNode = null;
-var lives = 3; // Number of lives
+var lives = 6; // Number of lives (increased for easier gameplay)
 var livesTxt; // Text2 for lives
 // Add ground
 ground = LK.getAsset('ground', {
 	anchorX: 0,