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 = left, 1 = middle, 2 = right
self.currentLane = 1;
self.invincible = false;
self.invincibilityTimer = 0;
self.slowEffect = false;
self.slowTimer = 0;
self.shrinkObstacles = false;
self.shrinkTimer = 0;
self.update = function () {
// Smooth lane transitions
var targetX = getLaneX(self.targetLane);
if (Math.abs(self.x - targetX) > 5) {
self.x += (targetX - self.x) * 0.2;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle invincibility
if (self.invincible) {
self.invincibilityTimer--;
carGraphics.alpha = self.invincibilityTimer % 10 < 5 ? 0.3 : 1.0;
carGraphics.tint = 0x00ffff;
if (self.invincibilityTimer <= 0) {
self.invincible = false;
carGraphics.alpha = 1.0;
carGraphics.tint = 0xffffff;
}
}
// Handle slow effect
if (self.slowEffect) {
self.slowTimer--;
if (self.slowTimer <= 0) {
self.slowEffect = false;
}
}
// Handle shrink obstacles effect
if (self.shrinkObstacles) {
self.shrinkTimer--;
if (self.shrinkTimer <= 0) {
self.shrinkObstacles = false;
}
}
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.glowTimer = 0;
self.update = function () {
self.y += gameSpeed;
// Glowing effect
self.glowTimer++;
var scale = 1.0 + Math.sin(self.glowTimer * 0.2) * 0.2;
coinGraphics.scaleX = scale;
coinGraphics.scaleY = scale;
// Rotation effect
coinGraphics.rotation += 0.1;
};
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.shrunk = false;
self.update = function () {
self.y += car.slowEffect ? gameSpeed * 0.5 : gameSpeed;
// Apply shrink effect if active
if (car.shrinkObstacles && !self.shrunk) {
self.shrunk = true;
tween(obstacleGraphics, {
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 300
});
} else if (!car.shrinkObstacles && self.shrunk) {
self.shrunk = false;
tween(obstacleGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300
});
}
// 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 = (self.shrunk ? 0.5 : 1.0) + flap;
} else if (self.type === 'firePit') {
var flicker = 1.0 + Math.sin(LK.ticks * 0.4) * 0.1;
var scale = self.shrunk ? 0.5 : 1.0;
obstacleGraphics.scaleX = scale * flicker;
obstacleGraphics.scaleY = scale * flicker;
}
};
return self;
});
var PowerUp = Container.expand(function (type) {
var self = Container.call(this);
var assetName = type + 'PowerUp';
var powerUpGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
self.collected = false;
self.update = function () {
self.y += 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;
});
var Road = Container.expand(function () {
var self = Container.call(this);
var roadGraphics = self.attachAsset('road', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
self.y += gameSpeed;
// Reset position when off screen
if (self.y > 2732 + 75) {
self.y = -75;
}
};
return self;
});
var Wall = Container.expand(function (side) {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.side = side; // 'left' or 'right'
self.update = function () {
self.y += gameSpeed;
// Reset position when off screen
if (self.y > 2732 + 50) {
self.y = -50;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xff0000
});
/****
* Game Code
****/
// Game variables
var gameSpeed = 8;
var baseSpeed = 8;
var car;
var coins = [];
var obstacles = [];
var powerUps = [];
var roads = [];
var walls = [];
var backgroundColorPhase = 0; // 0=red, 1=purple, 2=black
var difficultyTimer = 0;
var devilEventTimer = 0;
var shakeTimer = 0;
var spawnTimer = 0;
var powerUpSpawnTimer = 0;
// Bonus system variables
var scoreMultiplier = 1;
var multiplierTimer = 0;
var comboCount = 0;
var comboTimer = 0;
var lastCollectTime = 0;
var bonusEventTimer = 0;
// Lane positions for vertical game (horizontal lanes)
var lanes = [2048 * 0.2, 2048 * 0.5, 2048 * 0.8];
function getLaneX(laneIndex) {
return lanes[laneIndex];
}
function getRandomLane() {
return Math.floor(Math.random() * 3);
}
function calculateBonus(basePoints) {
var bonus = basePoints * scoreMultiplier;
// Combo bonus
if (comboCount > 1) {
bonus += comboCount * 5;
}
// Speed bonus - higher speed gives more points
var speedBonus = Math.floor((gameSpeed - baseSpeed) * 2);
bonus += speedBonus;
return Math.floor(bonus);
}
function updateCombo() {
var currentTime = LK.ticks;
// Check if within combo window (2 seconds)
if (currentTime - lastCollectTime < 120) {
comboCount++;
comboTimer = 180; // Show combo for 3 seconds
} else {
comboCount = 1;
comboTimer = 180;
}
lastCollectTime = currentTime;
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + '!');
tween(comboTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
onComplete: function onComplete() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
}
function triggerBonusEvent() {
// Random bonus events
var eventType = Math.floor(Math.random() * 3);
if (eventType === 0) {
// Score multiplier boost
scoreMultiplier = Math.min(scoreMultiplier + 1, 5);
multiplierTimer = 600; // 10 seconds
LK.effects.flashScreen(0xffff00, 300);
} else if (eventType === 1) {
// Instant score bonus
var bonus = calculateBonus(100);
LK.setScore(LK.getScore() + bonus);
scoreTxt.setText('Score: ' + LK.getScore());
LK.effects.flashScreen(0x00ff00, 300);
} else {
// Combo extension
comboTimer += 300; // Extra 5 seconds
LK.effects.flashScreen(0xff6600, 300);
}
}
// 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 multiplier display
var multiplierTxt = new Text2('x1', {
size: 60,
fill: 0xffff00
});
multiplierTxt.anchor.set(1, 0);
multiplierTxt.x = -20;
multiplierTxt.y = 100;
LK.gui.topRight.addChild(multiplierTxt);
// Create combo display
var comboTxt = new Text2('', {
size: 50,
fill: 0xff6600
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 120;
LK.gui.top.addChild(comboTxt);
// Create road segments
for (var i = 0; i < 3; i++) {
var road = new Road();
road.x = 2048 / 2;
road.y = i * 150 - 75;
roads.push(road);
game.addChild(road);
}
// Create walls
var leftWall = new Wall('left');
leftWall.x = 100;
leftWall.y = 2732 / 2;
walls.push(leftWall);
game.addChild(leftWall);
var rightWall = new Wall('right');
rightWall.x = 2048 - 100;
rightWall.y = 2732 / 2;
walls.push(rightWall);
game.addChild(rightWall);
// Create car
car = game.addChild(new Car());
car.x = getLaneX(1);
car.y = 2732 - 200;
// Touch controls
game.down = function (x, y, obj) {
if (x < 2048 / 3) {
// Left third - move left
if (car.targetLane > 0) {
car.targetLane--;
}
} else if (x > 2048 * 2 / 3) {
// Right third - move right
if (car.targetLane < 2) {
car.targetLane++;
}
}
};
function spawnCoin() {
var coin = new Coin();
coin.x = getLaneX(getRandomLane());
coin.y = -50;
coins.push(coin);
game.addChild(coin);
}
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 = getLaneX(getRandomLane());
obstacle.y = -100;
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnPowerUp() {
var types = ['invisibility', 'slow', 'shrink'];
var type = types[Math.floor(Math.random() * types.length)];
var powerUp = new PowerUp(type);
powerUp.x = getLaneX(getRandomLane());
powerUp.y = -75;
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 coins
if (spawnTimer > 60 - Math.min(40, LK.getScore() / 10)) {
if (Math.random() < 0.7) {
spawnCoin();
}
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 coins
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
if (coin.y > 2732 + 100) {
coin.destroy();
coins.splice(i, 1);
continue;
}
// Check collision with car
if (!coin.collected && car.intersects(coin)) {
coin.collected = true;
var bonus = calculateBonus(10);
LK.setScore(LK.getScore() + bonus);
scoreTxt.setText('Score: ' + LK.getScore());
updateCombo();
LK.getSound('collect').play();
coin.destroy();
coins.splice(i, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.y > 2732 + 150) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with car
if (!car.invincible && car.currentLane === Math.round((obstacle.x - 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.y > 2732 + 100) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collision with car
if (!powerUp.collected && car.intersects(powerUp)) {
powerUp.collected = true;
if (powerUp.type === 'invisibility') {
car.invincible = true;
car.invincibilityTimer = 300; // 5 seconds
scoreMultiplier += 1;
multiplierTimer = 300; // 5 seconds
} else if (powerUp.type === 'slow') {
car.slowEffect = true;
car.slowTimer = 360; // 6 seconds
var bonus = calculateBonus(25);
LK.setScore(LK.getScore() + bonus);
scoreTxt.setText('Score: ' + LK.getScore());
} else if (powerUp.type === 'shrink') {
car.shrinkObstacles = true;
car.shrinkTimer = 480; // 8 seconds
var bonus = calculateBonus(30);
LK.setScore(LK.getScore() + bonus);
scoreTxt.setText('Score: ' + LK.getScore());
}
updateCombo();
LK.getSound('collect').play();
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Update background color progression
updateBackground();
// Update bonus system timers
if (multiplierTimer > 0) {
multiplierTimer--;
if (multiplierTimer <= 0) {
scoreMultiplier = Math.max(1, scoreMultiplier - 1);
}
}
if (comboTimer > 0) {
comboTimer--;
if (comboTimer <= 0) {
comboCount = 0;
comboTxt.setText('');
}
}
// Update displays
multiplierTxt.setText('x' + scoreMultiplier);
if (scoreMultiplier > 1) {
multiplierTxt.fill = 0x00ff00;
} else {
multiplierTxt.fill = 0xffff00;
}
// Bonus events
bonusEventTimer++;
if (bonusEventTimer > 1200 + Math.random() * 600) {
// 20-30 seconds
if (Math.random() < 0.3) {
// 30% chance
triggerBonusEvent();
}
bonusEventTimer = 0;
}
// Add score over time with multiplier
if (LK.ticks % 30 === 0) {
var timeBonus = calculateBonus(1);
LK.setScore(LK.getScore() + timeBonus);
scoreTxt.setText('Score: ' + LK.getScore());
}
};
// Start background music
LK.playMusic('hellMusic'); ===================================================================
--- original.js
+++ change.js
@@ -11,48 +11,70 @@
var carGraphics = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
- self.targetLane = 1; // 0 = top, 1 = middle, 2 = bottom
+ self.targetLane = 1; // 0 = left, 1 = middle, 2 = right
self.currentLane = 1;
self.invincible = false;
self.invincibilityTimer = 0;
+ self.slowEffect = false;
+ self.slowTimer = 0;
+ self.shrinkObstacles = false;
+ self.shrinkTimer = 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;
+ var targetX = getLaneX(self.targetLane);
+ if (Math.abs(self.x - targetX) > 5) {
+ self.x += (targetX - self.x) * 0.2;
} else {
- self.y = targetY;
+ self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle invincibility
if (self.invincible) {
self.invincibilityTimer--;
- carGraphics.alpha = self.invincibilityTimer % 10 < 5 ? 0.5 : 1.0;
+ carGraphics.alpha = self.invincibilityTimer % 10 < 5 ? 0.3 : 1.0;
+ carGraphics.tint = 0x00ffff;
if (self.invincibilityTimer <= 0) {
self.invincible = false;
carGraphics.alpha = 1.0;
+ carGraphics.tint = 0xffffff;
}
}
+ // Handle slow effect
+ if (self.slowEffect) {
+ self.slowTimer--;
+ if (self.slowTimer <= 0) {
+ self.slowEffect = false;
+ }
+ }
+ // Handle shrink obstacles effect
+ if (self.shrinkObstacles) {
+ self.shrinkTimer--;
+ if (self.shrinkTimer <= 0) {
+ self.shrinkObstacles = false;
+ }
+ }
};
return self;
});
-var FireOrb = Container.expand(function () {
+var Coin = Container.expand(function () {
var self = Container.call(this);
- var orbGraphics = self.attachAsset('fireOrb', {
+ var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.glowTimer = 0;
self.update = function () {
- self.x -= gameSpeed;
+ self.y += gameSpeed;
// Glowing effect
self.glowTimer++;
var scale = 1.0 + Math.sin(self.glowTimer * 0.2) * 0.2;
- orbGraphics.scaleX = scale;
- orbGraphics.scaleY = scale;
+ coinGraphics.scaleX = scale;
+ coinGraphics.scaleY = scale;
+ // Rotation effect
+ coinGraphics.rotation += 0.1;
};
return self;
});
var Obstacle = Container.expand(function (type) {
@@ -61,36 +83,55 @@
anchorX: 0.5,
anchorY: 0.5
});
self.type = type;
+ self.shrunk = false;
self.update = function () {
- self.x -= gameSpeed;
+ self.y += car.slowEffect ? gameSpeed * 0.5 : gameSpeed;
+ // Apply shrink effect if active
+ if (car.shrinkObstacles && !self.shrunk) {
+ self.shrunk = true;
+ tween(obstacleGraphics, {
+ scaleX: 0.5,
+ scaleY: 0.5
+ }, {
+ duration: 300
+ });
+ } else if (!car.shrinkObstacles && self.shrunk) {
+ self.shrunk = false;
+ tween(obstacleGraphics, {
+ scaleX: 1.0,
+ scaleY: 1.0
+ }, {
+ duration: 300
+ });
+ }
// 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;
+ obstacleGraphics.scaleY = (self.shrunk ? 0.5 : 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;
+ var scale = self.shrunk ? 0.5 : 1.0;
+ obstacleGraphics.scaleX = scale * flicker;
+ obstacleGraphics.scaleY = scale * 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', {
+ var assetName = type + 'PowerUp';
+ var powerUpGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
- powerUpGraphics.tint = color;
self.type = type;
self.collected = false;
self.update = function () {
- self.x -= gameSpeed;
+ self.y += gameSpeed;
// Spinning effect
powerUpGraphics.rotation += 0.1;
// Pulsing effect
var pulse = 1.2 + Math.sin(LK.ticks * 0.2) * 0.3;
@@ -98,8 +139,39 @@
powerUpGraphics.scaleY = pulse;
};
return self;
});
+var Road = Container.expand(function () {
+ var self = Container.call(this);
+ var roadGraphics = self.attachAsset('road', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.update = function () {
+ self.y += gameSpeed;
+ // Reset position when off screen
+ if (self.y > 2732 + 75) {
+ self.y = -75;
+ }
+ };
+ return self;
+});
+var Wall = Container.expand(function (side) {
+ var self = Container.call(this);
+ var wallGraphics = self.attachAsset('wall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.side = side; // 'left' or 'right'
+ self.update = function () {
+ self.y += gameSpeed;
+ // Reset position when off screen
+ if (self.y > 2732 + 50) {
+ self.y = -50;
+ }
+ };
+ return self;
+});
/****
* Initialize Game
****/
@@ -113,11 +185,13 @@
// Game variables
var gameSpeed = 8;
var baseSpeed = 8;
var car;
-var fireOrbs = [];
+var coins = [];
var obstacles = [];
var powerUps = [];
+var roads = [];
+var walls = [];
var backgroundColorPhase = 0; // 0=red, 1=purple, 2=black
var difficultyTimer = 0;
var devilEventTimer = 0;
var shakeTimer = 0;
@@ -129,11 +203,11 @@
var comboCount = 0;
var comboTimer = 0;
var lastCollectTime = 0;
var bonusEventTimer = 0;
-// Lane positions
-var lanes = [2732 * 0.25, 2732 * 0.5, 2732 * 0.75];
-function getLaneY(laneIndex) {
+// Lane positions for vertical game (horizontal lanes)
+var lanes = [2048 * 0.2, 2048 * 0.5, 2048 * 0.8];
+function getLaneX(laneIndex) {
return lanes[laneIndex];
}
function getRandomLane() {
return Math.floor(Math.random() * 3);
@@ -222,48 +296,67 @@
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 120;
LK.gui.top.addChild(comboTxt);
+// Create road segments
+for (var i = 0; i < 3; i++) {
+ var road = new Road();
+ road.x = 2048 / 2;
+ road.y = i * 150 - 75;
+ roads.push(road);
+ game.addChild(road);
+}
+// Create walls
+var leftWall = new Wall('left');
+leftWall.x = 100;
+leftWall.y = 2732 / 2;
+walls.push(leftWall);
+game.addChild(leftWall);
+var rightWall = new Wall('right');
+rightWall.x = 2048 - 100;
+rightWall.y = 2732 / 2;
+walls.push(rightWall);
+game.addChild(rightWall);
// Create car
car = game.addChild(new Car());
-car.x = 400;
-car.y = getLaneY(1);
+car.x = getLaneX(1);
+car.y = 2732 - 200;
// Touch controls
game.down = function (x, y, obj) {
- if (y < 2732 / 3) {
- // Top third - move up
+ if (x < 2048 / 3) {
+ // Left third - move left
if (car.targetLane > 0) {
car.targetLane--;
}
- } else if (y > 2732 * 2 / 3) {
- // Bottom third - move down
+ } else if (x > 2048 * 2 / 3) {
+ // Right third - move right
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 spawnCoin() {
+ var coin = new Coin();
+ coin.x = getLaneX(getRandomLane());
+ coin.y = -50;
+ coins.push(coin);
+ game.addChild(coin);
}
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());
+ obstacle.x = getLaneX(getRandomLane());
+ obstacle.y = -100;
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnPowerUp() {
- var types = ['invincibility', 'speed'];
+ var types = ['invisibility', 'slow', 'shrink'];
var type = types[Math.floor(Math.random() * types.length)];
var powerUp = new PowerUp(type);
- powerUp.x = 2048 + 200;
- powerUp.y = getLaneY(getRandomLane());
+ powerUp.x = getLaneX(getRandomLane());
+ powerUp.y = -75;
powerUps.push(powerUp);
game.addChild(powerUp);
}
function updateBackground() {
@@ -321,12 +414,12 @@
}
// Spawn objects
spawnTimer++;
powerUpSpawnTimer++;
- // Spawn fire orbs
+ // Spawn coins
if (spawnTimer > 60 - Math.min(40, LK.getScore() / 10)) {
if (Math.random() < 0.7) {
- spawnFireOrb();
+ spawnCoin();
}
spawnTimer = 0;
}
// Spawn obstacles
@@ -338,38 +431,38 @@
// 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);
+ // Update coins
+ for (var i = coins.length - 1; i >= 0; i--) {
+ var coin = coins[i];
+ if (coin.y > 2732 + 100) {
+ coin.destroy();
+ coins.splice(i, 1);
continue;
}
// Check collision with car
- if (!orb.collected && car.intersects(orb)) {
- orb.collected = true;
+ if (!coin.collected && car.intersects(coin)) {
+ coin.collected = true;
var bonus = calculateBonus(10);
LK.setScore(LK.getScore() + bonus);
scoreTxt.setText('Score: ' + LK.getScore());
updateCombo();
LK.getSound('collect').play();
- orb.destroy();
- fireOrbs.splice(i, 1);
+ coin.destroy();
+ coins.splice(i, 1);
}
}
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
- if (obstacle.x < -150) {
+ if (obstacle.y > 2732 + 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)) {
+ if (!car.invincible && car.currentLane === Math.round((obstacle.x - lanes[0]) / (lanes[1] - lanes[0])) && car.intersects(obstacle)) {
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
@@ -377,25 +470,33 @@
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
- if (powerUp.x < -100) {
+ if (powerUp.y > 2732 + 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') {
+ if (powerUp.type === 'invisibility') {
car.invincible = true;
car.invincibilityTimer = 300; // 5 seconds
scoreMultiplier += 1;
multiplierTimer = 300; // 5 seconds
- } else if (powerUp.type === 'speed') {
- var bonus = calculateBonus(50);
+ } else if (powerUp.type === 'slow') {
+ car.slowEffect = true;
+ car.slowTimer = 360; // 6 seconds
+ var bonus = calculateBonus(25);
LK.setScore(LK.getScore() + bonus);
scoreTxt.setText('Score: ' + LK.getScore());
+ } else if (powerUp.type === 'shrink') {
+ car.shrinkObstacles = true;
+ car.shrinkTimer = 480; // 8 seconds
+ var bonus = calculateBonus(30);
+ LK.setScore(LK.getScore() + bonus);
+ scoreTxt.setText('Score: ' + LK.getScore());
}
updateCombo();
LK.getSound('collect').play();
powerUp.destroy();
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