User prompt
Why is chicken getting stuck in ropes
User prompt
Remove the animated green and yellow screens
User prompt
Remove the yellow and green coloured backgrounds that keep popping up
User prompt
Make bottom rope act the same as the other ropes
User prompt
Move entire arena right 20
User prompt
Add bogerk sound when you earn bonuses
User prompt
Play Chicken cluck sound when chicken bounces of ropes
User prompt
Don't play gamestart sound in title scene class
User prompt
Only play gamestart sound when you start a game
User prompt
Create instructions screen
User prompt
When you click play to initiate game show title screen asset first click on title screen asset to move on to the main game
User prompt
Position chicken in centre of screen when high score tally is shown
User prompt
Please fix the bug: 'TypeError: LK.effects.fireworks is not a function' in or related to this line: 'LK.effects.fireworks();' Line Number: 1080
User prompt
Add fireworks effect on big scoring launches
User prompt
Move somersaults text down 120
User prompt
Move launches text down 20
User prompt
Move launches text up 100
User prompt
Move launches text down 200
User prompt
Move launches text down 300
User prompt
Clean up code
User prompt
Create a title page with start button add chickenjockeylogo as a backdrop
User prompt
Add title screen with chickenjockeylogo asset as backdrop
User prompt
Please fix the bug: 'ReferenceError: logoBackdrop is not defined' in or related to this line: 'if (logoBackdrop.parent) {' Line Number: 150
User prompt
Add galaxy animation to green multiplier animation background
User prompt
Please fix the bug: 'TypeError: self.scoreMultiplierText.bringToFront is not a function' in or related to this line: 'self.scoreMultiplierText.bringToFront(); // Ensure text is on top' Line Number: 144
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var ChickenJockey = Container.expand(function () {
var self = Container.call(this);
// Create and attach chicken asset
var chickenGraphics = self.attachAsset('chicken', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.vx = 0;
self.vy = 0;
self.gravity = 0.5;
self.bounceDecay = 0.7; // Reduced bounce decay for more sustained bounces
self.friction = 0.998; // Increased horizontal friction for less horizontal drift
self.launched = false;
self.bounceCount = 0;
self.maxBounces = 5; // Allow 5 bounces per swipe
self.lastBouncePosition = {
x: 0,
y: 0
}; // Track last bounce position to prevent getting stuck
// Score multiplier based on somersaults
self.scoreMultiplier = 1;
self.scoreMultiplierText = null;
// Rotation properties
self.rotationSpeed = 0;
self.somersaulting = false;
self.somersaultRotation = 0;
self.somersaultDirection = 1; // 1 for clockwise, -1 for counter-clockwise
self.launch = function (power, angle) {
// Convert angle to radians
var radians = angle * Math.PI / 180;
// Set initial velocity based on power and angle
self.vx = Math.cos(radians) * power;
self.vy = Math.sin(radians) * power;
// Set rotation speed based on velocity
self.rotationSpeed = power / 50;
self.launched = true;
self.bounceCount = 0;
// Play launch sound
LK.getSound('launch').play();
};
self.reset = function () {
self.vx = 0;
self.vy = 0;
self.rotation = 0;
self.rotationSpeed = 0;
self.launched = false;
self.bounceCount = 0;
self.maxBounces = 300; // Set the max bounces here too
self.somersaulting = false;
self.somersaultRotation = 0;
self.rewardedFreeLaunch = false; // Track if we've already given free launch reward
self.scoreMultiplier = 1; // Reset score multiplier
// Remove multiplier text if it exists
if (self.scoreMultiplierText && self.scoreMultiplierText.parent) {
self.scoreMultiplierText.parent.removeChild(self.scoreMultiplierText);
self.scoreMultiplierText = null;
}
// Reset the chicken graphic rotation
var chickenGraphics = self.getChildAt(0);
if (chickenGraphics) {
chickenGraphics.rotation = 0;
}
};
self.update = function () {
if (!self.launched) {
return;
}
// Apply physics with speed limiting
self.vy += self.gravity;
// Cap maximum velocity to prevent freezing
var maxSpeed = 30;
self.vx = Math.max(-maxSpeed, Math.min(maxSpeed, self.vx));
self.vy = Math.max(-maxSpeed, Math.min(maxSpeed, self.vy));
self.x += self.vx;
self.y += self.vy;
self.vx *= self.friction;
// Apply rotation with speed limiting
self.rotationSpeed = Math.max(-0.2, Math.min(0.2, self.rotationSpeed));
self.rotation += self.rotationSpeed;
// Update score multiplier based on somersaults (1x for 0 somersaults, +0.5x per somersault)
var newMultiplier = 1 + Math.min(10, self.bounceCount) * 0.5;
if (newMultiplier !== self.scoreMultiplier) {
self.scoreMultiplier = newMultiplier;
// Create or update multiplier text
if (!self.scoreMultiplierText) {
self.scoreMultiplierText = new Text2("x" + self.scoreMultiplier.toFixed(1), {
size: 60,
fill: 0xFFFF00
});
self.scoreMultiplierText.anchor.set(0.5, 1);
self.addChild(self.scoreMultiplierText);
} else {
self.scoreMultiplierText.setText("x" + self.scoreMultiplier.toFixed(1));
}
// Animate multiplier change
if (self.bounceCount > 0) {
self.scoreMultiplierText.alpha = 1;
tween.stop(self.scoreMultiplierText);
self.scoreMultiplierText.scaleX = 1.5;
self.scoreMultiplierText.scaleY = 1.5;
tween(self.scoreMultiplierText, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
}
}
// Position the multiplier text above the chicken
if (self.scoreMultiplierText) {
self.scoreMultiplierText.y = -60;
}
// Keep chicken within arena boundaries
if (self.x < bounds.left) {
self.x = bounds.left;
self.vx = -self.vx * self.bounceDecay;
// Flip chicken when hitting arena boundary
var chickenGraphics = self.getChildAt(0);
if (chickenGraphics.scaleX !== 1) {
// Start somersault animation
self.somersaulting = true;
self.somersaultDirection = -1;
tween.stop(chickenGraphics); // Stop any existing rotation animations
tween(chickenGraphics, {
rotation: -Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
chickenGraphics.rotation = 0;
chickenGraphics.scaleX = 1; // Facing left
self.somersaulting = false;
}
});
}
} else if (self.x > bounds.right) {
self.x = bounds.right;
self.vx = -self.vx * self.bounceDecay;
// Flip chicken when hitting arena boundary
var chickenGraphics = self.getChildAt(0);
if (chickenGraphics.scaleX !== -1) {
// Start somersault animation
self.somersaulting = true;
self.somersaultDirection = 1;
tween.stop(chickenGraphics); // Stop any existing rotation animations
tween(chickenGraphics, {
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
chickenGraphics.rotation = 0;
chickenGraphics.scaleX = -1; // Facing right
self.somersaulting = false;
}
});
}
}
if (self.y < bounds.top) {
self.y = bounds.top;
self.vy = -self.vy * self.bounceDecay;
} else if (self.y > bounds.bottom) {
self.y = bounds.bottom;
self.vy = -self.vy * self.bounceDecay;
}
// Check if stuck in ropes (very low velocity but still touching a rope)
var touchingRope = false;
if (ropes && ropes.length > 0) {
for (var i = 0; i < ropes.length; i++) {
if (self.intersects(ropes[i])) {
touchingRope = true;
break;
}
}
}
if (touchingRope && Math.abs(self.vx) < 1 && Math.abs(self.vy) < 1) {
// Apply escape velocity in a random direction to break free
var escapeAngle = Math.random() * Math.PI * 2;
self.vx = Math.cos(escapeAngle) * 8;
self.vy = Math.sin(escapeAngle) * 8;
// Reset last bounce position to allow for new bounce
self.lastBouncePosition.x = -9999;
self.lastBouncePosition.y = -9999;
}
// Check if stopped
else if (Math.abs(self.vx) < 0.5 && Math.abs(self.vy) < 0.5 && self.bounceCount > 0) {
self.launched = false;
// Notify game that chicken jockey has stopped
if (typeof game.onChickenJockeyStop === 'function') {
game.onChickenJockeyStop();
}
}
// Bounce from side to side
if (self.x <= bounds.left || self.x >= bounds.right) {
self.vx = -self.vx * self.bounceDecay;
// Add a minimum velocity to prevent getting stuck
if (Math.abs(self.vx) < 5) {
self.vx = self.vx > 0 ? 5 : -5;
}
self.bounceCount++;
LK.getSound('bounce').play();
game.addScore(2000);
}
// Check if reached 10 somersaults and reward the player
if (self.bounceCount >= 10 && !self.rewardedFreeLaunch) {
self.rewardedFreeLaunch = true;
// Award free launch
if (typeof game.onFreeLaunchEarned === 'function') {
game.onFreeLaunchEarned();
}
}
// Check if max bounces reached
if (self.bounceCount >= self.maxBounces) {
self.launched = false;
// Notify game that max bounces reached
if (typeof game.onMaxBouncesReached === 'function') {
game.onMaxBouncesReached();
}
}
};
return self;
});
var HighScoreTally = Container.expand(function () {
var self = Container.call(this);
// Background container
var background = self.attachAsset('Hiscorebackdrop', {
anchorX: 0.5,
anchorY: 0.5
});
background.width = 1400;
background.height = 1200;
background.alpha = 0.8;
// Title text
var titleText = new Text2("HIGH SCORES", {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0);
titleText.y = -background.height / 2 + 100;
self.addChild(titleText);
// Score entries container
var scoreEntries = [];
self.updateScores = function (highScores) {
// Clear existing entries
for (var i = 0; i < scoreEntries.length; i++) {
if (scoreEntries[i].parent) {
scoreEntries[i].parent.removeChild(scoreEntries[i]);
}
}
scoreEntries = [];
// Create new entries
var startY = -background.height / 2 + 250;
var padding = 80;
for (var i = 0; i < highScores.length && i < 5; i++) {
var entry = new Container();
// Rank
var rankText = new Text2(i + 1 + ".", {
size: 70,
fill: 0xFFFFFF
});
rankText.anchor.set(0, 0.5);
rankText.x = -background.width / 2 + 200;
entry.addChild(rankText);
// Score
var scoreText = new Text2(highScores[i] ? highScores[i].toLocaleString() : "0", {
size: 70,
fill: 0xFFD700
});
scoreText.anchor.set(1, 0.5);
scoreText.x = background.width / 2 - 200;
entry.addChild(scoreText);
// Position entry
entry.y = startY + i * padding;
self.addChild(entry);
scoreEntries.push(entry);
}
// If no scores available
if (highScores.length === 0) {
var noScoreText = new Text2("No scores yet!", {
size: 70,
fill: 0xFFFFFF
});
noScoreText.anchor.set(0.5, 0.5);
noScoreText.y = 0;
self.addChild(noScoreText);
scoreEntries.push(noScoreText);
}
};
// Play Game button
var startButton = new Container();
var buttonBg = startButton.attachAsset('rope', {
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.width = 600;
buttonBg.height = 150;
buttonBg.tint = 0x00AA00;
var buttonText = new Text2("PLAY GAME", {
size: 70,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
startButton.addChild(buttonText);
startButton.y = background.height / 2 - 200;
self.addChild(startButton);
startButton.interactive = true;
startButton.down = function () {
buttonBg.tint = 0x007700;
};
startButton.up = function () {
buttonBg.tint = 0x00AA00;
if (typeof self.onStart === 'function') {
self.onStart();
}
};
// Reset button removed
// Make container position in center of screen
self.x = 2048 / 2;
self.y = 2732 / 2;
return self;
});
var InstructionsScreen = Container.expand(function () {
var self = Container.call(this);
// Background container
var background = self.attachAsset('Hiscorebackdrop', {
anchorX: 0.5,
anchorY: 0.5
});
background.width = 1400;
background.height = 1600;
background.alpha = 0.8;
// Title text
var titleText = new Text2("HOW TO PLAY", {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0);
titleText.y = -background.height / 2 + 100;
self.addChild(titleText);
// Instructions text
var instructions = ["1. Swipe to launch the chicken", "2. Bounce off ropes for points", "3. Collect popcorn for bonus points", "4. Each somersault increases your score multiplier", "5. Perform 10+ somersaults to earn a free launch", "6. Collect power-ups for special abilities", "7. Tap while chicken is flying to extend somersaults"];
var startY = -background.height / 2 + 250;
var padding = 80;
for (var i = 0; i < instructions.length; i++) {
var instructionText = new Text2(instructions[i], {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0, 0.5);
instructionText.x = -background.width / 2 + 100;
instructionText.y = startY + i * padding;
self.addChild(instructionText);
}
// Continue button
var continueButton = new Container();
var buttonBg = continueButton.attachAsset('rope', {
anchorX: 0.5,
anchorY: 0.5
});
buttonBg.width = 600;
buttonBg.height = 150;
buttonBg.tint = 0x00AA00;
var buttonText = new Text2("CONTINUE", {
size: 70,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
continueButton.addChild(buttonText);
continueButton.y = background.height / 2 - 200;
self.addChild(continueButton);
continueButton.interactive = true;
continueButton.down = function () {
buttonBg.tint = 0x007700;
};
continueButton.up = function () {
buttonBg.tint = 0x00AA00;
// Animate out
tween(self, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove from parent
if (self.parent) {
self.parent.removeChild(self);
}
// Start the game
if (typeof self.onContinue === 'function') {
self.onContinue();
}
}
});
};
// Position in center of screen
self.x = 2048 / 2;
self.y = 2732 / 2;
return self;
});
var PathTracer = Container.expand(function () {
var self = Container.call(this);
self.points = [];
self.maxPoints = 50;
self.lineWidth = 5;
self.lineColor = 0xFFFFFF;
self.active = false;
// Create visual representation of the path
var pathGraphics = self.attachAsset('rope', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize path graphics
pathGraphics.alpha = 0.5;
pathGraphics.width = 0;
pathGraphics.height = 0;
self.startTracing = function (x, y) {
self.points = [{
x: x,
y: y
}];
self.active = true;
};
self.addPoint = function (x, y) {
if (!self.active) {
return;
}
// Only add point if it's significantly different from last point
var lastPoint = self.points[self.points.length - 1];
var dx = x - lastPoint.x;
var dy = y - lastPoint.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 20) {
self.points.push({
x: x,
y: y
});
// Limit number of points
if (self.points.length > self.maxPoints) {
self.points.shift();
}
}
};
self.stopTracing = function () {
self.active = false;
return self.points.length >= 2 ? self.points : null;
};
self.clear = function () {
self.points = [];
self.active = false;
};
self.update = function () {
// Update path visualization based on current points
if (self.points.length < 2) {
pathGraphics.alpha = 0;
return;
}
pathGraphics.alpha = 0.5;
// Calculate path visual representation
var firstPoint = self.points[0];
var lastPoint = self.points[self.points.length - 1];
// Position at midpoint of path
self.x = (firstPoint.x + lastPoint.x) / 2;
self.y = (firstPoint.y + lastPoint.y) / 2;
// Calculate path length and angle
var dx = lastPoint.x - firstPoint.x;
var dy = lastPoint.y - firstPoint.y;
var length = Math.sqrt(dx * dx + dy * dy);
var angle = Math.atan2(dy, dx);
// Update path graphics
pathGraphics.width = length;
pathGraphics.height = self.lineWidth;
pathGraphics.rotation = angle;
};
return self;
});
var Popcorn = Container.expand(function () {
var self = Container.call(this);
// Create and attach popcorn asset
var popcornGraphics = self.attachAsset('popcorn', {
anchorX: 0.5,
anchorY: 0.5
});
// Add slight animation
self.animationOffset = Math.random() * Math.PI * 2;
self.animationSpeed = 0.03 + Math.random() * 0.02;
self.baseY = 0;
self.collect = function () {
// Play collect sound
LK.getSound('collect').play();
// Flash effect
LK.effects.flashObject(self, 0xFFFFFF, 200);
// Animate collection (flying up)
tween(self, {
y: self.y - 100,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove from parent
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.update = function () {
// Hover animation
if (self.baseY === 0) {
self.baseY = self.y;
}
self.y = self.baseY + Math.sin(LK.ticks * self.animationSpeed + self.animationOffset) * 5;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
// Create and attach power-up asset (using popcorn as base)
var powerUpGraphics = self.attachAsset('popcorn', {
anchorX: 0.5,
anchorY: 0.5
});
// Make it visually distinct
powerUpGraphics.tint = 0x00FFFF;
// PowerUp properties
self.type = "multiplier"; // Default type
self.value = 2; // Default multiplier value
self.duration = 10000; // 10 seconds
self.active = false;
// Animation properties
self.animationOffset = Math.random() * Math.PI * 2;
self.animationSpeed = 0.05 + Math.random() * 0.03;
self.baseY = 0;
self.scale = 1.5; // Make power-ups slightly larger
// Pulse animation
self.pulseDirection = 1;
self.pulseSpeed = 0.02;
self.minScale = 1.3;
self.maxScale = 1.7;
self.collect = function () {
// Play Bogerk sound for power-up collection
LK.getSound('Bogerk').play();
// Flash effect
LK.effects.flashObject(self, 0xFFFFFF, 300);
// Animate collection (flying up)
tween(self, {
y: self.y - 150,
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove from parent
if (self.parent) {
self.parent.removeChild(self);
}
}
});
// Activate the powerup effect
if (typeof game.activatePowerUp === 'function') {
game.activatePowerUp(self.type, self.value, self.duration);
}
};
self.update = function () {
// Hover animation
if (self.baseY === 0) {
self.baseY = self.y;
}
// Vertical hover
self.y = self.baseY + Math.sin(LK.ticks * self.animationSpeed + self.animationOffset) * 8;
// Pulsing animation
var currentScale = self.scale;
currentScale += self.pulseDirection * self.pulseSpeed;
if (currentScale > self.maxScale) {
currentScale = self.maxScale;
self.pulseDirection = -1;
} else if (currentScale < self.minScale) {
currentScale = self.minScale;
self.pulseDirection = 1;
}
self.scale = currentScale;
self.scaleX = self.scale;
self.scaleY = self.scale;
};
return self;
});
var Rope = Container.expand(function () {
var self = Container.call(this);
// Create and attach rope asset
var ropeGraphics = self.attachAsset('rope', {
anchorX: 0.5,
anchorY: 0.5
});
// Rope properties
self.tension = 0.8; // Increased tension for more springy, elastic bounces
self.bounce = function (chickenJockey) {
// Check if we've already bounced in the same place to prevent getting stuck
var distFromLastBounce = Math.sqrt(Math.pow(chickenJockey.x - chickenJockey.lastBouncePosition.x, 2) + Math.pow(chickenJockey.y - chickenJockey.lastBouncePosition.y, 2));
// If too close to last bounce position, give an extra boost to escape
if (distFromLastBounce < 100) {
// Extra velocity away from the rope with greater force
var awayX = chickenJockey.x - self.x;
var awayY = chickenJockey.y - self.y;
var awayDist = Math.sqrt(awayX * awayX + awayY * awayY);
if (awayDist > 0) {
// Apply much stronger repulsion
chickenJockey.vx = awayX / awayDist * 20;
chickenJockey.vy = awayY / awayDist * 20;
// Reset last bounce position to a far away point to ensure next bounce registers
chickenJockey.lastBouncePosition.x = -9999;
chickenJockey.lastBouncePosition.y = -9999;
}
}
// Store current position as last bounce position
chickenJockey.lastBouncePosition.x = chickenJockey.x;
chickenJockey.lastBouncePosition.y = chickenJockey.y;
// Store original position for rope displacement effect
var originalX = self.x;
var originalY = self.y;
// Calculate normal angle (perpendicular to rope)
var normalAngle = Math.atan2(chickenJockey.y - self.y, chickenJockey.x - self.x);
// Account for rope rotation when calculating normal
normalAngle += self.rotation + Math.PI / 2;
// Calculate velocity components
var speed = Math.sqrt(chickenJockey.vx * chickenJockey.vx + chickenJockey.vy * chickenJockey.vy);
var incomingAngle = Math.atan2(chickenJockey.vy, chickenJockey.vx);
// Flip the chicken based on horizontal velocity after bounce
var chickenGraphics = chickenJockey.getChildAt(0);
if (chickenJockey.vx > 0) {
if (chickenGraphics.scaleX !== -1) {
// Starting a flip from left to right
chickenJockey.somersaulting = true;
chickenJockey.somersaultDirection = 1;
chickenJockey.somersaultRotation = 0;
// Start somersault animation with tween
tween.stop(chickenGraphics); // Stop any existing rotation animations
tween(chickenGraphics, {
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
chickenGraphics.rotation = 0;
chickenGraphics.scaleX = -1; // Facing right
chickenJockey.somersaulting = false;
}
});
}
} else {
if (chickenGraphics.scaleX !== 1) {
// Starting a flip from right to left
chickenJockey.somersaulting = true;
chickenJockey.somersaultDirection = -1;
chickenJockey.somersaultRotation = 0;
// Start somersault animation with tween
tween.stop(chickenGraphics); // Stop any existing rotation animations
tween(chickenGraphics, {
rotation: -Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
chickenGraphics.rotation = 0;
chickenGraphics.scaleX = 1; // Facing left
chickenJockey.somersaulting = false;
}
});
}
}
// Calculate angle of reflection
var bounceAngle = 2 * normalAngle - incomingAngle;
// Calculate new velocity with enhanced force based on incoming speed
// Higher incoming speed = stronger bounce back effect
var bounceForce = speed * self.tension * (1 + Math.min(1.0, speed / 20)); // Further adjusted to depend more on incoming velocity
// Ensure minimum bounce force to prevent getting stuck
bounceForce = Math.max(bounceForce, 5);
// Add screen shake effect on powerful impacts
if (speed > 20) {
// Custom screen shake effect using tween
var originalPosition = {
x: game.x,
y: game.y
};
tween(game, {
x: originalPosition.x + (Math.random() - 0.5) * 20,
y: originalPosition.y + (Math.random() - 0.5) * 20
}, {
duration: 100,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(game, {
x: originalPosition.x,
y: originalPosition.y
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
}
// Reduce random angle variation for more predictable wrestling-style bounces
var angleVariation = (Math.random() - 0.5) * 0.05; // Further reduced random angle adjustment for predictability
bounceAngle += angleVariation;
// Apply immediate minimum velocity to prevent sticking
var minVelocity = 3.0;
chickenJockey.vx = Math.cos(bounceAngle) * Math.max(bounceForce * 0.3, minVelocity) * chickenJockey.bounceDecay;
chickenJockey.vy = Math.sin(bounceAngle) * Math.max(bounceForce * 0.3, minVelocity) * chickenJockey.bounceDecay;
// Brief pause to simulate rope stretching and chicken "sticking" to rope momentarily
// Store original velocities but don't slow down as much to prevent sticking
var originalVX = chickenJockey.vx;
var originalVY = chickenJockey.vy;
// Momentarily slow down the chicken but not enough to get stuck
chickenJockey.vx *= 0.3;
chickenJockey.vy *= 0.3;
// Add a slight delay before applying the bounce-back force
LK.setTimeout(function () {
// Now apply the full bounce force with enhanced velocity
chickenJockey.vx = Math.cos(bounceAngle) * bounceForce * chickenJockey.bounceDecay;
chickenJockey.vy = Math.sin(bounceAngle) * bounceForce * chickenJockey.bounceDecay;
// Add a burst of rotation to simulate impact force
chickenJockey.rotationSpeed = (Math.random() - 0.5) * 0.2; // Increased rotation burst for more dramatic impact
}, 30);
// Create enhanced bounce visual effect with more dramatic rope "give"
tween(self, {
scaleY: 1.8,
// More dramatic stretch
alpha: 0.7,
// Add slight displacement in direction of impact
x: originalX + Math.cos(incomingAngle) * 10,
y: originalY + Math.sin(incomingAngle) * 10
}, {
duration: 200,
// Extended stretch duration
easing: tween.easeOut,
onFinish: function onFinish() {
// After brief delay, apply the full bounce force
// We're not setting additional velocity here to prevent doubling the effect
LK.setTimeout(function () {
// Ensure the chicken is still moving away from the rope
if (Math.abs(chickenJockey.vx) < minVelocity && Math.abs(chickenJockey.vy) < minVelocity) {
chickenJockey.vx = Math.cos(bounceAngle) * bounceForce * chickenJockey.bounceDecay;
chickenJockey.vy = Math.sin(bounceAngle) * bounceForce * chickenJockey.bounceDecay;
}
// Add a burst of rotation to simulate impact force
chickenJockey.rotationSpeed = (Math.random() - 0.5) * 0.15;
}, 30);
// Snap the rope back with more dramatic effect
tween(self, {
scaleY: 1.0,
alpha: 1.0,
x: originalX,
y: originalY
}, {
duration: 500,
// Longer snap-back for more visual impact
easing: tween.elasticOut,
onFinish: function onFinish() {
// Add rope vibration effect after snap-back
tween(self, {
x: originalX + Math.sin(LK.ticks * 0.1) * 5,
y: originalY + Math.cos(LK.ticks * 0.1) * 5
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Reset position after vibration
self.x = originalX;
self.y = originalY;
}
});
}
});
}
});
// Increment bounce count
chickenJockey.bounceCount++;
// Play bounce sound with increased volume for high-speed bounces
var bounceSound = LK.getSound('bounce');
bounceSound.volume = Math.min(1, speed / 30); // Increase volume based on speed
bounceSound.play();
// Play chicken cluck sound when chicken bounces off ropes
LK.getSound('Chickencluck').play();
// Flash rope to indicate bounce with more intensity for high-speed bounces
var flashIntensity = Math.min(0xFFFFFF, 0xFFFFFF * (speed / 30));
LK.effects.flashObject(self, flashIntensity, 200);
// Add points for bouncing - more points for higher somersault count
var somersaultBonus = Math.min(10, chickenJockey.bounceCount) * 500; // Bonus increases with somersault count
if (typeof game.addScore === 'function') {
game.addScore(5000 + somersaultBonus);
}
// Spawn more popcorn on rope bounce (increased chance and count)
if (Math.random() < 0.7 && typeof game.createPopcornAt === 'function') {
game.createPopcornAt(chickenJockey.x, chickenJockey.y, 5);
}
};
self.intersectsWithPoint = function (x, y) {
var halfWidth = ropeGraphics.width / 2;
var halfHeight = ropeGraphics.height / 2;
// Check if point is within the rope's bounding box
return x >= self.x - halfWidth && x <= self.x + halfWidth && y >= self.y - halfHeight && y <= self.y + halfHeight;
};
return self;
});
var TitleScreen = Container.expand(function () {
var self = Container.call(this);
// Create and attach title screen asset
var titleGraphics = self.attachAsset('Titlescreen', {
anchorX: 0.5,
anchorY: 0.5
});
// Position in center of screen
self.x = 2048 / 2;
self.y = 2732 / 2;
// Make interactive to handle clicks
self.interactive = true;
// Handle click/tap to start game
self.down = function () {
// Visual feedback
titleGraphics.alpha = 0.8;
};
self.up = function () {
// Animate out
tween(self, {
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove from parent
if (self.parent) {
self.parent.removeChild(self);
}
// Start the game
if (typeof self.onStart === 'function') {
self.onStart();
}
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Black background
});
/****
* Game Code
****/
// Game state
var gameState = "ready"; // ready, aiming, launched, gameOver
var score = 0;
var launches = 0;
var maxLaunches = 5;
var maxLaunchesFromBonuses = 0; // Track how many launches came from bonuses
var popcorns = [];
var ropes = [];
var powerUps = [];
var scoreMultiplier = 1;
var multiplierEndTime = 0;
var highScoresKey = 'chickenJockeyHighScores';
var pathTracer = game.addChild(new PathTracer());
// Add backdrop first
var backdrop = game.addChild(LK.getAsset('Backdrop', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Create wrestling arena
var arena = game.addChild(LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 20,
y: 2732 / 2
}));
// Create chicken jockey
var chickenJockey = game.addChild(new ChickenJockey());
// Game boundaries
var bounds = {
left: arena.x - arena.width / 2,
right: arena.x + arena.width / 2,
top: arena.y - arena.height / 2,
bottom: arena.y + arena.height / 2
};
// Create GUI elements
var scoreText = new Text2("Score: 0", {
size: 70,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
var launchesText = new Text2("Launches: 0/" + maxLaunches, {
size: 50,
fill: 0xFFFFFF
});
launchesText.anchor.set(0, 0);
launchesText.x = 120; // Avoid top-left corner
launchesText.y = 140;
LK.gui.topLeft.addChild(launchesText);
// Add somersault counter display
var somersaultText = new Text2("Somersaults: 0", {
size: 50,
fill: 0xFFFFFF
});
somersaultText.anchor.set(1, 0);
somersaultText.x = -120; // Position on right side
somersaultText.y = 140;
LK.gui.topRight.addChild(somersaultText);
var instructionText = new Text2("Drag to aim and launch the chicken!", {
size: 40,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 100;
LK.gui.top.addChild(instructionText);
// Initialize game
function initGame() {
// Reset variables
score = 0;
launches = 0;
maxLaunches = 5; // Starting launches, can go up to 20 max
maxLaunchesFromBonuses = 0; // Reset bonus launches counter
scoreMultiplier = 1;
multiplierEndTime = 0;
gameState = "ready";
// Update UI
scoreText.setText("Score: " + score);
launchesText.setText("Launches: " + launches + "/" + maxLaunches);
instructionText.setText("Swipe to launch! Somersaults = SCORE MULTIPLIER + FREE LAUNCH!");
somersaultText.setText("Somersaults: 0");
// Reset chicken jockey
resetChickenJockey();
// Clear existing popcorn and ropes
clearPopcornsAndRopes();
// Create ropes around the arena
createRopes();
// Create more popcorn scattered around the arena
createPopcorn(60);
// Create a few power-ups
for (var i = 0; i < 3; i++) {
createPowerUp();
}
// Play game start sound
LK.getSound('Gamestart').play();
// Play background music after a short delay to ensure it starts after the game start sound
LK.setTimeout(function () {
LK.playMusic('gameMusic', {
loop: true
});
}, 1000); // Delay of 1000ms (1 second)
}
function resetChickenJockey() {
chickenJockey.reset();
// Position chicken in the center of the arena
chickenJockey.x = arena.x;
chickenJockey.y = arena.y;
}
function clearPopcornsAndRopes() {
// Remove all popcorn
for (var i = 0; i < popcorns.length; i++) {
if (popcorns[i].parent) {
popcorns[i].parent.removeChild(popcorns[i]);
}
}
popcorns = [];
// Remove all ropes
for (var i = 0; i < ropes.length; i++) {
if (ropes[i].parent) {
ropes[i].parent.removeChild(ropes[i]);
}
}
ropes = [];
// Remove all power-ups
for (var i = 0; i < powerUps.length; i++) {
if (powerUps[i].parent) {
powerUps[i].parent.removeChild(powerUps[i]);
}
}
powerUps = [];
}
function createRopes() {
// Create top rope
var topRope = new Rope();
topRope.x = arena.x;
topRope.y = bounds.top + 100;
game.addChild(topRope);
ropes.push(topRope);
// Create right rope
var rightRope = new Rope();
rightRope.x = bounds.right - 100;
rightRope.y = arena.y;
rightRope.rotation = Math.PI / 2; // Rotate 90 degrees
game.addChild(rightRope);
ropes.push(rightRope);
// Create bottom rope
var bottomRope = new Rope();
bottomRope.x = arena.x;
bottomRope.y = bounds.bottom - 100;
game.addChild(bottomRope);
ropes.push(bottomRope);
// Create left rope
var leftRope = new Rope();
leftRope.x = bounds.left + 100;
leftRope.y = arena.y;
leftRope.rotation = Math.PI / 2; // Rotate 90 degrees
game.addChild(leftRope);
ropes.push(leftRope);
// Center horizontal rope removed
}
function createPopcorn(count) {
for (var i = 0; i < count; i++) {
var popcorn = new Popcorn();
// Random position within arena bounds
popcorn.x = bounds.left + 100 + Math.random() * (arena.width - 200);
popcorn.y = bounds.top + 100 + Math.random() * (arena.height - 200);
game.addChild(popcorn);
popcorns.push(popcorn);
}
}
function createPowerUp() {
var powerUp = new PowerUp();
// Random position within arena bounds
powerUp.x = bounds.left + 150 + Math.random() * (arena.width - 300);
powerUp.y = bounds.top + 150 + Math.random() * (arena.height - 300);
// Random power-up type
var types = ["multiplier", "extraLaunch", "superBounce"];
var randomType = types[Math.floor(Math.random() * types.length)];
powerUp.type = randomType;
// Configure based on type
if (randomType === "multiplier") {
powerUp.tint = 0x00FFFF; // Cyan
powerUp.value = 2 + Math.floor(Math.random() * 3); // 2x to 4x multiplier
} else if (randomType === "extraLaunch") {
powerUp.tint = 0xFF00FF; // Purple
powerUp.value = 1; // Extra launch
} else if (randomType === "superBounce") {
powerUp.tint = 0xFFFF00; // Yellow
powerUp.value = 2; // Double bounce points
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Game events
game.onChickenJockeyStop = function () {
gameState = "ready";
// Add more popcorn when chicken jockey stops
if (popcorns.length < 40) {
createPopcorn(25);
}
// Occasionally add a power-up when chicken stops
if (Math.random() < 0.3 && powerUps.length < 5) {
createPowerUp();
}
// Check if out of launches
if (launches >= maxLaunches) {
// Game over
instructionText.setText("Game Over! Final Score: " + score);
gameState = "gameOver";
// Show game over after a short delay
// Removed call to LK.showGameOver to prevent freezing and default win screen
} else {
// Reset for next launch
resetChickenJockey();
instructionText.setText("Drag to aim and launch the chicken!");
}
};
game.onMaxBouncesReached = function () {
// Same as onChickenJockeyStop for now
game.onChickenJockeyStop();
};
// Input handling
var dragStartX = 0;
var dragStartY = 0;
var dragEndX = 0;
var dragEndY = 0;
game.down = function (x, y, obj) {
if (gameState === "ready") {
gameState = "aiming";
dragStartX = x;
dragStartY = y;
pathTracer.startTracing(x, y);
instructionText.setText("Draw a path for the chicken!");
}
// Add quick tap detection for increasing somersaults when chicken is launched
else if (gameState === "launched" && chickenJockey.launched) {
// Increase max bounces to allow more somersaults
chickenJockey.maxBounces += 3;
// Show feedback
showMessage("+" + 3 + " somersaults!", 0x00FF00);
// Add some visual feedback
LK.effects.flashObject(chickenJockey, 0x00FF00, 200);
// Play sound
LK.getSound('bounce').play();
}
};
game.move = function (x, y, obj) {
if (gameState === "aiming") {
pathTracer.addPoint(x, y);
}
};
game.up = function (x, y, obj) {
if (gameState === "aiming") {
// Get the path from the path tracer
var path = pathTracer.stopTracing();
// Only launch if we have a valid path
if (path && path.length >= 2) {
// Record drag end position
dragEndX = x;
dragEndY = y;
// Calculate direction from the path
var firstPoint = path[0];
var lastPoint = path[path.length - 1];
var dx = lastPoint.x - firstPoint.x;
var dy = lastPoint.y - firstPoint.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Calculate power based on path length (with a more controlled range)
var power = Math.min(distance, 200) * 0.2;
// Calculate angle based on path direction
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
chickenJockey.launch(power, angle);
// Update game state
gameState = "launched";
launches++;
launchesText.setText("Launches: " + launches + "/" + maxLaunches);
instructionText.setText("Watch the chicken bounce!");
} else {
// Cancel the launch if the path was too short
gameState = "ready";
}
// Clear the path tracer regardless
pathTracer.clear();
}
};
// Add helper to update score
game.addScore = function (points) {
// Apply multiplier if active (powerup multiplier)
var finalPoints = points;
if (Date.now() < multiplierEndTime) {
finalPoints = Math.floor(points * scoreMultiplier);
}
// Apply somersault multiplier if chicken is launched
if (chickenJockey.launched && chickenJockey.scoreMultiplier > 1) {
finalPoints = Math.floor(finalPoints * chickenJockey.scoreMultiplier);
// Show somersault multiplier notification for big scores
if (points >= 2000) {
var multiplierText = new Text2("SOMERSAULT BONUS x" + chickenJockey.scoreMultiplier.toFixed(1), {
size: 70,
fill: 0x00FFAA
});
multiplierText.anchor.set(0.5, 0.5);
multiplierText.x = chickenJockey.x;
multiplierText.y = chickenJockey.y - 180;
game.addChild(multiplierText);
// Animate multiplier text
tween(multiplierText, {
y: multiplierText.y - 100,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
if (multiplierText.parent) {
multiplierText.parent.removeChild(multiplierText);
}
}
});
}
}
score += finalPoints;
scoreText.setText("Score: " + score);
LK.setScore(score);
// Visual feedback for big point gains
if (finalPoints >= 5000) {
// Add fireworks effect - LK.effects.fireworks is not a function
// LK.effects.fireworks();
var pointText = new Text2("+" + finalPoints, {
size: 80,
fill: 0xFFFF00,
font: "'Arial',Impact,'Helvetica'" // Start with standard font
});
pointText.anchor.set(0.5, 0.5);
pointText.x = chickenJockey.x;
pointText.y = chickenJockey.y - 120;
game.addChild(pointText);
// Animate font change and movement
tween(pointText, {
y: pointText.y - 70,
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Change font to more dramatic one mid-animation
pointText.font = "'Impact','Arial Black'";
pointText.fill = 0xFF4500; // Change color to orange-red
// Finish animation with new font
tween(pointText, {
y: pointText.y - 100,
alpha: 0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
if (pointText.parent) {
pointText.parent.removeChild(pointText);
}
}
});
}
});
}
};
// Helper method to create popcorn at specific location
game.createPopcornAt = function (x, y, count) {
count = count || 1;
for (var i = 0; i < count; i++) {
var popcorn = new Popcorn();
// Position near the specified location with some random offset
var offsetX = (Math.random() - 0.5) * 200;
var offsetY = (Math.random() - 0.5) * 200;
popcorn.x = Math.max(bounds.left + 50, Math.min(bounds.right - 50, x + offsetX));
popcorn.y = Math.max(bounds.top + 50, Math.min(bounds.bottom - 50, y + offsetY));
// Add to game
game.addChild(popcorn);
popcorns.push(popcorn);
}
};
// Power-up activation function
game.activatePowerUp = function (type, value, duration) {
// Visual feedback for power-up activation
// Removed LK.effects.flashScreen to prevent green and yellow screen flashes
if (type === "multiplier") {
// Set score multiplier
scoreMultiplier = value;
// Display message
showMessage("Score x" + value + " for " + duration / 1000 + "s!", 0x00FFFF);
// Set timer to end effect
multiplierEndTime = Date.now() + duration;
} else if (type === "extraLaunch") {
// Check if adding value would exceed the maximum of 20 launches or max bonus launches
if (maxLaunches < 20 && maxLaunchesFromBonuses < 15) {
// Calculate how many launches to add without exceeding the cap
var maxBonusRemaining = 15 - maxLaunchesFromBonuses;
var maxTotalRemaining = 20 - maxLaunches;
var launchesToAdd = Math.min(value, Math.min(maxBonusRemaining, maxTotalRemaining));
maxLaunches += launchesToAdd;
maxLaunchesFromBonuses += launchesToAdd;
launches = Math.max(0, launches - launchesToAdd); // Refund launches
launchesText.setText("Launches: " + launches + "/" + maxLaunches);
// Display message
showMessage("+" + launchesToAdd + " Extra Launch!", 0xFF00FF);
// Show warning if we had to cap the bonus
if (launchesToAdd < value) {
LK.setTimeout(function () {
showMessage("MAX LAUNCHES REACHED (20)!", 0xFF0000);
}, 1000);
}
} else {
// Already at max launches
showMessage("MAX LAUNCHES REACHED (20)!", 0xFF0000);
}
} else if (type === "superBounce") {
// Temporarily increase bounce values
var oldBounceDecay = chickenJockey.bounceDecay;
chickenJockey.bounceDecay = Math.min(1.0, chickenJockey.bounceDecay * 1.3);
// Display message
showMessage("Super Bounce for " + duration / 1000 + "s!", 0xFFFF00);
// Set timer to end effect
LK.setTimeout(function () {
chickenJockey.bounceDecay = oldBounceDecay;
}, duration);
}
};
// Helper function to show temporary messages
function showMessage(text, color) {
var message = new Text2(text, {
size: 60,
fill: color || 0xFFFFFF
});
message.anchor.set(0.5, 0.5);
message.x = 2048 / 2;
message.y = 400;
LK.gui.center.addChild(message);
// Animate in
message.alpha = 0;
message.scaleX = 0.5;
message.scaleY = 0.5;
tween(message, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOut
});
// Animate out after delay
LK.setTimeout(function () {
tween(message, {
alpha: 0,
y: message.y - 100
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
if (message.parent) {
message.parent.removeChild(message);
}
}
});
}, 2000);
}
// Main game loop
game.update = function () {
// Update all game objects
if (gameState === "launched") {
chickenJockey.update();
if (chickenJockey.lastRopeCollision === undefined) {
chickenJockey.lastRopeCollision = null;
}
// Count how many ropes the chicken is intersecting
var intersectingRopes = 0;
for (var i = 0; i < ropes.length; i++) {
if (chickenJockey.intersects(ropes[i])) {
intersectingRopes++;
}
}
// If intersecting multiple ropes (stuck in corner/intersection), apply emergency escape
if (intersectingRopes > 1) {
// Calculate center of arena
var centerX = arena.x;
var centerY = arena.y;
// Calculate vector toward center
var towardCenterX = centerX - chickenJockey.x;
var towardCenterY = centerY - chickenJockey.y;
var distance = Math.sqrt(towardCenterX * towardCenterX + towardCenterY * towardCenterY);
// Apply strong impulse toward center
if (distance > 0) {
chickenJockey.vx = towardCenterX / distance * 25;
chickenJockey.vy = towardCenterY / distance * 25;
chickenJockey.lastRopeCollision = null;
// Clear last bounce position
chickenJockey.lastBouncePosition.x = -9999;
chickenJockey.lastBouncePosition.y = -9999;
}
}
// Normal single rope collision handling
else {
// Check for collisions with ropes
for (var i = 0; i < ropes.length; i++) {
// Only bounce if we weren't already intersecting this rope
if (chickenJockey.intersects(ropes[i]) && chickenJockey.lastRopeCollision !== ropes[i]) {
// Calculate direction vectors for bounce
var dx = chickenJockey.x - ropes[i].x;
var dy = chickenJockey.y - ropes[i].y;
var dist = Math.sqrt(dx * dx + dy * dy);
// Push chicken away from rope slightly to prevent sticking
if (dist > 0) {
chickenJockey.x += dx / dist * 10;
chickenJockey.y += dy / dist * 10;
}
ropes[i].bounce(chickenJockey);
chickenJockey.lastRopeCollision = ropes[i];
// Clear last rope collision after a shorter delay to allow for new collisions
LK.setTimeout(function () {
chickenJockey.lastRopeCollision = null;
}, 100); // Reduced from 150 to 100ms
// Only bounce on one rope per frame to prevent chaotic behavior
break;
}
}
}
// Check for collisions with popcorn
for (var i = popcorns.length - 1; i >= 0; i--) {
if (chickenJockey.intersects(popcorns[i])) {
// Collect popcorn
popcorns[i].collect();
popcorns.splice(i, 1);
// Increase score - reduced from 10000 to 2000
game.addScore(2000);
scoreText.setText("Score: " + score);
// Save score to LK
LK.setScore(score);
// No longer reset launches when score reaches 1000
}
}
// Check for collisions with power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
if (chickenJockey.intersects(powerUps[i])) {
// Collect power-up
powerUps[i].collect();
powerUps.splice(i, 1);
}
}
}
// Update popcorn animations
for (var i = 0; i < popcorns.length; i++) {
popcorns[i].update();
}
// Update power-up animations
for (var i = 0; i < powerUps.length; i++) {
powerUps[i].update();
}
// Randomly spawn new power-ups (rare)
if (gameState === "launched" && Math.random() < 0.001 && powerUps.length < 5) {
createPowerUp();
}
// Randomly create popcorn explosions during gameplay
if (gameState === "launched" && Math.random() < 0.01) {
// Create random popcorn explosion in the arena
var explosionX = bounds.left + 150 + Math.random() * (arena.width - 300);
var explosionY = bounds.top + 150 + Math.random() * (arena.height - 300);
game.createPopcornAt(explosionX, explosionY, 8);
// Visual feedback
var popText = new Text2("POP!", {
size: 60,
fill: 0xFFD700
});
popText.anchor.set(0.5, 0.5);
popText.x = explosionX;
popText.y = explosionY;
game.addChild(popText);
// Animate out
tween(popText, {
alpha: 0,
y: popText.y - 100,
scaleX: 2,
scaleY: 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
if (popText.parent) {
popText.parent.removeChild(popText);
}
}
});
}
// Update path tracer
pathTracer.update();
// Update score multiplier UI if active
if (Date.now() < multiplierEndTime && scoreMultiplier > 1) {
// Update multiplier display in score text
var remainingSecs = Math.ceil((multiplierEndTime - Date.now()) / 1000);
scoreText.setText("Score: " + score + " (x" + scoreMultiplier + " for " + remainingSecs + "s)");
}
// Update somersault counter if chicken is launched
if (gameState === "launched" && chickenJockey.launched) {
somersaultText.setText("Somersaults: " + chickenJockey.bounceCount);
}
// Award extra launch for every million points
if (score >= 1000000) {
// Calculate current million mark
var currentMillionMark = Math.floor(score / 1000000);
// Check if we crossed a new million point threshold
if (!game.lastMillionMark || currentMillionMark > game.lastMillionMark) {
// Award free launch if not at max cap and not exceeding max bonus launches
if (maxLaunches < 20 && maxLaunchesFromBonuses < 15) {
maxLaunches++;
maxLaunchesFromBonuses++;
// Optionally refund a launch for immediate use
launches = Math.max(0, launches - 1);
// Play Bogerk sound for million point bonus
LK.getSound('Bogerk').play();
showMessage("FREE LAUNCH FOR " + currentMillionMark + " MILLION POINTS!", 0xFFFF00);
} else {
showMessage("MAX LAUNCHES REACHED (20)!", 0xFF0000);
}
launchesText.setText("Launches: " + launches + "/" + maxLaunches);
game.lastMillionMark = currentMillionMark;
// Add popcorn explosion for million point milestone
game.createPopcornAt(chickenJockey.x, chickenJockey.y, 20);
// Create animated free launch text
var freeText = new Text2("FREE LAUNCH!", {
size: 100,
fill: 0xFFFF00
});
freeText.anchor.set(0.5, 0.5);
freeText.x = 2048 / 2;
freeText.y = 2732 / 2;
freeText.alpha = 0;
freeText.scaleX = 0.5;
freeText.scaleY = 0.5;
LK.gui.center.addChild(freeText);
// Flash the screen for dramatic effect
// Removed LK.effects.flashScreen to prevent green and yellow screen flashes
// Animate in with bounce effect
tween(freeText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Pulse animation
tween(freeText, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Animate out with upward movement
tween(freeText, {
alpha: 0,
y: freeText.y - 200
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
if (freeText.parent) {
freeText.parent.removeChild(freeText);
}
}
});
}
});
}
});
}
}
};
// Handle free launch earned by player getting 10+ somersaults
game.onFreeLaunchEarned = function () {
// Award free launch if we haven't reached the cap and not exceeding max bonus launches
if (maxLaunches < 20 && maxLaunchesFromBonuses < 15) {
maxLaunches++;
maxLaunchesFromBonuses++;
// Play Bogerk sound for free launch bonus
LK.getSound('Bogerk').play();
// Show message
showMessage("FREE LAUNCH! 10+ SOMERSAULTS!", 0x00FF00);
launchesText.setText("Launches: " + launches + "/" + maxLaunches);
} else {
// Show message about reaching the max launches cap
showMessage("MAX LAUNCHES REACHED (20)!", 0xFF0000);
}
// Create animated free launch text
var freeText = new Text2("FREE LAUNCH!", {
size: 100,
fill: 0x00FF00
});
freeText.anchor.set(0.5, 0.5);
freeText.x = 2048 / 2;
freeText.y = 2732 / 2;
freeText.alpha = 0;
freeText.scaleX = 0.5;
freeText.scaleY = 0.5;
LK.gui.center.addChild(freeText);
// Flash screen
// Removed LK.effects.flashScreen to prevent green and yellow screen flashes
// Animate the text
tween(freeText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.elasticOut,
onFinish: function onFinish() {
tween(freeText, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(freeText, {
alpha: 0,
y: freeText.y - 200
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
if (freeText.parent) {
freeText.parent.removeChild(freeText);
}
}
});
}
});
}
});
};
// High score management functions
function getHighScores() {
return storage[highScoresKey] || [];
}
function saveHighScore(score) {
var highScores = getHighScores();
highScores.push(score);
// Sort in descending order
highScores.sort(function (a, b) {
return b - a;
});
// Keep only top 10 scores
if (highScores.length > 10) {
highScores = highScores.slice(0, 10);
}
// Save to storage
storage[highScoresKey] = highScores;
}
// Create high score tally
var highScoreTally = new HighScoreTally();
highScoreTally.visible = true;
highScoreTally.onStart = function () {
game.removeChild(highScoreTally);
initGame();
};
// Create title screen
var titleScreen = new TitleScreen();
game.addChild(titleScreen);
// Set up title screen callback
titleScreen.onStart = function () {
// Show instructions screen instead of high scores
var instructionsScreen = new InstructionsScreen();
game.addChild(instructionsScreen);
// Set up callback for when instructions screen is closed
instructionsScreen.onContinue = function () {
// Show high scores after instructions
game.addChild(highScoreTally);
highScoreTally.updateScores(getHighScores());
// Position chicken in the center of the screen when high score tally is shown
chickenJockey.x = arena.x;
chickenJockey.y = arena.y;
};
};
// Modified game over handling
var originalOnChickenJockeyStop = game.onChickenJockeyStop;
game.onChickenJockeyStop = function () {
// Call original function first
originalOnChickenJockeyStop();
// If game over, save score
if (gameState === "gameOver") {
saveHighScore(score);
// We'll show high scores after game over in LK.showGameOver callback
}
};
// Handle game start
LK.onGameOver = function () {
// Show high score tally after game over
game.addChild(highScoreTally);
highScoreTally.updateScores(getHighScores());
}; ===================================================================
--- original.js
+++ change.js
@@ -173,10 +173,29 @@
} else if (self.y > bounds.bottom) {
self.y = bounds.bottom;
self.vy = -self.vy * self.bounceDecay;
}
+ // Check if stuck in ropes (very low velocity but still touching a rope)
+ var touchingRope = false;
+ if (ropes && ropes.length > 0) {
+ for (var i = 0; i < ropes.length; i++) {
+ if (self.intersects(ropes[i])) {
+ touchingRope = true;
+ break;
+ }
+ }
+ }
+ if (touchingRope && Math.abs(self.vx) < 1 && Math.abs(self.vy) < 1) {
+ // Apply escape velocity in a random direction to break free
+ var escapeAngle = Math.random() * Math.PI * 2;
+ self.vx = Math.cos(escapeAngle) * 8;
+ self.vy = Math.sin(escapeAngle) * 8;
+ // Reset last bounce position to allow for new bounce
+ self.lastBouncePosition.x = -9999;
+ self.lastBouncePosition.y = -9999;
+ }
// Check if stopped
- if (Math.abs(self.vx) < 0.5 && Math.abs(self.vy) < 0.5 && self.bounceCount > 0) {
+ else if (Math.abs(self.vx) < 0.5 && Math.abs(self.vy) < 0.5 && self.bounceCount > 0) {
self.launched = false;
// Notify game that chicken jockey has stopped
if (typeof game.onChickenJockeyStop === 'function') {
game.onChickenJockeyStop();
@@ -184,8 +203,12 @@
}
// Bounce from side to side
if (self.x <= bounds.left || self.x >= bounds.right) {
self.vx = -self.vx * self.bounceDecay;
+ // Add a minimum velocity to prevent getting stuck
+ if (Math.abs(self.vx) < 5) {
+ self.vx = self.vx > 0 ? 5 : -5;
+ }
self.bounceCount++;
LK.getSound('bounce').play();
game.addScore(2000);
}
@@ -586,16 +609,20 @@
self.bounce = function (chickenJockey) {
// Check if we've already bounced in the same place to prevent getting stuck
var distFromLastBounce = Math.sqrt(Math.pow(chickenJockey.x - chickenJockey.lastBouncePosition.x, 2) + Math.pow(chickenJockey.y - chickenJockey.lastBouncePosition.y, 2));
// If too close to last bounce position, give an extra boost to escape
- if (distFromLastBounce < 50) {
- // Extra velocity away from the rope
+ if (distFromLastBounce < 100) {
+ // Extra velocity away from the rope with greater force
var awayX = chickenJockey.x - self.x;
var awayY = chickenJockey.y - self.y;
var awayDist = Math.sqrt(awayX * awayX + awayY * awayY);
if (awayDist > 0) {
- chickenJockey.vx += awayX / awayDist * 10;
- chickenJockey.vy += awayY / awayDist * 10;
+ // Apply much stronger repulsion
+ chickenJockey.vx = awayX / awayDist * 20;
+ chickenJockey.vy = awayY / awayDist * 20;
+ // Reset last bounce position to a far away point to ensure next bounce registers
+ chickenJockey.lastBouncePosition.x = -9999;
+ chickenJockey.lastBouncePosition.y = -9999;
}
}
// Store current position as last bounce position
chickenJockey.lastBouncePosition.x = chickenJockey.x;
@@ -1309,29 +1336,58 @@
chickenJockey.update();
if (chickenJockey.lastRopeCollision === undefined) {
chickenJockey.lastRopeCollision = null;
}
- // Check for collisions with ropes
+ // Count how many ropes the chicken is intersecting
+ var intersectingRopes = 0;
for (var i = 0; i < ropes.length; i++) {
- // Only bounce if we weren't already intersecting this rope
- if (chickenJockey.intersects(ropes[i]) && chickenJockey.lastRopeCollision !== ropes[i]) {
- // Calculate direction vectors for bounce
- var dx = chickenJockey.x - ropes[i].x;
- var dy = chickenJockey.y - ropes[i].y;
- var dist = Math.sqrt(dx * dx + dy * dy);
- // Push chicken away from rope slightly to prevent sticking
- if (dist > 0) {
- chickenJockey.x += dx / dist * 10;
- chickenJockey.y += dy / dist * 10;
+ if (chickenJockey.intersects(ropes[i])) {
+ intersectingRopes++;
+ }
+ }
+ // If intersecting multiple ropes (stuck in corner/intersection), apply emergency escape
+ if (intersectingRopes > 1) {
+ // Calculate center of arena
+ var centerX = arena.x;
+ var centerY = arena.y;
+ // Calculate vector toward center
+ var towardCenterX = centerX - chickenJockey.x;
+ var towardCenterY = centerY - chickenJockey.y;
+ var distance = Math.sqrt(towardCenterX * towardCenterX + towardCenterY * towardCenterY);
+ // Apply strong impulse toward center
+ if (distance > 0) {
+ chickenJockey.vx = towardCenterX / distance * 25;
+ chickenJockey.vy = towardCenterY / distance * 25;
+ chickenJockey.lastRopeCollision = null;
+ // Clear last bounce position
+ chickenJockey.lastBouncePosition.x = -9999;
+ chickenJockey.lastBouncePosition.y = -9999;
+ }
+ }
+ // Normal single rope collision handling
+ else {
+ // Check for collisions with ropes
+ for (var i = 0; i < ropes.length; i++) {
+ // Only bounce if we weren't already intersecting this rope
+ if (chickenJockey.intersects(ropes[i]) && chickenJockey.lastRopeCollision !== ropes[i]) {
+ // Calculate direction vectors for bounce
+ var dx = chickenJockey.x - ropes[i].x;
+ var dy = chickenJockey.y - ropes[i].y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ // Push chicken away from rope slightly to prevent sticking
+ if (dist > 0) {
+ chickenJockey.x += dx / dist * 10;
+ chickenJockey.y += dy / dist * 10;
+ }
+ ropes[i].bounce(chickenJockey);
+ chickenJockey.lastRopeCollision = ropes[i];
+ // Clear last rope collision after a shorter delay to allow for new collisions
+ LK.setTimeout(function () {
+ chickenJockey.lastRopeCollision = null;
+ }, 100); // Reduced from 150 to 100ms
+ // Only bounce on one rope per frame to prevent chaotic behavior
+ break;
}
- ropes[i].bounce(chickenJockey);
- chickenJockey.lastRopeCollision = ropes[i];
- // Clear last rope collision after a shorter delay to allow for new collisions
- LK.setTimeout(function () {
- chickenJockey.lastRopeCollision = null;
- }, 150);
- // Only bounce on one rope per frame to prevent chaotic behavior
- break;
}
}
// Check for collisions with popcorn
for (var i = popcorns.length - 1; i >= 0; i--) {
X5 symbol. In-Game asset. 2d. High contrast. No shadows
X2 symbol. In-Game asset. 2d. High contrast. No shadows
Super popcorn yellow. In-Game asset. 2d. High contrast. No shadows
Start button. In-Game asset. 2d. High contrast. No shadows
High score button. In-Game asset. 2d. High contrast. No shadows
Back button. In-Game asset. 2d. High contrast. No shadows
SELECT YOUR CHARACTER button. In-Game asset. 2d. High contrast. No shadows
Launches button. In-Game asset. 2d. High contrast. No shadows
How to play button. In-Game asset. 2d. High contrast. No shadows
Score button. In-Game asset. 2d. High contrast. No shadows
High Scores button. In-Game asset. 2d. High contrast. No shadows
Transparent padlock. In-Game asset. 2d. High contrast. No shadows
Chicken jockey character. In-Game asset. 2d. High contrast. No shadows
Reset scores button. In-Game asset. 2d. High contrast. No shadows
Spider jockey unlocked button. In-Game asset. 2d. High contrast. No shadows
Minecraft Steve unlocked button. In-Game asset. 2d. High contrast. No shadows
Piglin unlocked button. In-Game asset. 2d. High contrast. No shadows
Minecraft skeleton unlocked button. In-Game asset. 2d. High contrast. No shadows
Minecraft villager unlocked button. In-Game asset. 2d. High contrast. No shadows
Star. In-Game asset. 2d. High contrast. No shadows
White star. In-Game asset. 2d. High contrast. No shadows
Red heart. In-Game asset. 2d. High contrast. No shadows
Purple heart. In-Game asset. 2d. High contrast. No shadows
A peanut. In-Game asset. 2d. High contrast. No shadows
Cashew nut. In-Game asset. 2d. High contrast. No shadows
Grimace shake. In-Game asset. 2d. High contrast. No shadows
MacDonald's fries. In-Game asset. 2d. High contrast. No shadows
Grimace unlocked button. In-Game asset. 2d. High contrast. No shadows
Michael Jackson unlocked button. In-Game asset. 2d. High contrast. No shadows
John Cena unlocked button. In-Game asset. 2d. High contrast. No shadows
Deez nuts unlocked button. In-Game asset. 2d. High contrast. No shadows
Shooting stars unlocked button. In-Game asset. 2d. High contrast. No shadows
Rick roll unlocked button. In-Game asset. 2d. High contrast. No shadows
Popcorn chicken. In-Game asset. 2d. High contrast. No shadows
Fried chicken drumstick. In-Game asset. 2d. High contrast. No shadows
Amazing digital circus button. In-Game asset. 2d. High contrast. No shadows
Select game mode button. In-Game asset. 2d. High contrast. No shadows
Diamond shaped colourful classic mode button. In-Game asset. 2d. High contrast. No shadows
Diamond shaped colourful mini games button. In-Game asset. 2d. High contrast. No shadows
Same picture in high definition
Diamond shaped colourful button that says sling shot mode. In-Game asset. 2d. High contrast. No shadows
Make picture transparent
Bullet. In-Game asset. 2d. High contrast. No shadows
Start game button. In-Game asset. 2d. High contrast. No shadows
Shooting gallery button. In-Game asset. 2d. High contrast. No shadows
Chain reaction button. In-Game asset. 2d. High contrast. No shadows
Realistic space backdrop. In-Game asset. 2d. High contrast. No shadows
launch
Sound effect
Gamestart
Sound effect
collect
Sound effect
gameMusic
Music
Gamemusic
Sound effect
Bogerk
Sound effect
pop
Sound effect
Pignoise
Sound effect
Steve
Sound effect
Villager
Sound effect
Spider
Sound effect
Skeleton
Sound effect
Shootingstars
Music
Maccas
Sound effect
Grimace
Sound effect
Thriller
Music
MJ
Sound effect
Cenaentrance
Music
Johncena
Sound effect
Chickencluck
Sound effect
Deeznuts
Sound effect
Deeznutstrap
Music
Rickroll
Sound effect
Nevergonna
Music
Starz
Sound effect
Grimaceshake
Music
Joenugget
Sound effect
gegagedi
Music
Shrek
Sound effect
Raveswamp
Music
Pomni
Sound effect
Digcircus
Music
Runandgo
Music
Gunshot
Sound effect
Reelbadman
Sound effect
Tinggoes
Music