User prompt
add needed sound effects and nonstop background music matches with the theme
User prompt
random obstacles extending from the left and right of the screen, but not overlapping with standard obstacles ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it background more realistic and give a motion toskeleton obstacle and fire pit obstacle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
remove escape power up. every time on left middle and right, one of them should be without obstacle but in every 250 points game should be harder obstacles can be more
User prompt
game should be faster in every 100 point
User prompt
it cannot be 3 obstacles at the same time in the way
User prompt
there should be a escape all the time
User prompt
Please fix the bug: 'TypeError: undefined is not an object (evaluating 'streamGraphics.skew.y = flow * 0.01')' in or related to this line: 'streamGraphics.skew.y = flow * 0.01;' Line Number: 135
User prompt
make background black lavas
User prompt
road should be last vertical as well and the road must flow with curves ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make it vertical. there should be road and walls. besides of obstacles there should be coins and special power-ups, coins for more score, power ups as being invisible, getting slower and making obstacles smaller ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
add bonus system
Code edit (1 edits merged)
Please save this source code
User prompt
Hell Escape Racer
Initial prompt
Create a simple 2D endless runner-style mobile game with the theme “Escape from Hell”. Core Features: - The player controls a car trying to escape Hell. - The car moves forward automatically. - The player can swipe or tap to move the car vertically (up/down) between lanes. - The environment should scroll continuously to simulate speed and escape. - Random obstacles appear ahead: demons, pits of fire, lava rocks, etc. Crashing ends the game. - Bonus items (like glowing fire orbs) can be collected to increase score. - A simple score counter should be visible during gameplay. - Graphics can be very simple (e.g., solid colors, minimal shapes). - The game should be lightweight, mobile-friendly, and written as simply as possible. Optional Enhancements (choose any): - Power-ups: Add items that give temporary invincibility or boost. - Absurd hell obstacles: Screaming skulls, hellish traffic lights, flying demon wings. - Dynamic difficulty: Speed or obstacle frequency increases over time. - Visual twist: Background color changes slowly (red → purple → black) as the game progresses. - Random events: Occasionally flash "The Devil is Near!" and shake the screen. - Parallax layers: Add a second or third scrolling background for atmosphere. - Sound (optional): Low growls, fire crackling, heartbeat when low on score. Avoid unnecessary complexity. Keep the code readable and beginner-friendly. Mobile-ready is a must.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Car = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1; // 0 = top, 1 = middle, 2 = bottom
self.currentLane = 1;
self.invincible = false;
self.invincibilityTimer = 0;
self.update = function () {
// Smooth lane transitions
var targetY = getLaneY(self.targetLane);
if (Math.abs(self.y - targetY) > 5) {
self.y += (targetY - self.y) * 0.2;
} else {
self.y = targetY;
self.currentLane = self.targetLane;
}
// Handle invincibility
if (self.invincible) {
self.invincibilityTimer--;
carGraphics.alpha = self.invincibilityTimer % 10 < 5 ? 0.5 : 1.0;
if (self.invincibilityTimer <= 0) {
self.invincible = false;
carGraphics.alpha = 1.0;
}
}
};
return self;
});
var FireOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('fireOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.glowTimer = 0;
self.update = function () {
self.x -= gameSpeed;
// Glowing effect
self.glowTimer++;
var scale = 1.0 + Math.sin(self.glowTimer * 0.2) * 0.2;
orbGraphics.scaleX = scale;
orbGraphics.scaleY = scale;
};
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
self.update = function () {
self.x -= gameSpeed;
// Animated effects for different obstacles
if (self.type === 'demon') {
obstacleGraphics.rotation += 0.05;
} else if (self.type === 'demonWing') {
var flap = Math.sin(LK.ticks * 0.3) * 0.3;
obstacleGraphics.scaleY = 1.0 + flap;
} else if (self.type === 'firePit') {
var flicker = 1.0 + Math.sin(LK.ticks * 0.4) * 0.1;
obstacleGraphics.scaleX = flicker;
obstacleGraphics.scaleY = flicker;
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
var color = type === 'invincibility' ? 0x00ff00 : 0x0066ff;
var powerUpGraphics = self.attachAsset('fireOrb', {
anchorX: 0.5,
anchorY: 0.5
});
powerUpGraphics.tint = color;
self.type = type;
self.collected = false;
self.update = function () {
self.x -= gameSpeed;
// Spinning effect
powerUpGraphics.rotation += 0.1;
// Pulsing effect
var pulse = 1.2 + Math.sin(LK.ticks * 0.2) * 0.3;
powerUpGraphics.scaleX = pulse;
powerUpGraphics.scaleY = pulse;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xff0000
});
/****
* Game Code
****/
// Game variables
var gameSpeed = 8;
var baseSpeed = 8;
var car;
var fireOrbs = [];
var obstacles = [];
var powerUps = [];
var backgroundColorPhase = 0; // 0=red, 1=purple, 2=black
var difficultyTimer = 0;
var devilEventTimer = 0;
var shakeTimer = 0;
var spawnTimer = 0;
var powerUpSpawnTimer = 0;
// Lane positions
var lanes = [2732 * 0.25, 2732 * 0.5, 2732 * 0.75];
function getLaneY(laneIndex) {
return lanes[laneIndex];
}
function getRandomLane() {
return Math.floor(Math.random() * 3);
}
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create car
car = game.addChild(new Car());
car.x = 400;
car.y = getLaneY(1);
// Touch controls
game.down = function (x, y, obj) {
if (y < 2732 / 3) {
// Top third - move up
if (car.targetLane > 0) {
car.targetLane--;
}
} else if (y > 2732 * 2 / 3) {
// Bottom third - move down
if (car.targetLane < 2) {
car.targetLane++;
}
}
};
function spawnFireOrb() {
var orb = new FireOrb();
orb.x = 2048 + 100;
orb.y = getLaneY(getRandomLane());
fireOrbs.push(orb);
game.addChild(orb);
}
function spawnObstacle() {
var types = ['demon', 'firePit', 'lavaRock', 'skull', 'demonWing'];
var type = types[Math.floor(Math.random() * types.length)];
var obstacle = new Obstacle(type);
obstacle.x = 2048 + 150;
obstacle.y = getLaneY(getRandomLane());
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnPowerUp() {
var types = ['invincibility', 'speed'];
var type = types[Math.floor(Math.random() * types.length)];
var powerUp = new PowerUp(type);
powerUp.x = 2048 + 200;
powerUp.y = getLaneY(getRandomLane());
powerUps.push(powerUp);
game.addChild(powerUp);
}
function updateBackground() {
var score = LK.getScore();
// Change background based on score
if (score > 100 && backgroundColorPhase === 0) {
backgroundColorPhase = 1;
tween(game, {
backgroundColor: 0x660066
}, {
duration: 2000
});
} else if (score > 250 && backgroundColorPhase === 1) {
backgroundColorPhase = 2;
tween(game, {
backgroundColor: 0x000000
}, {
duration: 2000
});
}
}
function triggerDevilEvent() {
// Screen shake effect
shakeTimer = 180; // 3 seconds at 60fps
// Flash screen red briefly
LK.effects.flashScreen(0xff0000, 500);
}
game.update = function () {
// Apply screen shake
if (shakeTimer > 0) {
shakeTimer--;
var shakeX = (Math.random() - 0.5) * 20;
var shakeY = (Math.random() - 0.5) * 20;
game.x = shakeX;
game.y = shakeY;
} else {
game.x = 0;
game.y = 0;
}
// Increase difficulty over time
difficultyTimer++;
if (difficultyTimer % 600 === 0) {
// Every 10 seconds
gameSpeed += 0.5;
if (gameSpeed > baseSpeed * 2.5) {
gameSpeed = baseSpeed * 2.5; // Cap speed
}
}
// Devil event timer
devilEventTimer++;
if (devilEventTimer > 1800 + Math.random() * 1800) {
// 30-60 seconds
triggerDevilEvent();
devilEventTimer = 0;
}
// Spawn objects
spawnTimer++;
powerUpSpawnTimer++;
// Spawn fire orbs
if (spawnTimer > 60 - Math.min(40, LK.getScore() / 10)) {
if (Math.random() < 0.7) {
spawnFireOrb();
}
spawnTimer = 0;
}
// Spawn obstacles
if (Math.random() < 0.02 + LK.getScore() * 0.0001) {
spawnObstacle();
}
// Spawn power-ups occasionally
if (powerUpSpawnTimer > 900 && Math.random() < 0.1) {
// Every 15+ seconds, 10% chance
spawnPowerUp();
powerUpSpawnTimer = 0;
}
// Update fire orbs
for (var i = fireOrbs.length - 1; i >= 0; i--) {
var orb = fireOrbs[i];
if (orb.x < -100) {
orb.destroy();
fireOrbs.splice(i, 1);
continue;
}
// Check collision with car
if (!orb.collected && car.intersects(orb)) {
orb.collected = true;
LK.setScore(LK.getScore() + 10);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('collect').play();
orb.destroy();
fireOrbs.splice(i, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.x < -150) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with car
if (!car.invincible && car.currentLane === Math.round((obstacle.y - lanes[0]) / (lanes[1] - lanes[0])) && car.intersects(obstacle)) {
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (powerUp.x < -100) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collision with car
if (!powerUp.collected && car.intersects(powerUp)) {
powerUp.collected = true;
if (powerUp.type === 'invincibility') {
car.invincible = true;
car.invincibilityTimer = 300; // 5 seconds
} else if (powerUp.type === 'speed') {
LK.setScore(LK.getScore() + 50);
scoreTxt.setText('Score: ' + LK.getScore());
}
LK.getSound('collect').play();
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Update background color progression
updateBackground();
// Add score over time
if (LK.ticks % 30 === 0) {
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Score: ' + LK.getScore());
}
};
// Start background music
LK.playMusic('hellMusic'); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,323 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+var Car = Container.expand(function () {
+ var self = Container.call(this);
+ var carGraphics = self.attachAsset('car', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.targetLane = 1; // 0 = top, 1 = middle, 2 = bottom
+ self.currentLane = 1;
+ self.invincible = false;
+ self.invincibilityTimer = 0;
+ self.update = function () {
+ // Smooth lane transitions
+ var targetY = getLaneY(self.targetLane);
+ if (Math.abs(self.y - targetY) > 5) {
+ self.y += (targetY - self.y) * 0.2;
+ } else {
+ self.y = targetY;
+ self.currentLane = self.targetLane;
+ }
+ // Handle invincibility
+ if (self.invincible) {
+ self.invincibilityTimer--;
+ carGraphics.alpha = self.invincibilityTimer % 10 < 5 ? 0.5 : 1.0;
+ if (self.invincibilityTimer <= 0) {
+ self.invincible = false;
+ carGraphics.alpha = 1.0;
+ }
+ }
+ };
+ return self;
+});
+var FireOrb = Container.expand(function () {
+ var self = Container.call(this);
+ var orbGraphics = self.attachAsset('fireOrb', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.collected = false;
+ self.glowTimer = 0;
+ self.update = function () {
+ self.x -= gameSpeed;
+ // Glowing effect
+ self.glowTimer++;
+ var scale = 1.0 + Math.sin(self.glowTimer * 0.2) * 0.2;
+ orbGraphics.scaleX = scale;
+ orbGraphics.scaleY = scale;
+ };
+ return self;
+});
+var Obstacle = Container.expand(function (type) {
+ var self = Container.call(this);
+ var obstacleGraphics = self.attachAsset(type, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.type = type;
+ self.update = function () {
+ self.x -= gameSpeed;
+ // Animated effects for different obstacles
+ if (self.type === 'demon') {
+ obstacleGraphics.rotation += 0.05;
+ } else if (self.type === 'demonWing') {
+ var flap = Math.sin(LK.ticks * 0.3) * 0.3;
+ obstacleGraphics.scaleY = 1.0 + flap;
+ } else if (self.type === 'firePit') {
+ var flicker = 1.0 + Math.sin(LK.ticks * 0.4) * 0.1;
+ obstacleGraphics.scaleX = flicker;
+ obstacleGraphics.scaleY = flicker;
+ }
+ };
+ return self;
+});
+var PowerUp = Container.expand(function (type) {
+ var self = Container.call(this);
+ var color = type === 'invincibility' ? 0x00ff00 : 0x0066ff;
+ var powerUpGraphics = self.attachAsset('fireOrb', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ powerUpGraphics.tint = color;
+ self.type = type;
+ self.collected = false;
+ self.update = function () {
+ self.x -= gameSpeed;
+ // Spinning effect
+ powerUpGraphics.rotation += 0.1;
+ // Pulsing effect
+ var pulse = 1.2 + Math.sin(LK.ticks * 0.2) * 0.3;
+ powerUpGraphics.scaleX = pulse;
+ powerUpGraphics.scaleY = pulse;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xff0000
+});
+
+/****
+* Game Code
+****/
+// Game variables
+var gameSpeed = 8;
+var baseSpeed = 8;
+var car;
+var fireOrbs = [];
+var obstacles = [];
+var powerUps = [];
+var backgroundColorPhase = 0; // 0=red, 1=purple, 2=black
+var difficultyTimer = 0;
+var devilEventTimer = 0;
+var shakeTimer = 0;
+var spawnTimer = 0;
+var powerUpSpawnTimer = 0;
+// Lane positions
+var lanes = [2732 * 0.25, 2732 * 0.5, 2732 * 0.75];
+function getLaneY(laneIndex) {
+ return lanes[laneIndex];
+}
+function getRandomLane() {
+ return Math.floor(Math.random() * 3);
+}
+// Create score display
+var scoreTxt = new Text2('Score: 0', {
+ size: 80,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Create car
+car = game.addChild(new Car());
+car.x = 400;
+car.y = getLaneY(1);
+// Touch controls
+game.down = function (x, y, obj) {
+ if (y < 2732 / 3) {
+ // Top third - move up
+ if (car.targetLane > 0) {
+ car.targetLane--;
+ }
+ } else if (y > 2732 * 2 / 3) {
+ // Bottom third - move down
+ if (car.targetLane < 2) {
+ car.targetLane++;
+ }
+ }
+};
+function spawnFireOrb() {
+ var orb = new FireOrb();
+ orb.x = 2048 + 100;
+ orb.y = getLaneY(getRandomLane());
+ fireOrbs.push(orb);
+ game.addChild(orb);
+}
+function spawnObstacle() {
+ var types = ['demon', 'firePit', 'lavaRock', 'skull', 'demonWing'];
+ var type = types[Math.floor(Math.random() * types.length)];
+ var obstacle = new Obstacle(type);
+ obstacle.x = 2048 + 150;
+ obstacle.y = getLaneY(getRandomLane());
+ obstacles.push(obstacle);
+ game.addChild(obstacle);
+}
+function spawnPowerUp() {
+ var types = ['invincibility', 'speed'];
+ var type = types[Math.floor(Math.random() * types.length)];
+ var powerUp = new PowerUp(type);
+ powerUp.x = 2048 + 200;
+ powerUp.y = getLaneY(getRandomLane());
+ powerUps.push(powerUp);
+ game.addChild(powerUp);
+}
+function updateBackground() {
+ var score = LK.getScore();
+ // Change background based on score
+ if (score > 100 && backgroundColorPhase === 0) {
+ backgroundColorPhase = 1;
+ tween(game, {
+ backgroundColor: 0x660066
+ }, {
+ duration: 2000
+ });
+ } else if (score > 250 && backgroundColorPhase === 1) {
+ backgroundColorPhase = 2;
+ tween(game, {
+ backgroundColor: 0x000000
+ }, {
+ duration: 2000
+ });
+ }
+}
+function triggerDevilEvent() {
+ // Screen shake effect
+ shakeTimer = 180; // 3 seconds at 60fps
+ // Flash screen red briefly
+ LK.effects.flashScreen(0xff0000, 500);
+}
+game.update = function () {
+ // Apply screen shake
+ if (shakeTimer > 0) {
+ shakeTimer--;
+ var shakeX = (Math.random() - 0.5) * 20;
+ var shakeY = (Math.random() - 0.5) * 20;
+ game.x = shakeX;
+ game.y = shakeY;
+ } else {
+ game.x = 0;
+ game.y = 0;
+ }
+ // Increase difficulty over time
+ difficultyTimer++;
+ if (difficultyTimer % 600 === 0) {
+ // Every 10 seconds
+ gameSpeed += 0.5;
+ if (gameSpeed > baseSpeed * 2.5) {
+ gameSpeed = baseSpeed * 2.5; // Cap speed
+ }
+ }
+ // Devil event timer
+ devilEventTimer++;
+ if (devilEventTimer > 1800 + Math.random() * 1800) {
+ // 30-60 seconds
+ triggerDevilEvent();
+ devilEventTimer = 0;
+ }
+ // Spawn objects
+ spawnTimer++;
+ powerUpSpawnTimer++;
+ // Spawn fire orbs
+ if (spawnTimer > 60 - Math.min(40, LK.getScore() / 10)) {
+ if (Math.random() < 0.7) {
+ spawnFireOrb();
+ }
+ spawnTimer = 0;
+ }
+ // Spawn obstacles
+ if (Math.random() < 0.02 + LK.getScore() * 0.0001) {
+ spawnObstacle();
+ }
+ // Spawn power-ups occasionally
+ if (powerUpSpawnTimer > 900 && Math.random() < 0.1) {
+ // Every 15+ seconds, 10% chance
+ spawnPowerUp();
+ powerUpSpawnTimer = 0;
+ }
+ // Update fire orbs
+ for (var i = fireOrbs.length - 1; i >= 0; i--) {
+ var orb = fireOrbs[i];
+ if (orb.x < -100) {
+ orb.destroy();
+ fireOrbs.splice(i, 1);
+ continue;
+ }
+ // Check collision with car
+ if (!orb.collected && car.intersects(orb)) {
+ orb.collected = true;
+ LK.setScore(LK.getScore() + 10);
+ scoreTxt.setText('Score: ' + LK.getScore());
+ LK.getSound('collect').play();
+ orb.destroy();
+ fireOrbs.splice(i, 1);
+ }
+ }
+ // Update obstacles
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obstacle = obstacles[i];
+ if (obstacle.x < -150) {
+ obstacle.destroy();
+ obstacles.splice(i, 1);
+ continue;
+ }
+ // Check collision with car
+ if (!car.invincible && car.currentLane === Math.round((obstacle.y - lanes[0]) / (lanes[1] - lanes[0])) && car.intersects(obstacle)) {
+ LK.getSound('crash').play();
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Update power-ups
+ for (var i = powerUps.length - 1; i >= 0; i--) {
+ var powerUp = powerUps[i];
+ if (powerUp.x < -100) {
+ powerUp.destroy();
+ powerUps.splice(i, 1);
+ continue;
+ }
+ // Check collision with car
+ if (!powerUp.collected && car.intersects(powerUp)) {
+ powerUp.collected = true;
+ if (powerUp.type === 'invincibility') {
+ car.invincible = true;
+ car.invincibilityTimer = 300; // 5 seconds
+ } else if (powerUp.type === 'speed') {
+ LK.setScore(LK.getScore() + 50);
+ scoreTxt.setText('Score: ' + LK.getScore());
+ }
+ LK.getSound('collect').play();
+ powerUp.destroy();
+ powerUps.splice(i, 1);
+ }
+ }
+ // Update background color progression
+ updateBackground();
+ // Add score over time
+ if (LK.ticks % 30 === 0) {
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText('Score: ' + LK.getScore());
+ }
+};
+// Start background music
+LK.playMusic('hellMusic');
\ No newline at end of file
fireFlicker
Sound effect
skullMoan
Sound effect
powerUp
Sound effect
hellMusic
Music
bonusEvent
Sound effect
laneChange
Sound effect
collect
Sound effect
gameOverMusic
Music
devilLaugh
Sound effect
explosion
Sound effect
crash
Sound effect
angelBlessing
Sound effect
failure
Sound effect
angelAppearance
Sound effect