User prompt
make red flash longer when killed
Code edit (1 edits merged)
Please save this source code
User prompt
also play killed_1 after accident_1
User prompt
play accident_1 when killed
User prompt
when setting killer[2] active, play ambulance_1
User prompt
when setting killer[1] active, play police_1
User prompt
when setting killer[0] active, play car_1
Code edit (4 edits merged)
Please save this source code
User prompt
play levelWin_1 when wining a level
User prompt
add a function playHit() thay randmoly plays hit_1, hit_2 or hit_3
User prompt
play hit_1 when hitting an obstacle
User prompt
stop bgMusic when player is killed
User prompt
play coin_1 when player collects a coin
User prompt
play bgMusic repeatedly after start button press
User prompt
Please fix the bug: 'ReferenceError: currentTime is not defined' in or related to this line: 'self.lastKillerUpdate = currentTime;' Line Number: 425
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'resetKillers')' in or related to this line: 'killerManager.resetKillers();' Line Number: 1452
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'resetKillers')' in or related to this line: 'killerManager.resetKillers();' Line Number: 1451
Code edit (1 edits merged)
Please save this source code
User prompt
create a KillerManager class to organize killers to activate killers[0] after killerDelay, then killers[1] after killerDelay, then killers[2] after killerDelay, then killers[0] after killerDelay, ....
User prompt
organize killers to activate killers[0] after killerDelay, then killers[1] after killerDelay, then killers[2] after killerDelay, then killers[0] after killerDelay, ....
User prompt
create 3 different killers instead of 1
User prompt
add an index to Killer constructor that allow asset selection
User prompt
create a global array for killers
Code edit (3 edits merged)
Please save this source code
/****
* Classes
****/
var Background = Container.expand(function () {
var self = Container.call(this);
var backgroundGraphics1 = self.attachAsset('background_1', {
anchorX: 0.5,
anchorY: 0.5,
visible: true
});
var backgroundGraphics2 = self.attachAsset('background_2', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
var backgroundGraphics3 = self.attachAsset('background_3', {
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
self.updateForLevel = function (level) {
backgroundGraphics1.visible = level === 1;
backgroundGraphics2.visible = level === 2;
backgroundGraphics3.visible = level === 3;
};
});
// Assets will be automatically created and loaded during gameplay
// Coin class
var Coin = Container.expand(function (index) {
var self = Container.call(this);
self.index = index;
var coinGraphics = self.attachAsset('coin1', {
anchorX: 0.5,
anchorY: 0.5
});
var coinGraphics2 = self.attachAsset('coin2', {
//'dollarsBundle'
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
var coinGraphics3 = self.attachAsset('dollarsBundle', {
//'dollarsBundle'
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
var speed = 5;
var startY = roadTop + 50;
var endY = startY + roadHeight;
var leftStartX = 1024 - 100;
var leftEndX = 1024 - 650;
var rightStartX = 1024 + 100;
var rightEndX = 1024 + 650;
var startSize = 2;
var endSize = 140;
coinGraphics.width = startSize;
coinGraphics.height = startSize;
coinGraphics2.width = startSize;
coinGraphics2.height = startSize;
coinGraphics3.width = startSize;
coinGraphics3.height = startSize;
self.pathIndex = 0;
self.update = function () {
// Road should animate even if the game hasn't started
if (!isPlaying || isKilled) {
return;
}
;
obstacleManager.updateObstacles();
self.progress = Math.max(0, self.y - startY) / (endY - startY); // Update progress property
coinGraphics.width = startSize + (endSize - startSize) * self.progress;
coinGraphics.height = startSize + (endSize - startSize) * self.progress;
coinGraphics2.width = startSize + (endSize - startSize) * self.progress;
coinGraphics2.height = startSize + (endSize - startSize) * self.progress;
coinGraphics3.width = startSize + (endSize - startSize) * self.progress;
coinGraphics3.height = startSize + (endSize - startSize) * self.progress;
var newSpeed = currentSpeed; // + 10 * self.progress;
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3);
newSpeed = tempSpeed;
self.y += newSpeed;
// Move innerLineLeft x progressively to innerLeftLineEndX
if (self.pathIndex == 0 && self.x != leftEndX) {
self.x = leftStartX + (leftEndX - leftStartX) * self.progress;
}
if (self.pathIndex == 2 && self.x != rightEndX) {
self.x = rightStartX + (rightEndX - rightStartX) * self.progress;
}
if (self.y > endY + endSize / 2) {
self.reset();
}
// Check for collision with player
if (!player.isJumping && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) {
updateScore(false);
// coinsCollected increment moved to increaseScore function
LK.effects.flashObject(player, 0x00ff00, 500); // Flash green for 0.5 seconds
self.reset();
// Increase speed every 3 coins collected
/*
if (coinsCollected % nextCoinTypeThreshold === 0 && currentSpeed < maxSpeed) {
currentSpeed += 3; // Increase speed by 3
}
*/
}
};
self.reset = function () {
self.y = startY;
self.progress = 0; // Initialize progress property
coinGraphics.width = startSize;
coinGraphics.height = startSize;
coinGraphics2.width = startSize;
coinGraphics2.height = startSize;
coinGraphics3.width = startSize;
coinGraphics3.height = startSize;
self.pathIndex = Math.floor(Math.random() * 3);
if (self.pathIndex === 0) {
self.x = leftStartX;
} else if (self.pathIndex === 2) {
self.x = rightStartX;
} else {
self.x = 1024;
}
};
self.updateForLevel = function (level) {
coinGraphics.visible = level === 1;
coinGraphics2.visible = level === 2;
coinGraphics3.visible = level === 3;
};
});
// CoinAnimation class
var CoinAnimation = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin1', {
anchorX: 0.5,
anchorY: 0.5,
visible: currentCoinType == 0
});
var coinGraphics2 = self.attachAsset('coin2', {
anchorX: 0.5,
anchorY: 0.5,
visible: currentCoinType == 1
});
// Initialize velocity and gravity
self.vx = (Math.random() < 0.5 ? -1 : 1) * 5; // Random horizontal velocity
self.vy = -15; // Initial vertical velocity
self.gravity = 0.5; // Gravity effect
self.update = function () {
self.vy += self.gravity; // Apply gravity to vertical velocity
self.x += self.vx; // Update horizontal position
self.y += self.vy; // Update vertical position
self.alpha -= 0.0035; // Fade out the coin
if (currentCoinType == 0) {
coinGraphics.alpha = 1;
coinGraphics2.alpha = 0;
} else if (currentCoinType == 1) {
coinGraphics.alpha = 0;
coinGraphics2.alpha = 1;
}
if (self.alpha <= 0) {
self.destroy(); // Remove the coin when it becomes invisible
}
};
});
// Decoration class
var Decoration = Container.expand(function (decoIndex) {
var self = Container.call(this);
self.index = decoIndex;
var assets = ['decoration_1_1', 'decoration_1_2', 'decoration_1_3', 'decoration_2_1', 'decoration_2_2', 'decoration_2_3', 'decoration_3_1', 'decoration_3_2', 'decoration_3_3'];
self.assets = assets.map(function (assetId) {
return self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5,
visible: false
});
});
self.ready = false;
var speed = 5;
var startY = roadTop + 50;
var endY = startY + roadHeight;
var xOffset = 1024;
var baseLeftStartX = 780;
var rand = Math.random();
self.leftStartX = baseLeftStartX; // - rand * xOffset;
self.leftEndX = self.leftStartX - xOffset * (1.5 + rand);
var baseRightStartX = 1280;
self.rightStartX = baseRightStartX; // + rand * xOffset / 2;
self.rightEndX = self.rightStartX + xOffset * (1.5 + rand);
self.assetWidthRatios = [100 / 300, 1, 1, 1, 1, 1, 1, 1];
self.endSizes = [600, 600, 600, 600, 600, 600, 600, 600, 600];
var startSize = 1;
self.assetIndex = Math.floor(Math.random() * 3) + (currentLevel - 1) * 3;
mainGraphics = self.assets[self.assetIndex];
mainGraphics.width = startSize;
mainGraphics.height = startSize;
self.pathIndex = 0;
self.update = function () {
if (isKilled) {
return;
}
var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf;
//mainGraphics.tint = newTint;
var tempSpeed = currentSpeed * 0.055 + currentSpeed * (self.progress * 3);
var newSpeed = currentSpeed; // + 10 * self.progress;
newSpeed = tempSpeed * 1; // TEMP DEBUG !!!
self.y += newSpeed;
self.progress = Math.max(0, self.y - startY) / (endY - startY); // Update progress property
// Move innerLineLeft x progressively to innerLeftLineEndX
if (self.index == 7) {
//log("Decoration " + self.index + " update - p=", self.progress, "x:", Math.round(self.x), "y:", Math.round(self.y));
//log(self.progress);
}
if (self.pathIndex == 0 && self.x > self.leftEndX) {
self.x = self.leftStartX + (self.leftEndX - self.leftStartX) * self.progress * 3;
}
if (self.pathIndex == 1 && self.x < self.rightEndX) {
self.x = self.rightStartX + (self.rightEndX - self.rightStartX) * self.progress * 3;
}
if (self.y > endY + self.endSizes[self.assetIndex] / 2) {
//self.y = -startSize; // Move obstacle back to the top
self.reset();
}
//mainGraphics = self.assets[self.assetIndex];
mainGraphics.height = startSize + (self.endSizes[self.assetIndex] - startSize) * self.progress * 2;
mainGraphics.width = mainGraphics.height * self.assetWidthRatios[self.assetIndex];
if (self.index == 8 && mainGraphics.width > 200) {
//log("Decoration " + self.index + " update - assetIndex:", self.assetIndex, "width:", mainGraphics.width, "x:", Math.round(self.x), "y:", Math.round(self.y));
}
if (self.index == 7 && mainGraphics.width > 200) {
//log("Decoration " + self.index + " update - assetIndex:", self.assetIndex, "width:", mainGraphics.width, "x:", Math.round(self.x), "y:", Math.round(self.y));
}
if (!self.ready) {
//log("Decoration " + self.index + " ready =" + self.ready);
}
//log("Decoration " + self.index + " update width:", Math.round(mainGraphics.width), "x:", Math.round(self.x), "y:", Math.round(self.y));
};
self.reset = function () {
self.ready = false;
//log("Decoration reset" + self.index);
self.y = startY;
self.progress = 0; // Initialize progress property
rand = Math.random();
self.assetIndex = Math.floor(Math.random() * 3) + (currentLevel - 1) * 3;
self.assets.forEach(function (asset, index) {
asset.visible = index === self.assetIndex;
});
mainGraphics = self.assets[self.assetIndex];
mainGraphics.height = startSize;
mainGraphics.width = mainGraphics.height * self.assetWidthRatios[self.assetIndex];
if (self.index == 1 && mainGraphics.width > 200) {
//log("=== Decoration " + self.index + " reset - assetIndex:", self.assetIndex, "width:", mainGraphics.width, "y:", self.y, " ===");
}
self.leftStartX = baseLeftStartX; // - rand * xOffset;
self.leftEndX = self.leftStartX - xOffset * (1 + rand);
self.rightStartX = baseRightStartX; // + rand * xOffset;
self.rightEndX = self.rightStartX + xOffset * (1 + rand);
if (self.index == 1) {
//log("=== Decoration " + self.index);
//log("Left StartX:", self.leftStartX, "Left EndX:", self.leftEndX);
//log("Right StartX:", self.rightStartX, "Right EndX:", self.rightEndX);
}
self.pathIndex = Math.floor(rand * 2);
if (self.pathIndex === 0) {
self.x = self.leftStartX;
} else {
self.x = self.rightStartX;
}
self.ready = true;
};
});
var Killer = Container.expand(function () {
var self = Container.call(this);
var assets = ['killer3'];
self.assetIndex = Math.floor(Math.random() * assets.length);
var randomAsset = assets[self.assetIndex];
var killerGraphics = self.attachAsset(randomAsset, {
anchorX: 0.5,
anchorY: 0.5
});
var speed = 5;
var startY = roadTop - 20;
var endY = startY + roadHeight;
var leftStartX = 1024 - 100;
var leftEndX = 1024 - 650;
var rightStartX = 1024 + 100;
var rightEndX = 1024 + 650;
var startSize = 1;
var endSize = 800;
var assetHeightRatio = 500 / 400;
killerGraphics.width = startSize;
killerGraphics.height = startSize;
self.pathIndex = 0;
self.inactive = true;
self.inactiveStartTime = Date.now();
self.update = function () {
if (!isPlaying) {
return;
}
var currentTime = Date.now();
if (self.inactive) {
if (currentTime - self.inactiveStartTime >= killerDelay) {
self.inactive = false;
}
return;
}
if (!isKilled && player && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) {
isKilled = true;
player.visible = false;
LK.effects.flashScreen(0xff0000, 2000);
// Spawn MurderShape at player's last position
var murderShape = new MurderShape();
murderShape.x = player.x;
murderShape.y = playerBaseY;
murderShape.fixPosition();
game.addChildAt(murderShape, game.getChildIndex(road) + 1);
return;
}
self.progress = Math.max(0, self.y - startY) / (endY - startY);
killerGraphics.width = startSize + (endSize - startSize) * self.progress;
debugTxt.setText(self.progress.toFixed(2));
killerGraphics.height = assetHeightRatio * killerGraphics.width;
var tempSpeed = currentSpeed * 0.5 + currentSpeed * (self.progress * 3);
var newSpeed = currentSpeed * 3;
newSpeed = tempSpeed * 1;
self.y += newSpeed;
if (self.pathIndex == 0 && self.x != leftEndX) {
self.x = leftStartX + (leftEndX - leftStartX) * self.progress;
}
if (self.pathIndex == 2 && self.x != rightEndX) {
self.x = rightStartX + (rightEndX - rightStartX) * self.progress;
}
if (self.y > endY + endSize / 2) {
self.reset();
}
};
self.reset = function () {
self.y = startY;
self.progress = 0;
killerGraphics.width = startSize;
killerGraphics.height = startSize;
self.pathIndex = Math.floor(Math.random() * 3);
if (self.pathIndex === 0) {
self.x = leftStartX;
} else if (self.pathIndex === 2) {
self.x = rightStartX;
} else {
self.x = 1024;
}
self.inactive = true;
self.inactiveStartTime = Date.now();
};
});
var Landscape = Container.expand(function () {
var self = Container.call(this);
var landscapeGraphics = self.attachAsset('landscape_1', {
anchorX: 0.5,
anchorY: 0.0
});
var landscapeGraphics2 = self.attachAsset('landscape_2', {
anchorX: 0.5,
anchorY: 0.0,
visible: false
});
var landscapeGraphics3 = self.attachAsset('landscape_3', {
anchorX: 0.5,
anchorY: 0.0,
visible: false
});
var gradientGraphics = self.attachAsset('gradient', {
anchorX: 0.5,
anchorY: 0.0,
scaleY: -1,
y: 1024,
blendMode: 2,
alpha: 0.5,
tint: 0xFEFEFE,
height: 15
});
self.x = 2048 / 2; // Center horizontally
self.y = 0; // Position at the top
self.update = function () {
var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf;
landscapeGraphics.tint = newTint; // Apply reduced tint to the road based on the intensity
};
self.updateForLevel = function (level) {
landscapeGraphics.visible = level === 1;
landscapeGraphics2.visible = level === 2;
landscapeGraphics3.visible = level === 3;
};
});
var MurderShape = Container.expand(function () {
var self = Container.call(this);
var murderShapeGraphics = self.attachAsset('murderShape', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// MurderShape does not need to update its position or behavior
};
self.fixPosition = function () {
if (self.x < 600) {
self.x += 150;
} else if (self.x > 1400) {
self.x -= 150;
}
};
});
// Obstacle class
var Obstacle = Container.expand(function (index) {
var self = Container.call(this);
self.active = true;
self.index = index;
var assets = [];
if (currentLevel === 1) {
assets = ['obstacle_1_1', 'obstacle_1_2', 'obstacle_1_3'];
} else if (currentLevel === 2) {
assets = ['obstacle_2_1', 'obstacle_2_2', 'obstacle_2_3'];
} else if (currentLevel === 3) {
assets = ['obstacle_3_1', 'obstacle_3_2', 'obstacle_3_3'];
}
self.assetIndex = Math.floor(Math.random() * assets.length);
var randomAsset = assets[self.assetIndex];
var obstacleGraphics = self.attachAsset(randomAsset, {
anchorX: 0.5,
anchorY: 0.5
});
var speed = 5;
var startY = roadTop + 50;
var endY = startY + roadHeight;
var leftStartX = 1024 - 100;
var leftEndX = 1024 - 650;
var rightStartX = 1024 + 100;
var rightEndX = 1024 + 650;
var innerLeftLineStartX = -150;
var innerLeftLineEndX = -390;
var startSize, endSize;
if (self.assetIndex == 0) {
startSize = 3;
endSize = 350;
} else if (self.assetIndex == 1) {
startSize = 1;
endSize = 350;
} else if (self.assetIndex == 2) {
startSize = 2;
endSize = 350;
}
obstacleGraphics.width = startSize;
obstacleGraphics.height = startSize;
self.pathIndex = 0;
self.update = function () {
if (!isPlaying || isKilled) {
return;
}
// coinsCollected increment moved to updateScore function
var currentTime = Date.now();
if (currentTime - lastObstacleHitTime > immunityDelay && player && !player.isJumping && self.y > 2500 && self.y < 2732 && player.shadow.intersects(self)) {
lastObstacleHitTime = currentTime; // Update the last hit time
// Make player flash red for 1 second
LK.effects.flashObject(player, 0xff0000, 1000);
// Add coin animation only if score is greater than 0
if (score > 0) {
var coinAnimation = new CoinAnimation();
coinAnimation.x = player.x;
coinAnimation.y = player.y;
game.addChild(coinAnimation);
}
// Reduce score by 1
updateScore(true);
//log("Obstacle y:", self.y);
// Reduce currentSpeed by a factor (e.g., 0.8)
//log("Old speed :", currentSpeed);
//currentSpeed = Math.max(10, Math.min(20, Math.round(currentSpeed * 0.8)));
//log("New speed :", currentSpeed);
}
self.progress = Math.max(0, self.y - startY) / (endY - startY); // Update progress property
obstacleGraphics.width = startSize + (endSize - startSize) * self.progress;
obstacleGraphics.height = startSize + (endSize - startSize) * self.progress;
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3);
var newSpeed = currentSpeed; // + 10 * self.progress;
newSpeed = tempSpeed * 1; // TEMP DEBUG !!!
self.y += newSpeed;
// Move innerLineLeft x progressively to innerLeftLineEndX
if (self.pathIndex == 0 && self.x != leftEndX) {
self.x = leftStartX + (leftEndX - leftStartX) * self.progress;
}
if (self.pathIndex == 2 && self.x != rightEndX) {
self.x = rightStartX + (rightEndX - rightStartX) * self.progress;
}
if (self.y > endY + endSize / 2) {
self.reset();
}
};
self.reset = function () {
obstacleManager.freePath(self.pathIndex); // Mark the path as unoccupied
self.active = false;
self.y = startY;
self.progress = 0; // Initialize progress property
obstacleGraphics.width = startSize;
obstacleGraphics.height = startSize;
};
self.setPath = function (newPathIndex) {
self.pathIndex = newPathIndex; //Math.floor(Math.random() * 3);
if (self.pathIndex === 0) {
self.x = leftStartX;
} else if (self.pathIndex === 2) {
self.x = rightStartX;
} else {
self.x = 1024;
}
};
self.updateForLevel = function (level) {
log("Obstacle updateForLevel", level);
var assets = [];
if (level === 1) {
assets = ['obstacle_1_1', 'obstacle_1_2', 'obstacle_1_3'];
} else if (level === 2) {
assets = ['obstacle_2_1', 'obstacle_2_2', 'obstacle_2_3'];
} else if (level === 3) {
assets = ['obstacle_3_1', 'obstacle_3_2', 'obstacle_3_3'];
}
self.assetIndex = Math.floor(Math.random() * assets.length);
var randomAsset = assets[self.assetIndex];
log("Obstacle asset =>", randomAsset);
obstacleGraphics.destroy();
obstacleGraphics = self.attachAsset(randomAsset, {
anchorX: 0.5,
anchorY: 0.5
});
self.reset();
};
});
var ObstacleManager = Container.expand(function () {
var self = Container.call(this);
self.obstacles = [];
self.occupiedPaths = [false, false, false];
self.addObstacle = function (obstacle) {
self.obstacles.push(obstacle);
};
self.resetObstacles = function () {
self.occupiedPaths = [false, false, false];
self.obstacles.forEach(function (obstacle) {
obstacle.reset();
});
};
self.updateObstacles = function () {
self.obstacles.forEach(function (obstacle) {
if (!obstacle.active) {
obstacle.reset();
}
});
};
self.update = function () {
if (!isPlaying || isKilled) {
return;
}
// Activate obstacles regularly in random path
var currentTime = Date.now();
log("ObstacleManager update...");
if (currentTime - lastObstacleSpawnTime > baseObstacleSpawnDelay) {
log("Attempting to spawn obstacle. Current time:", currentTime, "Last spawn time:", lastObstacleSpawnTime);
var availablePaths = self.occupiedPaths.map(function (occupied, index) {
return occupied ? null : index;
}).filter(function (index) {
return index !== null;
});
log("Available paths for obstacle activation:", availablePaths);
if (availablePaths.length > 0) {
var randomPathIndex = availablePaths[Math.floor(Math.random() * availablePaths.length)];
var inactiveObstacles = self.obstacles.filter(function (obstacle) {
return !obstacle.active;
});
log("Inactive obstacles available for activation:", inactiveObstacles.length);
if (inactiveObstacles.length > 0) {
var obstacleToActivate = inactiveObstacles[Math.floor(Math.random() * inactiveObstacles.length)];
log("Activating obstacle in path:", randomPathIndex);
obstacleToActivate.setPath(randomPathIndex);
log("Obstacle activated:", obstacleToActivate);
obstacleToActivate.active = true;
self.setPathOccupied(randomPathIndex, true);
log("Path occupied status updated. Path:", randomPathIndex, "Occupied:", self.isPathOccupied(randomPathIndex));
lastObstacleSpawnTime = currentTime; // Update the last spawn time
}
}
}
};
self.isPathOccupied = function (pathIndex) {
return self.occupiedPaths[pathIndex];
};
self.setPathOccupied = function (pathIndex, occupied) {
self.occupiedPaths[pathIndex] = occupied;
};
self.freePath = function (pathIndex) {
self.setPathOccupied(pathIndex, false);
};
self.updateForLevel = function (level) {
self.obstacles.forEach(function (obstacle) {
obstacle.updateForLevel(level);
});
};
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
self.shadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5
});
self.isJumping = false; // Initialize isJumping to false
self.shadow.alpha = 0.5; // Make the shadow semi-transparent
self.shadow.y = 270; // Offset the shadow slightly below the player
var playerGraphics1_1 = self.attachAsset('player_1_1', {
anchorX: 0.5,
anchorY: 0.5,
x: -5
});
var playerGraphics1_2 = self.attachAsset('player_1_2', {
anchorX: 0.5,
anchorY: 0.5,
x: 5
});
var playerGraphics2_1 = self.attachAsset('player_2_1', {
anchorX: 0.5,
anchorY: 0.5,
x: -5,
visible: false // Initially hide player2_1 asset
});
var playerGraphics2_2 = self.attachAsset('player_2_2', {
anchorX: 0.5,
anchorY: 0.5,
x: 5,
visible: false // Initially hide player2_2 asset
});
var playerGraphics3_1 = self.attachAsset('player_3_1', {
anchorX: 0.5,
anchorY: 0.5,
x: -5,
visible: false // Initially hide player3_1 asset
});
var playerGraphics3_2 = self.attachAsset('player_3_2', {
anchorX: 0.5,
anchorY: 0.5,
x: 5,
visible: false // Initially hide player3_2 asset
});
var frame = 0;
self.update = function () {
if (!self.isJumping) {
frame += Math.min(currentSpeed, 20); // Add a max limit to avoid optical effects
if (frame >= 100) {
frame = 0;
// Swap frames every 10 game ticks
if (currentLevel <= 1) {
var visible = playerGraphics1_1.visible;
playerGraphics1_1.visible = !visible;
playerGraphics1_2.visible = visible;
}
if (currentLevel === 2) {
var visible = playerGraphics2_1.visible;
playerGraphics2_1.visible = !visible;
playerGraphics2_2.visible = visible;
}
if (currentLevel === 3) {
var visible = playerGraphics3_1.visible;
playerGraphics3_1.visible = !visible;
playerGraphics3_2.visible = visible;
}
}
}
};
self.updateForLevel = function (level) {
playerGraphics1_1.visible = level === 1;
playerGraphics1_2.visible = level === 1;
playerGraphics2_1.visible = level === 2;
playerGraphics2_2.visible = level === 2;
playerGraphics3_1.visible = level === 3;
playerGraphics3_2.visible = level === 3;
};
self.jump = function () {
if (!self.isJumping) {
self.isJumping = true;
var initialY = self.y;
var initialShadowY = self.shadow.y;
var jumpHeight = 300;
var jumpDuration = 30;
var jumpStep = jumpHeight / jumpDuration;
var fallStep = jumpHeight / jumpDuration;
var jumpStartTime = Date.now();
var jumpInterval = LK.setInterval(function () {
var elapsed = Date.now() - jumpStartTime;
var progress = elapsed / (jumpDuration * 1000 / 60);
if (progress < 1) {
var easeProgress = Math.sin(progress * Math.PI / 2);
self.y = initialY - jumpHeight * easeProgress;
self.shadow.y = initialShadowY + jumpHeight * easeProgress; // Move shadow inversely
self.shadow.width = 240 * (1 - 0.5 * easeProgress); // Reduce shadow width
self.shadow.height = 100 * (1 - 0.5 * easeProgress); // Reduce shadow height
} else {
LK.clearInterval(jumpInterval);
var fallStartTime = Date.now();
var fallInterval = LK.setInterval(function () {
var elapsed = Date.now() - fallStartTime;
var progress = elapsed / (jumpDuration * 1000 / 60);
if (progress < 1) {
var easeProgress = Math.sin(progress * Math.PI / 2);
self.y = initialY - jumpHeight + jumpHeight * easeProgress;
self.shadow.y = initialShadowY + jumpHeight - jumpHeight * easeProgress; // Move shadow inversely
self.shadow.width = 120 + 120 * easeProgress; // Reset shadow width
self.shadow.height = 50 + 50 * easeProgress; // Reset shadow height
} else {
self.y = initialY;
self.shadow.y = initialShadowY; // Reset shadow position
self.isJumping = false;
LK.clearInterval(fallInterval);
}
}, 1000 / 60);
}
}, 1000 / 60);
}
};
});
// Road class
var Road = Container.expand(function () {
var self = Container.call(this);
var baseY = 750;
var roadGraphics = self.attachAsset('triangle', {
tint: 0x555555,
// Initialize tint to white
anchorX: 0.5,
anchorY: 0,
width: 2048,
height: roadHeight,
y: baseY
});
var speed = 5;
var lineOffset = -150;
// Inner lines
var innerLineStartY = roadTop;
var innerLineEndY = roadTop + roadHeight + 200;
// Left
var innerLeftLineStartX = -50;
var innerLeftLineEndX = -412;
var innerLeftLineStartW = 3;
var innerLeftLineEndW = 80;
var innerLeftLineStartH = 3;
var innerLeftLineEndH = 500;
var innerLeftLineStartR = 0.22; //0.075;
var innerLeftLineEndR = 0.275;
// Right
var innerRightLineStartX = 50;
var innerRightLineEndX = 412;
var innerRightLineStartW = 3;
var innerRightLineEndW = 80;
var innerRightLineStartH = 3;
var innerRightLineEndH = 500;
var innerRightLineStartR = -0.22;
var innerRightLineEndR = -0.275;
// Lamp posts
// Left Lamp
var leftLampStartX = -130;
var leftLampEndX = -1600;
var leftLampStartY = roadTop;
var leftLampEndY = roadTop + roadHeight + 0; // Define leftLampEndY variable
var leftLampStartH = 2;
var leftLampEndH = 900;
var leftLampWRatio = 1 / 3;
// Right Lamp
var rightLampStartX = 130;
var rightLampEndX = 1600;
var rightLampStartY = roadTop;
var rightLampEndY = roadTop + roadHeight + 0; // Define leftLampEndY variable
var rightLampStartH = 2;
var rightLampEndH = 900;
var rightLampWRatio = 1 / 3;
var nbInnerLines = 6;
var leftLine = self.attachAsset('triangle', {
anchorX: 0.5,
anchorY: 0,
width: 100,
height: 1950,
rotation: 0.45
});
leftLine.x = lineOffset; // Position the left line on the left side of the road
leftLine.y = roadTop + 45; // Center the left line vertically
var rightLine = self.attachAsset('triangle', {
anchorX: 0.5,
anchorY: 0,
width: 100,
height: 1950,
rotation: -0.45
});
rightLine.x = -lineOffset; // Position the right line on the right side of the road
rightLine.y = roadTop + 45; // Center the right line vertically
self.innerLeftLines = [];
self.innerRightLines = [];
self.leftLampPosts = [];
self.rightLampPosts = [];
// Define arrays to store assets for each level
var leftLampPostAssets = ['lampPost_1',
// Level 1 asset
'lampPost_2',
// Level 2 asset
'lampPost_3' // Level 3 asset
];
var rightLampPostAssets = ['lampPost_1',
// Level 1 asset
'lampPost_2',
// Level 2 asset
'lampPost_3' // Level 3 asset
];
for (var i = 0; i < nbInnerLines; i++) {
var innerLineLeft = self.attachAsset('line', {
anchorX: 0.5,
anchorY: 0.5,
width: innerLeftLineStartW,
height: innerLeftLineStartH,
rotation: innerLeftLineStartR,
alpha: 1
});
innerLineLeft.x = innerLeftLineStartX;
innerLineLeft.y = innerLineStartY - 0.1 * i * roadHeight / nbInnerLines;
//log(i + " : " + innerLineStartY + " + " + i * roadHeight / nbInnerLines + " => " + innerLineLeft.y);
innerLineLeft.progress = 0; // Initialize progress property
self.innerLeftLines.push(innerLineLeft);
var innerLineRight = self.attachAsset('line', {
anchorX: 0.5,
anchorY: 0.5,
width: innerRightLineStartW,
height: innerRightLineStartH,
rotation: innerRightLineStartR,
alpha: 1
});
innerLineRight.x = innerRightLineStartX;
innerLineRight.y = innerLineStartY - 0.1 * i * roadHeight / nbInnerLines;
innerLineRight.progress = 0; // Initialize progress property
self.innerRightLines.push(innerLineRight);
if (i % 2 == 0) {
continue;
}
var leftLampPost = self.attachAsset(leftLampPostAssets[currentLevel - 1], {
anchorX: 0.5,
anchorY: 0.5,
height: leftLampStartH,
width: leftLampStartH * leftLampWRatio
});
var leftLampShadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5,
width: leftLampPost.width * 0.8,
height: leftLampPost.height * 0.1,
y: leftLampPost.height * 0.5 + 10 // Offset shadow slightly below the lamp post
});
leftLampPost.addChild(leftLampShadow);
leftLampPost.x = leftLampStartX;
leftLampPost.y = leftLampStartY - (i - 1) * 40;
self.addChild(leftLampPost);
self.leftLampPosts.push(leftLampPost);
var rightLampPost = self.attachAsset(rightLampPostAssets[currentLevel - 1], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1,
height: rightLampStartH,
width: rightLampStartH * rightLampWRatio
});
var rightLampShadow = self.attachAsset('shadow', {
anchorX: 0.5,
anchorY: 0.5,
width: rightLampPost.width * 0.8,
height: rightLampPost.height * 0.1,
y: rightLampPost.height * 0.5 + 10 // Offset shadow slightly below the lamp post
});
rightLampPost.addChild(rightLampShadow);
rightLampPost.x = rightLampStartX;
rightLampPost.y = rightLampStartY - (i - 1) * 40;
self.addChild(rightLampPost);
self.rightLampPosts.push(rightLampPost);
}
self.update = function () {
if (isKilled) {
return;
}
var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf;
//roadGraphics.tint = newTint; // Apply reduced tint to the road based on the intensity
leftLine.tint = newTint;
rightLine.tint = newTint;
// Add any update logic for the road if needed
for (var i = 0; i < self.innerLeftLines.length; i++) {
innerLineLeft = self.innerLeftLines[i];
innerLineLeft.tint = newTint;
if (innerLineLeft.y > innerLineEndY) {
self.resetInnerLine(innerLineLeft, true);
} else {
innerLineLeft.progress = Math.max(0, innerLineLeft.y - innerLineStartY) / (innerLineEndY - innerLineStartY); // Update progress property
}
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (innerLineLeft.progress * 3);
var newSpeed = currentSpeed; // + 10 * self.progress;
newSpeed = tempSpeed * 1; // TEMP DEBUG !!!
innerLineLeft.y += newSpeed;
// Move innerLineLeft x progressively to innerLeftLineEndX
if (innerLineLeft.x != innerLeftLineEndX) {
innerLineLeft.x = innerLeftLineStartX + (innerLeftLineEndX - innerLeftLineStartX) * innerLineLeft.progress;
}
// Move innerLineLeft x progressively
if (innerLineLeft.rotation != innerLeftLineEndR) {
//innerLineLeft.rotation = innerLeftLineStartR + (innerLeftLineEndR - innerLeftLineStartR) * innerLineLeft.progress;
}
// Move innerLineLeft x progressively
if (innerLineLeft.width != innerLeftLineEndW) {
innerLineLeft.width = innerLeftLineStartW + (innerLeftLineEndW - innerLeftLineStartW) * innerLineLeft.progress;
}
// Move innerLineLeft x progressively
if (innerLineLeft.height != innerLeftLineEndH) {
innerLineLeft.height = innerLeftLineStartH + (innerLeftLineEndH - innerLeftLineStartH) * innerLineLeft.progress;
}
}
for (var i = 0; i < self.innerRightLines.length; i++) {
innerLineRight = self.innerRightLines[i];
innerLineRight.tint = newTint;
if (innerLineRight.y > innerLineEndY) {
self.resetInnerLine(innerLineRight, false);
} else {
innerLineRight.progress = Math.max(0, innerLineRight.y - innerLineStartY) / (innerLineEndY - innerLineStartY);
}
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (innerLineRight.progress * 3);
var newSpeed = currentSpeed; // + 10 * self.progress;
newSpeed = tempSpeed * 1; // TEMP DEBUG !!!
innerLineRight.y += newSpeed;
// Move innerLineRight x progressively to innerRightLineEndX
if (innerLineRight.x != innerRightLineEndX) {
innerLineRight.x = innerRightLineStartX + (innerRightLineEndX - innerRightLineStartX) * innerLineRight.progress;
}
// Move innerLineRight x progressively
if (innerLineRight.rotation != innerRightLineEndR) {
//innerLineRight.rotation = innerRightLineStartR + (innerRightLineEndR - innerRightLineStartR) * innerLineRight.progress;
}
// Move innerLineRight x progressively
if (innerLineRight.width != innerRightLineEndW) {
innerLineRight.width = innerRightLineStartW + (innerRightLineEndW - innerRightLineStartW) * innerLineRight.progress;
}
// Move innerLineRight x progressively
if (innerLineRight.height != innerRightLineEndH) {
innerLineRight.height = innerRightLineStartH + (innerRightLineEndH - innerRightLineStartH) * innerLineRight.progress;
}
}
// Lamp posts
for (var i = 0; i < self.leftLampPosts.length; i++) {
var leftLampPost = self.leftLampPosts[i];
//leftLampPost.tint = newTint;
var tempProgress = Math.max(0, leftLampPost.y - leftLampStartY) / (leftLampEndY - leftLampStartY);
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (tempProgress * 3);
leftLampPost.y += tempSpeed;
//leftLampPost.visible = currentLevel !== 1; // Make lampPost not visible when level is 1
if (leftLampPost.y > leftLampEndY) {
leftLampPost.y = leftLampStartY;
leftLampPost.x = leftLampStartX;
leftLampPost.height = leftLampStartH;
}
leftLampPost.progress = Math.max(0, leftLampPost.y - leftLampStartY) / (leftLampEndY - leftLampStartY); // Update progress property
leftLampPost.alpha = 0.75 + Math.min(0.25, leftLampPost.progress);
if (i == 0) {
//debugTxt.setText(leftLampPost.progress.toFixed(2));
}
if (leftLampPost.x != leftLampEndX) {
leftLampPost.x = leftLampStartX + (leftLampEndX - leftLampStartX) * Math.min(1, leftLampPost.progress * 1);
}
if (leftLampPost.height != leftLampEndH) {
leftLampPost.height = Math.min(1, leftLampPost.progress * 2) * leftLampEndH; // leftLampStartH + (leftLampEndH - leftLampStartH) * Math.min(1, leftLampPost.progress * 1);
leftLampPost.width = leftLampPost.height * leftLampWRatio;
}
}
for (var i = 0; i < self.rightLampPosts.length; i++) {
var rightLampPost = self.rightLampPosts[i];
var tempProgress = Math.max(0, rightLampPost.y - rightLampStartY) / (rightLampEndY - rightLampStartY);
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (tempProgress * 3);
rightLampPost.y += tempSpeed;
//rightLampPost.visible = currentLevel !== 1; // Make right lampPost not visible when level is 1
if (rightLampPost.y > rightLampEndY) {
rightLampPost.y = rightLampStartY;
rightLampPost.x = rightLampStartX;
rightLampPost.height = rightLampStartH;
}
rightLampPost.progress = Math.max(0, rightLampPost.y - rightLampStartY) / (rightLampEndY - rightLampStartY);
rightLampPost.alpha = 0.75 + Math.min(0.25, rightLampPost.progress);
if (rightLampPost.x != rightLampEndX) {
rightLampPost.x = rightLampStartX + (rightLampEndX - rightLampStartX) * rightLampPost.progress;
}
if (rightLampPost.height != leftLampEndH) {
rightLampPost.height = rightLampStartH + (rightLampEndH - rightLampStartH) * Math.min(1, rightLampPost.progress * 2);
rightLampPost.width = rightLampPost.height * rightLampWRatio;
}
}
};
self.updateForLevel = function (level) {
// Iterate through left lamp posts
for (var i = 0; i < self.leftLampPosts.length; i++) {
var leftLampPost = self.leftLampPosts[i];
var newLeftLampPost = self.attachAsset(leftLampPostAssets[level - 1], {
anchorX: 0.5,
anchorY: 0.5,
height: leftLampPost.height,
width: leftLampPost.width
});
newLeftLampPost.visible = leftLampPost.visible;
newLeftLampPost.x = leftLampPost.x;
newLeftLampPost.y = leftLampPost.y;
self.leftLampPosts[i] = newLeftLampPost;
leftLampPost.destroy();
}
for (var i = 0; i < self.rightLampPosts.length; i++) {
var rightLampPost = self.rightLampPosts[i];
rightLampPost.children.forEach(function (child) {
child.visible = false;
});
var newRightLampPost = self.attachAsset(rightLampPostAssets[level - 1], {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1,
height: rightLampPost.height,
width: rightLampPost.width
});
newRightLampPost.visible = rightLampPost.visible;
newRightLampPost.x = rightLampPost.x;
newRightLampPost.y = rightLampPost.y;
self.rightLampPosts[i] = newRightLampPost;
rightLampPost.destroy();
}
};
self.resetInnerLine = function (innerLine, isLeft) {
if (isLeft) {
innerLine.x = innerLeftLineStartX;
innerLine.rotation = innerLeftLineStartR;
innerLine.width = innerLeftLineStartW;
innerLine.height = innerLeftLineStartH;
} else {
innerLine.x = innerRightLineStartX;
innerLine.rotation = innerRightLineStartR;
innerLine.width = innerRightLineStartW;
innerLine.height = innerRightLineStartH;
}
innerLine.y = innerLineStartY - 0.2 * roadHeight / nbInnerLines;
innerLine.progress = 0; // Reset progress property
};
});
var StartButton = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5
});
self.interactive = true;
self.buttonMode = true;
self.on('down', function () {
self.visible = false;
isPlaying = true;
scoreTxt.visible = true;
updateGoalForLevel(1); // Call updateGoalForLevel(1) when start button is pressed
});
});
var Stripe = Container.expand(function () {
var self = Container.call(this);
self.stripeGraphics = self.attachAsset('stripe_1', {
anchorX: 0,
anchorY: 1,
height: 1
});
self.stripeGraphics2 = self.attachAsset('stripe_2', {
anchorX: 0,
anchorY: 1,
height: 1,
visible: false
});
self.stripeGraphics3 = self.attachAsset('stripe_3', {
anchorX: 0,
anchorY: 1,
height: 1,
visible: false
});
self.progress = 0; // Initialize progress property
self.update = function () {
if (isKilled) {
return;
}
self.progress = Math.max(0, self.y - roadTop) / roadHeight; // Update progress property
var newTint = intensityHalf << 16 | intensityHalf << 8 | intensityHalf;
self.stripeGraphics.tint = newTint;
self.stripeGraphics2.tint = newTint;
self.stripeGraphics3.tint = newTint;
var tempSpeed = currentSpeed * 0.05 + currentSpeed * (self.progress * 3);
self.y += tempSpeed;
self.stripeGraphics.height = 400 * self.progress; // Adjust height based on progress
self.stripeGraphics2.height = 400 * self.progress; // Adjust height based on progress
self.stripeGraphics3.height = 400 * self.progress; // Adjust height based on progress
if (self.y > roadTop + roadHeight) {
self.y = roadTop;
self.stripeGraphics.height = 0; // Reset height to initial value
self.stripeGraphics.tint = 0xFFFFFF; // Reset tint to initial value
self.stripeGraphics2.height = 0;
self.stripeGraphics2.tint = 0xFFFFFF;
self.stripeGraphics3.height = 0;
self.stripeGraphics3.tint = 0xFFFFFF;
}
};
self.updateForLevel = function (level) {
self.stripeGraphics.visible = level === 1;
self.stripeGraphics2.visible = level === 2;
self.stripeGraphics3.visible = level === 3;
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Init game with black background
});
/****
* Game Code
****/
function updateGoalForLevel(level) {
if (level === 1) {
goalText.setText('COLLECT\r\n$10');
} else if (level === 2) {
goalText.setText('COLLECT\r\n$100');
} else if (level === 3) {
goalText.setText('COLLECT\r\n$1 000 000');
}
goalText.visible = true;
LK.setTimeout(function () {
goalText.visible = false;
}, goalAnnounceDelay);
}
var moneyLost = 0; // Initialize global moneyLost variable
var isDebug = true; // Define global isDebug variable
var occupiedPaths = [false, false, false]; // Initialize an array to track occupied paths
var baseObstacleSpawnDelay = 2000; // Define global baseObstacleSpawnDelay
var obstacleManager; // Define obstacleManager in the global scope
var lastObstacleSpawnTime = 0; // Track the last time an obstacle was spawned
var levelConfigs = [{}, {
name: "Level 1",
backgroundTint: 0xeda716,
coinValue: 0.10,
baseSpeed: 10
}, {
name: "Level 2",
backgroundTint: 0x2faf1d,
coinValue: 1,
baseSpeed: 15
}, {
name: "Level 3",
backgroundTint: 0x6c6060,
coinValue: 100,
baseSpeed: 20
}];
var stripes = [];
var nbDecorations = 10;
var decorations = [];
// Initialize arrays and variables
var currentLevel = 1;
var road = new Road();
var nextLevelCoinThreshold = 10;
var isPlaying = false;
var isKilled = false;
var killerDelay = 10000; // Delay in milliseconds before updating killer
var lastKillerUpdate = 0; // Timestamp of the last killer update
var currentCoinType = 0;
var nextCoinTypeThreshold = 100;
var isNight = false;
var roadHeight = 2000;
var roadTop = 1000; // ~= road.height/2 - baseY
var background;
var landscape;
var nbStripes = 33;
var baseNbCoins = 10;
var baseNbObstacles = 10;
var coins = [];
var obstacles = [];
var road;
var score = 0;
var scoreTxt;
var goalText;
var goalAnnounceDelay = 3000;
var startX = 0;
var startY = 0;
var endX = 0;
var endY = 0;
var intensity = 0;
var intensityHalf = 0;
var leftLampPosts = [];
var rightLampPosts = [];
var leftDecorations = [];
var rightDecorationss = [];
var maxSpeed = 70; // Define a maximum speed limit
var currentSpeed = 15; //20; // Initialize currentSpeed
var coinsCollected = 0; // Initialize coins collected counter
var isIntersectingObstacle = false; // Flag to track if the player is currently intersecting an obstacle
var lastObstacleHitTime = 0; // Timestamp of the last obstacle hit
var immunityDelay = 500; // Immunity delay in milliseconds
var playerPositionIndex = 1; // Initialize player position index
var playerBaseY = 2732 - 300;
// Define the three fixed x positions for the player
var playerPositions = [2048 / 5, 2048 / 2, 4 * 2048 / 5];
// Create player
var player;
var debugMarker;
var debugText;
var debugTxt;
/****************************************************************************************** */
/************************************** GAME FUNCTIONS ************************************ */
/****************************************************************************************** */
function updateScore() {
var negative = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
if (negative) {
if (score > 0) {
moneyLost += Math.min(levelConfigs[currentLevel].coinValue || 1, score);
}
score -= levelConfigs[currentLevel].coinValue || 1;
score = parseFloat(score.toFixed(1));
score = Math.max(0, score); // Ensure score doesn't go below 0
} else {
score += levelConfigs[currentLevel].coinValue || 1;
score = parseFloat(score.toFixed(1));
coinsCollected += 1; // Increment coins collected counter
}
if (coinsCollected >= nextLevelCoinThreshold * currentLevel) {
changeLevel(currentLevel + 1);
}
// Format score
log("score=", score, " => ", (score * 100).toFixed(0) + "¢");
if (score < 1) {
scoreTxt.setText((score * 100).toFixed(0) + "¢");
} else if (score < 10) {
scoreTxt.setText("$" + score.toFixed(2));
} else {
scoreTxt.setText("$" + Math.floor(score));
}
}
// Function to change the level
function changeLevel(newLevel) {
obstacleManager.updateForLevel(currentLevel);
log("changeLevel:", newLevel);
newLevel = Math.max(1, Math.min(levelConfigs.length, newLevel));
currentLevel = newLevel;
currentSpeed = levelConfigs[currentLevel].baseSpeed;
nextLevelCoinThreshold = levelConfigs[currentLevel].coinValue * 10; // Example threshold calculation
console.log("Level changed to:", currentLevel);
// Add a big white flash effect
LK.effects.flashScreen(0xFFFFFF, 1000); // Flash white for 1 second
// Change background tint using levelConfig
background.updateForLevel(currentLevel);
// Update stripe graphics visibility based on the level
stripes.forEach(function (stripe) {
stripe.updateForLevel(currentLevel);
});
// Update landscape based on the level
landscape.updateForLevel(currentLevel);
// Update player graphics based on the level
player.updateForLevel(currentLevel);
if (road) {
road.updateForLevel(currentLevel);
}
coins.forEach(function (coin) {
coin.updateForLevel(currentLevel);
});
updateGoalForLevel(currentLevel);
}
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
function updateBackgroundColor() {
var time = 1000 + new Date().getTime() * 0.0002;
intensity = Math.sin(time) * 127 + 128;
var baseColor = levelConfigs[currentLevel].backgroundTint;
var r = (baseColor >> 16 & 0xFF) + intensity;
var g = (baseColor >> 8 & 0xFF) + intensity;
var b = (baseColor & 0xFF) + intensity;
r = Math.min(255, Math.max(0, r));
g = Math.min(255, Math.max(0, g));
b = Math.min(255, Math.max(0, b));
var color = r << 16 | g << 8 | b;
background.tint = color;
isNight = intensity < 128;
intensityHalf = 128 + Math.floor(intensity * 0.5);
}
function log() {
if (isDebug) {
var _console;
(_console = console).log.apply(_console, arguments);
}
}
/****************************************************************************************** */
/************************************** INPUT HANDLERS ************************************ */
/****************************************************************************************** */
// Handle move events
game.down = function (x, y, obj) {
if (!isPlaying) {
return;
}
startX = x;
startY = y;
};
game.up = function (x, y, obj) {
if (isKilled) {
LK.setTimeout(function () {
LK.showGameOver();
}, 500);
return;
}
if (!isPlaying) {
return;
}
endX = x;
endY = y;
var deltaX = endX - startX;
var deltaY = endY - startY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (deltaX > 0) {
// Swipe right
if (playerPositionIndex < 2) {
playerPositionIndex++;
}
} else {
// Swipe left
if (playerPositionIndex > 0) {
playerPositionIndex--;
}
}
} else {
if (deltaY < 0) {
// Swipe up
player.jump();
}
}
// Make the player move progressively to the next path
var targetX = playerPositions[playerPositionIndex];
var initialX = player.x;
var moveDuration = 30;
var moveStartTime = Date.now();
var moveInterval = LK.setInterval(function () {
var elapsed = Date.now() - moveStartTime;
var progress = elapsed / (moveDuration * 1000 / 60);
if (progress < 1) {
var easeProgress = easeInOutQuad(progress);
player.x = initialX + (targetX - initialX) * easeProgress;
} else {
player.x = targetX;
LK.clearInterval(moveInterval);
}
}, 1000 / 60);
};
// Update game every tick
game.update = function () {
updateBackgroundColor();
if (!isPlaying || isKilled) {
return;
}
};
// Initialize game
function gameInitialize() {
// Initialize arrays and variables
// Attach the background asset to the game
background = game.addChild(new Background());
background.updateForLevel(currentLevel);
// Add a series of Stripe instances to cover the bottom half of the screen
for (var i = 0; i < nbStripes; i++) {
var stripe = new Stripe();
stripe.y = i === 0 ? roadTop : stripes[i - 1].y + stripes[i - 1].stripeGraphics.height; // Position stripe under the previous one using previous stripe y and height
stripe.progress = Math.max(0, stripe.y - roadTop) / roadHeight; // Calculate progress
stripes.push(stripe);
game.addChild(stripe);
stripe.stripeGraphics.height = 1 + 400 * stripe.progress; // Adjust height based on progress
//log("Stripe ", i, " y=", stripe.y, " h=", stripe.stripeGraphics.height, " p=", stripe.progress);
}
for (var i = 0; i < stripes.length; i++) {
stripes[i].update();
}
// Create and attach decoration instances to the game
for (var i = 0; i < nbDecorations; i++) {
var newDecoration = new Decoration(i);
newDecoration.reset();
decorations.push(newDecoration);
game.addChild(newDecoration);
}
// Create and attach the road instance to the game
road = game.addChild(new Road());
road.x = 2048 / 2;
road.y = 0;
if (road) {
//road.updateForLevel(currentLevel);
}
score = 0;
scoreTxt = new Text2('0¢', {
size: 150,
fill: "#ffffff",
dropShadow: true,
dropShadowColor: "#000000",
dropShadowBlur: 5,
dropShadowDistance: 5
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
goalText = new Text2('', {
size: 150,
fill: "#ffffff",
dropShadow: true,
dropShadowColor: "#111111",
dropShadowBlur: 10,
dropShadowDistance: 10,
align: 'center',
weight: 1000
});
goalText.anchor.set(0.5, 1);
LK.gui.center.addChild(goalText);
//goalText.x = 2048 / 2;
//goalText.y = 100;
//goalText.visible = true;
LK.gui.top.addChild(scoreTxt);
coins = [];
for (var i = 0; i < baseNbCoins; i++) {
var newCoin = new Coin(i);
newCoin.reset();
newCoin.y = roadTop - i * 50;
coins.push(newCoin);
game.addChild(newCoin);
}
// Create a variable to store the current player position index
playerPositionIndex = 1;
// Create and attach obstacle instances to the game
obstacleManager = new ObstacleManager();
var numObstacles = Math.floor(Math.random() * baseNbObstacles) + 1; // Randomize number of obstacles (1 to baseNbObstacles)
for (var i = 0; i < numObstacles; i++) {
var newObstacle = new Obstacle(i);
obstacleManager.addObstacle(newObstacle);
game.addChild(newObstacle);
}
obstacleManager.resetObstacles();
game.addChild(obstacleManager);
// Create and attach the killer instance to the game
var newKiller = new Killer();
newKiller.reset();
obstacles.push(newKiller);
game.addChild(newKiller);
// Create player
player = game.addChild(new Player());
player.frame = 0;
player.x = playerPositions[playerPositionIndex]; // Start at the center position
player.y = playerBaseY;
// Create and attach the landscape instance to the game
landscape = game.addChild(new Landscape());
var startButton = game.addChild(new StartButton());
startButton.x = 2048 / 2;
startButton.y = 2732 / 4;
// TEMP DEBUG !!!
startButton.width = 100;
startButton.height = 100;
// Attach a debugMarker asset to the game at position (1000, 0)
debugMarker = game.attachAsset('debugMarker', {
anchorX: 0.5,
anchorY: 0.5
});
debugMarker.x = 1280;
debugMarker.y = roadTop;
debugTxt = new Text2('Debug Info', {
size: 50,
fill: "#ff0000"
});
debugTxt.anchor.set(1, 1); // Set anchor to the bottom right corner
LK.gui.bottomRight.addChild(debugTxt);
isPlaying = false;
}
gameInitialize();
// DEVLOG:
// Add obstacles assets switch depending on level and a goal text to inform of collect goal
Directly overhead, plumb view of a beggar heading top (we see his back).. Zenith view, directly overhead, plumb view. NOT PERSPECTIVE! Fantasy theme. Pixel art
a traffic cone. video game sprite
face view of a big start button in the shape of a dollar bill. video game style
a tree. video game style
a black garbage bag. video game style
Dollar bill. Perspective. video game sprite
perspective of a simple snake rolled up on itself.. video game sprite
Ball of dry desert bushes. video game sprite
tractor. high definition video game sprite
street ad billboard with 1 or 2 posts with "Get rich!" on it. high definition video game sprite
a dog sleeping on a street. video game sprite
desert bush. video game sprite
profile view of an empty motorcycle helmet. black with a white vertical central band and another thiner orange band on the center. NOT PERSPECTIVE!. Pixel art high definition
simple red and white magnet. video game style
gold sign with a "X" and a "2". video game style
bgMusic
Music
coin_1
Sound effect
hit_1
Sound effect
hit_2
Sound effect
hit_3
Sound effect
levelWin_1
Sound effect
car_1
Sound effect
police_1
Sound effect
ambulance_1
Sound effect
accident_1
Sound effect
killed_1
Sound effect
jump_1
Sound effect
rip_1
Sound effect
bonus_take
Sound effect
bonus_approaching
Sound effect