/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Car Class
var EnemyCar = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('enemyCar', {
anchorX: 0.5,
anchorY: 0.5
});
// Lane index (0,1,2)
self.lane = 1;
// Speed in px per frame
self.speed = 12;
// Update method called by LK
self.update = function () {
self.y += self.speed * gameSpeed;
};
return self;
});
// Obstacle Class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obs = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
// Lane index (0,1,2)
self.lane = 1;
// Speed in px per frame
self.speed = 12;
self.update = function () {
self.y += self.speed * gameSpeed;
};
return self;
});
// Player Car Class
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var car = self.attachAsset('bmwCar', {
anchorX: 0.5,
anchorY: 0.5
});
// Current lane index (0 = left, 1 = center, 2 = right)
self.lane = 1;
// Move to lane with animation and drifting effect
self.moveToLane = function (laneIndex, duration) {
self.lane = laneIndex;
var targetX = getLaneX(laneIndex);
// Determine drift direction
var driftAngle = 0;
if (laneIndex > self.lane) driftAngle = Math.PI / 10; // right drift
else if (laneIndex < self.lane) driftAngle = -Math.PI / 10; // left drift
// Animate drift: rotate, move, then straighten
tween(self, {
rotation: driftAngle,
x: targetX
}, {
duration: (duration || 120) * 0.6,
easing: tween.cubicOut,
onComplete: function onComplete() {
tween(self, {
rotation: 0
}, {
duration: (duration || 120) * 0.4,
easing: tween.cubicIn
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// BMW: white, slightly larger
// Obstacle: yellow ellipse (e.g. traffic cone)
// Enemy car: red box
// Player car: BMW (white box) with drifting animation
// Lane setup
var NUM_LANES = 3;
var laneWidth = 410; // 2048 / 5 = ~410, leaves margin on sides
var laneMargin = (2048 - NUM_LANES * laneWidth) / 2; // Center lanes
function getLaneX(laneIndex) {
// Center of each lane
return laneMargin + laneWidth * laneIndex + laneWidth / 2;
}
// Player car setup
var playerCar = new PlayerCar();
playerCar.x = getLaneX(1);
// Adjust y for larger BMW car
playerCar.y = 2732 - 420;
playerCar.lane = 1;
game.addChild(playerCar);
// Score display
var score = 0;
var scoreTxt = new Text2('Drift: 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Game speed
var gameSpeed = 1.0;
var speedIncreaseInterval = 180; // every 3 seconds at 60fps
var speedIncreaseAmount = 0.08;
var maxGameSpeed = 2.8;
// Enemy/obstacle spawn
var enemyCars = [];
var obstacles = [];
var spawnTimer = 0;
var spawnInterval = 60; // frames between spawns (1 sec at 60fps), will decrease as speed increases
var minSpawnInterval = 24; // fastest spawn rate
// Touch/swipe handling
var dragStartX = null;
var dragStartY = null;
var dragActive = false;
var swipeThreshold = 80; // px
// Prevent input in top-left 100x100
function isInMenuArea(x, y) {
return x < 100 && y < 100;
}
// Touch down
game.down = function (x, y, obj) {
if (isInMenuArea(x, y)) return;
dragStartX = x;
dragStartY = y;
dragActive = true;
};
// Touch up
game.up = function (x, y, obj) {
dragStartX = null;
dragStartY = null;
dragActive = false;
};
// Touch move (swipe detection)
game.move = function (x, y, obj) {
if (!dragActive || dragStartX === null) return;
var dx = x - dragStartX;
var dy = y - dragStartY;
// Only consider horizontal swipes, ignore vertical
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > swipeThreshold) {
if (dx < 0 && playerCar.lane > 0) {
// Swipe left
playerCar.moveToLane(playerCar.lane - 1);
} else if (dx > 0 && playerCar.lane < NUM_LANES - 1) {
// Swipe right
playerCar.moveToLane(playerCar.lane + 1);
}
dragActive = false; // Only one move per swipe
}
};
// Helper: spawn enemy or obstacle
function spawnEnemyOrObstacle() {
// Randomly decide: 70% enemy car, 30% obstacle
var isEnemy = Math.random() < 0.7;
var lane = Math.floor(Math.random() * NUM_LANES);
if (isEnemy) {
var enemy = new EnemyCar();
enemy.lane = lane;
enemy.x = getLaneX(lane);
enemy.y = -200;
enemyCars.push(enemy);
game.addChild(enemy);
} else {
var obs = new Obstacle();
obs.lane = lane;
obs.x = getLaneX(lane);
obs.y = -120;
obstacles.push(obs);
game.addChild(obs);
}
}
// Main game update
game.update = function () {
// Increase game speed over time
if (LK.ticks % speedIncreaseInterval === 0 && gameSpeed < maxGameSpeed) {
gameSpeed += speedIncreaseAmount;
if (gameSpeed > maxGameSpeed) gameSpeed = maxGameSpeed;
// Decrease spawn interval as speed increases
spawnInterval = Math.max(minSpawnInterval, 60 - Math.floor((gameSpeed - 1) * 18));
}
// Spawn enemies/obstacles
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnEnemyOrObstacle();
spawnTimer = 0;
}
// Update enemy cars
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemy = enemyCars[i];
enemy.update();
// Collision detection
if (enemy.intersects(playerCar)) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
// Passed player (score)
if (!enemy.passed && enemy.y > playerCar.y + 200) {
enemy.passed = true;
score++;
scoreTxt.setText('Drift: ' + score);
}
// Remove off-screen
if (enemy.y > 2900) {
enemy.destroy();
enemyCars.splice(i, 1);
}
}
// Update obstacles
for (var j = obstacles.length - 1; j >= 0; j--) {
var obs = obstacles[j];
obs.update();
// Collision detection
if (obs.intersects(playerCar)) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
// Passed player (score)
if (!obs.passed && obs.y > playerCar.y + 200) {
obs.passed = true;
score++;
scoreTxt.setText('Drift: ' + score);
}
// Remove off-screen
if (obs.y > 2900) {
obs.destroy();
obstacles.splice(j, 1);
}
}
};
// Center score text horizontally
scoreTxt.setText('Drift: ' + score);
scoreTxt.anchor.set(0.5, 0);
// Play music (if any, not specified in MVP) ===================================================================
--- original.js
+++ change.js
@@ -41,23 +41,37 @@
});
// Player Car Class
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
- var car = self.attachAsset('playerCar', {
+ var car = self.attachAsset('bmwCar', {
anchorX: 0.5,
anchorY: 0.5
});
// Current lane index (0 = left, 1 = center, 2 = right)
self.lane = 1;
- // Move to lane with animation
+ // Move to lane with animation and drifting effect
self.moveToLane = function (laneIndex, duration) {
self.lane = laneIndex;
var targetX = getLaneX(laneIndex);
+ // Determine drift direction
+ var driftAngle = 0;
+ if (laneIndex > self.lane) driftAngle = Math.PI / 10; // right drift
+ else if (laneIndex < self.lane) driftAngle = -Math.PI / 10; // left drift
+ // Animate drift: rotate, move, then straighten
tween(self, {
+ rotation: driftAngle,
x: targetX
}, {
- duration: duration || 120,
- easing: tween.cubicOut
+ duration: (duration || 120) * 0.6,
+ easing: tween.cubicOut,
+ onComplete: function onComplete() {
+ tween(self, {
+ rotation: 0
+ }, {
+ duration: (duration || 120) * 0.4,
+ easing: tween.cubicIn
+ });
+ }
});
};
return self;
});
@@ -71,11 +85,12 @@
/****
* Game Code
****/
+// BMW: white, slightly larger
// Obstacle: yellow ellipse (e.g. traffic cone)
// Enemy car: red box
-// Player car: blue box
+// Player car: BMW (white box) with drifting animation
// Lane setup
var NUM_LANES = 3;
var laneWidth = 410; // 2048 / 5 = ~410, leaves margin on sides
var laneMargin = (2048 - NUM_LANES * laneWidth) / 2; // Center lanes
@@ -85,14 +100,15 @@
}
// Player car setup
var playerCar = new PlayerCar();
playerCar.x = getLaneX(1);
-playerCar.y = 2732 - 350;
+// Adjust y for larger BMW car
+playerCar.y = 2732 - 420;
playerCar.lane = 1;
game.addChild(playerCar);
// Score display
var score = 0;
-var scoreTxt = new Text2('0', {
+var scoreTxt = new Text2('Drift: 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
@@ -196,9 +212,9 @@
// Passed player (score)
if (!enemy.passed && enemy.y > playerCar.y + 200) {
enemy.passed = true;
score++;
- scoreTxt.setText(score);
+ scoreTxt.setText('Drift: ' + score);
}
// Remove off-screen
if (enemy.y > 2900) {
enemy.destroy();
@@ -218,9 +234,9 @@
// Passed player (score)
if (!obs.passed && obs.y > playerCar.y + 200) {
obs.passed = true;
score++;
- scoreTxt.setText(score);
+ scoreTxt.setText('Drift: ' + score);
}
// Remove off-screen
if (obs.y > 2900) {
obs.destroy();
@@ -228,7 +244,7 @@
}
}
};
// Center score text horizontally
-scoreTxt.setText(score);
+scoreTxt.setText('Drift: ' + score);
scoreTxt.anchor.set(0.5, 0);
// Play music (if any, not specified in MVP)
\ No newline at end of file