Code edit (19 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: currentPosture is not defined' in or related to this line: 'self.y = linesGroundLevels[self.lineIndex] + (currentPosture.name == startingBlockPosture.name ? 150 : 0);' Line Number: 398
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: obstacles[i][j] is undefined' in or related to this line: 'obstacles[i][j].destroy();' Line Number: 927
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: raceFinishTime is not defined' in or related to this line: 'if (Date.now() - raceFinishTime > 1000) {' Line Number: 726
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: self is undefined' in or related to this line: 'self._update_migrated = function () {' Line Number: 1155
User prompt
add an update function in StartingBlocks
Code edit (1 edits merged)
Please save this source code
Code edit (5 edits merged)
Please save this source code
User prompt
Migrate to the latest version of LK
Code edit (12 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: t.setStageReference is not a function' in or related to this line: 'game.addChild(startingBlocks);' Line Number: 882
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (18 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: athlete.setposition is not a function' in or related to this line: 'athlete.setposition(startingBlockPosture);' Line Number: 874
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
use startingBlocks class in initHurdlesStartingState
User prompt
create a class for startingBlocks
Code edit (3 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: athletes is not defined' in or related to this line: 'var startingBlocks = LK.getAsset('startingBlocks', {' Line Number: 826
/****
* Classes
****/
/****************************************************************************************** */
/**************************************** CLASSES ***************************************** */
/****************************************************************************************** */
/****************************************************************************************** */
/************************************* ATHLETE CLASS ************************************** */
/****************************************************************************************** */
var Athlete = Container.expand(function (line) {
var self = Container.call(this);
self.speedX = -1 * globalSpeedPerLine[line];
self.nextHurdleSpeedX = 0;
self.jumpSpeed = -20; // -17;
self.lastJumpTime = 0;
self.interJumpDelayMs = 500;
self.gravity = 0.5;
self.lineIndex = line;
self.isAi = line > 0;
self.isOnGround = true;
self.isRunning = false;
self.isFalling = false; // Indicates if the athlete is currently falling
self.currentPosture = ""; // Store the name of the current posture
self.isChangingPosture = false; // 0 when idle or moving down, 1 when moving up
self.nextPosture = null;
self.tint = colorsArray[self.lineIndex % colorsArray.length];
self.previousX = 0;
// BODY PARTS
self.trunk = self.attachAsset('bodyPart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1,
scaleY: 1,
rotation: 0.125,
tint: 0x000000 //self.tint // TEMP DEBUG
});
self.head = self.trunk.attachAsset('head', {
anchorX: 0.5,
anchorY: 2,
scaleX: 1,
scaleY: 1,
tint: 0x000000 // self.tint
});
self.rightArm = self.trunk.attachAsset('bodyPart', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1,
scaleY: 1,
tint: self.tint
});
// Right hand asset attachment removed
self.leftArm = self.trunk.attachAsset('bodyPart', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1,
scaleY: 1,
tint: self.tint
});
// Left hand asset attachment removed
self.rightLeg = self.trunk.attachAsset('bodyPart', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1,
scaleY: 1.0,
tint: self.tint
});
// Right foot asset attachment removed
self.leftLeg = self.trunk.attachAsset('bodyPart', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1,
scaleY: 1.0,
tint: self.tint
});
// Left foot asset attachment removed
// FUNCTIONS
self.updatePosture = function () {
var speed = 0.2; // Speed of transition
if (!self.targetPosture) {
//log("no targetPosture.");
return;
}
// Check if the target posture for hands and legs is reached
//log("self.targetPosture: " + self.targetPosture.name + " : self.rightHand.x: " + self.rightHand.x, " self.targetPosture.rightHand.x: " + self.targetPosture.rightHand.x);
var handsAndLegsReached = Math.abs(self.rightLeg.x - self.targetPosture.rightLeg.x) < 1 && Math.abs(self.rightLeg.y - self.targetPosture.rightLeg.y) < 1 && Math.abs(self.leftLeg.x - self.targetPosture.leftLeg.x) < 1 && Math.abs(self.leftLeg.y - self.targetPosture.leftLeg.y) < 1 && Math.abs(self.head.x - self.targetPosture.head.x) < 1 && Math.abs(self.head.y - self.targetPosture.head.y) < 1;
if (handsAndLegsReached) {
log("handsAndLegsReached !");
// Update currentPosture to the name of the targetPosture when hands and legs posture is reached
self.currentPosture = self.targetPosture.name;
self.targetPosture = null;
self.isChangingPosture = false;
if (self.nextPosture) {
self.setPosture(self.nextPosture);
}
return;
} else {
self.isChangingPosture = true;
}
self.head.x += (self.targetPosture.head.x - self.head.x) * speed;
self.trunk.rotation += (self.targetPosture.trunk.r - self.trunk.rotation) * speed;
self.head.y += (self.targetPosture.head.y - self.head.y) * speed;
self.rightArm.x += (self.targetPosture.rightArm.x - self.rightArm.x) * speed;
self.rightArm.y += (self.targetPosture.rightArm.y - self.rightArm.y) * speed;
self.rightArm.rotation += (self.targetPosture.rightArm.r - self.rightArm.rotation) * speed;
//log("Posture rightArm.rotation=" + self.rightArm.rotation);
// Right hand updates removed due to hand assets being removed
self.leftArm.x += (self.targetPosture.leftArm.x - self.leftArm.x) * speed;
self.leftArm.y += (self.targetPosture.leftArm.y - self.leftArm.y) * speed;
self.leftArm.rotation += (self.targetPosture.leftArm.r - self.leftArm.rotation) * speed;
// Left hand updates removed due to hand assets being removed
self.trunk.x += (self.targetPosture.trunk.x - self.trunk.x) * speed;
self.trunk.y += (self.targetPosture.trunk.y - self.trunk.y) * speed;
self.rightLeg.x += (self.targetPosture.rightLeg.x - self.rightLeg.x) * speed;
self.rightLeg.y += (self.targetPosture.rightLeg.y - self.rightLeg.y) * speed;
self.rightLeg.rotation += (self.targetPosture.rightLeg.r - self.rightLeg.rotation) * speed;
// Right foot updates removed due to foot assets being removed
self.leftLeg.x += (self.targetPosture.leftLeg.x - self.leftLeg.x) * speed;
self.leftLeg.y += (self.targetPosture.leftLeg.y - self.leftLeg.y) * speed;
self.leftLeg.rotation += (self.targetPosture.leftLeg.r - self.leftLeg.rotation) * speed;
};
self.update = function () {
/* ********************************************************** AI ATHLETE **************************************************** */
if (self.isAi) {
// AI Athlete
var nextX = self.x;
self.previousX = self.x;
if (self.isRunning) {
var deltaSpeed = Math.abs(globalSpeedPerLine[self.lineIndex]) - Math.abs(globalSpeedPerLine[0]);
nextX += deltaSpeed;
if (!self.isFalling) {
// Normal running
if (self.isOnGround) {
// Running
self.leftLeg.height = 200;
self.leftArm.height = 200;
if (self.isRunning) {
self.trunk.rotation = 0.125;
self.runAnim();
}
// Auto jump first hurdle of the line
if (obstacles[self.lineIndex].length) {
var distance = obstacles[self.lineIndex][0].x - nextX;
if (self.lineIndex == 1) {
log((self.isOnGround ? 'On ground' : 'In air 1') + " / x=" + self.x + " / y=" + self.y + " / DeltaY=" + (obstacles[self.lineIndex][0].y - obstacles[self.lineIndex][0].centralRod.y - self.y) + " / distance=" + distance);
}
if (self.x > aiJumpLeftLimit && self.x < aiJumpRightLimit && distance > 0 && distance <= 300) {
self.jump();
} else {
// Reduce advance when out of screen
var normalize = self.nextHurdleSpeedX;
normalize = self.x < -200 ? Math.abs(normalize) : normalize;
normalize = self.x > 2100 ? -10 + Math.random() * 2 : normalize;
normalize = self.x > 3000 ? -20 : normalize;
nextX += normalize;
}
}
} else {
if (obstacles[self.lineIndex].length) {
var distance = obstacles[self.lineIndex][0].x - nextX;
if (self.lineIndex == 1) {
log((self.isOnGround ? 'On ground' : 'In air 2') + " / x=" + self.x + " / y=" + self.y + " / DeltaY=" + (obstacles[self.lineIndex][0].y - obstacles[self.lineIndex][0].centralRod.y - self.y) + " / distance=" + distance);
}
}
// Jumping - if not running, finish the jump
self.speedY += self.gravity * Math.abs(globalSpeedPerLine[self.lineIndex] / 10) + (!self.isRunning ? 0.5 : 0);
self.y += self.speedY * Math.abs(globalSpeedPerLine[self.lineIndex] / 10) + (!self.isRunning ? self.speedY : 0);
if (self.y >= linesGroundLevels[self.lineIndex]) {
// Reached the ground
self.isOnGround = true;
self.speedY = 0;
self.y = linesGroundLevels[self.lineIndex];
// Define speed for next hurdle
self.nextHurdleSpeedX = -1 + (-5 + 10 * Math.random()); //(1 - difficultyLevel) * 4 + difficultyLevel * 2 * Math.random();
if (obstacles[self.lineIndex].length <= 3 && self.x > athlete.x) {
self.nextHurdleSpeedX = -1 - 1 * Math.abs(self.nextHurdleSpeedX);
}
} else {
self.jumpAnim();
}
}
} else {
// Falling
self.y += 5;
if (self.y >= linesGroundLevels[self.lineIndex]) {
self.isOnGround = true;
self.speedY = 0;
self.y = linesGroundLevels[self.lineIndex];
} else {
self.fallAnim();
}
}
} else {
if (self.lineIndex == 1) {
//log("WAITING / x=" + self.x + " / y=" + self.y + " / globalSpeedPerLine[0]=" + globalSpeedPerLine[0]);
}
if (self.finishPosition == 1) {
self.victoryAnim();
}
nextX += -1 * globalSpeedPerLine[0];
}
// Update athlete position
self.x = nextX;
self.previousX = self.x;
} else {
// Player Athlete
/* ********************************************************** PLAYER ATHLETE **************************************************** */
if (self.isRunning) {
if (!self.isFalling) {
// Normal running
if (self.isOnGround) {
// Running
self.leftLeg.height = 200;
self.leftArm.height = 200;
if (self.isRunning) {
self.trunk.rotation = 0.125;
self.runAnim();
}
} else {
// Jumping
self.speedY += self.gravity * Math.abs(globalSpeedPerLine[self.lineIndex] / 10);
self.y += self.speedY * Math.abs(globalSpeedPerLine[self.lineIndex] / 10);
if (self.y >= linesGroundLevels[self.lineIndex]) {
// Reached the ground
self.isOnGround = true;
self.speedY = 0;
self.y = linesGroundLevels[self.lineIndex];
} else {
self.jumpAnim();
}
}
} else {
// Falling
self.y += 5;
self.fallAnim();
if (self.y >= linesGroundLevels[self.lineIndex] + 200) {
// 200 for horizontal trunk offset
self.isOnGround = true;
self.speedY = 0;
self.y = linesGroundLevels[self.lineIndex] + 200;
}
}
} else {
if (self.finishPosition == 1) {
self.victoryAnim();
}
}
}
self.updatePosture();
};
self.jump = function () {
if (self.isAI || Date.now() - self.lastJumpTime > self.interJumpDelayMs) {
if (self.isOnGround) {
self.isOnGround = false;
self.speedY = self.jumpSpeed;
self.lastJumpTime = Date.now();
//globalSpeedPerLine[self.lineIndex] = globalSpeedPerLine[self.lineIndex] * 1.1;
if (self.lineIndex == 1) {
log("--------------- JUMP -------------------- speedY :" + self.speedY);
}
}
}
};
self.runAnim = function () {
if (self.lineIndex == 1) {
log("Check finish for #3 at x=" + opponents[line - 1].x + " vs " + (finishLine.x + 512));
}
var ocsilDelay = 5;
var armsAmplitude = 0.5;
var legsAmplitude = 0.5;
// Simulate running by continuously balancing the arms and legs
var runningArmAngle = Math.sin(LK.ticks / ocsilDelay) * armsAmplitude; // Oscillate arm angle to simulate running faster
var runningLegAngle = Math.sin(LK.ticks / ocsilDelay) * legsAmplitude; // Oscillate leg angle to simulate running faster
var armSwitchProgress = (Math.sin(LK.ticks / 5) + 0) / 2; // Normalize between 0 and 1
self.rightArm.x = 10 * (1 - armSwitchProgress) - 5 * armSwitchProgress;
self.leftArm.x = -15 * (1 - armSwitchProgress) + 20 * armSwitchProgress;
self.rightLeg.x = 5 * (1 - armSwitchProgress) - 5 * armSwitchProgress;
self.leftLeg.x = -10 * (1 - armSwitchProgress) + 10 * armSwitchProgress;
//log("Run rightArm.rotation=" + runningArmAngle);
self.rightArm.rotation = runningArmAngle;
self.leftArm.rotation = -runningArmAngle;
self.rightLeg.rotation = -runningLegAngle;
self.leftLeg.rotation = runningLegAngle;
self.trunk.width = 30 - 10 * (runningArmAngle * Math.PI * 0.5);
self.head.width = 50 - 10 * (runningArmAngle * Math.PI * 0.5);
};
self.jumpAnim = function () {
if (self.lineIndex == 1) {
log("Check finish for #3 at x=" + opponents[line - 1].x + " vs " + (finishLine.x + 512));
}
var ocsilDelay = 50;
var armsAmplitude = 1;
// Simulate running by continuously balancing the arms and legs
var runningArmAngle = Math.sin(LK.ticks / ocsilDelay) * armsAmplitude; // Oscillate arm angle to simulate running faster
var armSwitchProgress = (Math.sin(LK.ticks / 5) + 0) / 2; // Normalize between 0 and 1
self.rightArm.x = 10 * (1 - armSwitchProgress) - 5 * armSwitchProgress;
self.leftArm.x = -15 * (1 - armSwitchProgress) + 20 * armSwitchProgress;
self.rightLeg.x = 5 * (1 - armSwitchProgress) - 5 * armSwitchProgress;
self.leftLeg.x = -10 * (1 - armSwitchProgress) + 10 * armSwitchProgress;
self.trunk.width = 30 - 10 * (runningArmAngle * Math.PI * 0.5); //armSwitchProgress; // + 10 * Math.abs(runningArmAngle);
self.trunk.rotation = 0.333; //armSwitchProgress; // + 10 * Math.abs(runningArmAngle);
var rotationSpeed = 0.05; // Speed of rotation change
if (self.speedY > 0) {
self.rightArm.rotation += (0 - self.rightArm.rotation) * rotationSpeed % (Math.PI * 2);
self.leftArm.rotation += (0 - self.leftArm.rotation) * rotationSpeed % (Math.PI * 2);
// Return legs to initial rotation when descending
self.rightLeg.rotation += (0 - self.rightLeg.rotation) * rotationSpeed;
self.leftLeg.rotation += (0 - self.leftLeg.rotation) * rotationSpeed;
self.leftLeg.height -= 30 * rotationSpeed;
self.leftArm.height -= 20 * rotationSpeed;
} else {
//log("self.rightArm.rotation=" + self.rightArm.rotation, " + " + -Math.PI * 3 * rotationSpeed % (Math.PI * 2));
self.rightArm.rotation += -Math.PI * 3 * rotationSpeed % (Math.PI * 2);
self.leftArm.rotation += Math.PI * 1.75 * rotationSpeed % (Math.PI * 2);
// Continue with jump animation adjustments
self.rightLeg.rotation += (-2.6 - self.rightLeg.rotation) * rotationSpeed;
self.leftLeg.rotation += (1 - self.leftLeg.rotation) * rotationSpeed;
self.leftLeg.height -= 0 * rotationSpeed;
self.leftArm.height -= 35 * rotationSpeed;
}
};
self.fallAnim = function () {
if (self.lineIndex == 1) {
log("Check finish for #3 at x=" + opponents[line - 1].x + " vs " + (finishLine.x + 512));
}
var fallSpeed = 0.1; // Speed of fall animation
// Adjust body parts to simulate falling
self.trunk.rotation += (Math.PI / 2 - self.trunk.rotation) * fallSpeed;
self.rightArm.rotation += (Math.PI / 2 - self.rightArm.rotation) * fallSpeed;
self.leftArm.rotation += (Math.PI / 2 - self.leftArm.rotation) * fallSpeed;
self.rightLeg.rotation += (Math.PI / 2 - self.rightLeg.rotation) * fallSpeed;
self.leftLeg.rotation += (Math.PI / 2 - self.leftLeg.rotation) * fallSpeed;
};
self.victoryAnim = function () {
if (self.lineIndex == 1) {
log("Victory #1");
}
var jumpHeight = 10;
var waveSpeed = 0.1;
var armWaveAmplitude = 0.5;
// Make the athlete do little jumps
if (self.isOnGround) {
self.speedY = -10; // Jump a little
self.isOnGround = false;
} else {
self.speedY += self.gravity;
self.y += self.speedY;
if (self.y >= linesGroundLevels[self.lineIndex]) {
self.y = linesGroundLevels[self.lineIndex];
self.isOnGround = true;
}
}
// Wave arms
self.rightArm.rotation = Math.max(-armWaveAmplitude, Math.min(armWaveAmplitude, Math.sin(LK.ticks * waveSpeed) * armWaveAmplitude)) + Math.PI;
self.leftArm.rotation = Math.max(-armWaveAmplitude, Math.min(armWaveAmplitude, -Math.sin(LK.ticks * waveSpeed) * armWaveAmplitude * 0.5));
};
self.setPosture = function (newPosture) {
log("Set posture: " + newPosture.name);
self.targetPosture = newPosture;
};
self.restore = function () {
log("restore...");
self.stop();
self.hasFlashed = false;
self.hasFlashedGround = false;
self.isRunning = true;
};
self.stop = function () {
log("stop...");
self.x = self.previousX || 400 + 100 * self.lineIndex;
self.y = linesGroundLevels[self.lineIndex];
self.speedY = 0;
self.trunk.rotation = 0;
self.rightArm.rotation = idlePosture.rightArm.r;
self.leftArm.rotation = 0;
self.rightLeg.rotation = 0;
self.leftLeg.rotation = 0;
self.setPosture(idlePosture);
self.isFalling = false;
self.isOnGround = true;
};
});
/****************************************************************************************** */
/************************************** FINISH LINE CLASS ************************************ */
/****************************************************************************************** */
var FinishLine = Container.expand(function () {
var self = Container.call(this);
self.isCut = false;
self.rightRod = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0,
x: 355,
y: -1120
});
self.centralRodRight = self.attachAsset('finishLine', {
anchorX: 0.5,
anchorY: 1,
y: -200,
rotation: Math.PI * 0.125,
tint: 0xFF0000
});
self.centralRodLeft = self.attachAsset('finishLine', {
anchorX: 0.5,
anchorY: 0,
x: 355,
y: -1060,
rotation: Math.PI * 2.125,
tint: 0xFF0000,
height: 450
});
self.leftRod = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0 // Anchor at the bottom for collision detection
});
self.flag = self.attachAsset('finishFlag', {
anchorX: 0.5,
anchorY: 0.0,
x: 580,
y: -1540
});
self.speedX = globalSpeedPerLine[0];
self.update = function () {
self.speedX = globalSpeedPerLine[0];
self.x += self.speedX;
};
self.cut = function () {
var cutHeight = 50; // Amount to reduce the height each frame
var cutDuration = 5000; // Duration of the cut in milliseconds
var cutRate = cutDuration / (60 * (self.centralRodRight.height / cutHeight)); // Calculate how often to cut based on 60 FPS and total height
var cutCounter = 0;
var cutInterval = LK.setInterval(function () {
if (cutCounter < cutRate) {
self.centralRodRight.height -= cutHeight;
self.centralRodLeft.height -= cutHeight;
cutCounter++;
} else {
LK.clearInterval(cutInterval);
}
}, 1500 / 60); // Execute at roughly 60 FPS
};
});
/****************************************************************************************** */
/************************************** OBSTACLE CLASS ************************************ */
/****************************************************************************************** */
// Obstacle class
var Obstacle = Container.expand(function (line) {
var self = Container.call(this);
self.lineIndex = line;
self.leftRod = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0 // Anchor at the bottom for collision detection
});
self.centralRod = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1,
y: -200,
rotation: Math.PI * 0.125,
tint: 0xffff00 // Apply a yellow tint for glow effect
});
self.rightRod = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0,
x: 95,
y: -460
});
self.speedX = globalSpeedPerLine[0];
self.update = function () {
self.speedX = globalSpeedPerLine[0];
self.x += self.speedX;
};
});
/****************************************************************************************** */
/************************************** TRACK CLASS ************************************ */
/****************************************************************************************** */
var Track = Container.expand(function (index) {
var self = Container.call(this);
self.speedX = globalSpeedPerLine[0]; // Use global speed for track movement
// Attach track asset
self.trackAsset = self.attachAsset(index % 2 ? 'track' : 'trackOdd', {
anchorX: 0.0,
anchorY: 0.0
});
// Method to update track position
self.update = function () {
self.speedX = globalSpeedPerLine[0];
self.x += self.speedX;
// Reset position to create a continuous track effect
if (self.x <= -2048 - self.speedX * 2) {
self.x = 2048 + self.speedX * 2;
}
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Light blue background to represent the sky
});
/****
* Game Code
****/
/****************************************************************************************** */
/************************************** GLOBAL VARIABLES ********************************** */
/****************************************************************************************** */
// Enumeration for game states
var GAME_STATE = {
INIT: 'INIT',
MENU: 'MENU',
HELP: 'HELP',
STARTING: 'STARTING',
NEW_ROUND: 'NEW_ROUND',
PLAYING: 'PLAYING',
SCORE: 'SCORE'
};
var gameState = GAME_STATE.INIT;
var athlete;
var opponents = [];
var numberOfOpponents = 3; // Adjust based on the actual number of opponents in the game
var groundLevel = 2732 - 200; // Ground level set 200px from the bottom
var linesGroundLevels = []; // Ground level set 200px from the bottom
var numberOfLines = 1 + numberOfOpponents;
var numberOfObstacles = 10; //20; // Total number of hurdles
var obstacles = [[]];
var obstacleSpawnTicker = 0;
var obstacleSpawnDistanceRate = 1.5; // Ratio of screen width between obstacles
var obstacleJustPassed = false;
var aiJumpLeftLimit = -350;
var aiJumpRightLimit = 2048 + 512;
var finishLine;
var stadium;
var stadiumOdd;
var field;
var fieldOdd;
var farfield;
var farfieldOdd;
var track;
var track2;
var track3;
var track4;
var scoreTxt;
var currentFinishPosition = 1;
var globalBaseSpeed = -20;
var globalSpeedPerLine = []; // Global speed for tracks and obstacles default -10 / min = -4
var difficultyLevel = 1; // TODO : Move to global
var colorsArray = [0x1188FF, 0xFF0000, 0x00FF00, 0xFFFF00, 0xFF00FF, 0x00FFFF, 0xFFFFFF, 0xFF8811];
var isDebug = true;
var debugMarker;
// UI
var startText;
var startButton;
/****************************************************************************************** */
/************************************** POSTURES ****************************************** */
/****************************************************************************************** */
var idlePosture = {
name: "idlePosture",
trunk: {
x: 0,
y: 0,
r: 0
},
head: {
x: 0,
y: 0
},
rightArm: {
x: 20,
y: -80,
r: Math.PI * 2 * -0.025
},
leftArm: {
x: -20,
y: -80,
r: Math.PI * 2 * 0.025
},
rightLeg: {
x: 5,
y: 100,
r: Math.PI * 2 * -0.025
},
leftLeg: {
x: -5,
y: 100,
r: Math.PI * 2 * 0.025
}
};
var startingBlockPosture = {
name: "startingBlockPosture",
trunk: {
x: 0,
y: 0,
r: -0.1
},
head: {
x: 0,
y: -20
},
rightArm: {
x: 15,
y: -60,
r: Math.PI * 2 * -0.15
},
leftArm: {
x: -15,
y: -60,
r: Math.PI * 2 * 0.15
},
rightLeg: {
x: 10,
y: 80,
r: Math.PI * 2 * 0.05
},
leftLeg: {
x: -10,
y: 80,
r: Math.PI * 2 * -0.05
}
};
/****************************************************************************************** */
/*********************************** UTILITY FUNCTIONS ************************************ */
/****************************************************************************************** */
function log() {
if (isDebug) {
var _console;
(_console = console).log.apply(_console, arguments);
}
}
/****************************************************************************************** */
/************************************** INPUT HANDLERS ************************************ */
/****************************************************************************************** */
// Touch event to make the athlete jump
game.on('down', function () {
switch (gameState) {
case GAME_STATE.MENU:
// Handle menu logic here
break;
case GAME_STATE.STARTING:
// Handle game starting logic here
break;
case GAME_STATE.PLAYING:
gamePlayingDown();
break;
case GAME_STATE.SCORE:
// Handle score display logic here
break;
}
});
function gamePlayingDown() {
// Make the athlete jump
athlete.jump();
}
/****************************************************************************************** */
/************************************* AI FUNCTIONS *************************************** */
/****************************************************************************************** */
/****************************************************************************************** */
/************************************* GAME STATES **************************************** */
/****************************************************************************************** */
function gameInitialize() {
log("Game initialize...");
// Add background asset
scoreTxt = new Text2('0', {
size: 100,
fill: "#ffffff" // White color for better visibility
});
scoreTxt.anchor.set(1.1, 0.15); // Center the score text horizontally
LK.gui.topRight.addChild(scoreTxt); // Add the score text to the GUI overlay at the top center
var background = LK.getAsset('background', {
anchorX: 0.0,
anchorY: 0.0,
y: -256,
visible: true
});
game.addChild(background);
field = LK.getAsset('field', {
anchorX: 0.0,
anchorY: 0.0,
y: 2732 - 1024 - 600
});
game.addChild(field);
fieldOdd = LK.getAsset('fieldOdd', {
anchorX: 0.0,
anchorY: 0.0,
x: 2048,
y: 2732 - 1024 - 600
});
game.addChild(fieldOdd);
farField = LK.getAsset('farField', {
anchorX: 0.0,
anchorY: 0.0,
y: 2732 - 1024 - 600 - 512
});
game.addChild(farField);
farFieldOdd = LK.getAsset('farFieldOdd', {
anchorX: 0.0,
anchorY: 0.0,
x: 2048,
y: 2732 - 1024 - 600 - 512
});
game.addChild(farFieldOdd);
stadium = LK.getAsset('stadium', {
anchorX: 0.0,
anchorY: 0.0,
x: 0,
y: 150
});
game.addChild(stadium);
stadiumOdd = LK.getAsset('stadiumOdd', {
anchorX: 0.0,
anchorY: 0.0,
x: 2048,
y: 150
});
game.addChild(stadiumOdd);
// Initialize track using Track class
track = game.addChild(new Track(0));
track.x = 0;
track.y = 2732 - 512;
// Second track instance for continuous effect
track2 = game.addChild(new Track(1));
track2.x = 2048; // Position the second track right after the first one
track2.y = 2732 - 512;
// Second line track 1
track3 = game.addChild(new Track(2));
track3.x = 0;
track3.y = 2732 - 1024;
// Second line track 2
track4 = game.addChild(new Track(3));
track4.x = 2048;
track4.y = 2732 - 1024;
// Initialize ground levels & speeds
for (var line = 0; line < numberOfLines; line++) {
linesGroundLevels[line] = groundLevel - 200 - 220 * line;
globalSpeedPerLine[line] = globalBaseSpeed;
}
// Add Button in the center of the screen
startButton = LK.getAsset('button', {
anchorX: 0.5,
// Center the button horizontally
anchorY: 0.5,
// Center the button vertically
x: 2048 / 2,
// Position horizontally in the center
y: 2732 / 2 // Position vertically above the start text
});
game.addChild(startButton);
startButton.on('down', function () {
cleanMenuState();
//initPlayingState();
initHurdlesStartingState();
});
// Add Start Text in the center of the screen
startText = new Text2('START', {
size: 200,
fill: "#ffffff" // White color for better visibility
});
startText.anchor.set(0.5, 0.5); // Center the text horizontally and vertically
startText.x = 2048 / 2; // Center horizontally
startText.y = 2732 / 2; // Center vertically
game.addChild(startText);
gameState = GAME_STATE.MENU;
if (isDebug) {
// Debug Marker
debugMarker = LK.getAsset('debugMarker', {
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(debugMarker);
debugMarker.x = 0;
debugMarker.y = groundLevel;
}
}
function gamePlaying() {
//log("Game playing...");
// Update fields
updateFields();
// Update obstacles
updateObstacles();
// Update tracks
updateTracks();
// Update Progress
updateProgress();
// Update opponents
for (var i = numberOfOpponents - 1; i >= 0; i--) {
opponents[i].update();
game.addChild(opponents[i]);
}
// Update athlete
athlete.update();
game.addChild(athlete);
// Check for collisions
checkForCollisions();
}
function hurdlesStarting() {
log("hurdlesStarting...");
//self.setPosture(startingBlockPosture); // TEMP DEBUG
}
function cleanMenuState() {
game.removeChild(startText);
game.removeChild(startButton);
}
function initHurdlesStartingState() {
// Add starting blocks to each athlete's starting position
for (var i = 0; i <= numberOfOpponents; i++) {
var athletes = [athlete].concat(opponents);
var startingBlocks = LK.getAsset('startingBlocks', {
anchorX: 0.5,
anchorY: 1.0,
x: athletes[i].x - 100,
// Position slightly behind the athlete
y: linesGroundLevels[i] + 50 // Adjusted to align with the ground level of each line
});
game.addChild(startingBlocks);
}
log("initHurdlesStartingState...");
// Spawn obstacles
spawnObstacles();
// Initialize opponents
for (var i = numberOfOpponents - 1; i >= 0; i--) {
opponents[i] = game.addChild(new Athlete(i + 1));
opponents[i].restore();
}
// Initialize athlete
athlete = game.addChild(new Athlete(0));
athlete.restore();
gameState = GAME_STATE.STARTING;
}
function initPlayingState() {
/*
// Spawn obstacles
spawnObstacles();
// Initialize opponents
for (var i = numberOfOpponents - 1; i >= 0; i--) {
opponents[i] = game.addChild(new Athlete(i + 1));
opponents[i].restore();
}
// Initialize athlete
athlete = game.addChild(new Athlete(0));
athlete.restore();
*/
gameState = GAME_STATE.PLAYING;
}
/****************************************************************************************** */
/************************************** GAME FUNCTIONS ************************************ */
/****************************************************************************************** */
function updateFields() {
if (!(athlete.isFalling && athlete.isOnGround)) {
field.x += globalSpeedPerLine[0];
// Reset position to create a continuous effect
if (field.x <= -2048 - globalSpeedPerLine[0]) {
field.x = 2048 + globalSpeedPerLine[0];
}
fieldOdd.x += globalSpeedPerLine[0];
// Reset position to create a continuous effect
if (fieldOdd.x <= -2048 - globalSpeedPerLine[0]) {
fieldOdd.x = 2048 + globalSpeedPerLine[0];
}
// Far field
farField.x += globalSpeedPerLine[0] * 0.8;
// Reset position to create a continuous effect
if (farField.x <= -2048 - globalSpeedPerLine[0]) {
farField.x = 2048 + globalSpeedPerLine[0];
}
farFieldOdd.x += globalSpeedPerLine[0] * 0.8;
// Reset position to create a continuous effect
if (farFieldOdd.x <= -2048 - globalSpeedPerLine[0]) {
farFieldOdd.x = 2048 + globalSpeedPerLine[0];
}
stadium.x += globalSpeedPerLine[0] * 0.4;
// Reset position to create a continuous effect
if (stadium.x <= -2048 - globalSpeedPerLine[0]) {
stadium.x = 2048 + globalSpeedPerLine[0];
}
stadiumOdd.x += globalSpeedPerLine[0] * 0.4;
// Reset position to create a continuous effect
if (stadiumOdd.x <= -2048 - globalSpeedPerLine[0]) {
stadiumOdd.x = 2048 + globalSpeedPerLine[0];
}
}
}
function updateTracks() {
if (!(athlete.isFalling && athlete.isOnGround)) {
track.update();
track2.update();
track3.update();
track4.update();
}
}
function spawnObstacles() {
// Set obstacles for line 0
obstacles[0] = [];
for (var i = 0; i < numberOfObstacles; i++) {
// 3 obstacles per line
var newObstacle = new Obstacle(0);
newObstacle.x = 2048 * obstacleSpawnDistanceRate * (i + 1); // Start from the right edge
//log("Obstacle "+ 0+","+i+" +> x="+ newObstacle.x);
newObstacle.y = groundLevel + 200;
obstacles[0].push(newObstacle);
game.addChild(newObstacle);
}
// Set obstacles for other lines
for (var line = 1; line < numberOfLines; line++) {
obstacles[line] = [];
for (var i = 0; i < numberOfObstacles; i++) {
// 3 obstacles per line
var newObstacle = new Obstacle(line);
newObstacle.x = obstacles[0][i].x + 100 * line; // Start from the right edge
//log("Obstacle "+ line+","+i+" +> x="+ newObstacle.x);
newObstacle.y = groundLevel + 200 - 220 * line;
obstacles[line].push(newObstacle);
game.addChild(newObstacle);
}
}
finishLine = new FinishLine();
finishLine.x = 2048 * obstacleSpawnDistanceRate * (numberOfObstacles + 1) + 1024; // Start from the right edge
finishLine.y = groundLevel + 200;
game.addChild(finishLine);
}
function updateObstacles() {
// Update obstacles
for (var line = 0; line < numberOfLines; line++) {
obstacles[line] = obstacles[line] || [];
for (var i = obstacles[line].length - 1; i >= 0; i--) {
obstacles[line][i].update();
// Remove obstacle if it moves off-screen and increase global speed
if (obstacles[line][i].x < -100) {
// Assuming obstacle width is less than 100px
obstacles[line][i].destroy();
obstacles[line].splice(i, 1);
if (line == 0) {
obstacleJustPassed = true;
}
}
}
}
finishLine.update();
}
function updateProgress() {
if (obstacleJustPassed && !finishLine.isCut) {
// Update Progress
obstacleJustPassed = false;
LK.setScore(LK.getScore() + 1); // Add 1 to score for each hurdle passed only if not falling
scoreTxt.setText(LK.getScore()); // Update score text with prefix
}
for (var line = 0; line < numberOfLines; line++) {
if (line == 0 && !athlete.finishPosition && athlete.x > finishLine.x) {
athlete.finishPosition = getFinishPosition();
log("Finish athlete => #" + athlete.finishPosition);
}
if (line > 0 && opponents[line - 1].x > finishLine.x) {
if (!opponents[line - 1].finishPosition) {
opponents[line - 1].finishPosition = getFinishPosition();
log("Finish opponent " + line + "=> #" + opponents[line - 1].finishPosition);
opponents[line - 1].finishStandingOffset = 512 * Math.random();
}
// Don't go to far after finish
var finishStandingPosition = finishLine.x + 2048 - 200 - (opponents[line - 1].finishStandingOffset || 0);
opponents[line - 1].x = Math.min(finishStandingPosition, opponents[line - 1].x);
if (opponents[line - 1].x >= finishStandingPosition) {
// Stop running when reach final position
opponents[line - 1].isRunning = false;
}
}
}
if (finishLine.isCut) {
for (var line = 0; line < numberOfLines; line++) {
if (line > 0 && opponents[line - 1].x < 0)
// let opponents finish
{
continue;
}
// Ensure a smooth transition to 0 speed
if (globalSpeedPerLine[line] < -0.4) {
globalSpeedPerLine[line] += 0.4; // Decrement speed gradually
} else if (globalSpeedPerLine[line] > 0.4) {
globalSpeedPerLine[line] -= 0.4; // Increment speed gradually if somehow above 0
} else {
globalSpeedPerLine[line] = 0; // Set to 0 if very close to it
if (line == 0 && athlete.isRunning) {
athlete.isRunning = false;
athlete.stop();
}
if (line > 0 && opponents[line - 1].isRunning) {
opponents[line - 1].isRunning = false;
opponents[line - 1].stop();
}
}
}
} else if (finishLine.x - athlete.x > 2048) {
for (var line = 1; line < numberOfLines; line++) {
if (line == 1) {
log("Check finish for #3 at x=" + opponents[line - 1].x + " vs " + (finishLine.x + 512));
}
if (opponents[line - 1].x > finishLine.x + 512 && opponents[line - 1].isRunning) {
if (line == 1) {
log("OK #3 Passed the line !");
}
// stop opponents at finish
log("Stoping #" + line + " at " + opponents[line - 1].x + " > " + finishLine.x);
opponents[line - 1].isRunning = false;
opponents[line - 1].stop();
//opponents[line - 1].x = finishLine.x + 512 * Math.random();
globalSpeedPerLine[line] = 0;
}
}
}
}
function checkForCollisions() {
if (finishLine.isCut) {
return;
}
for (var line = 0; line < numberOfLines; line++) {
obstacles[line] = obstacles[line] || [];
if (obstacles[line].length) {
var obstacle = obstacles[line][0]; // Check only the first obstacle in the line
if (line === 0) {
if (athlete.intersects(obstacle.centralRod)) {
athlete.isFalling = true;
athlete.isOnGround = false;
}
} else {
if (opponents[line - 1].x > aiJumpLeftLimit && opponents[line - 1].x < aiJumpRightLimit && opponents[line - 1].intersects(obstacle.centralRod)) {
log("Line " + line + " : opponent " + opponents[line - 1].lineIndex + " collided with obstacle " + obstacle.lineIndex);
opponents[line - 1].isFalling = true;
opponents[line - 1].isOnGround = false;
}
}
}
}
handleFallEvent();
if (!obstacles[0].length && !finishLine.isCut) {
var isReached = athlete.x > finishLine.x;
if (isReached) {
finishLine.isCut = true;
finishLine.cut();
}
}
}
function handleFallEvent() {
if (athlete.isFalling && !athlete.hasFlashed) {
LK.effects.flashScreen(0xaaaaaa, 500); // Flash screen red for half a second
athlete.hasFlashed = true;
globalSpeedPerLine[0] /= 1.5;
globalSlowDownAfterJump = true;
}
if (athlete.hasFlashed && !athlete.hasFlashedGround && athlete.isFalling && athlete.isOnGround) {
LK.effects.flashScreen(0xff0000, 500); // Flash screen red for half a second
athlete.hasFlashedGround = true;
globalSpeedPerLine[0] = 0;
LK.setTimeout(function () {
globalSpeedPerLine[0] = globalBaseSpeed;
globalSlowDownAfterJump = false;
athlete.restore();
}, 1000); // Delay game over to allow fall animation to be seen
}
opponents.forEach(function (opponent, index) {
if (opponent.isFalling && !opponent.hasFlashed && !opponent.isOnGround) {
opponent.hasFlashed = true;
LK.setTimeout(function () {
globalSpeedPerLine[opponent.lineIndex] = globalBaseSpeed;
opponent.restore();
}, 2000);
}
});
}
function getFinishPosition() {
return currentFinishPosition++;
}
/****************************************************************************************** */
/************************************** MAIN GAME LOOP ************************************ */
/****************************************************************************************** */
LK.on('tick', function () {
switch (gameState) {
case GAME_STATE.MENU:
// Handle menu logic here
break;
case GAME_STATE.STARTING:
hurdlesStarting();
break;
case GAME_STATE.PLAYING:
gamePlaying();
break;
case GAME_STATE.SCORE:
// Handle score display logic here
break;
}
});
gameInitialize();
Elongated elipse with black top half and white bottom half.
full close and front view of empty stands. retro gaming style
delete
delete
Basquettes à ressort futuriste. vue de profile. Retro gaming style
a blue iron man style armor flying. Retro gaming style
a blue iron man style armor flying horizontally. Retro gaming style
round button with a big "up" arrow icon and a small line under it. UI
A big black horizontal arrow pointing left with centred text 'YOU' in capital letters, painted on an orange floor.. horizontal and pointing left
remove
gold athletics medal with ribbon. retro gaming style
a black oval with a crying smiley face.