User prompt
The game should slow down a bit when the player gets the star assets
User prompt
add a new asset and it becomes a superpower
User prompt
add superpower to an asset other than coin
User prompt
Special powers like coins will appear at random times so that you don't get stuck in obstacles when you get them.
User prompt
Every time you reach 20 coins, a super power potion that helps you avoid obstacles will appear in a random place.
User prompt
Coins will randomly give you between 1 and 5 coins
User prompt
add coin counter top right
User prompt
Right and left movements can be made from anywhere on the screen
User prompt
coins should not go over obstacles
User prompt
slower at the beginning, faster as the score increases
Code edit (1 edits merged)
Please save this source code
User prompt
Ice Run
Initial prompt
make ice run game
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Coin class: 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; // will be set on spawn self.speed = 16; // will be set by game for difficulty self.update = function () { self.y += self.speed; // Optional: spin effect self.rotation += 0.03; }; return self; }); // Obstacle class: cracks, snow piles, ice blocks, trees, rocks var Obstacle = Container.expand(function () { var self = Container.call(this); // Default to 'block', will be replaced on spawn if needed var assetId = 'block'; var obstacleAsset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.type = assetId; self.width = obstacleAsset.width; self.height = obstacleAsset.height; self.lane = 1; // will be set on spawn self.speed = 16; // will be set by game for difficulty self.update = function () { self.y += self.speed; }; return self; }); // Player class: the sliding character var Player = Container.expand(function () { var self = Container.call(this); // Attach player asset (blue ellipse for ice runner) var playerAsset = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); // Set up initial properties self.width = playerAsset.width; self.height = playerAsset.height; self.lane = 1; // 0: left, 1: center, 2: right // For smooth lane transitions self.targetX = 0; // Walking animation state self._walkTween = null; self._walkDir = 1; // Start walking animation function startWalking() { // Stop any previous tweens on playerAsset for scaleX and scaleY tween.stop(playerAsset, { scaleX: true, scaleY: true }); // Animate scaleX to create a "waddle" effect tween(playerAsset, { scaleX: 1.15 }, { duration: 120, easing: tween.linear, yoyo: true, repeat: Infinity, onYoyo: function onYoyo() { // Flip direction for next step self._walkDir *= -1; playerAsset.scaleX = 1 + 0.15 * self._walkDir; } }); // Animate scaleY for a subtle bounce tween(playerAsset, { scaleY: 0.92 }, { duration: 120, easing: tween.linear, yoyo: true, repeat: Infinity }); } startWalking(); // Update method: smoothly move to targetX self.update = function () { // Smoothly move towards targetX self.x += (self.targetX - self.x) * 0.25; }; return self; }); // SpecialPower class: clears all obstacles when collected var SpecialPower = Container.expand(function () { var self = Container.call(this); var asset = self.attachAsset('star', { // Use new star asset for superpower anchorX: 0.5, anchorY: 0.5 }); self.width = asset.width; self.height = asset.height; self.lane = 1; self.speed = 16; self.update = function () { self.y += self.speed; self.rotation += 0.03; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ // No title, no description // Always backgroundColor is black backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- Moving, repeating background setup --- var bg1 = LK.getAsset('bg_ice_landscape', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); var bg2 = LK.getAsset('bg_ice_landscape', { anchorX: 0, anchorY: 0, x: 0, y: -2732, width: 2048, height: 2732 }); game.addChild(bg1); game.addChild(bg2); // --- Lane setup --- // new superpower asset var laneCount = 3; var laneWidth = 400; // Each lane is 400px wide var laneCenters = [2048 / 2 - laneWidth, // left 2048 / 2, // center 2048 / 2 + laneWidth // right ]; // --- Player setup --- var player = new Player(); player.y = 2732 - 400; // Near bottom player.lane = 1; player.x = laneCenters[player.lane]; player.targetX = player.x; game.addChild(player); // --- Score and GUI --- var score = 0; var scoreTxt = new Text2('Score: 0', { size: 70, fill: 0xFFFFFF, font: "Pixel, 'Press Start 2P', 'Courier New', monospace" }); scoreTxt.anchor.set(1, 0); // Anchor to right edge, top scoreTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu) scoreTxt.y = 20; // Padding from top LK.gui.topRight.addChild(scoreTxt); // --- Coin counter --- var coinCount = 0; var coinTxt = new Text2('Coin: 0', { size: 50, fill: 0xFFE066, font: "Pixel, 'Press Start 2P', 'Courier New', monospace" }); coinTxt.anchor.set(1, 0); // Anchor to right edge, top coinTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu) coinTxt.y = 150; // Place below score LK.gui.topRight.addChild(coinTxt); // --- Game state --- var obstacles = []; var coins = []; var specialPowers = []; var gameSpeed = 16; // Initial speed var ticksSinceLastObstacle = 0; var ticksSinceLastCoin = 0; var ticksSinceLastPower = 0; var nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Random interval for next power var obstacleInterval = 60; // Frames between obstacles var coinInterval = 90; // Frames between coins var isDragging = false; var dragStartX = 0; var dragStartLane = 1; // --- Asset initialization (shapes) --- // --- Touch/drag controls --- game.down = function (x, y, obj) { isDragging = true; dragStartX = x; dragStartLane = player.lane; }; game.move = function (x, y, obj) { if (!isDragging) return; // Calculate drag offset var dx = x - dragStartX; // Determine which lane the drag is closest to, relative to dragStartX var laneOffset = Math.round(dx / laneWidth); var newLane = dragStartLane + laneOffset; if (newLane < 0) newLane = 0; if (newLane > 2) newLane = 2; if (newLane !== player.lane) { player.lane = newLane; player.targetX = laneCenters[player.lane]; } }; game.up = function (x, y, obj) { isDragging = false; }; // --- Main game update loop --- game.update = function () { // --- Animate and repeat background --- bg1.y += gameSpeed; bg2.y += gameSpeed; // If a background has moved off the bottom, move it above the other if (bg1.y >= 2732) { bg1.y = bg2.y - 2732; } if (bg2.y >= 2732) { bg2.y = bg1.y - 2732; } // Scale speed and intervals with score for dynamic difficulty (0 to 1000 points) var difficulty = score; if (difficulty > 1000) difficulty = 1000; // Speed: from 12 (easy) to 40 (hard) linearly gameSpeed = 12 + difficulty / 1000 * (40 - 12); // Intervals: from 60 (easy) to 30 (hard) for obstacles, 90 to 50 for coins obstacleInterval = 60 - difficulty / 1000 * (60 - 30); if (obstacleInterval < 30) obstacleInterval = 30; coinInterval = 90 - difficulty / 1000 * (90 - 50); if (coinInterval < 50) coinInterval = 50; gameSpeed = Math.round(gameSpeed); obstacleInterval = Math.round(obstacleInterval); coinInterval = Math.round(coinInterval); // Player update (smooth lane movement) player.update(); // --- Spawn obstacles --- ticksSinceLastObstacle++; if (ticksSinceLastObstacle >= obstacleInterval) { ticksSinceLastObstacle = 0; // Prevent same obstacle type from spawning consecutively var lastType = obstacles.length > 0 ? obstacles[obstacles.length - 1].type : null; var possibleTypes = ['crack', 'snow', 'block', 'tree', 'rock']; if (lastType !== null && possibleTypes.length > 1) { var idx = possibleTypes.indexOf(lastType); if (idx !== -1) possibleTypes.splice(idx, 1); } var chosenType = possibleTypes[Math.floor(Math.random() * possibleTypes.length)]; var obs = new Obstacle(); obs.lane = Math.floor(Math.random() * laneCount); obs.x = laneCenters[obs.lane]; obs.y = -120; obs.speed = gameSpeed; // Always use current gameSpeed // Overwrite type and asset if needed obs.type = chosenType; // Remove old asset and attach new one while (obs.children.length > 0) obs.removeChild(obs.children[0]); var obstacleAsset = obs.attachAsset(chosenType, { anchorX: 0.5, anchorY: 0.5 }); obs.width = obstacleAsset.width; obs.height = obstacleAsset.height; obstacles.push(obs); game.addChild(obs); } // --- Spawn coins --- ticksSinceLastCoin++; if (ticksSinceLastCoin >= coinInterval) { ticksSinceLastCoin = 0; // Try to spawn coin in a lane without an obstacle at the spawn Y var availableLanes = [0, 1, 2]; // Remove lanes where an obstacle is at the spawn Y (within 200px above) for (var i = 0; i < obstacles.length; i++) { var obs = obstacles[i]; if (Math.abs(obs.y + 100) < 200) { // Obstacle is close to coin spawn Y var idx = availableLanes.indexOf(obs.lane); if (idx !== -1) availableLanes.splice(idx, 1); } } if (availableLanes.length > 0) { var coin = new Coin(); coin.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)]; coin.x = laneCenters[coin.lane]; coin.y = -100; coin.speed = gameSpeed; // Always use current gameSpeed coin.value = 1 + Math.floor(Math.random() * 5); // Random value 1-5 coins.push(coin); game.addChild(coin); } } // --- Update obstacles --- for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.update(); // Remove if off screen if (obs.y > 2732 + 200) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision with player if (obs.lane === player.lane) { // Use bounding box collision if (obs.intersects(player)) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } } // --- Update coins --- for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; coin.update(); // Remove if off screen if (coin.y > 2732 + 120) { coin.destroy(); coins.splice(j, 1); continue; } // Collect coin if (coin.lane === player.lane) { if (coin.intersects(player)) { coinCount += coin.value || 1; coinTxt.setText('Coin: ' + coinCount); coin.destroy(); coins.splice(j, 1); continue; } } } // --- Special Power spawn/update --- ticksSinceLastPower++; if (ticksSinceLastPower >= nextPowerInterval) { ticksSinceLastPower = 0; nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Next random interval // Try to spawn in a lane without an obstacle at spawn Y var availableLanes = [0, 1, 2]; for (var i = 0; i < obstacles.length; i++) { var obs = obstacles[i]; if (Math.abs(obs.y + 100) < 200) { var idx = availableLanes.indexOf(obs.lane); if (idx !== -1) availableLanes.splice(idx, 1); } } if (availableLanes.length > 0) { var power = new SpecialPower(); power.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)]; power.x = laneCenters[power.lane]; power.y = -100; power.speed = gameSpeed; specialPowers.push(power); game.addChild(power); } } // --- Update special powers --- for (var k = specialPowers.length - 1; k >= 0; k--) { var power = specialPowers[k]; power.update(); if (power.y > 2732 + 120) { power.destroy(); specialPowers.splice(k, 1); continue; } // Collect special power if (power.lane === player.lane) { if (power.intersects(player)) { // Clear all obstacles on screen for (var i = obstacles.length - 1; i >= 0; i--) { obstacles[i].destroy(); obstacles.splice(i, 1); } power.destroy(); specialPowers.splice(k, 1); continue; } } } // --- Score increases with time survived --- if (LK.ticks % 6 === 0) { score += 1; scoreTxt.setText('Score: ' + score); } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Coin class: 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; // will be set on spawn
self.speed = 16; // will be set by game for difficulty
self.update = function () {
self.y += self.speed;
// Optional: spin effect
self.rotation += 0.03;
};
return self;
});
// Obstacle class: cracks, snow piles, ice blocks, trees, rocks
var Obstacle = Container.expand(function () {
var self = Container.call(this);
// Default to 'block', will be replaced on spawn if needed
var assetId = 'block';
var obstacleAsset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.type = assetId;
self.width = obstacleAsset.width;
self.height = obstacleAsset.height;
self.lane = 1; // will be set on spawn
self.speed = 16; // will be set by game for difficulty
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player class: the sliding character
var Player = Container.expand(function () {
var self = Container.call(this);
// Attach player asset (blue ellipse for ice runner)
var playerAsset = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Set up initial properties
self.width = playerAsset.width;
self.height = playerAsset.height;
self.lane = 1; // 0: left, 1: center, 2: right
// For smooth lane transitions
self.targetX = 0;
// Walking animation state
self._walkTween = null;
self._walkDir = 1;
// Start walking animation
function startWalking() {
// Stop any previous tweens on playerAsset for scaleX and scaleY
tween.stop(playerAsset, {
scaleX: true,
scaleY: true
});
// Animate scaleX to create a "waddle" effect
tween(playerAsset, {
scaleX: 1.15
}, {
duration: 120,
easing: tween.linear,
yoyo: true,
repeat: Infinity,
onYoyo: function onYoyo() {
// Flip direction for next step
self._walkDir *= -1;
playerAsset.scaleX = 1 + 0.15 * self._walkDir;
}
});
// Animate scaleY for a subtle bounce
tween(playerAsset, {
scaleY: 0.92
}, {
duration: 120,
easing: tween.linear,
yoyo: true,
repeat: Infinity
});
}
startWalking();
// Update method: smoothly move to targetX
self.update = function () {
// Smoothly move towards targetX
self.x += (self.targetX - self.x) * 0.25;
};
return self;
});
// SpecialPower class: clears all obstacles when collected
var SpecialPower = Container.expand(function () {
var self = Container.call(this);
var asset = self.attachAsset('star', {
// Use new star asset for superpower
anchorX: 0.5,
anchorY: 0.5
});
self.width = asset.width;
self.height = asset.height;
self.lane = 1;
self.speed = 16;
self.update = function () {
self.y += self.speed;
self.rotation += 0.03;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
// No title, no description
// Always backgroundColor is black
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- Moving, repeating background setup ---
var bg1 = LK.getAsset('bg_ice_landscape', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
var bg2 = LK.getAsset('bg_ice_landscape', {
anchorX: 0,
anchorY: 0,
x: 0,
y: -2732,
width: 2048,
height: 2732
});
game.addChild(bg1);
game.addChild(bg2);
// --- Lane setup ---
// new superpower asset
var laneCount = 3;
var laneWidth = 400; // Each lane is 400px wide
var laneCenters = [2048 / 2 - laneWidth,
// left
2048 / 2,
// center
2048 / 2 + laneWidth // right
];
// --- Player setup ---
var player = new Player();
player.y = 2732 - 400; // Near bottom
player.lane = 1;
player.x = laneCenters[player.lane];
player.targetX = player.x;
game.addChild(player);
// --- Score and GUI ---
var score = 0;
var scoreTxt = new Text2('Score: 0', {
size: 70,
fill: 0xFFFFFF,
font: "Pixel, 'Press Start 2P', 'Courier New', monospace"
});
scoreTxt.anchor.set(1, 0); // Anchor to right edge, top
scoreTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu)
scoreTxt.y = 20; // Padding from top
LK.gui.topRight.addChild(scoreTxt);
// --- Coin counter ---
var coinCount = 0;
var coinTxt = new Text2('Coin: 0', {
size: 50,
fill: 0xFFE066,
font: "Pixel, 'Press Start 2P', 'Courier New', monospace"
});
coinTxt.anchor.set(1, 0); // Anchor to right edge, top
coinTxt.x = -40; // Padding from right edge (avoid top right 100x100 for menu)
coinTxt.y = 150; // Place below score
LK.gui.topRight.addChild(coinTxt);
// --- Game state ---
var obstacles = [];
var coins = [];
var specialPowers = [];
var gameSpeed = 16; // Initial speed
var ticksSinceLastObstacle = 0;
var ticksSinceLastCoin = 0;
var ticksSinceLastPower = 0;
var nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Random interval for next power
var obstacleInterval = 60; // Frames between obstacles
var coinInterval = 90; // Frames between coins
var isDragging = false;
var dragStartX = 0;
var dragStartLane = 1;
// --- Asset initialization (shapes) ---
// --- Touch/drag controls ---
game.down = function (x, y, obj) {
isDragging = true;
dragStartX = x;
dragStartLane = player.lane;
};
game.move = function (x, y, obj) {
if (!isDragging) return;
// Calculate drag offset
var dx = x - dragStartX;
// Determine which lane the drag is closest to, relative to dragStartX
var laneOffset = Math.round(dx / laneWidth);
var newLane = dragStartLane + laneOffset;
if (newLane < 0) newLane = 0;
if (newLane > 2) newLane = 2;
if (newLane !== player.lane) {
player.lane = newLane;
player.targetX = laneCenters[player.lane];
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// --- Main game update loop ---
game.update = function () {
// --- Animate and repeat background ---
bg1.y += gameSpeed;
bg2.y += gameSpeed;
// If a background has moved off the bottom, move it above the other
if (bg1.y >= 2732) {
bg1.y = bg2.y - 2732;
}
if (bg2.y >= 2732) {
bg2.y = bg1.y - 2732;
}
// Scale speed and intervals with score for dynamic difficulty (0 to 1000 points)
var difficulty = score;
if (difficulty > 1000) difficulty = 1000;
// Speed: from 12 (easy) to 40 (hard) linearly
gameSpeed = 12 + difficulty / 1000 * (40 - 12);
// Intervals: from 60 (easy) to 30 (hard) for obstacles, 90 to 50 for coins
obstacleInterval = 60 - difficulty / 1000 * (60 - 30);
if (obstacleInterval < 30) obstacleInterval = 30;
coinInterval = 90 - difficulty / 1000 * (90 - 50);
if (coinInterval < 50) coinInterval = 50;
gameSpeed = Math.round(gameSpeed);
obstacleInterval = Math.round(obstacleInterval);
coinInterval = Math.round(coinInterval);
// Player update (smooth lane movement)
player.update();
// --- Spawn obstacles ---
ticksSinceLastObstacle++;
if (ticksSinceLastObstacle >= obstacleInterval) {
ticksSinceLastObstacle = 0;
// Prevent same obstacle type from spawning consecutively
var lastType = obstacles.length > 0 ? obstacles[obstacles.length - 1].type : null;
var possibleTypes = ['crack', 'snow', 'block', 'tree', 'rock'];
if (lastType !== null && possibleTypes.length > 1) {
var idx = possibleTypes.indexOf(lastType);
if (idx !== -1) possibleTypes.splice(idx, 1);
}
var chosenType = possibleTypes[Math.floor(Math.random() * possibleTypes.length)];
var obs = new Obstacle();
obs.lane = Math.floor(Math.random() * laneCount);
obs.x = laneCenters[obs.lane];
obs.y = -120;
obs.speed = gameSpeed; // Always use current gameSpeed
// Overwrite type and asset if needed
obs.type = chosenType;
// Remove old asset and attach new one
while (obs.children.length > 0) obs.removeChild(obs.children[0]);
var obstacleAsset = obs.attachAsset(chosenType, {
anchorX: 0.5,
anchorY: 0.5
});
obs.width = obstacleAsset.width;
obs.height = obstacleAsset.height;
obstacles.push(obs);
game.addChild(obs);
}
// --- Spawn coins ---
ticksSinceLastCoin++;
if (ticksSinceLastCoin >= coinInterval) {
ticksSinceLastCoin = 0;
// Try to spawn coin in a lane without an obstacle at the spawn Y
var availableLanes = [0, 1, 2];
// Remove lanes where an obstacle is at the spawn Y (within 200px above)
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
if (Math.abs(obs.y + 100) < 200) {
// Obstacle is close to coin spawn Y
var idx = availableLanes.indexOf(obs.lane);
if (idx !== -1) availableLanes.splice(idx, 1);
}
}
if (availableLanes.length > 0) {
var coin = new Coin();
coin.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
coin.x = laneCenters[coin.lane];
coin.y = -100;
coin.speed = gameSpeed; // Always use current gameSpeed
coin.value = 1 + Math.floor(Math.random() * 5); // Random value 1-5
coins.push(coin);
game.addChild(coin);
}
}
// --- Update obstacles ---
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.update();
// Remove if off screen
if (obs.y > 2732 + 200) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision with player
if (obs.lane === player.lane) {
// Use bounding box collision
if (obs.intersects(player)) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
}
// --- Update coins ---
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
coin.update();
// Remove if off screen
if (coin.y > 2732 + 120) {
coin.destroy();
coins.splice(j, 1);
continue;
}
// Collect coin
if (coin.lane === player.lane) {
if (coin.intersects(player)) {
coinCount += coin.value || 1;
coinTxt.setText('Coin: ' + coinCount);
coin.destroy();
coins.splice(j, 1);
continue;
}
}
}
// --- Special Power spawn/update ---
ticksSinceLastPower++;
if (ticksSinceLastPower >= nextPowerInterval) {
ticksSinceLastPower = 0;
nextPowerInterval = 300 + Math.floor(Math.random() * 300); // Next random interval
// Try to spawn in a lane without an obstacle at spawn Y
var availableLanes = [0, 1, 2];
for (var i = 0; i < obstacles.length; i++) {
var obs = obstacles[i];
if (Math.abs(obs.y + 100) < 200) {
var idx = availableLanes.indexOf(obs.lane);
if (idx !== -1) availableLanes.splice(idx, 1);
}
}
if (availableLanes.length > 0) {
var power = new SpecialPower();
power.lane = availableLanes[Math.floor(Math.random() * availableLanes.length)];
power.x = laneCenters[power.lane];
power.y = -100;
power.speed = gameSpeed;
specialPowers.push(power);
game.addChild(power);
}
}
// --- Update special powers ---
for (var k = specialPowers.length - 1; k >= 0; k--) {
var power = specialPowers[k];
power.update();
if (power.y > 2732 + 120) {
power.destroy();
specialPowers.splice(k, 1);
continue;
}
// Collect special power
if (power.lane === player.lane) {
if (power.intersects(player)) {
// Clear all obstacles on screen
for (var i = obstacles.length - 1; i >= 0; i--) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
power.destroy();
specialPowers.splice(k, 1);
continue;
}
}
}
// --- Score increases with time survived ---
if (LK.ticks % 6 === 0) {
score += 1;
scoreTxt.setText('Score: ' + score);
}
};
Pixel 2d coin. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
2d pixel snow. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
2d pixel ice block. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
2d pixel crack. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
2d pixel potion. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Let it be turned back
2d pixel dried tree. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
2d pixel rock. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Let it be in a way that can repeat itself when it moves