/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Boost class
var Boost = Container.expand(function () {
var self = Container.call(this);
var boostAsset = self.attachAsset('boost', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = boostAsset.width;
self.height = boostAsset.height;
self.update = function () {
self.y += roadSpeed;
};
return self;
});
// Car class
var Car = Container.expand(function () {
var self = Container.call(this);
var carAsset = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
// For collision, use the container itself
self.width = carAsset.width;
self.height = carAsset.height;
// Car speed (pixels per tick)
self.speed = 18;
// Lateral speed (for smooth steering)
self.lateralSpeed = 0;
// Max lateral speed
self.maxLateralSpeed = 32;
// Steering target (x position)
self.targetX = self.x;
// Update method
self.update = function () {
// Smoothly move towards targetX
var dx = self.targetX - self.x;
if (Math.abs(dx) > 2) {
self.lateralSpeed = Math.max(-self.maxLateralSpeed, Math.min(self.maxLateralSpeed, dx * 0.25));
self.x += self.lateralSpeed;
} else {
self.lateralSpeed = 0;
self.x = self.targetX;
}
};
return self;
});
// Lane marker class
var Lane = Container.expand(function () {
var self = Container.call(this);
var laneAsset = self.attachAsset('lane', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = laneAsset.width;
self.height = laneAsset.height;
self.update = function () {
self.y += roadSpeed;
};
return self;
});
// Obstacle class
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obsAsset = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = obsAsset.width;
self.height = obsAsset.height;
// Update method: move down by road speed
self.update = function () {
self.y += roadSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Lane marker
// Road
// Speed boost
// Obstacle
// Car (player)
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var ROAD_WIDTH = 900;
var ROAD_X = (GAME_WIDTH - ROAD_WIDTH) / 2;
var ROAD_Y = 0;
var LANE_COUNT = 3;
var LANE_WIDTH = ROAD_WIDTH / LANE_COUNT;
var CAR_START_X = GAME_WIDTH / 2;
var CAR_START_Y = GAME_HEIGHT - 500;
var OBSTACLE_MIN_GAP = 600;
var OBSTACLE_MAX_GAP = 1100;
var BOOST_CHANCE = 0.25; // 25% chance to spawn a boost with an obstacle
// Road speed (pixels per tick)
var roadSpeed = 18;
var roadSpeedBase = 18;
var roadSpeedBoosted = 32;
var boostDuration = 90; // ticks (1.5 seconds)
var boostTicks = 0;
// Score
var score = 0;
// Arrays for game objects
var obstacles = [];
var boosts = [];
var lanes = [];
// Road background
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
x: ROAD_X,
y: ROAD_Y
});
game.addChild(road);
// Lane markers
function spawnLaneMarkers() {
// Remove old lanes
for (var i = 0; i < lanes.length; i++) {
lanes[i].destroy();
}
lanes = [];
// For each lane (except the leftmost), draw a marker
for (var l = 1; l < LANE_COUNT; l++) {
for (var y = -200; y < GAME_HEIGHT + 200; y += 400) {
var lane = new Lane();
lane.x = ROAD_X + l * LANE_WIDTH;
lane.y = y;
lanes.push(lane);
game.addChild(lane);
}
}
}
spawnLaneMarkers();
// Car (player)
var car = new Car();
car.x = CAR_START_X;
car.y = CAR_START_Y;
car.targetX = car.x;
game.addChild(car);
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: get lane center x
function getLaneCenter(laneIdx) {
return ROAD_X + LANE_WIDTH * (laneIdx + 0.5);
}
// Helper: spawn an obstacle (and maybe a boost)
function spawnObstacle() {
// Random lane
var laneIdx = Math.floor(Math.random() * LANE_COUNT);
var obs = new Obstacle();
obs.x = getLaneCenter(laneIdx);
obs.y = -obs.height / 2;
obstacles.push(obs);
game.addChild(obs);
// Maybe spawn a boost in a different lane
if (Math.random() < BOOST_CHANCE) {
var boostLane = laneIdx;
// Try to pick a different lane
if (LANE_COUNT > 1) {
while (boostLane === laneIdx) {
boostLane = Math.floor(Math.random() * LANE_COUNT);
}
}
var boost = new Boost();
boost.x = getLaneCenter(boostLane);
boost.y = obs.y;
boosts.push(boost);
game.addChild(boost);
}
}
// Helper: spawn lane markers as they scroll
function updateLaneMarkers() {
for (var i = lanes.length - 1; i >= 0; i--) {
var lane = lanes[i];
lane.update();
if (lane.y > GAME_HEIGHT + 200) {
// Recycle to top
lane.y -= GAME_HEIGHT + 400;
}
}
}
// Dragging
var dragging = false;
var dragOffsetX = 0;
// Touch/mouse controls
game.down = function (x, y, obj) {
// Only allow drag if touch is on car or on road
if (x > ROAD_X && x < ROAD_X + ROAD_WIDTH && y > 0 && y < GAME_HEIGHT) {
dragging = true;
dragOffsetX = x - car.x;
// Set targetX immediately
car.targetX = Math.max(ROAD_X + car.width / 2, Math.min(ROAD_X + ROAD_WIDTH - car.width / 2, x - dragOffsetX));
}
};
game.up = function (x, y, obj) {
dragging = false;
};
game.move = function (x, y, obj) {
if (dragging) {
// Clamp to road
var tx = Math.max(ROAD_X + car.width / 2, Math.min(ROAD_X + ROAD_WIDTH - car.width / 2, x - dragOffsetX));
car.targetX = tx;
}
};
// Game update
var lastObstacleY = -OBSTACLE_MIN_GAP;
game.update = function () {
// Update car
car.update();
// Update lane markers
updateLaneMarkers();
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// Remove if off screen
if (obs.y - obs.height / 2 > GAME_HEIGHT + 100) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with car
if (car.intersects(obs)) {
// Flash screen red, game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
// Update boosts
for (var i = boosts.length - 1; i >= 0; i--) {
var boost = boosts[i];
boost.update();
// Remove if off screen
if (boost.y - boost.height / 2 > GAME_HEIGHT + 100) {
boost.destroy();
boosts.splice(i, 1);
continue;
}
// Collect boost
if (car.intersects(boost)) {
boost.destroy();
boosts.splice(i, 1);
// Activate speed boost
boostTicks = boostDuration;
roadSpeed = roadSpeedBoosted;
// Flash car yellow
LK.effects.flashObject(car, 0xffeb3b, 400);
}
}
// Handle boost timer
if (boostTicks > 0) {
boostTicks--;
if (boostTicks === 0) {
roadSpeed = roadSpeedBase;
}
}
// Spawn new obstacles
if (obstacles.length === 0 || obstacles[obstacles.length - 1].y > OBSTACLE_MIN_GAP + Math.random() * (OBSTACLE_MAX_GAP - OBSTACLE_MIN_GAP)) {
spawnObstacle();
}
// Update score: based on distance survived
score += Math.floor(roadSpeed / 4);
scoreTxt.setText(score);
// Check if car is off the road
if (car.x - car.width / 2 < ROAD_X || car.x + car.width / 2 > ROAD_X + ROAD_WIDTH) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
};
// Reset game state on new game
LK.on('gameStart', function () {
// Remove all obstacles and boosts
for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy();
for (var i = 0; i < boosts.length; i++) boosts[i].destroy();
obstacles = [];
boosts = [];
// Reset car position
car.x = CAR_START_X;
car.y = CAR_START_Y;
car.targetX = car.x;
// Reset score and speed
score = 0;
roadSpeed = roadSpeedBase;
boostTicks = 0;
scoreTxt.setText(score);
// Reset lane markers
spawnLaneMarkers();
}); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,313 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Boost class
+var Boost = Container.expand(function () {
+ var self = Container.call(this);
+ var boostAsset = self.attachAsset('boost', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = boostAsset.width;
+ self.height = boostAsset.height;
+ self.update = function () {
+ self.y += roadSpeed;
+ };
+ return self;
+});
+// Car class
+var Car = Container.expand(function () {
+ var self = Container.call(this);
+ var carAsset = self.attachAsset('car', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // For collision, use the container itself
+ self.width = carAsset.width;
+ self.height = carAsset.height;
+ // Car speed (pixels per tick)
+ self.speed = 18;
+ // Lateral speed (for smooth steering)
+ self.lateralSpeed = 0;
+ // Max lateral speed
+ self.maxLateralSpeed = 32;
+ // Steering target (x position)
+ self.targetX = self.x;
+ // Update method
+ self.update = function () {
+ // Smoothly move towards targetX
+ var dx = self.targetX - self.x;
+ if (Math.abs(dx) > 2) {
+ self.lateralSpeed = Math.max(-self.maxLateralSpeed, Math.min(self.maxLateralSpeed, dx * 0.25));
+ self.x += self.lateralSpeed;
+ } else {
+ self.lateralSpeed = 0;
+ self.x = self.targetX;
+ }
+ };
+ return self;
+});
+// Lane marker class
+var Lane = Container.expand(function () {
+ var self = Container.call(this);
+ var laneAsset = self.attachAsset('lane', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = laneAsset.width;
+ self.height = laneAsset.height;
+ self.update = function () {
+ self.y += roadSpeed;
+ };
+ return self;
+});
+// Obstacle class
+var Obstacle = Container.expand(function () {
+ var self = Container.call(this);
+ var obsAsset = self.attachAsset('obstacle', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = obsAsset.width;
+ self.height = obsAsset.height;
+ // Update method: move down by road speed
+ self.update = function () {
+ self.y += roadSpeed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// Lane marker
+// Road
+// Speed boost
+// Obstacle
+// Car (player)
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var ROAD_WIDTH = 900;
+var ROAD_X = (GAME_WIDTH - ROAD_WIDTH) / 2;
+var ROAD_Y = 0;
+var LANE_COUNT = 3;
+var LANE_WIDTH = ROAD_WIDTH / LANE_COUNT;
+var CAR_START_X = GAME_WIDTH / 2;
+var CAR_START_Y = GAME_HEIGHT - 500;
+var OBSTACLE_MIN_GAP = 600;
+var OBSTACLE_MAX_GAP = 1100;
+var BOOST_CHANCE = 0.25; // 25% chance to spawn a boost with an obstacle
+// Road speed (pixels per tick)
+var roadSpeed = 18;
+var roadSpeedBase = 18;
+var roadSpeedBoosted = 32;
+var boostDuration = 90; // ticks (1.5 seconds)
+var boostTicks = 0;
+// Score
+var score = 0;
+// Arrays for game objects
+var obstacles = [];
+var boosts = [];
+var lanes = [];
+// Road background
+var road = LK.getAsset('road', {
+ anchorX: 0,
+ anchorY: 0,
+ x: ROAD_X,
+ y: ROAD_Y
+});
+game.addChild(road);
+// Lane markers
+function spawnLaneMarkers() {
+ // Remove old lanes
+ for (var i = 0; i < lanes.length; i++) {
+ lanes[i].destroy();
+ }
+ lanes = [];
+ // For each lane (except the leftmost), draw a marker
+ for (var l = 1; l < LANE_COUNT; l++) {
+ for (var y = -200; y < GAME_HEIGHT + 200; y += 400) {
+ var lane = new Lane();
+ lane.x = ROAD_X + l * LANE_WIDTH;
+ lane.y = y;
+ lanes.push(lane);
+ game.addChild(lane);
+ }
+ }
+}
+spawnLaneMarkers();
+// Car (player)
+var car = new Car();
+car.x = CAR_START_X;
+car.y = CAR_START_Y;
+car.targetX = car.x;
+game.addChild(car);
+// Score text
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Helper: get lane center x
+function getLaneCenter(laneIdx) {
+ return ROAD_X + LANE_WIDTH * (laneIdx + 0.5);
+}
+// Helper: spawn an obstacle (and maybe a boost)
+function spawnObstacle() {
+ // Random lane
+ var laneIdx = Math.floor(Math.random() * LANE_COUNT);
+ var obs = new Obstacle();
+ obs.x = getLaneCenter(laneIdx);
+ obs.y = -obs.height / 2;
+ obstacles.push(obs);
+ game.addChild(obs);
+ // Maybe spawn a boost in a different lane
+ if (Math.random() < BOOST_CHANCE) {
+ var boostLane = laneIdx;
+ // Try to pick a different lane
+ if (LANE_COUNT > 1) {
+ while (boostLane === laneIdx) {
+ boostLane = Math.floor(Math.random() * LANE_COUNT);
+ }
+ }
+ var boost = new Boost();
+ boost.x = getLaneCenter(boostLane);
+ boost.y = obs.y;
+ boosts.push(boost);
+ game.addChild(boost);
+ }
+}
+// Helper: spawn lane markers as they scroll
+function updateLaneMarkers() {
+ for (var i = lanes.length - 1; i >= 0; i--) {
+ var lane = lanes[i];
+ lane.update();
+ if (lane.y > GAME_HEIGHT + 200) {
+ // Recycle to top
+ lane.y -= GAME_HEIGHT + 400;
+ }
+ }
+}
+// Dragging
+var dragging = false;
+var dragOffsetX = 0;
+// Touch/mouse controls
+game.down = function (x, y, obj) {
+ // Only allow drag if touch is on car or on road
+ if (x > ROAD_X && x < ROAD_X + ROAD_WIDTH && y > 0 && y < GAME_HEIGHT) {
+ dragging = true;
+ dragOffsetX = x - car.x;
+ // Set targetX immediately
+ car.targetX = Math.max(ROAD_X + car.width / 2, Math.min(ROAD_X + ROAD_WIDTH - car.width / 2, x - dragOffsetX));
+ }
+};
+game.up = function (x, y, obj) {
+ dragging = false;
+};
+game.move = function (x, y, obj) {
+ if (dragging) {
+ // Clamp to road
+ var tx = Math.max(ROAD_X + car.width / 2, Math.min(ROAD_X + ROAD_WIDTH - car.width / 2, x - dragOffsetX));
+ car.targetX = tx;
+ }
+};
+// Game update
+var lastObstacleY = -OBSTACLE_MIN_GAP;
+game.update = function () {
+ // Update car
+ car.update();
+ // Update lane markers
+ updateLaneMarkers();
+ // Update obstacles
+ for (var i = obstacles.length - 1; i >= 0; i--) {
+ var obs = obstacles[i];
+ obs.update();
+ // Remove if off screen
+ if (obs.y - obs.height / 2 > GAME_HEIGHT + 100) {
+ obs.destroy();
+ obstacles.splice(i, 1);
+ continue;
+ }
+ // Collision with car
+ if (car.intersects(obs)) {
+ // Flash screen red, game over
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Update boosts
+ for (var i = boosts.length - 1; i >= 0; i--) {
+ var boost = boosts[i];
+ boost.update();
+ // Remove if off screen
+ if (boost.y - boost.height / 2 > GAME_HEIGHT + 100) {
+ boost.destroy();
+ boosts.splice(i, 1);
+ continue;
+ }
+ // Collect boost
+ if (car.intersects(boost)) {
+ boost.destroy();
+ boosts.splice(i, 1);
+ // Activate speed boost
+ boostTicks = boostDuration;
+ roadSpeed = roadSpeedBoosted;
+ // Flash car yellow
+ LK.effects.flashObject(car, 0xffeb3b, 400);
+ }
+ }
+ // Handle boost timer
+ if (boostTicks > 0) {
+ boostTicks--;
+ if (boostTicks === 0) {
+ roadSpeed = roadSpeedBase;
+ }
+ }
+ // Spawn new obstacles
+ if (obstacles.length === 0 || obstacles[obstacles.length - 1].y > OBSTACLE_MIN_GAP + Math.random() * (OBSTACLE_MAX_GAP - OBSTACLE_MIN_GAP)) {
+ spawnObstacle();
+ }
+ // Update score: based on distance survived
+ score += Math.floor(roadSpeed / 4);
+ scoreTxt.setText(score);
+ // Check if car is off the road
+ if (car.x - car.width / 2 < ROAD_X || car.x + car.width / 2 > ROAD_X + ROAD_WIDTH) {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+};
+// Reset game state on new game
+LK.on('gameStart', function () {
+ // Remove all obstacles and boosts
+ for (var i = 0; i < obstacles.length; i++) obstacles[i].destroy();
+ for (var i = 0; i < boosts.length; i++) boosts[i].destroy();
+ obstacles = [];
+ boosts = [];
+ // Reset car position
+ car.x = CAR_START_X;
+ car.y = CAR_START_Y;
+ car.targetX = car.x;
+ // Reset score and speed
+ score = 0;
+ roadSpeed = roadSpeedBase;
+ boostTicks = 0;
+ scoreTxt.setText(score);
+ // Reset lane markers
+ spawnLaneMarkers();
});
\ No newline at end of file