User prompt
undo that
User prompt
get rid of the image for when you are down (tap to get up) and die when the counter reaches zero
Code edit (1 edits merged)
Please save this source code
User prompt
Stop the game when you fall over, (stop it from moving) and make the player have to tap the screen in labeled places 5 times in 15 seconds.
User prompt
Make it so when you hit an object you don’t die, you fall over, then you wait 5 seconds before getting up and continuing. The distance also resets at this ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add the feature above
User prompt
Add a enable debugging feature in the settings, but to turn it on you have to type the developer’s name (which it will ask you to do) which is Chazlin
User prompt
Make different music depending on what game mode you are playing
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'LK.showLeaderboard();' Line Number: 408
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'storage.showLeaderboard();' Line Number: 408
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'LK.showLeaderboard();' Line Number: 407
User prompt
Add a setting bar in the menu which has an option to turn sound off, sfx off, game test codes, leaderboard, and language settings ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Make it stop in all levels from spawning obstacles across all three lanes very closely
User prompt
Make the no don’t do it etc mode actually possible to win and add in the enemies moving 4x faster than you
User prompt
Make a “No don’t do it I’m scared help” mode where the player is half the speed, and everything else is doubled. Everything is covered by a reddish colour and all the text is in welsh until the game is reloaded ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a “winning zone” where you win after reaching 1000 distance on Hard, 2000 on average Joe, and 5000 on Easy
User prompt
Add a Hard Mode where there are more obstacles, and double the enemies
User prompt
Make the easy mode button green, bigger, and make the normal mode button orange, bigger, and change the normal mode to “Average Joe”
User prompt
Make the lane rider sign at the top, huge and in an appealing font, and make the other items bigger and more spaced apart ON THE START SCREEN
User prompt
Create a start menu with an easy mode button that removes the character that chases you
User prompt
When moving lanes, make the player hit the sprite it could collide with then kill the player
User prompt
Add in a sprite that swerves all over the lanes yet slowly chases you when you get close enough and add a stopwatch to see how long you survive ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the character move a bit quicker
Code edit (1 edits merged)
Please save this source code
User prompt
Lane Rider: Bike Rush
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var EnemyChaser = Container.expand(function () {
var self = Container.call(this);
// Enemy state
self.lane = 1; // Start in middle lane
self.speed = GAME_SPEED * 0.8; // Slightly slower than player initially
self.targetX = LANE_POSITIONS[self.lane];
self.chasingPlayer = false;
self.swerveTimer = 0;
self.swerveInterval = 120; // Time between lane changes when not chasing
self.detectionRange = 500; // Distance to start chasing player
// Create enemy graphics
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF0000 // Red tint to distinguish from player
});
// Random swerving behavior
self.swerve = function () {
var newLane;
// Choose a random lane that's different from current
do {
newLane = Math.floor(Math.random() * 3);
} while (newLane === self.lane);
self.moveToLane(newLane);
};
// Chase player behavior
self.chase = function () {
// Move toward player's lane
if (self.lane < player.lane) {
self.moveToLane(self.lane + 1);
} else if (self.lane > player.lane) {
self.moveToLane(self.lane - 1);
}
};
// Move enemy to lane
self.moveToLane = function (laneIndex) {
if (laneIndex < 0 || laneIndex > 2) {
return;
}
self.lane = laneIndex;
self.targetX = LANE_POSITIONS[laneIndex];
tween.stop(self, {
x: true
});
tween(self, {
x: self.targetX
}, {
duration: 300,
easing: tween.easeOut
});
};
self.update = function () {
// Move forward
// In scared mode, enemies move 4x faster than player
if (scaredMode) {
self.y += self.speed * 4;
} else {
self.y += self.speed;
}
// Check if close enough to chase player
var distanceToPlayer = Math.abs(player.y - self.y);
self.chasingPlayer = distanceToPlayer < self.detectionRange;
// Update behavior based on proximity to player
if (self.chasingPlayer) {
// Chase every 60 frames when close (or faster in scared mode)
if (LK.ticks % (scaredMode ? 30 : 60) === 0) {
self.chase();
}
// Speed up when chasing
self.speed = Math.min(GAME_SPEED * 1.1, MAX_GAME_SPEED);
} else {
// Random swerving when not chasing
self.swerveTimer++;
if (self.swerveTimer >= self.swerveInterval) {
self.swerve();
self.swerveTimer = 0;
// Randomize next swerve interval
self.swerveInterval = 90 + Math.floor(Math.random() * 90);
}
// Normal speed when not chasing
self.speed = GAME_SPEED * 0.8;
}
// Reset enemy if it goes off screen
if (self.y > 2732 + graphics.height) {
self.y = -300;
self.swerveTimer = 0;
}
};
return self;
});
var FallenRecoveryGame = Container.expand(function () {
var self = Container.call(this);
// Container for tap targets
var targetsContainer = new Container();
self.addChild(targetsContainer);
// Game state
self.tapCount = 0;
self.totalTapsNeeded = 5;
self.timeRemaining = 15; // 15 seconds to complete
self.isActive = false;
self.timeoutId = null;
// Create background panel
var panel = LK.getAsset('construction', {
anchorX: 0.5,
anchorY: 0.5,
width: 1800,
height: 1000,
tint: 0x333333
});
self.addChild(panel);
// Create title text
var titleText = new Text2('TAP TO GET UP!', {
size: 100,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0);
titleText.y = -400;
self.addChild(titleText);
// Create progress text
var progressText = new Text2('0/' + self.totalTapsNeeded, {
size: 80,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0);
progressText.y = -300;
self.addChild(progressText);
// Create timer text
var timerText = new Text2('Time: 15.0s', {
size: 70,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
timerText.y = -200;
self.addChild(timerText);
// Create tap targets
function createTapTargets() {
// Clear existing targets
while (targetsContainer.children.length > 0) {
targetsContainer.removeChildAt(0);
}
// Create new random tap target
var tapTarget = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 200,
tint: 0x00CC00
});
// Position randomly in the container
tapTarget.x = Math.random() * 1400 - 700; // Range: -700 to 700
tapTarget.y = Math.random() * 600 - 100; // Range: -100 to 500
// Add label
var tapLabel = new Text2('TAP', {
size: 60,
fill: 0xFFFFFF
});
tapLabel.anchor.set(0.5, 0.5);
tapLabel.x = tapTarget.x;
tapLabel.y = tapTarget.y;
// Make target interactive
tapTarget.interactive = true;
tapLabel.interactive = true;
// Handle tap
tapTarget.down = tapLabel.down = function () {
self.handleTap();
};
// Add to container
targetsContainer.addChild(tapTarget);
targetsContainer.addChild(tapLabel);
}
// Handle tap on target
self.handleTap = function () {
if (!self.isActive) {
return;
}
self.tapCount++;
progressText.setText(self.tapCount + '/' + self.totalTapsNeeded);
// Play sound effect
if (settingsMenu && settingsMenu.isSfxEnabled()) {
LK.getSound('powerup').play();
}
// Check if player has tapped enough times
if (self.tapCount >= self.totalTapsNeeded) {
self.success();
} else {
// Create new tap target
createTapTargets();
}
};
// Start recovery game
self.start = function () {
self.isActive = true;
self.tapCount = 0;
self.timeRemaining = 15;
// Update UI
progressText.setText('0/' + self.totalTapsNeeded);
timerText.setText('Time: 15.0s');
// Create initial tap target
createTapTargets();
// Start timer
self.updateTimer();
};
// Update timer
self.updateTimer = function () {
if (!self.isActive) {
return;
}
self.timeRemaining -= 0.1;
timerText.setText('Time: ' + self.timeRemaining.toFixed(1) + 's');
// Check for time out
if (self.timeRemaining <= 0) {
self.fail();
return;
}
// Continue timer
self.timeoutId = LK.setTimeout(self.updateTimer, 100);
};
// Success - player tapped enough times
self.success = function () {
self.isActive = false;
// Clear timer
if (self.timeoutId !== null) {
LK.clearTimeout(self.timeoutId);
self.timeoutId = null;
}
// Hide this container
self.visible = false;
// Tell the game the player succeeded
if (self.onSuccess) {
self.onSuccess();
}
};
// Fail - player ran out of time
self.fail = function () {
self.isActive = false;
// Show game over immediately instead of restarting
LK.showGameOver();
};
// Clean up
self.cleanup = function () {
if (self.timeoutId !== null) {
LK.clearTimeout(self.timeoutId);
self.timeoutId = null;
}
self.isActive = false;
};
// Initially hidden
self.visible = false;
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'car';
self.lane = Math.floor(Math.random() * 3); // Random lane (0, 1, 2)
self.speed = GAME_SPEED;
var assetType;
switch (self.type) {
case 'car':
assetType = 'car';
break;
case 'pedestrian':
assetType = 'pedestrian';
break;
case 'pothole':
assetType = 'pothole';
break;
case 'construction':
assetType = 'construction';
break;
default:
assetType = 'car';
}
var graphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.y += self.speed;
// Mark for removal if off screen
if (self.y > 2732 + graphics.height) {
self.markedForRemoval = true;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Player state
self.lane = 1; // Middle lane
self.isInvincible = false;
self.invincibleTimer = null;
self.isFallen = false;
self.fallTimer = null;
// Fall over animation
self.fallOver = function () {
if (self.isFallen) {
return;
} // Already fallen
self.isFallen = true;
// Stop any ongoing tweens
tween.stop(self, {
rotation: true
});
// Play fall animation
tween(playerGraphics, {
rotation: Math.PI / 2 // 90 degrees - fall on side
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Show game over immediately
LK.showGameOver();
}
});
};
// Get back up animation
self.getBackUp = function () {
self.isFallen = false;
if (self.fallTimer) {
LK.clearTimeout(self.fallTimer);
self.fallTimer = null;
}
// Hide and clean up recovery game if it exists
if (recoveryGame) {
recoveryGame.visible = false;
recoveryGame.cleanup();
}
// Play get back up animation
tween(playerGraphics, {
rotation: 0 // Upright position
}, {
duration: 300,
easing: tween.easeOut
});
};
// Move player to lane
self.moveToLane = function (laneIndex) {
if (laneIndex < 0 || laneIndex > 2 || self.isFallen) {
return;
}
self.lane = laneIndex;
var targetX = LANE_POSITIONS[laneIndex];
tween.stop(self, {
x: true
});
tween(self, {
x: targetX
}, {
duration: self.moveSpeed || 150,
// Use moveSpeed if set (for scared mode)
easing: tween.easeOut
});
};
// Make player invincible for a duration
self.setInvincible = function (duration) {
self.isInvincible = true;
playerGraphics.tint = 0x2ECC71; // Green tint
if (self.invincibleTimer) {
LK.clearTimeout(self.invincibleTimer);
}
self.invincibleTimer = LK.setTimeout(function () {
self.isInvincible = false;
playerGraphics.tint = 0xFFFFFF; // Reset tint
}, duration);
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
self.lane = Math.floor(Math.random() * 3); // Random lane (0, 1, 2)
self.speed = GAME_SPEED;
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Add pulsing animation
function pulse() {
tween(graphics, {
scale: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(graphics, {
scale: 1.0
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulse
});
}
});
}
pulse();
self.update = function () {
self.y += self.speed;
// Mark for removal if off screen
if (self.y > 2732 + graphics.height) {
self.markedForRemoval = true;
}
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
// Load settings from storage (with defaults)
var settings = {
sound: storage.sound !== undefined ? storage.sound : true,
sfx: storage.sfx !== undefined ? storage.sfx : true,
language: storage.language || 'en',
testCodes: storage.testCodes || false,
debug: storage.debug || false
};
// Create background panel
var panel = LK.getAsset('construction', {
anchorX: 0.5,
anchorY: 0.5,
width: 1200,
height: 1100,
tint: 0x333333
});
self.addChild(panel);
// Create title
var title = new Text2('SETTINGS', {
size: 100,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
title.anchor.set(0.5, 0.5);
title.y = -400;
self.addChild(title);
// Helper function to create toggle buttons
function createToggleButton(labelText, _isOn, y, callback) {
var container = new Container();
container.y = y;
self.addChild(container);
// Label
var label = new Text2(labelText, {
size: 70,
fill: 0xFFFFFF
});
label.anchor.set(0, 0.5);
label.x = -450;
container.addChild(label);
// Toggle button background
var toggleBg = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 200,
height: 100,
tint: 0x666666
});
toggleBg.x = 350;
container.addChild(toggleBg);
// Toggle indicator
var toggleIndicator = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
width: 80,
height: 80,
tint: _isOn ? 0x00CC00 : 0xCC0000
});
toggleIndicator.x = 350 + (_isOn ? 40 : -40);
container.addChild(toggleIndicator);
// Status text
var statusText = new Text2(_isOn ? "ON" : "OFF", {
size: 50,
fill: 0xFFFFFF
});
statusText.anchor.set(0.5, 0.5);
statusText.x = 350;
container.addChild(statusText);
// Make toggle interactive
toggleBg.interactive = true;
toggleIndicator.interactive = true;
statusText.interactive = true;
// Toggle functionality
function toggle() {
// If this is test codes toggle or debug toggle and turning it on, verify developer name
if ((labelText === "Test Codes" || labelText === "Debug Mode") && !_isOn) {
var updateInput = function updateInput(key) {
if (key === "DEL") {
currentInput = currentInput.slice(0, -1);
} else {
currentInput += key;
}
inputText.setText(currentInput);
}; // Function to check developer name and close dialog
var checkAndClose = function checkAndClose() {
if (currentInput.toLowerCase() === "chazlin") {
// Correct developer name
inputContainer.destroy();
// Toggle on
_isOn = true;
toggleIndicator.tint = 0x00CC00;
toggleIndicator.x = 350 + 40;
statusText.setText("ON");
if (callback) {
callback(true);
}
} else {
// Wrong developer name - shake dialog
tween(dialogBg, {
x: 10
}, {
duration: 50,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(dialogBg, {
x: -10
}, {
duration: 50,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(dialogBg, {
x: 0
}, {
duration: 50,
easing: tween.easeInOut
});
}
});
}
});
// Clear input
currentInput = "";
inputText.setText("");
}
};
// Create input dialog for developer name
var inputContainer = new Container();
inputContainer.x = 0;
inputContainer.y = 0;
self.addChild(inputContainer);
// Dialog background
var dialogBg = LK.getAsset('construction', {
anchorX: 0.5,
anchorY: 0.5,
width: 800,
height: 400,
tint: 0x444444
});
inputContainer.addChild(dialogBg);
// Prompt text
var promptText = new Text2("Enter developer name:", {
size: 60,
fill: 0xFFFFFF
});
promptText.anchor.set(0.5, 0.5);
promptText.y = -100;
inputContainer.addChild(promptText);
// Input field background
var inputFieldBg = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 80,
tint: 0x666666
});
inputFieldBg.y = 0;
inputContainer.addChild(inputFieldBg);
// Input text (initially empty)
var inputText = new Text2("", {
size: 50,
fill: 0xFFFFFF
});
inputText.anchor.set(0.5, 0.5);
inputText.y = 0;
inputContainer.addChild(inputText);
// Create keyboard buttons
var keys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
var keyButtons = [];
var currentInput = "";
// Function to update input text
for (var i = 0; i < keys.length; i++) {
var keyButton = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
width: 40,
height: 40,
tint: 0x888888
});
var keyLabel = new Text2(keys[i], {
size: 25,
fill: 0xFFFFFF
});
keyLabel.anchor.set(0.5, 0.5);
// Position keys in rows
var row = Math.floor(i / 13);
var col = i % 13;
keyButton.x = (col - 6) * 45;
keyButton.y = 100 + row * 45;
keyLabel.x = keyButton.x;
keyLabel.y = keyButton.y;
inputContainer.addChild(keyButton);
inputContainer.addChild(keyLabel);
// Make button interactive
keyButton.interactive = true;
keyLabel.interactive = true;
// Capture current key for closure
(function (currentKey) {
keyButton.down = keyLabel.down = function () {
updateInput(currentKey);
};
})(keys[i]);
}
// Add delete button
var delButton = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 100,
height: 40,
tint: 0xCC4444
});
delButton.x = 230;
delButton.y = 100;
inputContainer.addChild(delButton);
var delLabel = new Text2("DEL", {
size: 25,
fill: 0xFFFFFF
});
delLabel.anchor.set(0.5, 0.5);
delLabel.x = delButton.x;
delLabel.y = delButton.y;
inputContainer.addChild(delLabel);
delButton.interactive = true;
delLabel.interactive = true;
delButton.down = delLabel.down = function () {
updateInput("DEL");
};
// Add submit button
var submitButton = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 60,
tint: 0x44CC44
});
submitButton.y = 180;
inputContainer.addChild(submitButton);
var submitLabel = new Text2("Submit", {
size: 30,
fill: 0xFFFFFF
});
submitLabel.anchor.set(0.5, 0.5);
submitLabel.y = submitButton.y;
inputContainer.addChild(submitLabel);
submitButton.interactive = true;
submitLabel.interactive = true;
submitButton.down = submitLabel.down = checkAndClose;
// Add cancel button
var cancelButton = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 150,
height: 60,
tint: 0xCC4444
});
cancelButton.x = -200;
cancelButton.y = 180;
inputContainer.addChild(cancelButton);
var cancelLabel = new Text2("Cancel", {
size: 30,
fill: 0xFFFFFF
});
cancelLabel.anchor.set(0.5, 0.5);
cancelLabel.x = cancelButton.x;
cancelLabel.y = cancelButton.y;
inputContainer.addChild(cancelLabel);
cancelButton.interactive = true;
cancelLabel.interactive = true;
cancelButton.down = cancelLabel.down = function () {
inputContainer.destroy();
};
} else {
// Normal toggle behavior for other settings
_isOn = !_isOn;
toggleIndicator.tint = _isOn ? 0x00CC00 : 0xCC0000;
toggleIndicator.x = 350 + (_isOn ? 40 : -40);
statusText.setText(_isOn ? "ON" : "OFF");
if (callback) {
callback(_isOn);
}
}
}
toggleBg.down = toggleIndicator.down = statusText.down = toggle;
return {
container: container,
toggle: toggle,
isOn: function isOn() {
return _isOn;
}
};
}
// Helper function to create language selector
function createLanguageSelector(y) {
var container = new Container();
container.y = y;
self.addChild(container);
// Label
var label = new Text2("Language", {
size: 70,
fill: 0xFFFFFF
});
label.anchor.set(0, 0.5);
label.x = -450;
container.addChild(label);
// Language options
var languages = ["English", "Welsh"];
var currentLang = settings.language === "cy" ? 1 : 0;
// Create language button
var langButton = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 300,
height: 100,
tint: 0x4488FF
});
langButton.x = 350;
container.addChild(langButton);
// Language text
var langText = new Text2(languages[currentLang], {
size: 50,
fill: 0xFFFFFF
});
langText.anchor.set(0.5, 0.5);
langText.x = 350;
container.addChild(langText);
// Make language button interactive
langButton.interactive = true;
langText.interactive = true;
// Toggle functionality
function toggle() {
currentLang = (currentLang + 1) % languages.length;
langText.setText(languages[currentLang]);
settings.language = currentLang === 0 ? "en" : "cy";
storage.language = settings.language;
}
langButton.down = langText.down = toggle;
return container;
}
// Create setting toggles
var soundToggle = createToggleButton("Music", settings.sound, -300, function (isOn) {
settings.sound = isOn;
storage.sound = isOn;
if (isOn) {
LK.playMusic('gameMusic');
} else {
LK.stopMusic();
}
});
var sfxToggle = createToggleButton("Sound Effects", settings.sfx, -200, function (isOn) {
settings.sfx = isOn;
storage.sfx = isOn;
});
var testCodesToggle = createToggleButton("Test Codes", settings.testCodes, -100, function (isOn) {
settings.testCodes = isOn;
storage.testCodes = isOn;
});
// Add debug toggle
var debugToggle = createToggleButton("Debug Mode", settings.debug || false, 0, function (isOn) {
settings.debug = isOn;
storage.debug = isOn;
});
// Create language selector
var languageSelector = createLanguageSelector(0);
// Create leaderboard button
var leaderboardBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 600,
height: 120,
tint: 0x4444FF
});
leaderboardBtn.y = 100;
self.addChild(leaderboardBtn);
var leaderboardText = new Text2("Leaderboard", {
size: 70,
fill: 0xFFFFFF
});
leaderboardText.anchor.set(0.5, 0.5);
leaderboardText.y = 100;
self.addChild(leaderboardText);
// Leaderboard button functionality
leaderboardBtn.interactive = true;
leaderboardText.interactive = true;
leaderboardBtn.down = leaderboardText.down = function () {
// Using LK.showLeaderboard to display the leaderboard (corrected syntax)
LK.showLeaderboard();
};
// Create back button
var backBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 300,
height: 120,
tint: 0xCC4444
});
backBtn.y = 250;
self.addChild(backBtn);
var backText = new Text2("Back", {
size: 70,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.y = 250;
self.addChild(backText);
// Back button functionality
backBtn.interactive = true;
backText.interactive = true;
backBtn.down = backText.down = function () {
self.visible = false;
startMenu.visible = true;
};
// Public method to apply settings
self.applySettings = function () {
// Apply sound settings
if (!settings.sound) {
LK.stopMusic();
}
};
// Method to check if SFX is enabled
self.isSfxEnabled = function () {
return settings.sfx;
};
return self;
});
var StartMenu = Container.expand(function () {
var self = Container.call(this);
// Create background panel
var panel = LK.getAsset('construction', {
anchorX: 0.5,
anchorY: 0.5,
width: 1200,
height: 1000,
// Increased height for settings button
tint: 0x333333
});
self.addChild(panel);
// Create title
var title = new Text2('LANE RIDER', {
size: 180,
fill: 0xFFFFFF,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
title.anchor.set(0.5, 0.5);
title.y = -250; // Adjusted position
self.addChild(title);
// Create normal mode button (now "Average Joe")
var normalBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 700,
height: 180,
tint: 0xFF8C00
});
normalBtn.y = 0; // Adjusted position
self.addChild(normalBtn);
var normalText = new Text2('Average Joe', {
size: 90,
fill: 0xFFFFFF
});
normalText.anchor.set(0.5, 0.5);
normalText.y = 0; // Adjusted position
self.addChild(normalText);
// Create easy mode button
var easyBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 700,
height: 180,
tint: 0x00CC00
});
easyBtn.y = 200; // Adjusted position
self.addChild(easyBtn);
var easyText = new Text2('Easy Mode', {
size: 90,
fill: 0xFFFFFF
});
easyText.anchor.set(0.5, 0.5);
easyText.y = 200; // Adjusted position
self.addChild(easyText);
// Create hard mode button
var hardBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 700,
height: 180,
tint: 0xFF0000
});
hardBtn.y = 400; // Adjusted position
self.addChild(hardBtn);
var hardText = new Text2('Hard Mode', {
size: 90,
fill: 0xFFFFFF
});
hardText.anchor.set(0.5, 0.5);
hardText.y = 400; // Adjusted position
self.addChild(hardText);
// Create scared mode button
var scaredBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 700,
height: 180,
tint: 0x800080 // Purple tint
});
scaredBtn.y = 600; // Adjusted position
self.addChild(scaredBtn);
var scaredText = new Text2('NO DONT DO IT IM SCARED', {
size: 50,
fill: 0xFFFFFF
});
scaredText.anchor.set(0.5, 0.5);
scaredText.y = 600; // Adjusted position
self.addChild(scaredText);
// Create settings button
var settingsBtn = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: 700,
height: 180,
tint: 0x00AAAA // Teal color
});
settingsBtn.y = 800; // Position below other buttons
self.addChild(settingsBtn);
var settingsText = new Text2('Settings', {
size: 90,
fill: 0xFFFFFF
});
settingsText.anchor.set(0.5, 0.5);
settingsText.y = 800;
self.addChild(settingsText);
// Add interaction for normal mode
normalBtn.interactive = true;
normalBtn.down = normalText.down = function () {
self.visible = false;
easyMode = false;
hardMode = false;
startGame();
};
// Add interaction for easy mode
easyBtn.interactive = true;
easyBtn.down = easyText.down = function () {
self.visible = false;
easyMode = true;
hardMode = false;
startGame();
};
// Add interaction for hard mode
hardBtn.interactive = true;
hardBtn.down = hardText.down = function () {
self.visible = false;
easyMode = false;
hardMode = true;
scaredMode = false;
startGame();
};
// Add interaction for scared mode
scaredBtn.interactive = true;
scaredBtn.down = scaredText.down = function () {
self.visible = false;
easyMode = false;
hardMode = false;
scaredMode = true;
startGame();
};
// Add interaction for settings button
settingsBtn.interactive = true;
settingsText.interactive = true;
settingsBtn.down = settingsText.down = function () {
self.visible = false;
settingsMenu.visible = true;
};
return self;
});
var WinningZone = Container.expand(function () {
var self = Container.call(this);
self.width = 2048;
self.height = 300;
// Create background for winning zone
var background = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
width: self.width,
height: self.height,
tint: 0xFFD700 // Gold color
});
self.addChild(background);
// Create winning text
var winText = new Text2(scaredMode ? welshTranslations['FINISH LINE'] : 'FINISH LINE', {
size: 100,
fill: 0x000000
});
winText.anchor.set(0.5, 0.5);
self.addChild(winText);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x7DCEA0 // Greenish background
});
/****
* Game Code
****/
// Constants
var LANE_WIDTH = 2048 / 3;
var LANE_POSITIONS = [LANE_WIDTH / 2, LANE_WIDTH + LANE_WIDTH / 2, 2 * LANE_WIDTH + LANE_WIDTH / 2];
var MIN_OBSTACLE_INTERVAL = 60;
var MAX_OBSTACLE_INTERVAL = 120;
var GAME_SPEED = 6;
var MAX_GAME_SPEED = 15;
var SPEED_INCREASE_RATE = 0.0005;
var OBSTACLE_TYPES = ['car', 'pedestrian', 'pothole', 'construction'];
var POWERUP_CHANCE = 0.1; // 10% chance per obstacle spawn
var INVINCIBLE_DURATION = 5000; // 5 seconds (base value)
// Game variables
var player;
var enemy;
var secondEnemy; // Second enemy for hard mode
var obstacles = [];
var powerups = [];
var lanes = [];
var obstacleTimer = 0;
var nextObstacleTime = 100;
var distance = 0;
var highScore = storage.highScore || 0;
var isGameStarted = false;
var isGamePaused = false;
var gameStartTime = 0;
var currentTime = 0;
var easyMode = false;
var hardMode = false;
var scaredMode = false; // New scared mode
var startMenu;
var settingsMenu;
var winningZone;
var winningDistance = 0; // Distance required to win based on difficulty
var redOverlay; // Reddish overlay for scared mode
var recoveryGame; // Recovery mini-game instance
// Welsh translations for scared mode
var welshTranslations = {
'Distance': 'Pellter',
'Best': 'Gorau',
'Time': 'Amser',
'FINISH LINE': 'LLINELL DERFYN',
'Easy Mode': 'Modd Hawdd',
'Average Joe': 'Joe Cyffredin',
'Hard Mode': 'Modd Caled',
'LANE RIDER': 'RIDER LÔN',
'NO DONT DO IT IM SCARED': 'PEIDIWCH Â GWNEUD OFNAIS WYFI'
};
// GUI elements
var scoreTxt;
var highScoreTxt;
var timeTxt;
var startInstructions;
// Initialize game UI
function initUI() {
// Create score display
scoreTxt = new Text2('Distance: 0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false;
LK.gui.top.addChild(scoreTxt);
// Create high score display
highScoreTxt = new Text2('Best: ' + highScore, {
size: 50,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(0.5, 0);
highScoreTxt.y = 80;
highScoreTxt.visible = false;
LK.gui.top.addChild(highScoreTxt);
// Create stopwatch display
timeTxt = new Text2('Time: 0.0s', {
size: 50,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
timeTxt.y = 150;
timeTxt.visible = false;
LK.gui.top.addChild(timeTxt);
// Create start instructions
startInstructions = new Text2('Tap to start\nSwipe left/right to change lanes', {
size: 80,
fill: 0xFFFFFF
});
startInstructions.anchor.set(0.5, 0.5);
startInstructions.visible = false;
LK.gui.center.addChild(startInstructions);
}
// Initialize game world
function initWorld() {
// Create the three lanes
for (var i = 0; i < 3; i++) {
var lane = LK.getAsset('lane', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
width: 20,
height: 2732
});
lane.x = (i + 1) * LANE_WIDTH;
game.addChild(lane);
lanes.push(lane);
}
// Create player
player = new Player();
player.x = LANE_POSITIONS[1]; // Start in middle lane
player.y = 2732 - 300; // Position near bottom of screen
game.addChild(player);
// Hide player initially
player.visible = false;
// Create enemy chaser
enemy = new EnemyChaser();
enemy.x = LANE_POSITIONS[1]; // Start in middle lane
enemy.y = -500; // Start above screen
game.addChild(enemy);
// Hide enemy initially
enemy.visible = false;
// Create second enemy chaser for hard mode
secondEnemy = new EnemyChaser();
secondEnemy.x = LANE_POSITIONS[0]; // Start in left lane
secondEnemy.y = -800; // Start above screen but offset from first enemy
game.addChild(secondEnemy);
// Hide second enemy initially
secondEnemy.visible = false;
// Create and display start menu
startMenu = new StartMenu();
startMenu.x = 2048 / 2;
startMenu.y = 2732 / 2;
game.addChild(startMenu);
// Create settings menu (hidden initially)
settingsMenu = new SettingsMenu();
settingsMenu.x = 2048 / 2;
settingsMenu.y = 2732 / 2;
settingsMenu.visible = false;
game.addChild(settingsMenu);
}
// Start the game
function startGame() {
isGameStarted = true;
player.visible = true;
// Show appropriate enemies based on game mode
enemy.visible = !easyMode && !scaredMode;
secondEnemy.visible = hardMode;
startInstructions.visible = true;
// Show UI elements
scoreTxt.visible = true;
highScoreTxt.visible = true;
timeTxt.visible = true;
// Reset game state
obstacles.forEach(function (obstacle) {
obstacle.destroy();
});
obstacles = [];
powerups.forEach(function (powerup) {
powerup.destroy();
});
powerups = [];
distance = 0;
// Handle scared mode speeds
if (scaredMode) {
GAME_SPEED = 3; // Half the normal speed
player.moveSpeed = 300; // Double the lane change time (slower movement)
// Make player start with invincibility to give them a better chance
player.setInvincible(10000); // 10 seconds of initial invincibility
// Create red overlay if it doesn't exist
if (!redOverlay) {
redOverlay = LK.getAsset('lane', {
anchorX: 0,
anchorY: 0,
width: 2048,
height: 2732,
tint: 0xFF0000
});
redOverlay.alpha = 0.3;
game.addChild(redOverlay);
} else {
redOverlay.visible = true;
}
// Translate text to Welsh for scared mode
scoreTxt.setText(welshTranslations['Distance'] + ': 0');
highScoreTxt.setText(welshTranslations['Best'] + ': ' + highScore);
timeTxt.setText(welshTranslations['Time'] + ': 0.0s');
startInstructions.setText(welshTranslations['Tap to start'] + '\n' + welshTranslations['Swipe left/right to change lanes']);
} else {
GAME_SPEED = hardMode ? 8 : 6; // Higher starting speed in hard mode
player.moveSpeed = 150; // Normal movement speed
// Hide red overlay if it exists
if (redOverlay) {
redOverlay.visible = false;
}
// Reset text to English
scoreTxt.setText('Distance: 0');
highScoreTxt.setText('Best: ' + highScore);
timeTxt.setText('Time: 0.0s');
startInstructions.setText('Tap to start\nSwipe left/right to change lanes');
}
obstacleTimer = 0;
nextObstacleTime = hardMode ? 70 : scaredMode ? 200 : 100; // Adjust obstacle intervals
// Set winning distance based on difficulty
if (hardMode) {
winningDistance = 1000;
} else if (easyMode) {
winningDistance = 5000;
} else if (scaredMode) {
winningDistance = 3000; // Scared mode winning distance
} else {
winningDistance = 2000; // Average Joe mode
}
// Reset enemy positions
enemy.y = -500;
enemy.lane = 1;
enemy.x = LANE_POSITIONS[1];
enemy.swerveTimer = 0;
// Reset second enemy
secondEnemy.y = -800;
secondEnemy.lane = 0;
secondEnemy.x = LANE_POSITIONS[0];
secondEnemy.swerveTimer = 50; // Offset timer so enemies don't swerve at the same time
// Reset stopwatch
gameStartTime = Date.now();
currentTime = 0;
// Play different background music based on game mode if enabled
if (storage.sound !== false) {
if (scaredMode) {
// Play eerie music for scared mode
LK.playMusic('scaredMusic', {
fade: {
start: 0,
end: 0.5,
duration: 500
}
});
} else if (hardMode) {
// Play intense music for hard mode
LK.playMusic('hardMusic', {
fade: {
start: 0,
end: 1,
duration: 300
}
});
} else if (easyMode) {
// Play relaxed music for easy mode
LK.playMusic('easyMusic', {
fade: {
start: 0,
end: 0.7,
duration: 400
}
});
} else {
// Play standard music for normal/average joe mode
LK.playMusic('gameMusic');
}
}
// Apply settings
settingsMenu.applySettings();
}
// Spawn a new obstacle
function spawnObstacle() {
// Choose random obstacle type
var type = OBSTACLE_TYPES[Math.floor(Math.random() * OBSTACLE_TYPES.length)];
var obstacle = new Obstacle(type);
// Ensure obstacle is in a valid lane
obstacle.x = LANE_POSITIONS[obstacle.lane];
obstacle.y = -200; // Start above screen
obstacles.push(obstacle);
game.addChild(obstacle);
// In scared mode, spawn more obstacles
if (scaredMode && Math.random() < 0.8) {
// 80% chance of additional obstacle in scared mode
for (var i = 0; i < 2; i++) {
// Two more obstacles
var extraType = OBSTACLE_TYPES[Math.floor(Math.random() * OBSTACLE_TYPES.length)];
var extraObstacle = new Obstacle(extraType);
// Try to find an available lane
var freeLanes = [0, 1, 2].filter(function (lane) {
return !obstacles.some(function (obs) {
return obs.lane === lane && Math.abs(obs.y + 200) < 300;
});
});
if (freeLanes.length > 0) {
extraObstacle.lane = freeLanes[Math.floor(Math.random() * freeLanes.length)];
extraObstacle.x = LANE_POSITIONS[extraObstacle.lane];
extraObstacle.y = -200 - i * 150; // Stagger obstacles
obstacles.push(extraObstacle);
game.addChild(extraObstacle);
}
}
}
// In hard mode, possibly spawn a second obstacle in a different lane
else if (hardMode && Math.random() < 0.6) {
// 60% chance of additional obstacle
var secondType = OBSTACLE_TYPES[Math.floor(Math.random() * OBSTACLE_TYPES.length)];
var secondObstacle = new Obstacle(secondType);
// Make sure it's in a different lane
do {
secondObstacle.lane = Math.floor(Math.random() * 3);
} while (secondObstacle.lane === obstacle.lane);
secondObstacle.x = LANE_POSITIONS[secondObstacle.lane];
secondObstacle.y = -350; // Offset from first obstacle
obstacles.push(secondObstacle);
game.addChild(secondObstacle);
}
// Possibly spawn a power-up
if (Math.random() < (scaredMode ? POWERUP_CHANCE * 2 : POWERUP_CHANCE)) {
// 2x more powerups in scared mode
spawnPowerUp();
}
// Set next obstacle spawn time
nextObstacleTime = MIN_OBSTACLE_INTERVAL + Math.floor(Math.random() * (MAX_OBSTACLE_INTERVAL - MIN_OBSTACLE_INTERVAL));
// Reduce spawn interval as game progresses
nextObstacleTime = Math.max(nextObstacleTime * (1 - distance / 50000), MIN_OBSTACLE_INTERVAL);
// In scared mode, increase obstacle spawn time
if (scaredMode) {
nextObstacleTime = Math.floor(nextObstacleTime * 2); // Double the time between obstacles
}
// In hard mode, reduce obstacle spawn time further
else if (hardMode) {
nextObstacleTime = Math.floor(nextObstacleTime * 0.7);
}
}
// Spawn a power-up
function spawnPowerUp() {
var powerup = new PowerUp();
// Make sure power-up is not in same lane as last obstacle
var lastObstacle = obstacles[obstacles.length - 1];
do {
powerup.lane = Math.floor(Math.random() * 3);
} while (powerup.lane === lastObstacle.lane);
powerup.x = LANE_POSITIONS[powerup.lane];
powerup.y = -500; // Start above screen, after the obstacle
powerups.push(powerup);
game.addChild(powerup);
}
// Check collisions between player and obstacles/powerups
function checkCollisions() {
// Check obstacle collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (player.lane === obstacle.lane && Math.abs(player.y - obstacle.y) < 100 && !player.isInvincible && !player.isFallen) {
// Collision detected - Play crash sound
if (settingsMenu.isSfxEnabled()) {
LK.getSound('crash').play();
}
// Flash screen to indicate collision
LK.effects.flashScreen(0xFF0000, 500);
// Reset distance counter
distance = 0;
scoreTxt.setText(scaredMode ? welshTranslations['Distance'] + ': 0' : 'Distance: 0');
// Make player fall over
player.fallOver();
return;
}
}
// Check enemy collision (skip in easy mode)
if (!easyMode && player.lane === enemy.lane && Math.abs(player.y - enemy.y) < 100 && !player.isInvincible && !player.isFallen) {
// Collision detected - Play crash sound
if (settingsMenu.isSfxEnabled()) {
LK.getSound('crash').play();
}
// Flash screen to indicate collision
LK.effects.flashScreen(0xFF0000, 500);
// Reset distance counter
distance = 0;
scoreTxt.setText(scaredMode ? welshTranslations['Distance'] + ': 0' : 'Distance: 0');
// Make player fall over
player.fallOver();
return;
}
// Check second enemy collision (hard mode only)
if (hardMode && player.lane === secondEnemy.lane && Math.abs(player.y - secondEnemy.y) < 100 && !player.isInvincible && !player.isFallen) {
// Collision detected - Play crash sound
if (settingsMenu.isSfxEnabled()) {
LK.getSound('crash').play();
}
// Flash screen to indicate collision
LK.effects.flashScreen(0xFF0000, 500);
// Reset distance counter
distance = 0;
scoreTxt.setText(scaredMode ? welshTranslations['Distance'] + ': 0' : 'Distance: 0');
// Make player fall over
player.fallOver();
return;
}
// Check power-up collisions
for (var j = powerups.length - 1; j >= 0; j--) {
var powerup = powerups[j];
if (player.lane === powerup.lane && Math.abs(player.y - powerup.y) < 100) {
// Collect power-up
if (settingsMenu.isSfxEnabled()) {
LK.getSound('powerup').play();
}
// Apply power-up effect (invincibility) - longer in scared mode
player.setInvincible(scaredMode ? INVINCIBLE_DURATION * 3 : INVINCIBLE_DURATION); // 3x longer invincibility in scared mode
// Remove power-up
powerup.destroy();
powerups.splice(j, 1);
}
}
}
// Handle touch events for swiping
var touchStartX = 0;
game.down = function (x, y) {
if (!isGameStarted) {
return;
}
touchStartX = x;
};
game.up = function (x, y) {
if (!isGameStarted) {
return;
}
var swipeDistance = x - touchStartX;
// Determine swipe direction and move player
if (Math.abs(swipeDistance) > 50) {
// Minimum swipe distance threshold
if (swipeDistance > 0) {
// Swipe right
player.moveToLane(Math.min(player.lane + 1, 2));
} else {
// Swipe left
player.moveToLane(Math.max(player.lane - 1, 0));
}
}
};
// Main game update loop
game.update = function () {
if (!isGameStarted || isGamePaused) {
return;
}
// Update stopwatch
currentTime = (Date.now() - gameStartTime) / 1000;
if (scaredMode) {
timeTxt.setText(welshTranslations['Time'] + ': ' + currentTime.toFixed(1) + 's');
// Increment distance at half the rate in scared mode
distance += GAME_SPEED / 20;
scoreTxt.setText(welshTranslations['Distance'] + ': ' + Math.floor(distance));
} else {
timeTxt.setText('Time: ' + currentTime.toFixed(1) + 's');
// Normal distance increment
distance += GAME_SPEED / 10;
scoreTxt.setText('Distance: ' + Math.floor(distance));
}
// Check for win condition
if (distance >= winningDistance) {
// Player has reached the required distance, show win
LK.showYouWin();
// Update high score if needed
if (distance > highScore) {
highScore = Math.floor(distance);
storage.highScore = highScore;
highScoreTxt.setText('Best: ' + highScore);
}
return;
}
// Display winning zone when approaching the finish
if (distance >= (scaredMode ? winningDistance - 1000 : winningDistance - 500) && !winningZone) {
winningZone = new WinningZone();
winningZone.x = 2048 / 2;
winningZone.y = -300; // Start off-screen
game.addChild(winningZone);
}
// Move winning zone toward player as they approach finish
if (winningZone) {
winningZone.y += GAME_SPEED;
}
// Gradually increase game speed
GAME_SPEED = Math.min(GAME_SPEED + SPEED_INCREASE_RATE, MAX_GAME_SPEED);
// Spawn obstacles
obstacleTimer++;
if (obstacleTimer >= nextObstacleTime) {
spawnObstacle();
obstacleTimer = 0;
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.speed = scaredMode ? GAME_SPEED * 2 : GAME_SPEED; // Double speed in scared mode
// Remove obstacles marked for removal
if (obstacle.markedForRemoval) {
obstacle.destroy();
obstacles.splice(i, 1);
}
}
// Update power-ups
for (var j = powerups.length - 1; j >= 0; j--) {
var powerup = powerups[j];
powerup.speed = scaredMode ? GAME_SPEED * 2 : GAME_SPEED; // Double speed in scared mode
// Remove power-ups marked for removal
if (powerup.markedForRemoval) {
powerup.destroy();
powerups.splice(j, 1);
}
}
// Update enemy chasers (based on game mode)
if (!easyMode) {
enemy.update();
// Update second enemy in hard mode
if (hardMode) {
secondEnemy.update();
}
}
// Check for collisions
checkCollisions();
};
// Initialize UI and game world
initUI();
initWorld(); ===================================================================
--- original.js
+++ change.js
@@ -241,15 +241,10 @@
};
// Fail - player ran out of time
self.fail = function () {
self.isActive = false;
- // Show failure message
- progressText.setText('FAILED!');
- // Wait a moment, then try again
- LK.setTimeout(function () {
- // Reset and restart
- self.start();
- }, 1000);
+ // Show game over immediately instead of restarting
+ LK.showGameOver();
};
// Clean up
self.cleanup = function () {
if (self.timeoutId !== null) {
@@ -325,25 +320,10 @@
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
- // Stop game movement
- isGamePaused = true;
- // Show recovery mini-game
- if (!recoveryGame) {
- recoveryGame = new FallenRecoveryGame();
- recoveryGame.x = 2048 / 2;
- recoveryGame.y = 2732 / 2;
- game.addChild(recoveryGame);
- // Set success callback
- recoveryGame.onSuccess = function () {
- isGamePaused = false;
- self.getBackUp();
- };
- }
- // Show and start the recovery game
- recoveryGame.visible = true;
- recoveryGame.start();
+ // Show game over immediately
+ LK.showGameOver();
}
});
};
// Get back up animation
A 2D, Pixalted Bike with one wheel in front and one at the back with a pixelated character on.. In-Game asset. 2d. High contrast. No shadows
A gem, a diamond with an emerald colour. In-Game asset. 2d. High contrast. No shadows
A pedestrian, walking down the street facing forwards. In-Game asset. 2d. High contrast. No shadows
A tarmac road, with 3 lanes, matching up with actual game lanes. In-Game asset. 2d. High contrast. No shadows
A person running backwards. In-Game asset. 2d. High contrast. No shadows
Make a pothole like hole in the road. In-Game asset. 2d. High contrast. No shadows