User prompt
bugs: still adding 2 dragon too small, increase size very slightly improve: speed text, when it gets to 1.08 when another 2 gets added make it 1.1 etc
User prompt
Please fix the bug: 'dragonTail is not defined' in or related to this line: 'self.dragonTail = dragonTail;' Line Number: 394
User prompt
its going up in 2 bugs: hotbox weird improve: dragon model use 25 shapes minimum when faster by 0.1% so 1.1 1.2 etc, make the spacing of the rocks and trees further away from eachother reasonably ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
now add a speed text in the top left, it says 1x but every time you go through one and get score it goes up by 0.01%
User prompt
make dragon and hitbox a bit smaller
User prompt
make the dragon always visible, and change the backgrounds so its more transparent with fog ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the jumps quicker so its easier. and make the rocks and trees loooooong so you cant cheat by going above the rock... ALSO make the background way bigger and at the bottom, make sure the main game is always visible ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
remove the coins, make it so every time you go through the rock and tree it adds 1 to score. and make background bigger
User prompt
0make the dragon smaller
User prompt
make it more like flappy bird, make the dragon look better and be smoother with its animations7 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the trees like flappy bird and rocks at the top, so bassacly rocks come down from top, trees from bottom, you have to navigate thru them. make the backgrounds at the back layer so dragon alsways visible and also bigger
User prompt
now make the kill bricks be at the bottom and top at all times, to stop camping. and improve dragon and tree models, add some different environments in the background ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cool. now make all the models look better and some kill blocks at the bottom and top ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
cool, now imrove the models to look like a full game ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Wings of Fire: Dragon Flight
Initial prompt
can you make a 2d wings of fire game based of the books? make it professional
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Castle = Container.expand(function () {
var self = Container.call(this);
// Castle base
var castleBase = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
scaleX: 2.0,
scaleY: 1.5,
tint: 0x696969
});
// Castle towers
var tower1 = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: -80,
y: -100,
scaleX: 0.8,
scaleY: 1.8,
tint: 0x555555
});
var tower2 = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 80,
y: -100,
scaleX: 0.8,
scaleY: 1.8,
tint: 0x555555
});
// Castle flags
var flag1 = self.attachAsset('scroll', {
anchorX: 0.0,
anchorY: 1.0,
x: -80,
y: -260,
scaleX: 1.2,
scaleY: 1.0,
tint: 0xff0000
});
var flag2 = self.attachAsset('scroll', {
anchorX: 0.0,
anchorY: 1.0,
x: 80,
y: -260,
scaleX: 1.2,
scaleY: 1.0,
tint: 0x0000ff
});
self.speed = -3;
self.update = function () {
self.x += self.speed;
// Flags wave in wind
flag1.rotation = Math.sin(LK.ticks * 0.1) * 0.2;
flag2.rotation = Math.sin(LK.ticks * 0.1 + 1) * 0.2;
};
return self;
});
var Cloud = Container.expand(function (size) {
var self = Container.call(this);
var cloudType = size || 'medium';
var cloudGraphics = self.attachAsset('cloud_' + cloudType, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.speed = -1 - Math.random() * 2;
self.driftY = Math.random() * 0.5 - 0.25;
self.update = function () {
self.x += self.speed;
self.y += self.driftY;
// Gentle cloud movement with fog effect
cloudGraphics.alpha = 0.2 + Math.sin(LK.ticks * 0.01) * 0.1;
};
return self;
});
var Dragon = Container.expand(function () {
var self = Container.call(this);
// Main dragon body (center)
var dragonBody = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.6,
tint: 0xff4500
});
// Body segments for segmented look
var bodySegment1 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: 3,
scaleX: 1.6,
scaleY: 1.4,
tint: 0xe03e00
});
var bodySegment2 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -90,
y: 8,
scaleX: 1.4,
scaleY: 1.2,
tint: 0xcc3700
});
var bodySegment3 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -125,
y: 12,
scaleX: 1.2,
scaleY: 1.0,
tint: 0xb83500
});
// Dragon head with neck
var dragonNeck = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: 80,
y: -10,
scaleX: 1.0,
scaleY: 0.8,
tint: 0xd4451a
});
var dragonHead = self.attachAsset('dragon_head', {
anchorX: 0.5,
anchorY: 0.5,
x: 110,
y: -20,
scaleX: 1.8,
scaleY: 1.7,
tint: 0xb30000
});
// Dragon snout details
var snout = self.attachAsset('dragon_head', {
anchorX: 0.5,
anchorY: 0.5,
x: 140,
y: -15,
scaleX: 0.8,
scaleY: 0.6,
tint: 0x990000
});
// Dragon eyes
var leftEye = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 120,
y: -28,
scaleX: 0.35,
scaleY: 0.35,
tint: 0x00ff00
});
var rightEye = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 120,
y: -12,
scaleX: 0.35,
scaleY: 0.35,
tint: 0x00ff00
});
// Eye pupils
var leftPupil = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 122,
y: -28,
scaleX: 0.15,
scaleY: 0.15,
tint: 0x000000
});
var rightPupil = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 122,
y: -12,
scaleX: 0.15,
scaleY: 0.15,
tint: 0x000000
});
// Dragon nostrils
var leftNostril = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 148,
y: -18,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000
});
var rightNostril = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 148,
y: -12,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000
});
// Dragon tail segments
var dragonTail1 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -155,
y: 5,
scaleX: 1.0,
scaleY: 1.8,
tint: 0xaa2200
});
var dragonTail2 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -185,
y: 10,
scaleX: 0.8,
scaleY: 1.5,
tint: 0x993300
});
var dragonTail3 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -210,
y: 15,
scaleX: 0.6,
scaleY: 1.2,
tint: 0x882200
});
// Main wings
var leftWing = self.attachAsset('dragon_wing_left', {
anchorX: 0.8,
anchorY: 0.5,
x: -30,
y: -35,
scaleX: 1.8,
scaleY: 1.6
});
var rightWing = self.attachAsset('dragon_wing_right', {
anchorX: 0.2,
anchorY: 0.5,
x: -30,
y: 35,
scaleX: 1.8,
scaleY: 1.6
});
// Wing membranes (inner wing details)
var leftWingMembrane = self.attachAsset('dragon_wing_left', {
anchorX: 0.8,
anchorY: 0.5,
x: -25,
y: -32,
scaleX: 1.4,
scaleY: 1.2,
tint: 0xcc5533,
alpha: 0.7
});
var rightWingMembrane = self.attachAsset('dragon_wing_right', {
anchorX: 0.2,
anchorY: 0.5,
x: -25,
y: 32,
scaleX: 1.4,
scaleY: 1.2,
tint: 0xcc5533,
alpha: 0.7
});
// Wing bones/struts
var leftWingBone1 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: -45,
scaleX: 0.3,
scaleY: 0.8,
tint: 0x886644,
rotation: -0.5
});
var leftWingBone2 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -70,
y: -40,
scaleX: 0.3,
scaleY: 0.6,
tint: 0x886644,
rotation: -0.3
});
var rightWingBone1 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: 45,
scaleX: 0.3,
scaleY: 0.8,
tint: 0x886644,
rotation: 0.5
});
var rightWingBone2 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -70,
y: 40,
scaleX: 0.3,
scaleY: 0.6,
tint: 0x886644,
rotation: 0.3
});
// Dragon horns
var leftHorn = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 1.0,
x: 105,
y: -45,
scaleX: 0.2,
scaleY: 0.4,
tint: 0x444444,
rotation: -0.3
});
var rightHorn = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 1.0,
x: 115,
y: -45,
scaleX: 0.2,
scaleY: 0.4,
tint: 0x444444,
rotation: 0.3
});
// Dragon belly scales
var bellyScale1 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 25,
scaleX: 1.4,
scaleY: 0.6,
tint: 0xffaa44,
alpha: 0.8
});
var bellyScale2 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -45,
y: 28,
scaleX: 1.2,
scaleY: 0.5,
tint: 0xffaa44,
alpha: 0.8
});
var bellyScale3 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -85,
y: 30,
scaleX: 1.0,
scaleY: 0.4,
tint: 0xffaa44,
alpha: 0.8
});
// Store references for animations
self.dragonBody = dragonBody;
self.dragonHead = dragonHead;
self.leftWing = leftWing;
self.rightWing = rightWing;
self.dragonTail = dragonTail1;
self.bodySegment1 = bodySegment1;
self.bodySegment2 = bodySegment2;
self.velocity = 0;
self.maxVelocity = 10;
self.gravity = 0.4;
self.flapPower = -16;
self.isFlapping = false;
self.wingFlapTimer = 0;
self.flap = function () {
self.velocity = self.flapPower;
self.isFlapping = true;
self.wingFlapTimer = 15; // Duration for wing flap animation
LK.getSound('flap').play();
// Wing flap animation with smoother tweens
tween(self.leftWing, {
rotation: -0.8,
scaleY: 1.8,
scaleX: 1.6
}, {
duration: 80,
easing: tween.easeOut
});
tween(self.rightWing, {
rotation: 0.8,
scaleY: 1.8,
scaleX: 1.6
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return wings to normal position
tween(self.leftWing, {
rotation: 0.1,
scaleY: 1.6,
scaleX: 1.8
}, {
duration: 120,
easing: tween.easeInOut
});
tween(self.rightWing, {
rotation: -0.1,
scaleY: 1.6,
scaleX: 1.8
}, {
duration: 120,
easing: tween.easeInOut
});
}
});
// Head bob animation with better smoothness
tween(self.dragonHead, {
y: -30,
rotation: -0.1
}, {
duration: 60,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self.dragonHead, {
y: -20,
rotation: 0
}, {
duration: 80,
easing: tween.easeIn
});
}
});
};
self.update = function () {
// Apply gravity - Flappy Bird style
self.velocity += self.gravity;
// Limit velocity to prevent too fast falling
if (self.velocity > self.maxVelocity) {
self.velocity = self.maxVelocity;
}
if (self.velocity < -self.maxVelocity) {
self.velocity = -self.maxVelocity;
}
// Update position
self.y += self.velocity;
// Flappy Bird style rotation based on velocity
var targetRotation = self.velocity * 0.08;
if (targetRotation > 0.5) targetRotation = 0.5;
if (targetRotation < -0.4) targetRotation = -0.4;
// Smooth rotation transitions
tween.stop(self.dragonBody);
tween(self.dragonBody, {
rotation: targetRotation
}, {
duration: 100,
easing: tween.easeOut
});
tween.stop(self.dragonHead);
tween(self.dragonHead, {
rotation: targetRotation * 0.6
}, {
duration: 80,
easing: tween.easeOut
});
tween.stop(self.dragonTail);
tween(self.dragonTail, {
rotation: targetRotation * 1.4
}, {
duration: 120,
easing: tween.easeOut
});
// Body segments follow with slight delay for more natural movement
tween.stop(self.bodySegment1);
tween(self.bodySegment1, {
rotation: targetRotation * 0.8
}, {
duration: 110,
easing: tween.easeOut
});
tween.stop(self.bodySegment2);
tween(self.bodySegment2, {
rotation: targetRotation * 0.6
}, {
duration: 140,
easing: tween.easeOut
});
// Wing flap timer countdown
if (self.wingFlapTimer > 0) {
self.wingFlapTimer--;
}
// Wings gentle movement when not actively flapping
if (self.wingFlapTimer <= 0) {
var gentleWingMovement = Math.sin(LK.ticks * 0.06) * 0.15;
self.leftWing.rotation = gentleWingMovement + 0.1;
self.rightWing.rotation = -gentleWingMovement - 0.1;
}
// Keep dragon on screen with kill zone boundaries
if (self.y < 120) {
self.y = 120;
self.velocity = Math.max(0, self.velocity);
}
if (self.y > 2612) {
self.y = 2612;
self.velocity = Math.min(0, self.velocity);
}
self.isFlapping = self.wingFlapTimer > 0;
};
return self;
});
var Mountain = Container.expand(function () {
var self = Container.call(this);
// Mountain peak
var mountainPeak = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
scaleX: 3.0,
scaleY: 2.5,
tint: 0x696969
});
// Mountain side
var mountainSide = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: -60,
y: 0,
scaleX: 2.5,
scaleY: 2.0,
tint: 0x778899
});
// Snow cap
var snowCap = self.attachAsset('cloud_small', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -200,
scaleX: 1.5,
scaleY: 0.6,
tint: 0xfffafa
});
self.speed = -2;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
var obstacleType = type || 'tree';
self.speed = -4;
self.passed = false;
if (obstacleType === 'tree') {
// Flappy Bird style tree pipe from bottom - much longer
var treePipe = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0,
x: 0,
y: 0,
scaleX: 1.5,
scaleY: 20.0,
tint: 0x228b22
});
// Pipe cap at top
var treeCap = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0,
x: 0,
y: treePipe.height - 40,
scaleX: 2.0,
scaleY: 0.8,
tint: 0x32cd32
});
} else if (obstacleType === 'rock') {
// Rock obstacle from top - much longer
var rockMain = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
scaleX: 1.8,
scaleY: 18.0,
tint: 0x696969
});
// Rock cap at bottom
var rockCap = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -rockMain.height + 40,
scaleX: 2.2,
scaleY: 0.9,
tint: 0x555555
});
}
self.update = function () {
self.x += self.speed;
};
return self;
});
var Scroll = Container.expand(function () {
var self = Container.call(this);
var scrollGraphics = self.attachAsset('scroll', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.collected = false;
self.update = function () {
self.x += self.speed;
// Gentle sway animation
scrollGraphics.rotation = Math.sin(LK.ticks * 0.02) * 0.1;
};
return self;
});
var Spike = Container.expand(function (type) {
var self = Container.call(this);
var spikeType = type || 'top';
var spikeGraphics = self.attachAsset('spike_' + spikeType, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.update = function () {
self.x += self.speed;
// Add menacing glow effect
var glowIntensity = 0.8 + Math.sin(LK.ticks * 0.2) * 0.2;
spikeGraphics.alpha = glowIntensity;
// Subtle color shift between dark gray and red
var colorShift = Math.sin(LK.ticks * 0.1);
if (colorShift > 0.3) {
spikeGraphics.tint = 0x4a0000; // Dark red
} else {
spikeGraphics.tint = 0x2c2c2c; // Dark gray
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Game variables
var dragon;
var obstacles = [];
var scrolls = [];
var clouds = [];
var mountains = [];
var castles = [];
var topSpikes = [];
var bottomSpikes = [];
var gameSpeed = 1;
var spawnTimer = 0;
var scrollSpawnTimer = 0;
var cloudSpawnTimer = 0;
var spikeSpawnTimer = 0;
var distance = 0;
var speedMultiplier = 1.00;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var distanceTxt = new Text2('Distance: 0m', {
size: 50,
fill: 0xFFFFFF
});
distanceTxt.anchor.set(1, 0);
distanceTxt.x = -20;
distanceTxt.y = 80;
LK.gui.topRight.addChild(distanceTxt);
var speedTxt = new Text2('1.00x', {
size: 50,
fill: 0xFFFFFF
});
speedTxt.anchor.set(0, 0);
speedTxt.x = 120;
speedTxt.y = 20;
LK.gui.topLeft.addChild(speedTxt);
// Create dragon
dragon = game.addChild(new Dragon());
dragon.x = 400;
dragon.y = 1366;
// Make dragon smaller to fix hitbox
dragon.scaleX = 0.45;
dragon.scaleY = 0.45;
// Ensure dragon is always visible by setting maximum z-index
dragon.zIndex = 10000;
// Create permanent kill zones to prevent camping
createPermanentKillZones();
// Controls
game.down = function (x, y, obj) {
dragon.flap();
};
game.move = function (x, y, obj) {
// Optional: Allow continuous flapping while holding
};
game.up = function (x, y, obj) {
// Release action if needed
};
// Spawn obstacle
function spawnObstacle() {
// Create Flappy Bird style obstacles - always spawn in pairs with gap
var gapSize = 400; // Size of gap between top and bottom obstacles
var gapCenter = 800 + Math.random() * 1200; // Random vertical position for gap center
// Bottom tree pipe
var treeObstacle = new Obstacle('tree');
treeObstacle.x = 2200;
treeObstacle.y = gapCenter + gapSize / 2; // Position bottom of gap
obstacles.push(treeObstacle);
game.addChild(treeObstacle);
// Top rock obstacle
var rockObstacle = new Obstacle('rock');
rockObstacle.x = 2200;
rockObstacle.y = gapCenter - gapSize / 2; // Position top of gap
obstacles.push(rockObstacle);
game.addChild(rockObstacle);
}
// Spawn scroll
function spawnScroll() {
var scroll = new Scroll();
scroll.x = 2200;
scroll.y = 400 + Math.random() * 1900;
scrolls.push(scroll);
game.addChild(scroll);
}
// Spawn cloud
function spawnCloud() {
var cloudSizes = ['small', 'medium', 'large'];
var size = cloudSizes[Math.floor(Math.random() * cloudSizes.length)];
var cloud = new Cloud(size);
cloud.x = 2200;
cloud.y = 200 + Math.random() * 2000;
cloud.zIndex = -200; // Put clouds in far background
cloud.scaleX = 3.5; // Make clouds much bigger
cloud.scaleY = 3.5;
cloud.alpha = 0.3; // Add fog effect - make clouds more transparent
clouds.push(cloud);
game.addChild(cloud);
}
// Create permanent kill zones at top and bottom
function createPermanentKillZones() {
// Top kill zone - continuous barrier
for (var i = 0; i < 30; i++) {
var topKillBrick = new Spike('top');
topKillBrick.x = i * 80;
topKillBrick.y = 30;
topKillBrick.speed = 0; // Static, doesn't move
topSpikes.push(topKillBrick);
game.addChild(topKillBrick);
}
// Bottom kill zone - continuous barrier
for (var j = 0; j < 30; j++) {
var bottomKillBrick = new Spike('bottom');
bottomKillBrick.x = j * 80;
bottomKillBrick.y = 2702;
bottomKillBrick.speed = 0; // Static, doesn't move
bottomSpikes.push(bottomKillBrick);
game.addChild(bottomKillBrick);
}
}
// Spawn deadly spikes at top
function spawnTopSpikes() {
for (var i = 0; i < 8; i++) {
var spike = new Spike('top');
spike.x = 2200 + i * 80;
spike.y = 30;
topSpikes.push(spike);
game.addChild(spike);
}
}
// Spawn deadly spikes at bottom
function spawnBottomSpikes() {
for (var i = 0; i < 8; i++) {
var spike = new Spike('bottom');
spike.x = 2200 + i * 80;
spike.y = 2702;
bottomSpikes.push(spike);
game.addChild(spike);
}
}
// Spawn mountain environment
function spawnMountain() {
var mountain = new Mountain();
mountain.x = 2400;
mountain.y = 2600 + Math.random() * 200; // Position at bottom
mountain.zIndex = -100; // Put mountains in background
mountain.scaleX = 4.0; // Make mountains much bigger
mountain.scaleY = 4.0;
mountain.alpha = 0.4; // Add fog effect - make mountains more transparent
mountains.push(mountain);
game.addChild(mountain);
}
// Spawn castle environment
function spawnCastle() {
var castle = new Castle();
castle.x = 2400;
castle.y = 2500 + Math.random() * 200; // Position at bottom
castle.zIndex = -100; // Put castles in background
castle.scaleX = 3.5; // Make castles much bigger
castle.scaleY = 3.5;
castle.alpha = 0.5; // Add fog effect - make castles more transparent
castles.push(castle);
game.addChild(castle);
}
// Main game loop
game.update = function () {
distance += gameSpeed;
distanceTxt.setText('Distance: ' + Math.floor(distance / 10) + 'm');
// Increase difficulty over time
if (LK.ticks % 1800 === 0) {
// Every 30 seconds
gameSpeed += 0.2;
}
// Spawn obstacles - Flappy Bird style with dynamic spacing based on speed
spawnTimer++;
var dynamicSpawnDelay = Math.floor(160 + (speedMultiplier - 1) * 2000); // Increase spacing as speed increases
if (spawnTimer > dynamicSpawnDelay) {
// More consistent spacing like Flappy Bird, adjusted for speed
spawnObstacle();
spawnTimer = 0;
}
// Spawn scrolls (rare)
scrollSpawnTimer++;
if (scrollSpawnTimer > 600) {
spawnScroll();
scrollSpawnTimer = 0;
}
// Spawn clouds for atmosphere
cloudSpawnTimer++;
if (cloudSpawnTimer > 200 + Math.random() * 300) {
spawnCloud();
cloudSpawnTimer = 0;
}
// Spawn mountains (background environment)
if (LK.ticks % 900 === 0) {
spawnMountain();
}
// Spawn castles (background environment)
if (LK.ticks % 1200 === 0) {
spawnCastle();
}
// Update and clean up mountains
for (var m = mountains.length - 1; m >= 0; m--) {
var mountain = mountains[m];
if (mountain.x < -600) {
mountain.destroy();
mountains.splice(m, 1);
}
}
// Update and clean up castles
for (var ct = castles.length - 1; ct >= 0; ct--) {
var castle = castles[ct];
if (castle.x < -400) {
castle.destroy();
castles.splice(ct, 1);
}
}
// Spawn deadly spikes periodically (less frequent now that we have permanent ones)
spikeSpawnTimer++;
if (spikeSpawnTimer > 800 + Math.random() * 400) {
spawnTopSpikes();
spawnBottomSpikes();
spikeSpawnTimer = 0;
}
// Update and clean up clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
if (cloud.x < -400) {
cloud.destroy();
clouds.splice(c, 1);
}
}
// Update and check obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.lastX === undefined) obstacle.lastX = obstacle.x;
// Remove off-screen obstacles
if (obstacle.lastX >= -100 && obstacle.x < -100) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with dragon
if (dragon.intersects(obstacle)) {
// Enhanced collision effect - shake dragon before game over
tween(dragon, {
x: dragon.x + 20
}, {
duration: 50,
onFinish: function onFinish() {
tween(dragon, {
x: dragon.x - 40
}, {
duration: 50,
onFinish: function onFinish() {
tween(dragon, {
x: dragon.x + 20
}, {
duration: 50,
onFinish: function onFinish() {
// Flash screen and show game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
});
}
});
}
});
return;
}
// Score for passing obstacle - 1 point per obstacle
if (!obstacle.passed && obstacle.x < dragon.x - 60) {
obstacle.passed = true;
LK.setScore(LK.getScore() + 1);
speedMultiplier += 0.01;
scoreTxt.setText('Score: ' + LK.getScore());
// Format speed display to show clean decimals (1.1, 1.2, etc)
var displaySpeed = Math.round(speedMultiplier * 100) / 100;
speedTxt.setText(displaySpeed.toFixed(1) + 'x');
}
obstacle.lastX = obstacle.x;
}
// Update and check scrolls
for (var k = scrolls.length - 1; k >= 0; k--) {
var scroll = scrolls[k];
if (scroll.lastX === undefined) scroll.lastX = scroll.x;
// Remove off-screen scrolls
if (scroll.lastX >= -50 && scroll.x < -50) {
scroll.destroy();
scrolls.splice(k, 1);
continue;
}
// Check collection
if (!scroll.collected && dragon.intersects(scroll)) {
scroll.collected = true;
LK.setScore(LK.getScore() + 100);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('collect').play();
// Scroll collection effect
tween(scroll, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 400,
onFinish: function onFinish() {
scroll.destroy();
}
});
scrolls.splice(k, 1);
continue;
}
scroll.lastX = scroll.x;
}
// Update and clean up top spikes
for (var s1 = topSpikes.length - 1; s1 >= 0; s1--) {
var topSpike = topSpikes[s1];
if (topSpike.x < -100) {
topSpike.destroy();
topSpikes.splice(s1, 1);
continue;
}
// Check deadly collision with dragon
if (dragon.intersects(topSpike)) {
// Enhanced death effect - make dragon flash red
tween(dragon, {
tint: 0xff0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
LK.effects.flashScreen(0xff0000, 1500);
LK.showGameOver();
}
});
return;
}
}
// Update and clean up bottom spikes
for (var s2 = bottomSpikes.length - 1; s2 >= 0; s2--) {
var bottomSpike = bottomSpikes[s2];
if (bottomSpike.x < -100) {
bottomSpike.destroy();
bottomSpikes.splice(s2, 1);
continue;
}
// Check deadly collision with dragon
if (dragon.intersects(bottomSpike)) {
// Enhanced death effect - make dragon flash red
tween(dragon, {
tint: 0xff0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
LK.effects.flashScreen(0xff0000, 1500);
LK.showGameOver();
}
});
return;
}
}
// Win condition - survive long enough
if (LK.getScore() >= 2000) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('flight'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Castle = Container.expand(function () {
var self = Container.call(this);
// Castle base
var castleBase = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
scaleX: 2.0,
scaleY: 1.5,
tint: 0x696969
});
// Castle towers
var tower1 = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: -80,
y: -100,
scaleX: 0.8,
scaleY: 1.8,
tint: 0x555555
});
var tower2 = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 80,
y: -100,
scaleX: 0.8,
scaleY: 1.8,
tint: 0x555555
});
// Castle flags
var flag1 = self.attachAsset('scroll', {
anchorX: 0.0,
anchorY: 1.0,
x: -80,
y: -260,
scaleX: 1.2,
scaleY: 1.0,
tint: 0xff0000
});
var flag2 = self.attachAsset('scroll', {
anchorX: 0.0,
anchorY: 1.0,
x: 80,
y: -260,
scaleX: 1.2,
scaleY: 1.0,
tint: 0x0000ff
});
self.speed = -3;
self.update = function () {
self.x += self.speed;
// Flags wave in wind
flag1.rotation = Math.sin(LK.ticks * 0.1) * 0.2;
flag2.rotation = Math.sin(LK.ticks * 0.1 + 1) * 0.2;
};
return self;
});
var Cloud = Container.expand(function (size) {
var self = Container.call(this);
var cloudType = size || 'medium';
var cloudGraphics = self.attachAsset('cloud_' + cloudType, {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.speed = -1 - Math.random() * 2;
self.driftY = Math.random() * 0.5 - 0.25;
self.update = function () {
self.x += self.speed;
self.y += self.driftY;
// Gentle cloud movement with fog effect
cloudGraphics.alpha = 0.2 + Math.sin(LK.ticks * 0.01) * 0.1;
};
return self;
});
var Dragon = Container.expand(function () {
var self = Container.call(this);
// Main dragon body (center)
var dragonBody = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.6,
tint: 0xff4500
});
// Body segments for segmented look
var bodySegment1 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: 3,
scaleX: 1.6,
scaleY: 1.4,
tint: 0xe03e00
});
var bodySegment2 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -90,
y: 8,
scaleX: 1.4,
scaleY: 1.2,
tint: 0xcc3700
});
var bodySegment3 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -125,
y: 12,
scaleX: 1.2,
scaleY: 1.0,
tint: 0xb83500
});
// Dragon head with neck
var dragonNeck = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: 80,
y: -10,
scaleX: 1.0,
scaleY: 0.8,
tint: 0xd4451a
});
var dragonHead = self.attachAsset('dragon_head', {
anchorX: 0.5,
anchorY: 0.5,
x: 110,
y: -20,
scaleX: 1.8,
scaleY: 1.7,
tint: 0xb30000
});
// Dragon snout details
var snout = self.attachAsset('dragon_head', {
anchorX: 0.5,
anchorY: 0.5,
x: 140,
y: -15,
scaleX: 0.8,
scaleY: 0.6,
tint: 0x990000
});
// Dragon eyes
var leftEye = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 120,
y: -28,
scaleX: 0.35,
scaleY: 0.35,
tint: 0x00ff00
});
var rightEye = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 120,
y: -12,
scaleX: 0.35,
scaleY: 0.35,
tint: 0x00ff00
});
// Eye pupils
var leftPupil = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 122,
y: -28,
scaleX: 0.15,
scaleY: 0.15,
tint: 0x000000
});
var rightPupil = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 122,
y: -12,
scaleX: 0.15,
scaleY: 0.15,
tint: 0x000000
});
// Dragon nostrils
var leftNostril = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 148,
y: -18,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000
});
var rightNostril = self.attachAsset('gem', {
anchorX: 0.5,
anchorY: 0.5,
x: 148,
y: -12,
scaleX: 0.1,
scaleY: 0.1,
tint: 0x000000
});
// Dragon tail segments
var dragonTail1 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -155,
y: 5,
scaleX: 1.0,
scaleY: 1.8,
tint: 0xaa2200
});
var dragonTail2 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -185,
y: 10,
scaleX: 0.8,
scaleY: 1.5,
tint: 0x993300
});
var dragonTail3 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -210,
y: 15,
scaleX: 0.6,
scaleY: 1.2,
tint: 0x882200
});
// Main wings
var leftWing = self.attachAsset('dragon_wing_left', {
anchorX: 0.8,
anchorY: 0.5,
x: -30,
y: -35,
scaleX: 1.8,
scaleY: 1.6
});
var rightWing = self.attachAsset('dragon_wing_right', {
anchorX: 0.2,
anchorY: 0.5,
x: -30,
y: 35,
scaleX: 1.8,
scaleY: 1.6
});
// Wing membranes (inner wing details)
var leftWingMembrane = self.attachAsset('dragon_wing_left', {
anchorX: 0.8,
anchorY: 0.5,
x: -25,
y: -32,
scaleX: 1.4,
scaleY: 1.2,
tint: 0xcc5533,
alpha: 0.7
});
var rightWingMembrane = self.attachAsset('dragon_wing_right', {
anchorX: 0.2,
anchorY: 0.5,
x: -25,
y: 32,
scaleX: 1.4,
scaleY: 1.2,
tint: 0xcc5533,
alpha: 0.7
});
// Wing bones/struts
var leftWingBone1 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: -45,
scaleX: 0.3,
scaleY: 0.8,
tint: 0x886644,
rotation: -0.5
});
var leftWingBone2 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -70,
y: -40,
scaleX: 0.3,
scaleY: 0.6,
tint: 0x886644,
rotation: -0.3
});
var rightWingBone1 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -50,
y: 45,
scaleX: 0.3,
scaleY: 0.8,
tint: 0x886644,
rotation: 0.5
});
var rightWingBone2 = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 0.5,
x: -70,
y: 40,
scaleX: 0.3,
scaleY: 0.6,
tint: 0x886644,
rotation: 0.3
});
// Dragon horns
var leftHorn = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 1.0,
x: 105,
y: -45,
scaleX: 0.2,
scaleY: 0.4,
tint: 0x444444,
rotation: -0.3
});
var rightHorn = self.attachAsset('dragon_tail', {
anchorX: 0.5,
anchorY: 1.0,
x: 115,
y: -45,
scaleX: 0.2,
scaleY: 0.4,
tint: 0x444444,
rotation: 0.3
});
// Dragon belly scales
var bellyScale1 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 25,
scaleX: 1.4,
scaleY: 0.6,
tint: 0xffaa44,
alpha: 0.8
});
var bellyScale2 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -45,
y: 28,
scaleX: 1.2,
scaleY: 0.5,
tint: 0xffaa44,
alpha: 0.8
});
var bellyScale3 = self.attachAsset('dragon_body', {
anchorX: 0.5,
anchorY: 0.5,
x: -85,
y: 30,
scaleX: 1.0,
scaleY: 0.4,
tint: 0xffaa44,
alpha: 0.8
});
// Store references for animations
self.dragonBody = dragonBody;
self.dragonHead = dragonHead;
self.leftWing = leftWing;
self.rightWing = rightWing;
self.dragonTail = dragonTail1;
self.bodySegment1 = bodySegment1;
self.bodySegment2 = bodySegment2;
self.velocity = 0;
self.maxVelocity = 10;
self.gravity = 0.4;
self.flapPower = -16;
self.isFlapping = false;
self.wingFlapTimer = 0;
self.flap = function () {
self.velocity = self.flapPower;
self.isFlapping = true;
self.wingFlapTimer = 15; // Duration for wing flap animation
LK.getSound('flap').play();
// Wing flap animation with smoother tweens
tween(self.leftWing, {
rotation: -0.8,
scaleY: 1.8,
scaleX: 1.6
}, {
duration: 80,
easing: tween.easeOut
});
tween(self.rightWing, {
rotation: 0.8,
scaleY: 1.8,
scaleX: 1.6
}, {
duration: 80,
easing: tween.easeOut,
onFinish: function onFinish() {
// Return wings to normal position
tween(self.leftWing, {
rotation: 0.1,
scaleY: 1.6,
scaleX: 1.8
}, {
duration: 120,
easing: tween.easeInOut
});
tween(self.rightWing, {
rotation: -0.1,
scaleY: 1.6,
scaleX: 1.8
}, {
duration: 120,
easing: tween.easeInOut
});
}
});
// Head bob animation with better smoothness
tween(self.dragonHead, {
y: -30,
rotation: -0.1
}, {
duration: 60,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self.dragonHead, {
y: -20,
rotation: 0
}, {
duration: 80,
easing: tween.easeIn
});
}
});
};
self.update = function () {
// Apply gravity - Flappy Bird style
self.velocity += self.gravity;
// Limit velocity to prevent too fast falling
if (self.velocity > self.maxVelocity) {
self.velocity = self.maxVelocity;
}
if (self.velocity < -self.maxVelocity) {
self.velocity = -self.maxVelocity;
}
// Update position
self.y += self.velocity;
// Flappy Bird style rotation based on velocity
var targetRotation = self.velocity * 0.08;
if (targetRotation > 0.5) targetRotation = 0.5;
if (targetRotation < -0.4) targetRotation = -0.4;
// Smooth rotation transitions
tween.stop(self.dragonBody);
tween(self.dragonBody, {
rotation: targetRotation
}, {
duration: 100,
easing: tween.easeOut
});
tween.stop(self.dragonHead);
tween(self.dragonHead, {
rotation: targetRotation * 0.6
}, {
duration: 80,
easing: tween.easeOut
});
tween.stop(self.dragonTail);
tween(self.dragonTail, {
rotation: targetRotation * 1.4
}, {
duration: 120,
easing: tween.easeOut
});
// Body segments follow with slight delay for more natural movement
tween.stop(self.bodySegment1);
tween(self.bodySegment1, {
rotation: targetRotation * 0.8
}, {
duration: 110,
easing: tween.easeOut
});
tween.stop(self.bodySegment2);
tween(self.bodySegment2, {
rotation: targetRotation * 0.6
}, {
duration: 140,
easing: tween.easeOut
});
// Wing flap timer countdown
if (self.wingFlapTimer > 0) {
self.wingFlapTimer--;
}
// Wings gentle movement when not actively flapping
if (self.wingFlapTimer <= 0) {
var gentleWingMovement = Math.sin(LK.ticks * 0.06) * 0.15;
self.leftWing.rotation = gentleWingMovement + 0.1;
self.rightWing.rotation = -gentleWingMovement - 0.1;
}
// Keep dragon on screen with kill zone boundaries
if (self.y < 120) {
self.y = 120;
self.velocity = Math.max(0, self.velocity);
}
if (self.y > 2612) {
self.y = 2612;
self.velocity = Math.min(0, self.velocity);
}
self.isFlapping = self.wingFlapTimer > 0;
};
return self;
});
var Mountain = Container.expand(function () {
var self = Container.call(this);
// Mountain peak
var mountainPeak = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
scaleX: 3.0,
scaleY: 2.5,
tint: 0x696969
});
// Mountain side
var mountainSide = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: -60,
y: 0,
scaleX: 2.5,
scaleY: 2.0,
tint: 0x778899
});
// Snow cap
var snowCap = self.attachAsset('cloud_small', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -200,
scaleX: 1.5,
scaleY: 0.6,
tint: 0xfffafa
});
self.speed = -2;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
var obstacleType = type || 'tree';
self.speed = -4;
self.passed = false;
if (obstacleType === 'tree') {
// Flappy Bird style tree pipe from bottom - much longer
var treePipe = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0,
x: 0,
y: 0,
scaleX: 1.5,
scaleY: 20.0,
tint: 0x228b22
});
// Pipe cap at top
var treeCap = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.0,
x: 0,
y: treePipe.height - 40,
scaleX: 2.0,
scaleY: 0.8,
tint: 0x32cd32
});
} else if (obstacleType === 'rock') {
// Rock obstacle from top - much longer
var rockMain = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: 0,
scaleX: 1.8,
scaleY: 18.0,
tint: 0x696969
});
// Rock cap at bottom
var rockCap = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0,
x: 0,
y: -rockMain.height + 40,
scaleX: 2.2,
scaleY: 0.9,
tint: 0x555555
});
}
self.update = function () {
self.x += self.speed;
};
return self;
});
var Scroll = Container.expand(function () {
var self = Container.call(this);
var scrollGraphics = self.attachAsset('scroll', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.collected = false;
self.update = function () {
self.x += self.speed;
// Gentle sway animation
scrollGraphics.rotation = Math.sin(LK.ticks * 0.02) * 0.1;
};
return self;
});
var Spike = Container.expand(function (type) {
var self = Container.call(this);
var spikeType = type || 'top';
var spikeGraphics = self.attachAsset('spike_' + spikeType, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -4;
self.update = function () {
self.x += self.speed;
// Add menacing glow effect
var glowIntensity = 0.8 + Math.sin(LK.ticks * 0.2) * 0.2;
spikeGraphics.alpha = glowIntensity;
// Subtle color shift between dark gray and red
var colorShift = Math.sin(LK.ticks * 0.1);
if (colorShift > 0.3) {
spikeGraphics.tint = 0x4a0000; // Dark red
} else {
spikeGraphics.tint = 0x2c2c2c; // Dark gray
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
// Game variables
var dragon;
var obstacles = [];
var scrolls = [];
var clouds = [];
var mountains = [];
var castles = [];
var topSpikes = [];
var bottomSpikes = [];
var gameSpeed = 1;
var spawnTimer = 0;
var scrollSpawnTimer = 0;
var cloudSpawnTimer = 0;
var spikeSpawnTimer = 0;
var distance = 0;
var speedMultiplier = 1.00;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var distanceTxt = new Text2('Distance: 0m', {
size: 50,
fill: 0xFFFFFF
});
distanceTxt.anchor.set(1, 0);
distanceTxt.x = -20;
distanceTxt.y = 80;
LK.gui.topRight.addChild(distanceTxt);
var speedTxt = new Text2('1.00x', {
size: 50,
fill: 0xFFFFFF
});
speedTxt.anchor.set(0, 0);
speedTxt.x = 120;
speedTxt.y = 20;
LK.gui.topLeft.addChild(speedTxt);
// Create dragon
dragon = game.addChild(new Dragon());
dragon.x = 400;
dragon.y = 1366;
// Make dragon smaller to fix hitbox
dragon.scaleX = 0.45;
dragon.scaleY = 0.45;
// Ensure dragon is always visible by setting maximum z-index
dragon.zIndex = 10000;
// Create permanent kill zones to prevent camping
createPermanentKillZones();
// Controls
game.down = function (x, y, obj) {
dragon.flap();
};
game.move = function (x, y, obj) {
// Optional: Allow continuous flapping while holding
};
game.up = function (x, y, obj) {
// Release action if needed
};
// Spawn obstacle
function spawnObstacle() {
// Create Flappy Bird style obstacles - always spawn in pairs with gap
var gapSize = 400; // Size of gap between top and bottom obstacles
var gapCenter = 800 + Math.random() * 1200; // Random vertical position for gap center
// Bottom tree pipe
var treeObstacle = new Obstacle('tree');
treeObstacle.x = 2200;
treeObstacle.y = gapCenter + gapSize / 2; // Position bottom of gap
obstacles.push(treeObstacle);
game.addChild(treeObstacle);
// Top rock obstacle
var rockObstacle = new Obstacle('rock');
rockObstacle.x = 2200;
rockObstacle.y = gapCenter - gapSize / 2; // Position top of gap
obstacles.push(rockObstacle);
game.addChild(rockObstacle);
}
// Spawn scroll
function spawnScroll() {
var scroll = new Scroll();
scroll.x = 2200;
scroll.y = 400 + Math.random() * 1900;
scrolls.push(scroll);
game.addChild(scroll);
}
// Spawn cloud
function spawnCloud() {
var cloudSizes = ['small', 'medium', 'large'];
var size = cloudSizes[Math.floor(Math.random() * cloudSizes.length)];
var cloud = new Cloud(size);
cloud.x = 2200;
cloud.y = 200 + Math.random() * 2000;
cloud.zIndex = -200; // Put clouds in far background
cloud.scaleX = 3.5; // Make clouds much bigger
cloud.scaleY = 3.5;
cloud.alpha = 0.3; // Add fog effect - make clouds more transparent
clouds.push(cloud);
game.addChild(cloud);
}
// Create permanent kill zones at top and bottom
function createPermanentKillZones() {
// Top kill zone - continuous barrier
for (var i = 0; i < 30; i++) {
var topKillBrick = new Spike('top');
topKillBrick.x = i * 80;
topKillBrick.y = 30;
topKillBrick.speed = 0; // Static, doesn't move
topSpikes.push(topKillBrick);
game.addChild(topKillBrick);
}
// Bottom kill zone - continuous barrier
for (var j = 0; j < 30; j++) {
var bottomKillBrick = new Spike('bottom');
bottomKillBrick.x = j * 80;
bottomKillBrick.y = 2702;
bottomKillBrick.speed = 0; // Static, doesn't move
bottomSpikes.push(bottomKillBrick);
game.addChild(bottomKillBrick);
}
}
// Spawn deadly spikes at top
function spawnTopSpikes() {
for (var i = 0; i < 8; i++) {
var spike = new Spike('top');
spike.x = 2200 + i * 80;
spike.y = 30;
topSpikes.push(spike);
game.addChild(spike);
}
}
// Spawn deadly spikes at bottom
function spawnBottomSpikes() {
for (var i = 0; i < 8; i++) {
var spike = new Spike('bottom');
spike.x = 2200 + i * 80;
spike.y = 2702;
bottomSpikes.push(spike);
game.addChild(spike);
}
}
// Spawn mountain environment
function spawnMountain() {
var mountain = new Mountain();
mountain.x = 2400;
mountain.y = 2600 + Math.random() * 200; // Position at bottom
mountain.zIndex = -100; // Put mountains in background
mountain.scaleX = 4.0; // Make mountains much bigger
mountain.scaleY = 4.0;
mountain.alpha = 0.4; // Add fog effect - make mountains more transparent
mountains.push(mountain);
game.addChild(mountain);
}
// Spawn castle environment
function spawnCastle() {
var castle = new Castle();
castle.x = 2400;
castle.y = 2500 + Math.random() * 200; // Position at bottom
castle.zIndex = -100; // Put castles in background
castle.scaleX = 3.5; // Make castles much bigger
castle.scaleY = 3.5;
castle.alpha = 0.5; // Add fog effect - make castles more transparent
castles.push(castle);
game.addChild(castle);
}
// Main game loop
game.update = function () {
distance += gameSpeed;
distanceTxt.setText('Distance: ' + Math.floor(distance / 10) + 'm');
// Increase difficulty over time
if (LK.ticks % 1800 === 0) {
// Every 30 seconds
gameSpeed += 0.2;
}
// Spawn obstacles - Flappy Bird style with dynamic spacing based on speed
spawnTimer++;
var dynamicSpawnDelay = Math.floor(160 + (speedMultiplier - 1) * 2000); // Increase spacing as speed increases
if (spawnTimer > dynamicSpawnDelay) {
// More consistent spacing like Flappy Bird, adjusted for speed
spawnObstacle();
spawnTimer = 0;
}
// Spawn scrolls (rare)
scrollSpawnTimer++;
if (scrollSpawnTimer > 600) {
spawnScroll();
scrollSpawnTimer = 0;
}
// Spawn clouds for atmosphere
cloudSpawnTimer++;
if (cloudSpawnTimer > 200 + Math.random() * 300) {
spawnCloud();
cloudSpawnTimer = 0;
}
// Spawn mountains (background environment)
if (LK.ticks % 900 === 0) {
spawnMountain();
}
// Spawn castles (background environment)
if (LK.ticks % 1200 === 0) {
spawnCastle();
}
// Update and clean up mountains
for (var m = mountains.length - 1; m >= 0; m--) {
var mountain = mountains[m];
if (mountain.x < -600) {
mountain.destroy();
mountains.splice(m, 1);
}
}
// Update and clean up castles
for (var ct = castles.length - 1; ct >= 0; ct--) {
var castle = castles[ct];
if (castle.x < -400) {
castle.destroy();
castles.splice(ct, 1);
}
}
// Spawn deadly spikes periodically (less frequent now that we have permanent ones)
spikeSpawnTimer++;
if (spikeSpawnTimer > 800 + Math.random() * 400) {
spawnTopSpikes();
spawnBottomSpikes();
spikeSpawnTimer = 0;
}
// Update and clean up clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
if (cloud.x < -400) {
cloud.destroy();
clouds.splice(c, 1);
}
}
// Update and check obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.lastX === undefined) obstacle.lastX = obstacle.x;
// Remove off-screen obstacles
if (obstacle.lastX >= -100 && obstacle.x < -100) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with dragon
if (dragon.intersects(obstacle)) {
// Enhanced collision effect - shake dragon before game over
tween(dragon, {
x: dragon.x + 20
}, {
duration: 50,
onFinish: function onFinish() {
tween(dragon, {
x: dragon.x - 40
}, {
duration: 50,
onFinish: function onFinish() {
tween(dragon, {
x: dragon.x + 20
}, {
duration: 50,
onFinish: function onFinish() {
// Flash screen and show game over
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
});
}
});
}
});
return;
}
// Score for passing obstacle - 1 point per obstacle
if (!obstacle.passed && obstacle.x < dragon.x - 60) {
obstacle.passed = true;
LK.setScore(LK.getScore() + 1);
speedMultiplier += 0.01;
scoreTxt.setText('Score: ' + LK.getScore());
// Format speed display to show clean decimals (1.1, 1.2, etc)
var displaySpeed = Math.round(speedMultiplier * 100) / 100;
speedTxt.setText(displaySpeed.toFixed(1) + 'x');
}
obstacle.lastX = obstacle.x;
}
// Update and check scrolls
for (var k = scrolls.length - 1; k >= 0; k--) {
var scroll = scrolls[k];
if (scroll.lastX === undefined) scroll.lastX = scroll.x;
// Remove off-screen scrolls
if (scroll.lastX >= -50 && scroll.x < -50) {
scroll.destroy();
scrolls.splice(k, 1);
continue;
}
// Check collection
if (!scroll.collected && dragon.intersects(scroll)) {
scroll.collected = true;
LK.setScore(LK.getScore() + 100);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('collect').play();
// Scroll collection effect
tween(scroll, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 400,
onFinish: function onFinish() {
scroll.destroy();
}
});
scrolls.splice(k, 1);
continue;
}
scroll.lastX = scroll.x;
}
// Update and clean up top spikes
for (var s1 = topSpikes.length - 1; s1 >= 0; s1--) {
var topSpike = topSpikes[s1];
if (topSpike.x < -100) {
topSpike.destroy();
topSpikes.splice(s1, 1);
continue;
}
// Check deadly collision with dragon
if (dragon.intersects(topSpike)) {
// Enhanced death effect - make dragon flash red
tween(dragon, {
tint: 0xff0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
LK.effects.flashScreen(0xff0000, 1500);
LK.showGameOver();
}
});
return;
}
}
// Update and clean up bottom spikes
for (var s2 = bottomSpikes.length - 1; s2 >= 0; s2--) {
var bottomSpike = bottomSpikes[s2];
if (bottomSpike.x < -100) {
bottomSpike.destroy();
bottomSpikes.splice(s2, 1);
continue;
}
// Check deadly collision with dragon
if (dragon.intersects(bottomSpike)) {
// Enhanced death effect - make dragon flash red
tween(dragon, {
tint: 0xff0000,
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
LK.effects.flashScreen(0xff0000, 1500);
LK.showGameOver();
}
});
return;
}
}
// Win condition - survive long enough
if (LK.getScore() >= 2000) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('flight');