/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Player Car var Car = Container.expand(function () { var self = Container.call(this); var carAsset = self.attachAsset('car', { anchorX: 0.5, anchorY: 0.5 }); // For collision, use bounding box of carAsset self.width = carAsset.width; self.height = carAsset.height; // Lane: 0 (left), 1 (center), 2 (right) self.lane = 1; // Move to lane (0,1,2) self.moveToLane = function (lane) { self.lane = lane; // Animate to new x position var targetX = roadLeft + laneWidth * (lane + 0.5); tween(self, { x: targetX }, { duration: 120, easing: tween.cubicOut }); }; return self; }); // Coin (collectible) var Coin = Container.expand(function () { var self = Container.call(this); var coinAsset = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.width = coinAsset.width; self.height = coinAsset.height; self.lane = 1; self.setLane = function (lane, y) { self.lane = lane; self.x = roadLeft + laneWidth * (lane + 0.5); self.y = y; }; self.update = function () { self.y += game.roadSpeed; }; return self; }); // Extra Life (collectible) var ExtraLife = Container.expand(function () { var self = Container.call(this); var heartAsset = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); self.width = heartAsset.width; self.height = heartAsset.height; self.lane = 1; self.setLane = function (lane, y) { self.lane = lane; self.x = roadLeft + laneWidth * (lane + 0.5); self.y = y; }; self.update = function () { self.y += game.roadSpeed; }; return self; }); // Heart (lives display) var Heart = Container.expand(function () { var self = Container.call(this); var heartAsset = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); self.width = heartAsset.width; self.height = heartAsset.height; self.setPosition = function (index) { self.x = -120 * index; self.y = 200; }; return self; }); // Lane Divider var LaneDivider = Container.expand(function () { var self = Container.call(this); var dividerAsset = self.attachAsset('laneDivider', { anchorX: 0.5, anchorY: 0.5 }); self.width = dividerAsset.width; self.height = dividerAsset.height; // Set lane and position self.setLane = function (lane, y) { self.lane = lane; self.x = roadLeft + laneWidth * (lane + 1); self.y = y; }; // Update per tick self.update = function () { self.y += game.roadSpeed; // Loop to top if out of screen if (self.y > 2732 + self.height / 2) { self.y -= 2732 + self.height; } }; return self; }); // Obstacle (other cars/roadblocks) 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; // Lane: 0,1,2 self.lane = 1; // Set lane and position self.setLane = function (lane, y) { self.lane = lane; self.x = roadLeft + laneWidth * (lane + 0.5); self.y = y; }; // Update per tick self.update = function () { self.y += game.roadSpeed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Lane divider - white thin rectangle // Road - gray rectangle, wide enough for 3 lanes // Obstacle - red rectangle (other cars/roadblocks) // Car (player) - blue rectangle, rear facing player // Road parameters var roadWidth = 1200; var roadLeft = (2048 - roadWidth) / 2; var laneCount = 3; var laneWidth = roadWidth / laneCount; // Add road background var road = LK.getAsset('road', { anchorX: 0, anchorY: 0 }); road.x = roadLeft; road.y = 0; game.addChild(road); // Lane dividers (2 between 3 lanes, repeated vertically) var laneDividers = []; var dividerCount = Math.ceil(2732 / 400) + 2; for (var l = 0; l < laneCount - 1; l++) { for (var i = 0; i < dividerCount; i++) { var divider = new LaneDivider(); divider.setLane(l, i * 400); laneDividers.push(divider); game.addChild(divider); } } // Player car var car = new Car(); car.y = 2732 - 400; car.moveToLane(1); // Start in center lane car.x = roadLeft + laneWidth * 1.5; game.addChild(car); // Obstacles array var obstacles = []; // Coins array var coins = []; // Extra Lives array var extraLives = []; // Maximum lives allowed var maxLives = 3; // Score var score = 0; var highScore = storage.highScore || 0; var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // High Score text var highScoreTxt = new Text2('High Score: ' + highScore, { size: 80, fill: 0xFFDD44 }); highScoreTxt.anchor.set(0.5, 0); highScoreTxt.y = 140; highScoreTxt.visible = false; LK.gui.top.addChild(highScoreTxt); // Coin counter var coinCount = 0; var coinTxt = new Text2('0', { size: 100, fill: 0xFFFF00 }); coinTxt.anchor.set(1, 0); // right-top coinTxt.x = 0; coinTxt.y = 40; LK.gui.topRight.addChild(coinTxt); // Lives system var lives = 1; var hearts = []; var heartsContainer = new Container(); heartsContainer.x = -20; heartsContainer.y = 0; LK.gui.topRight.addChild(heartsContainer); // Create hearts for lives display for (var i = 0; i < lives; i++) { var heart = new Heart(); heart.setPosition(i); hearts.push(heart); heartsContainer.addChild(heart); } // Game state game.roadSpeed = 16; // Initial speed (pixels per frame) var minRoadSpeed = 16; var maxRoadSpeed = 38; var speedIncreaseInterval = 600; // ticks between speed increases var lastSpeedIncreaseTick = 0; var obstacleInterval = 60; // ticks between obstacles var lastObstacleTick = 0; var gameOver = false; // Reset high score visibility when game starts highScoreTxt.visible = false; // Touch/drag handling var dragStartX = null; var dragStartLane = null; var dragActive = false; // Helper: get lane from x function getLaneFromX(x) { var relX = x - roadLeft; var lane = Math.floor(relX / laneWidth); if (lane < 0) { lane = 0; } if (lane > laneCount - 1) { lane = laneCount - 1; } return lane; } // Helper: clamp lane function clampLane(lane) { if (lane < 0) { return 0; } if (lane > laneCount - 1) { return laneCount - 1; } return lane; } // Handle swipe left/right to change lanes game.down = function (x, y, obj) { if (gameOver) { return; } dragStartX = x; dragStartLane = car.lane; dragActive = true; }; game.move = function (x, y, obj) { if (!dragActive || gameOver) { return; } var dx = x - dragStartX; // If drag exceeds 120px, move lane if (Math.abs(dx) > 120) { var dir = dx > 0 ? 1 : -1; var newLane = clampLane(dragStartLane + dir); if (newLane !== car.lane) { car.moveToLane(newLane); dragActive = false; // Only allow one lane change per swipe } } }; game.up = function (x, y, obj) { dragActive = false; }; // Main update loop game.update = function () { if (gameOver) { return; } // Update lane dividers for (var i = 0; i < laneDividers.length; i++) { laneDividers[i].update(); } // 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 > 2732) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision with car if (obs.intersects(car)) { // Play hasar sound LK.getSound('hasar').play(); // Take damage // Flash screen red LK.effects.flashScreen(0xff0000, 800); // Reduce lives lives--; // Remove one heart if (hearts.length > 0) { var heart = hearts.pop(); heart.destroy(); } // If no more lives, game over if (lives <= 0) { gameOver = true; // Update high score if current score is higher if (score > highScore) { highScore = score; storage.highScore = highScore; } // Show high score text highScoreTxt.setText('High Score: ' + highScore); highScoreTxt.visible = true; // Show game over immediately LK.showGameOver(); return; } else { // Remove this obstacle obs.destroy(); obstacles.splice(i, 1); // Brief invulnerability period car.alpha = 0.5; LK.setTimeout(function () { car.alpha = 1; }, 1500); continue; } } } // Update coins for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; coin.update(); // Remove if off screen if (coin.y - coin.height / 2 > 2732) { coin.destroy(); coins.splice(i, 1); continue; } // Collect coin if (coin.intersects(car)) { score += 10; scoreTxt.setText(score); coinCount += 1; coinTxt.setText(coinCount); // Play para sound LK.getSound('para').play(); coin.destroy(); coins.splice(i, 1); continue; } } // Update extra lives for (var i = extraLives.length - 1; i >= 0; i--) { var extraLife = extraLives[i]; extraLife.update(); // Remove if off screen if (extraLife.y - extraLife.height / 2 > 2732) { extraLife.destroy(); extraLives.splice(i, 1); continue; } // Collect extra life if (extraLife.intersects(car)) { // Play kalp sound LK.getSound('kalp').play(); if (lives < maxLives) { // Add a life lives++; // Add heart display var heart = new Heart(); heart.setPosition(hearts.length); hearts.push(heart); heartsContainer.addChild(heart); // Flash green to indicate positive effect LK.effects.flashScreen(0x00ff00, 400); } else { // Too many lives - penalize score score -= 20; if (score < 0) { score = 0; } scoreTxt.setText(score); // Flash yellow to indicate warning LK.effects.flashScreen(0xffff00, 400); } extraLife.destroy(); extraLives.splice(i, 1); continue; } } // Spawn obstacles if (LK.ticks - lastObstacleTick >= obstacleInterval) { lastObstacleTick = LK.ticks; // Randomly pick 1 or 2 lanes to spawn obstacles var lanesToBlock = []; var blockCount = Math.random() < 0.7 ? 1 : 2; while (lanesToBlock.length < blockCount) { var lane = Math.floor(Math.random() * laneCount); var already = false; for (var j = 0; j < lanesToBlock.length; j++) { if (lanesToBlock[j] === lane) { already = true; } } if (!already) { lanesToBlock.push(lane); } } for (var k = 0; k < lanesToBlock.length; k++) { var obs = new Obstacle(); obs.setLane(lanesToBlock[k], -obs.height / 2); obstacles.push(obs); game.addChild(obs); } // Spawn coins in lanes not blocked by obstacles for (var laneIdx = 0; laneIdx < laneCount; laneIdx++) { var blocked = false; for (var b = 0; b < lanesToBlock.length; b++) { if (lanesToBlock[b] === laneIdx) { blocked = true; } } if (!blocked) { // Spawn extra life (5% chance if below max lives) if (lives < maxLives && Math.random() < 0.05) { var extraLife = new ExtraLife(); extraLife.setLane(laneIdx, -extraLife.height / 2 - 120); extraLives.push(extraLife); game.addChild(extraLife); } // Spawn coin (70% chance if not spawning extra life) else if (Math.random() < 0.7) { var coin = new Coin(); // Place coin a bit ahead of obstacles coin.setLane(laneIdx, -coin.height / 2 - 120); coins.push(coin); game.addChild(coin); } } } } // Increase speed and difficulty over time if (LK.ticks - lastSpeedIncreaseTick >= speedIncreaseInterval) { lastSpeedIncreaseTick = LK.ticks; if (game.roadSpeed < maxRoadSpeed) { game.roadSpeed += 2; if (game.roadSpeed > maxRoadSpeed) { game.roadSpeed = maxRoadSpeed; } } if (obstacleInterval > 28) { obstacleInterval -= 4; if (obstacleInterval < 28) { obstacleInterval = 28; } } } // Score: increase by 1 every 10 ticks if (LK.ticks % 10 === 0) { score += 1; scoreTxt.setText(score); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Player Car
var Car = Container.expand(function () {
var self = Container.call(this);
var carAsset = self.attachAsset('car', {
anchorX: 0.5,
anchorY: 0.5
});
// For collision, use bounding box of carAsset
self.width = carAsset.width;
self.height = carAsset.height;
// Lane: 0 (left), 1 (center), 2 (right)
self.lane = 1;
// Move to lane (0,1,2)
self.moveToLane = function (lane) {
self.lane = lane;
// Animate to new x position
var targetX = roadLeft + laneWidth * (lane + 0.5);
tween(self, {
x: targetX
}, {
duration: 120,
easing: tween.cubicOut
});
};
return self;
});
// Coin (collectible)
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinAsset = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = coinAsset.width;
self.height = coinAsset.height;
self.lane = 1;
self.setLane = function (lane, y) {
self.lane = lane;
self.x = roadLeft + laneWidth * (lane + 0.5);
self.y = y;
};
self.update = function () {
self.y += game.roadSpeed;
};
return self;
});
// Extra Life (collectible)
var ExtraLife = Container.expand(function () {
var self = Container.call(this);
var heartAsset = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = heartAsset.width;
self.height = heartAsset.height;
self.lane = 1;
self.setLane = function (lane, y) {
self.lane = lane;
self.x = roadLeft + laneWidth * (lane + 0.5);
self.y = y;
};
self.update = function () {
self.y += game.roadSpeed;
};
return self;
});
// Heart (lives display)
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartAsset = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = heartAsset.width;
self.height = heartAsset.height;
self.setPosition = function (index) {
self.x = -120 * index;
self.y = 200;
};
return self;
});
// Lane Divider
var LaneDivider = Container.expand(function () {
var self = Container.call(this);
var dividerAsset = self.attachAsset('laneDivider', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = dividerAsset.width;
self.height = dividerAsset.height;
// Set lane and position
self.setLane = function (lane, y) {
self.lane = lane;
self.x = roadLeft + laneWidth * (lane + 1);
self.y = y;
};
// Update per tick
self.update = function () {
self.y += game.roadSpeed;
// Loop to top if out of screen
if (self.y > 2732 + self.height / 2) {
self.y -= 2732 + self.height;
}
};
return self;
});
// Obstacle (other cars/roadblocks)
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;
// Lane: 0,1,2
self.lane = 1;
// Set lane and position
self.setLane = function (lane, y) {
self.lane = lane;
self.x = roadLeft + laneWidth * (lane + 0.5);
self.y = y;
};
// Update per tick
self.update = function () {
self.y += game.roadSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Lane divider - white thin rectangle
// Road - gray rectangle, wide enough for 3 lanes
// Obstacle - red rectangle (other cars/roadblocks)
// Car (player) - blue rectangle, rear facing player
// Road parameters
var roadWidth = 1200;
var roadLeft = (2048 - roadWidth) / 2;
var laneCount = 3;
var laneWidth = roadWidth / laneCount;
// Add road background
var road = LK.getAsset('road', {
anchorX: 0,
anchorY: 0
});
road.x = roadLeft;
road.y = 0;
game.addChild(road);
// Lane dividers (2 between 3 lanes, repeated vertically)
var laneDividers = [];
var dividerCount = Math.ceil(2732 / 400) + 2;
for (var l = 0; l < laneCount - 1; l++) {
for (var i = 0; i < dividerCount; i++) {
var divider = new LaneDivider();
divider.setLane(l, i * 400);
laneDividers.push(divider);
game.addChild(divider);
}
}
// Player car
var car = new Car();
car.y = 2732 - 400;
car.moveToLane(1); // Start in center lane
car.x = roadLeft + laneWidth * 1.5;
game.addChild(car);
// Obstacles array
var obstacles = [];
// Coins array
var coins = [];
// Extra Lives array
var extraLives = [];
// Maximum lives allowed
var maxLives = 3;
// Score
var score = 0;
var highScore = storage.highScore || 0;
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// High Score text
var highScoreTxt = new Text2('High Score: ' + highScore, {
size: 80,
fill: 0xFFDD44
});
highScoreTxt.anchor.set(0.5, 0);
highScoreTxt.y = 140;
highScoreTxt.visible = false;
LK.gui.top.addChild(highScoreTxt);
// Coin counter
var coinCount = 0;
var coinTxt = new Text2('0', {
size: 100,
fill: 0xFFFF00
});
coinTxt.anchor.set(1, 0); // right-top
coinTxt.x = 0;
coinTxt.y = 40;
LK.gui.topRight.addChild(coinTxt);
// Lives system
var lives = 1;
var hearts = [];
var heartsContainer = new Container();
heartsContainer.x = -20;
heartsContainer.y = 0;
LK.gui.topRight.addChild(heartsContainer);
// Create hearts for lives display
for (var i = 0; i < lives; i++) {
var heart = new Heart();
heart.setPosition(i);
hearts.push(heart);
heartsContainer.addChild(heart);
}
// Game state
game.roadSpeed = 16; // Initial speed (pixels per frame)
var minRoadSpeed = 16;
var maxRoadSpeed = 38;
var speedIncreaseInterval = 600; // ticks between speed increases
var lastSpeedIncreaseTick = 0;
var obstacleInterval = 60; // ticks between obstacles
var lastObstacleTick = 0;
var gameOver = false;
// Reset high score visibility when game starts
highScoreTxt.visible = false;
// Touch/drag handling
var dragStartX = null;
var dragStartLane = null;
var dragActive = false;
// Helper: get lane from x
function getLaneFromX(x) {
var relX = x - roadLeft;
var lane = Math.floor(relX / laneWidth);
if (lane < 0) {
lane = 0;
}
if (lane > laneCount - 1) {
lane = laneCount - 1;
}
return lane;
}
// Helper: clamp lane
function clampLane(lane) {
if (lane < 0) {
return 0;
}
if (lane > laneCount - 1) {
return laneCount - 1;
}
return lane;
}
// Handle swipe left/right to change lanes
game.down = function (x, y, obj) {
if (gameOver) {
return;
}
dragStartX = x;
dragStartLane = car.lane;
dragActive = true;
};
game.move = function (x, y, obj) {
if (!dragActive || gameOver) {
return;
}
var dx = x - dragStartX;
// If drag exceeds 120px, move lane
if (Math.abs(dx) > 120) {
var dir = dx > 0 ? 1 : -1;
var newLane = clampLane(dragStartLane + dir);
if (newLane !== car.lane) {
car.moveToLane(newLane);
dragActive = false; // Only allow one lane change per swipe
}
}
};
game.up = function (x, y, obj) {
dragActive = false;
};
// Main update loop
game.update = function () {
if (gameOver) {
return;
}
// Update lane dividers
for (var i = 0; i < laneDividers.length; i++) {
laneDividers[i].update();
}
// 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 > 2732) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with car
if (obs.intersects(car)) {
// Play hasar sound
LK.getSound('hasar').play();
// Take damage
// Flash screen red
LK.effects.flashScreen(0xff0000, 800);
// Reduce lives
lives--;
// Remove one heart
if (hearts.length > 0) {
var heart = hearts.pop();
heart.destroy();
}
// If no more lives, game over
if (lives <= 0) {
gameOver = true;
// Update high score if current score is higher
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
// Show high score text
highScoreTxt.setText('High Score: ' + highScore);
highScoreTxt.visible = true;
// Show game over immediately
LK.showGameOver();
return;
} else {
// Remove this obstacle
obs.destroy();
obstacles.splice(i, 1);
// Brief invulnerability period
car.alpha = 0.5;
LK.setTimeout(function () {
car.alpha = 1;
}, 1500);
continue;
}
}
}
// Update coins
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
coin.update();
// Remove if off screen
if (coin.y - coin.height / 2 > 2732) {
coin.destroy();
coins.splice(i, 1);
continue;
}
// Collect coin
if (coin.intersects(car)) {
score += 10;
scoreTxt.setText(score);
coinCount += 1;
coinTxt.setText(coinCount);
// Play para sound
LK.getSound('para').play();
coin.destroy();
coins.splice(i, 1);
continue;
}
}
// Update extra lives
for (var i = extraLives.length - 1; i >= 0; i--) {
var extraLife = extraLives[i];
extraLife.update();
// Remove if off screen
if (extraLife.y - extraLife.height / 2 > 2732) {
extraLife.destroy();
extraLives.splice(i, 1);
continue;
}
// Collect extra life
if (extraLife.intersects(car)) {
// Play kalp sound
LK.getSound('kalp').play();
if (lives < maxLives) {
// Add a life
lives++;
// Add heart display
var heart = new Heart();
heart.setPosition(hearts.length);
hearts.push(heart);
heartsContainer.addChild(heart);
// Flash green to indicate positive effect
LK.effects.flashScreen(0x00ff00, 400);
} else {
// Too many lives - penalize score
score -= 20;
if (score < 0) {
score = 0;
}
scoreTxt.setText(score);
// Flash yellow to indicate warning
LK.effects.flashScreen(0xffff00, 400);
}
extraLife.destroy();
extraLives.splice(i, 1);
continue;
}
}
// Spawn obstacles
if (LK.ticks - lastObstacleTick >= obstacleInterval) {
lastObstacleTick = LK.ticks;
// Randomly pick 1 or 2 lanes to spawn obstacles
var lanesToBlock = [];
var blockCount = Math.random() < 0.7 ? 1 : 2;
while (lanesToBlock.length < blockCount) {
var lane = Math.floor(Math.random() * laneCount);
var already = false;
for (var j = 0; j < lanesToBlock.length; j++) {
if (lanesToBlock[j] === lane) {
already = true;
}
}
if (!already) {
lanesToBlock.push(lane);
}
}
for (var k = 0; k < lanesToBlock.length; k++) {
var obs = new Obstacle();
obs.setLane(lanesToBlock[k], -obs.height / 2);
obstacles.push(obs);
game.addChild(obs);
}
// Spawn coins in lanes not blocked by obstacles
for (var laneIdx = 0; laneIdx < laneCount; laneIdx++) {
var blocked = false;
for (var b = 0; b < lanesToBlock.length; b++) {
if (lanesToBlock[b] === laneIdx) {
blocked = true;
}
}
if (!blocked) {
// Spawn extra life (5% chance if below max lives)
if (lives < maxLives && Math.random() < 0.05) {
var extraLife = new ExtraLife();
extraLife.setLane(laneIdx, -extraLife.height / 2 - 120);
extraLives.push(extraLife);
game.addChild(extraLife);
}
// Spawn coin (70% chance if not spawning extra life)
else if (Math.random() < 0.7) {
var coin = new Coin();
// Place coin a bit ahead of obstacles
coin.setLane(laneIdx, -coin.height / 2 - 120);
coins.push(coin);
game.addChild(coin);
}
}
}
}
// Increase speed and difficulty over time
if (LK.ticks - lastSpeedIncreaseTick >= speedIncreaseInterval) {
lastSpeedIncreaseTick = LK.ticks;
if (game.roadSpeed < maxRoadSpeed) {
game.roadSpeed += 2;
if (game.roadSpeed > maxRoadSpeed) {
game.roadSpeed = maxRoadSpeed;
}
}
if (obstacleInterval > 28) {
obstacleInterval -= 4;
if (obstacleInterval < 28) {
obstacleInterval = 28;
}
}
}
// Score: increase by 1 every 10 ticks
if (LK.ticks % 10 === 0) {
score += 1;
scoreTxt.setText(score);
}
};
pixel art car top view In-Game asset. 2d. High contrast. No shadows
pixel art coin 2d. In-Game asset. 2d. High contrast. No shadows
pixel art 2d road 3 lane top view
pixel art 2d road 3 lane top view no lane
pixel art 2d white anime girl In-Game asset. 2d. High contrast. No shadows
pixel art 2d heart. In-Game asset. 2d. High contrast. No shadows