/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Cloud = Container.expand(function (size) {
var self = Container.call(this);
// Create cloud using white ellipse shapes
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
cloudGraphics.alpha = 0.8;
self.speed = -1 - Math.random() * 0.5; // Variable speed for depth effect
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.02 + Math.random() * 0.01;
self.originalY = 0;
self.update = function () {
self.x += self.speed;
// Gentle floating motion
self.y = self.originalY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 10;
// Remove when off screen
if (self.x < -200) {
self.destroy();
var index = clouds.indexOf(self);
if (index > -1) {
clouds.splice(index, 1);
}
}
};
return self;
});
var Pipe = Container.expand(function (isTop, height) {
var self = Container.call(this);
var pipeAsset = isTop ? 'pipeTop' : 'pipeBottom';
var pipeGraphics = self.attachAsset(pipeAsset, {
anchorX: 0.5,
anchorY: isTop ? 1 : 0
});
// Scale pipe to desired height
pipeGraphics.scaleY = height / 800;
self.speed = -4;
self.scored = false;
self.isTop = isTop;
self.update = function () {
self.x += self.speed;
// Remove pipe when off screen
if (self.x < -100) {
self.destroy();
var index = pipes.indexOf(self);
if (index > -1) {
pipes.splice(index, 1);
}
}
};
return self;
});
var Pony = Container.expand(function (characterType) {
var self = Container.call(this);
// Create character graphics based on type
var ponyGraphics = self.attachAsset(characterType, {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocity = 0;
self.gravity = 0.8;
self.jumpForce = -12;
self.maxFallSpeed = 15;
// Character type
self.characterType = characterType;
// Flap animation
self.flap = function () {
self.velocity = self.jumpForce;
LK.getSound('flap').play();
// Wing flap animation
tween(ponyGraphics, {
scaleY: 1.2
}, {
duration: 100
});
tween(ponyGraphics, {
scaleY: 1.0
}, {
duration: 100
});
// Add sparkle effect
LK.effects.flashObject(ponyGraphics, 0xffffff, 200);
};
self.update = function () {
// Apply gravity
self.velocity += self.gravity;
// Limit fall speed
if (self.velocity > self.maxFallSpeed) {
self.velocity = self.maxFallSpeed;
}
// Update position
self.y += self.velocity;
// Rotation based on velocity
ponyGraphics.rotation = Math.max(-0.3, Math.min(0.3, self.velocity * 0.03));
// Check ground collision
if (self.y > 2632) {
// Ground level minus pony height
self.y = 2632;
if (!gameOver) {
gameOver = true;
LK.getSound('hit').play();
LK.showGameOver();
}
}
// Check top boundary
if (self.y < 0) {
self.y = 0;
self.velocity = 0;
}
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
starGraphics.rotation = Math.PI / 4; // 45 degree rotation to make it look like a diamond
self.speed = -2;
self.twinkleTimer = 0;
self.update = function () {
self.x += self.speed;
self.twinkleTimer++;
// Twinkling effect
if (self.twinkleTimer % 60 < 30) {
starGraphics.alpha = 0.3 + self.twinkleTimer % 30 / 30 * 0.7;
} else {
starGraphics.alpha = 1.0 - self.twinkleTimer % 30 / 30 * 0.7;
}
// Remove when off screen
if (self.x < -50) {
self.destroy();
var index = stars.indexOf(self);
if (index > -1) {
stars.splice(index, 1);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Sounds
// Ground asset
// Pipe assets
// Character assets
// Game variables
var pony = null;
var pipes = [];
var ground = null;
var stars = [];
var starSpawnTimer = 0;
var clouds = [];
var cloudSpawnTimer = 0;
var gameStarted = false;
var gameOver = false;
var selectedCharacter = 'rainbowDash'; // Default character
var showingCharacterSelect = true;
var pipeSpawnTimer = 0;
var pipeGap = 300;
var lastPipeX = 0;
// Character selection buttons
var rainbowButton = null;
var fluttershyButton = null;
var selectText = null;
var rainbowLabel = null;
var fluttershyLabel = null;
// UI elements
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionText = new Text2('TAP TO FLY', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1000;
game.addChild(instructionText);
// Initialize ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2632
}));
// Character selection setup
function setupCharacterSelection() {
selectText = new Text2('Choose Your Pony', {
size: 80,
fill: 0xFFFFFF
});
selectText.anchor.set(0.5, 0.5);
selectText.x = 1024;
selectText.y = 800;
game.addChild(selectText);
// Rainbow Dash button
rainbowButton = game.addChild(LK.getAsset('rainbowDash', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 1200,
scaleX: 1.5,
scaleY: 1.5
}));
// Fluttershy button
fluttershyButton = game.addChild(LK.getAsset('fluttershy', {
anchorX: 0.5,
anchorY: 0.5,
x: 1348,
y: 1200,
scaleX: 1.5,
scaleY: 1.5
}));
// Character labels
rainbowLabel = new Text2('Rainbow Dash', {
size: 40,
fill: 0xFFFFFF
});
rainbowLabel.anchor.set(0.5, 0.5);
rainbowLabel.x = 700;
rainbowLabel.y = 1350;
game.addChild(rainbowLabel);
fluttershyLabel = new Text2('Fluttershy', {
size: 40,
fill: 0xFFFFFF
});
fluttershyLabel.anchor.set(0.5, 0.5);
fluttershyLabel.x = 1348;
fluttershyLabel.y = 1350;
game.addChild(fluttershyLabel);
}
// Start game with selected character
function startGame() {
showingCharacterSelect = false;
gameStarted = true;
// Remove character selection UI
if (selectText) selectText.destroy();
if (rainbowButton) rainbowButton.destroy();
if (fluttershyButton) fluttershyButton.destroy();
if (rainbowLabel) rainbowLabel.destroy();
if (fluttershyLabel) fluttershyLabel.destroy();
// Create pony
pony = game.addChild(new Pony(selectedCharacter));
pony.x = 400;
pony.y = 1366;
// Hide instruction text after a delay
LK.setTimeout(function () {
if (instructionText) {
tween(instructionText, {
alpha: 0
}, {
duration: 500
});
}
}, 2000);
// Reset score
LK.setScore(0);
scoreTxt.setText('0');
// Start background music
LK.playMusic('bgmusic');
}
// Spawn pipe pair
function spawnPipes() {
var centerY = 800 + Math.random() * 1200; // Random center position
var topHeight = centerY - pipeGap / 2;
var bottomHeight = 2632 - (centerY + pipeGap / 2);
if (topHeight > 0) {
var topPipe = game.addChild(new Pipe(true, topHeight));
topPipe.x = 2150;
topPipe.y = topHeight;
pipes.push(topPipe);
}
if (bottomHeight > 0) {
var bottomPipe = game.addChild(new Pipe(false, bottomHeight));
bottomPipe.x = 2150;
bottomPipe.y = centerY + pipeGap / 2;
pipes.push(bottomPipe);
}
lastPipeX = 2150;
}
// Check collisions
function checkCollisions() {
if (!pony || gameOver) return;
for (var i = 0; i < pipes.length; i++) {
var pipe = pipes[i];
// Check collision
if (pony.intersects(pipe)) {
gameOver = true;
LK.getSound('hit').play();
LK.showGameOver();
return;
}
// Check scoring (only for top pipes to avoid double scoring)
if (pipe.isTop && !pipe.scored && pony.x > pipe.x + 75) {
pipe.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore().toString());
LK.getSound('score').play();
}
}
}
// Setup character selection
setupCharacterSelection();
// Event handlers
game.down = function (x, y, obj) {
if (showingCharacterSelect) {
// Check character selection using position-based detection
// Rainbow Dash button is at x: 700, y: 1200 with 1.5x scale (180x120 effective size)
var rainbowLeft = 700 - 90; // 700 - (120 * 1.5 / 2)
var rainbowRight = 700 + 90;
var rainbowTop = 1200 - 60; // 1200 - (80 * 1.5 / 2)
var rainbowBottom = 1200 + 60;
// Fluttershy button is at x: 1348, y: 1200 with 1.5x scale (180x120 effective size)
var fluttershyLeft = 1348 - 90;
var fluttershyRight = 1348 + 90;
var fluttershyTop = 1200 - 60;
var fluttershyBottom = 1200 + 60;
if (x >= rainbowLeft && x <= rainbowRight && y >= rainbowTop && y <= rainbowBottom) {
selectedCharacter = 'rainbowDash';
startGame();
} else if (x >= fluttershyLeft && x <= fluttershyRight && y >= fluttershyTop && y <= fluttershyBottom) {
selectedCharacter = 'fluttershy';
startGame();
}
} else if (gameStarted && !gameOver && pony) {
// Make pony flap
pony.flap();
}
};
// Main game loop
game.update = function () {
if (!gameStarted || gameOver) return;
// Spawn pipes with proper spacing
pipeSpawnTimer++;
var minSpacing = 900; // Increased minimum horizontal distance between pipe pairs
var shouldSpawn = false;
if (pipeSpawnTimer >= 150) {
// Check if we have enough horizontal space from the last pipe
if (lastPipeX <= 2048 + minSpacing) {
shouldSpawn = true;
}
} else if (pipeSpawnTimer >= 120) {
// Allow earlier spawning if there's enough space
if (lastPipeX <= 2048 + minSpacing * 1.5) {
shouldSpawn = true;
}
}
if (shouldSpawn) {
spawnPipes();
pipeSpawnTimer = 0;
}
// Update pipes
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
if (pipe.update) {
pipe.update();
}
}
// Spawn clouds for background atmosphere
cloudSpawnTimer++;
if (cloudSpawnTimer >= 120) {
// Every 2 seconds - more frequent spawning
var cloud = game.addChild(new Cloud());
cloud.x = 2200;
cloud.y = 200 + Math.random() * 1200; // Expanded height range
cloud.originalY = cloud.y;
// Make clouds larger
cloud.scaleX = 2.0 + Math.random() * 1.5; // Scale between 2.0 and 3.5
cloud.scaleY = 1.5 + Math.random() * 1.0; // Scale between 1.5 and 2.5
clouds.push(cloud);
cloudSpawnTimer = 0;
}
// Update clouds
for (var i = clouds.length - 1; i >= 0; i--) {
var cloud = clouds[i];
if (cloud.update) {
cloud.update();
}
}
// Spawn stars for visual enhancement
starSpawnTimer++;
if (starSpawnTimer >= 180) {
// Every 3 seconds
var star = game.addChild(new Star());
star.x = 2100;
star.y = 200 + Math.random() * 1000; // Random height in upper portion
stars.push(star);
starSpawnTimer = 0;
}
// Update stars
for (var i = stars.length - 1; i >= 0; i--) {
var star = stars[i];
if (star.update) {
star.update();
}
}
// Check collisions
checkCollisions();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Cloud = Container.expand(function (size) {
var self = Container.call(this);
// Create cloud using white ellipse shapes
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
cloudGraphics.alpha = 0.8;
self.speed = -1 - Math.random() * 0.5; // Variable speed for depth effect
self.floatOffset = Math.random() * Math.PI * 2;
self.floatSpeed = 0.02 + Math.random() * 0.01;
self.originalY = 0;
self.update = function () {
self.x += self.speed;
// Gentle floating motion
self.y = self.originalY + Math.sin(LK.ticks * self.floatSpeed + self.floatOffset) * 10;
// Remove when off screen
if (self.x < -200) {
self.destroy();
var index = clouds.indexOf(self);
if (index > -1) {
clouds.splice(index, 1);
}
}
};
return self;
});
var Pipe = Container.expand(function (isTop, height) {
var self = Container.call(this);
var pipeAsset = isTop ? 'pipeTop' : 'pipeBottom';
var pipeGraphics = self.attachAsset(pipeAsset, {
anchorX: 0.5,
anchorY: isTop ? 1 : 0
});
// Scale pipe to desired height
pipeGraphics.scaleY = height / 800;
self.speed = -4;
self.scored = false;
self.isTop = isTop;
self.update = function () {
self.x += self.speed;
// Remove pipe when off screen
if (self.x < -100) {
self.destroy();
var index = pipes.indexOf(self);
if (index > -1) {
pipes.splice(index, 1);
}
}
};
return self;
});
var Pony = Container.expand(function (characterType) {
var self = Container.call(this);
// Create character graphics based on type
var ponyGraphics = self.attachAsset(characterType, {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocity = 0;
self.gravity = 0.8;
self.jumpForce = -12;
self.maxFallSpeed = 15;
// Character type
self.characterType = characterType;
// Flap animation
self.flap = function () {
self.velocity = self.jumpForce;
LK.getSound('flap').play();
// Wing flap animation
tween(ponyGraphics, {
scaleY: 1.2
}, {
duration: 100
});
tween(ponyGraphics, {
scaleY: 1.0
}, {
duration: 100
});
// Add sparkle effect
LK.effects.flashObject(ponyGraphics, 0xffffff, 200);
};
self.update = function () {
// Apply gravity
self.velocity += self.gravity;
// Limit fall speed
if (self.velocity > self.maxFallSpeed) {
self.velocity = self.maxFallSpeed;
}
// Update position
self.y += self.velocity;
// Rotation based on velocity
ponyGraphics.rotation = Math.max(-0.3, Math.min(0.3, self.velocity * 0.03));
// Check ground collision
if (self.y > 2632) {
// Ground level minus pony height
self.y = 2632;
if (!gameOver) {
gameOver = true;
LK.getSound('hit').play();
LK.showGameOver();
}
}
// Check top boundary
if (self.y < 0) {
self.y = 0;
self.velocity = 0;
}
};
return self;
});
var Star = Container.expand(function () {
var self = Container.call(this);
var starGraphics = self.attachAsset('star', {
anchorX: 0.5,
anchorY: 0.5
});
starGraphics.rotation = Math.PI / 4; // 45 degree rotation to make it look like a diamond
self.speed = -2;
self.twinkleTimer = 0;
self.update = function () {
self.x += self.speed;
self.twinkleTimer++;
// Twinkling effect
if (self.twinkleTimer % 60 < 30) {
starGraphics.alpha = 0.3 + self.twinkleTimer % 30 / 30 * 0.7;
} else {
starGraphics.alpha = 1.0 - self.twinkleTimer % 30 / 30 * 0.7;
}
// Remove when off screen
if (self.x < -50) {
self.destroy();
var index = stars.indexOf(self);
if (index > -1) {
stars.splice(index, 1);
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
// Sounds
// Ground asset
// Pipe assets
// Character assets
// Game variables
var pony = null;
var pipes = [];
var ground = null;
var stars = [];
var starSpawnTimer = 0;
var clouds = [];
var cloudSpawnTimer = 0;
var gameStarted = false;
var gameOver = false;
var selectedCharacter = 'rainbowDash'; // Default character
var showingCharacterSelect = true;
var pipeSpawnTimer = 0;
var pipeGap = 300;
var lastPipeX = 0;
// Character selection buttons
var rainbowButton = null;
var fluttershyButton = null;
var selectText = null;
var rainbowLabel = null;
var fluttershyLabel = null;
// UI elements
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var instructionText = new Text2('TAP TO FLY', {
size: 60,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1000;
game.addChild(instructionText);
// Initialize ground
ground = game.addChild(LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2632
}));
// Character selection setup
function setupCharacterSelection() {
selectText = new Text2('Choose Your Pony', {
size: 80,
fill: 0xFFFFFF
});
selectText.anchor.set(0.5, 0.5);
selectText.x = 1024;
selectText.y = 800;
game.addChild(selectText);
// Rainbow Dash button
rainbowButton = game.addChild(LK.getAsset('rainbowDash', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 1200,
scaleX: 1.5,
scaleY: 1.5
}));
// Fluttershy button
fluttershyButton = game.addChild(LK.getAsset('fluttershy', {
anchorX: 0.5,
anchorY: 0.5,
x: 1348,
y: 1200,
scaleX: 1.5,
scaleY: 1.5
}));
// Character labels
rainbowLabel = new Text2('Rainbow Dash', {
size: 40,
fill: 0xFFFFFF
});
rainbowLabel.anchor.set(0.5, 0.5);
rainbowLabel.x = 700;
rainbowLabel.y = 1350;
game.addChild(rainbowLabel);
fluttershyLabel = new Text2('Fluttershy', {
size: 40,
fill: 0xFFFFFF
});
fluttershyLabel.anchor.set(0.5, 0.5);
fluttershyLabel.x = 1348;
fluttershyLabel.y = 1350;
game.addChild(fluttershyLabel);
}
// Start game with selected character
function startGame() {
showingCharacterSelect = false;
gameStarted = true;
// Remove character selection UI
if (selectText) selectText.destroy();
if (rainbowButton) rainbowButton.destroy();
if (fluttershyButton) fluttershyButton.destroy();
if (rainbowLabel) rainbowLabel.destroy();
if (fluttershyLabel) fluttershyLabel.destroy();
// Create pony
pony = game.addChild(new Pony(selectedCharacter));
pony.x = 400;
pony.y = 1366;
// Hide instruction text after a delay
LK.setTimeout(function () {
if (instructionText) {
tween(instructionText, {
alpha: 0
}, {
duration: 500
});
}
}, 2000);
// Reset score
LK.setScore(0);
scoreTxt.setText('0');
// Start background music
LK.playMusic('bgmusic');
}
// Spawn pipe pair
function spawnPipes() {
var centerY = 800 + Math.random() * 1200; // Random center position
var topHeight = centerY - pipeGap / 2;
var bottomHeight = 2632 - (centerY + pipeGap / 2);
if (topHeight > 0) {
var topPipe = game.addChild(new Pipe(true, topHeight));
topPipe.x = 2150;
topPipe.y = topHeight;
pipes.push(topPipe);
}
if (bottomHeight > 0) {
var bottomPipe = game.addChild(new Pipe(false, bottomHeight));
bottomPipe.x = 2150;
bottomPipe.y = centerY + pipeGap / 2;
pipes.push(bottomPipe);
}
lastPipeX = 2150;
}
// Check collisions
function checkCollisions() {
if (!pony || gameOver) return;
for (var i = 0; i < pipes.length; i++) {
var pipe = pipes[i];
// Check collision
if (pony.intersects(pipe)) {
gameOver = true;
LK.getSound('hit').play();
LK.showGameOver();
return;
}
// Check scoring (only for top pipes to avoid double scoring)
if (pipe.isTop && !pipe.scored && pony.x > pipe.x + 75) {
pipe.scored = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore().toString());
LK.getSound('score').play();
}
}
}
// Setup character selection
setupCharacterSelection();
// Event handlers
game.down = function (x, y, obj) {
if (showingCharacterSelect) {
// Check character selection using position-based detection
// Rainbow Dash button is at x: 700, y: 1200 with 1.5x scale (180x120 effective size)
var rainbowLeft = 700 - 90; // 700 - (120 * 1.5 / 2)
var rainbowRight = 700 + 90;
var rainbowTop = 1200 - 60; // 1200 - (80 * 1.5 / 2)
var rainbowBottom = 1200 + 60;
// Fluttershy button is at x: 1348, y: 1200 with 1.5x scale (180x120 effective size)
var fluttershyLeft = 1348 - 90;
var fluttershyRight = 1348 + 90;
var fluttershyTop = 1200 - 60;
var fluttershyBottom = 1200 + 60;
if (x >= rainbowLeft && x <= rainbowRight && y >= rainbowTop && y <= rainbowBottom) {
selectedCharacter = 'rainbowDash';
startGame();
} else if (x >= fluttershyLeft && x <= fluttershyRight && y >= fluttershyTop && y <= fluttershyBottom) {
selectedCharacter = 'fluttershy';
startGame();
}
} else if (gameStarted && !gameOver && pony) {
// Make pony flap
pony.flap();
}
};
// Main game loop
game.update = function () {
if (!gameStarted || gameOver) return;
// Spawn pipes with proper spacing
pipeSpawnTimer++;
var minSpacing = 900; // Increased minimum horizontal distance between pipe pairs
var shouldSpawn = false;
if (pipeSpawnTimer >= 150) {
// Check if we have enough horizontal space from the last pipe
if (lastPipeX <= 2048 + minSpacing) {
shouldSpawn = true;
}
} else if (pipeSpawnTimer >= 120) {
// Allow earlier spawning if there's enough space
if (lastPipeX <= 2048 + minSpacing * 1.5) {
shouldSpawn = true;
}
}
if (shouldSpawn) {
spawnPipes();
pipeSpawnTimer = 0;
}
// Update pipes
for (var i = pipes.length - 1; i >= 0; i--) {
var pipe = pipes[i];
if (pipe.update) {
pipe.update();
}
}
// Spawn clouds for background atmosphere
cloudSpawnTimer++;
if (cloudSpawnTimer >= 120) {
// Every 2 seconds - more frequent spawning
var cloud = game.addChild(new Cloud());
cloud.x = 2200;
cloud.y = 200 + Math.random() * 1200; // Expanded height range
cloud.originalY = cloud.y;
// Make clouds larger
cloud.scaleX = 2.0 + Math.random() * 1.5; // Scale between 2.0 and 3.5
cloud.scaleY = 1.5 + Math.random() * 1.0; // Scale between 1.5 and 2.5
clouds.push(cloud);
cloudSpawnTimer = 0;
}
// Update clouds
for (var i = clouds.length - 1; i >= 0; i--) {
var cloud = clouds[i];
if (cloud.update) {
cloud.update();
}
}
// Spawn stars for visual enhancement
starSpawnTimer++;
if (starSpawnTimer >= 180) {
// Every 3 seconds
var star = game.addChild(new Star());
star.x = 2100;
star.y = 200 + Math.random() * 1000; // Random height in upper portion
stars.push(star);
starSpawnTimer = 0;
}
// Update stars
for (var i = stars.length - 1; i >= 0; i--) {
var star = stars[i];
if (star.update) {
star.update();
}
}
// Check collisions
checkCollisions();
};
Fluttershy, flying position, 2D, side view. In-Game asset. 2d. High contrast. No shadows
Rainbow Dash, flight position, 2D, side view. In-Game asset. 2d. High contrast. No shadows
grassy ground, complete, texture, 2D, side view. In-Game asset. 2d. High contrast. No shadows
star, 2D. In-Game asset. 2d. High contrast. No shadows
cloud, 2D, animated, cute, My Little Pony style. In-Game asset. 2d. High contrast. No shadows