Code edit (4 edits merged)
Please save this source code
User prompt
make sure they can never spawn on screen, but to the right instead, and give them a minimum of 360 distance between each
User prompt
what i want is that they are randomly spared each time they get spawned, so give them an horizontal offset at the moment of the spawn
User prompt
make it so that ground obstacles dont always have the same distance between them
Code edit (2 edits merged)
Please save this source code
User prompt
make the flying obstacle be just above the ground obstacles
User prompt
put the flying obstacle at half its height
User prompt
now lets make a flying obstacle, only one at the same time on screen, it flies straight forward at a medium height
Code edit (1 edits merged)
Please save this source code
User prompt
lets make it so there can be a small offset between obstacles so they dont appear to be always at the same distance to one another, but prevent them from being too close together
User prompt
now lets make simple obstacles that appear on the ground, they must be boxes with 2 sizes, one is same than the box of the player and one is double that size, they appear infinitely and there is not more than 3 total obstacles at the same time on screen
Code edit (1 edits merged)
Please save this source code
User prompt
ground tiles still have gaps, and as the game speed increases the gaps become bigger, fix it please
User prompt
lets make it so that ground is infinitely seamless, no gaps between diferent pieces
Code edit (1 edits merged)
Please save this source code
User prompt
Dino Jump - Evolving Runner
Initial prompt
quiero hacer un juego que consista en el juego del dinosaurio de google, pero al que poco a poco le iremos añadiendo mas mecanicas, vamos a empezar por tener un suelo en el que se apoye el dinosaurio, y que pueda saltar cuando hagamos click
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.baseSpeed = Math.random() * 3 + 2; // Random base speed between 2 and 5
self.speed = self.baseSpeed; // Initialize speed
self.update = function () {
if (!hasGameStopped) {
// Update speed based on current game speed
self.speed = self.baseSpeed * (gameSpeed / 6); // Scale with game speed (6 is initial speed)
self.x -= self.speed;
}
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 1.5;
}
};
return self;
});
var Dinosaur = Container.expand(function () {
var self = Container.call(this);
var dinoGraphics = self.attachAsset('dino', {
anchorX: 0.5,
anchorY: 1.0
});
var dinoGraphics2 = self.attachAsset('dino2', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0,
scaleX: 2.4,
scaleY: 2.4
});
self.hitbox = self.attachAsset('dino-hitbox', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
// Start image cycling animation - 4 times per second = 250ms per cycle
self.currentImage = 0;
self.startImageCycling = function () {
var cycleDuration = 250; // 250ms = 4 times per second
function cycleImages() {
if (self.currentImage === 0) {
// Switch to image 2
dinoGraphics.alpha = 0;
dinoGraphics2.alpha = 1;
self.currentImage = 1;
} else {
// Switch to image 1
dinoGraphics2.alpha = 0;
dinoGraphics.alpha = 1;
self.currentImage = 0;
}
// Schedule next cycle
LK.setTimeout(cycleImages, cycleDuration);
}
// Start the cycling
cycleImages();
};
// Start cycling immediately
self.startImageCycling();
self.velocityY = 0;
self.gravity = 1;
self.jumpPower = -30;
self.isGrounded = false;
self.groundY = 0;
self.hasCollided = false;
// Jump is now handled by the input system
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
self.y += self.velocityY;
// If collided, add horizontal movement to simulate being thrown
if (self.hasCollided) {
self.x += 3; // Move right when thrown
}
// Check ground collision
if (self.y >= self.groundY && !self.hasCollided) {
self.y = self.groundY;
self.velocityY = 0;
self.isGrounded = true;
}
// Check if fallen off screen (game over condition) - only trigger if collided
if (self.y > 2732 + 100 && self.hasCollided) {
LK.showGameOver();
}
};
return self;
});
var FlyingObstacle = Container.expand(function () {
var self = Container.call(this);
var flyingGraphics = self.attachAsset('flying_obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
var flyingGraphics2 = self.attachAsset('flying_obstacle2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.hitbox = self.attachAsset('flying_obstacle-hitbox', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Start image cycling animation - 4 times per second = 250ms per cycle
self.currentImage = 0;
self.startImageCycling = function () {
var cycleDuration = 250; // 250ms = 4 times per second
function cycleImages() {
if (self.currentImage === 0) {
// Switch to image 2
flyingGraphics.alpha = 0;
flyingGraphics2.alpha = 1;
self.currentImage = 1;
} else {
// Switch to image 1
flyingGraphics2.alpha = 0;
flyingGraphics.alpha = 1;
self.currentImage = 0;
}
// Schedule next cycle
LK.setTimeout(cycleImages, cycleDuration);
}
// Start the cycling
cycleImages();
};
// Start cycling immediately
self.startImageCycling();
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 2 * 1.5;
}
};
return self;
});
var GroundTile = Container.expand(function () {
var self = Container.call(this);
var groundGraphics = self.attachAsset('ground', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 1.5;
}
};
return self;
});
var Obstacle = Container.expand(function (size) {
var self = Container.call(this);
// Determine which asset to use based on size parameter
var assetId = size === 'large' ? 'obstacle_large' : 'obstacle_small';
var obstacleGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 1.0
});
// Add hitbox for obstacles
if (size === 'large') {
self.hitbox = self.attachAsset('obstacle_large-hitbox', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
} else if (size === 'small') {
self.hitbox = self.attachAsset('obstacle_small-hitbox', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
}
self.size = size;
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 1.5;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var dinosaur;
var groundTiles = [];
var obstacles = [];
var coins = [];
var coinCount = 0;
var flyingObstacle = null;
var flyingObstacleSpawnTimer = 0;
var flyingObstacleHeight = 2040; // Just above ground obstacles (flying obstacle height is 60)
var groundY = 2732 - 120; // Ground level - position ground tiles so they fill to bottom of screen
var gameSpeed = 6;
var distanceScore = 0;
var gameSpeedBeforeCollision = 6;
var hasGameStopped = false;
var obstacleSpawnTimer = 0;
var minObstacleSpacing = 600;
var maxObstacles = 3;
var clouds = [];
var cloudSpawnTimer = 0;
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0x333333
});
scoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreTxt);
// Create coin count display
var coinTxt = new Text2('Coins: 0', {
size: 60,
fill: 0x333333
});
coinTxt.anchor.set(1, 0);
coinTxt.y = 90; // Position below score
LK.gui.topRight.addChild(coinTxt);
// Create dinosaur
dinosaur = game.addChild(new Dinosaur());
dinosaur.x = 400;
dinosaur.y = groundY;
dinosaur.groundY = groundY;
// Create initial ground tiles
function createGroundTile(x) {
var tile = new GroundTile();
tile.x = x;
tile.y = groundY;
return tile;
}
// Create obstacle function
function createObstacle(x) {
var sizes = ['small', 'large'];
var randomSize = sizes[Math.floor(Math.random() * sizes.length)];
var obstacle = new Obstacle(randomSize);
obstacle.x = x;
obstacle.y = groundY + 20;
// Create coin above obstacle
var coinY = obstacle.y - (randomSize === 'large' ? 350 : 250);
var coin = game.addChild(createCoin(x, coinY));
coins.push(coin);
return obstacle;
}
// Create flying obstacle function
function createFlyingObstacle(x) {
var obstacle = new FlyingObstacle();
obstacle.x = x;
obstacle.y = flyingObstacleHeight + 20;
return obstacle;
}
// Create cloud function
function createCloud(x, y) {
var cloud = new Cloud();
cloud.x = x;
cloud.y = y;
var randomScale = 0.6 + Math.random() * 0.8; // Random scale between 0.6 and 1.4
cloud.scaleX = randomScale;
cloud.scaleY = randomScale;
return cloud;
}
// Create coin function
function createCoin(x, y) {
var coin = new Coin();
coin.x = x;
coin.y = y;
return coin;
}
// Create initial ground tiles to cover screen width plus extra for scrolling
for (var i = 0; i < 15; i++) {
var tile = game.addChild(createGroundTile(i * 200));
groundTiles.push(tile);
}
// Create initial background clouds
for (var c = 0; c < 8; c++) {
var cloudX = Math.random() * (2048 + 400) - 200; // Spread across screen width
var cloudY = Math.random() * 800 + 200; // Upper portion of screen
var cloud = game.addChild(createCloud(cloudX, cloudY));
clouds.push(cloud);
}
// Play main theme music
LK.playMusic('main-theme');
// Override LK.showGameOver to show meters travelled and coins collected
LK.showGameOver = function () {
// Calculate meters travelled (using display score which is already 1/10 of actual)
var metersText = "Meters travelled: " + Math.floor(distanceScore / 100);
var coinsText = "Coins collected: " + coinCount;
// Display custom game over with meters and coins
console.log(metersText);
console.log(coinsText);
// Call original game over but with custom score display
var originalScore = LK.getScore();
LK.setScore(Math.floor(distanceScore / 100)); // Ensure score shows meters
// Override the default game over text
var originalGameOverElement = document.querySelector('.game-over-score-label');
if (originalGameOverElement) {
originalGameOverElement.textContent = 'Meters travelled';
}
// Show standard game over which will display the meters as score
LK.Game.prototype.showGameOver.call(this);
};
// Game input handling - variable jump system
var isHolding = false;
var jumpHoldTime = 0;
var maxJumpHoldTime = 20; // Maximum frames to hold for full jump
var minJumpPower = -20; // Minimum jump power for taps
var maxJumpPower = -35; // Maximum jump power for full hold
game.down = function (x, y, obj) {
if (dinosaur.isGrounded && !hasGameStopped) {
isHolding = true;
jumpHoldTime = 0;
// Start with minimum jump
dinosaur.velocityY = minJumpPower;
dinosaur.isGrounded = false;
LK.getSound('jump').play();
}
};
game.up = function (x, y, obj) {
isHolding = false;
};
// Main game update loop
game.update = function () {
// Handle variable jump height
if (isHolding && !dinosaur.isGrounded && jumpHoldTime < maxJumpHoldTime && !hasGameStopped) {
jumpHoldTime++;
// Apply additional upward force while holding
var holdForce = -0.8; // Additional upward force per frame
dinosaur.velocityY += holdForce;
// Ensure we don't exceed maximum jump power
if (dinosaur.velocityY < maxJumpPower) {
dinosaur.velocityY = maxJumpPower;
}
}
// Only update score and spawn objects if game hasn't stopped
if (!hasGameStopped) {
// Update distance score
distanceScore += gameSpeed;
var displayScore = Math.floor(distanceScore / 100);
LK.setScore(displayScore);
scoreTxt.setText(displayScore);
}
// Manage ground tiles
for (var i = groundTiles.length - 1; i >= 0; i--) {
var tile = groundTiles[i];
// Remove tiles that have scrolled off screen
if (tile.x < -250) {
tile.destroy();
groundTiles.splice(i, 1);
}
}
// Add new ground tiles as needed
var lastTile = groundTiles[groundTiles.length - 1];
if (lastTile && lastTile.x + 200 < 2048 + 200) {
var newTile = game.addChild(createGroundTile(lastTile.x + 200));
groundTiles.push(newTile);
}
// Manage obstacles
for (var k = obstacles.length - 1; k >= 0; k--) {
var obstacle = obstacles[k];
// Remove obstacles that have scrolled off screen
if (obstacle.x < -200) {
obstacle.destroy();
obstacles.splice(k, 1);
}
}
// Manage coins
for (var c = coins.length - 1; c >= 0; c--) {
var coin = coins[c];
// Remove coins that have scrolled off screen
if (coin.x < -200) {
coin.destroy();
coins.splice(c, 1);
}
}
// Manage flying obstacle
if (flyingObstacle) {
// Remove flying obstacle if it's off screen
if (flyingObstacle.x < -200) {
flyingObstacle.destroy();
flyingObstacle = null;
}
}
// Spawn flying obstacle
if (!hasGameStopped) {
flyingObstacleSpawnTimer++;
}
if (!hasGameStopped && !flyingObstacle && flyingObstacleSpawnTimer > 300) {
// Spawn every 5 seconds
flyingObstacle = game.addChild(createFlyingObstacle(2048 + 100));
flyingObstacleSpawnTimer = 0;
}
// Spawn new obstacles
if (!hasGameStopped) {
obstacleSpawnTimer++;
var baseSpawnTime = 120; // Base spawn time (2 seconds at 60fps)
var spawnVariation = 120; // ±2 second variation for more varied spacing
var currentSpawnTime = baseSpawnTime + Math.floor(Math.random() * spawnVariation * 2) - spawnVariation;
}
if (!hasGameStopped && obstacles.length < maxObstacles && obstacleSpawnTimer > currentSpawnTime) {
var canSpawn = true;
var spawnX = 2048 + 200; // Spawn well off-screen to the right
// Check if there's enough space from last obstacle
if (obstacles.length > 0) {
var lastObstacle = obstacles[obstacles.length - 1];
if (lastObstacle.x > spawnX - 600) {
// Ensure minimum 600px spacing
canSpawn = false;
}
}
if (canSpawn) {
// Add random horizontal offset while maintaining minimum spacing
var offsetRange = 100; // Reduced range to ensure proper spacing
var horizontalOffset = Math.floor(Math.random() * offsetRange);
var newObstacle = game.addChild(createObstacle(spawnX + horizontalOffset));
obstacles.push(newObstacle);
// Reset timer with additional random offset for next spawn
obstacleSpawnTimer = -Math.floor(Math.random() * 60); // Start next timer with up to 1 second head start
}
}
// Collision detection with ground obstacles
for (var o = 0; o < obstacles.length; o++) {
var obstacle = obstacles[o];
var collisionTarget = obstacle.hitbox || obstacle;
if (dinosaur.hitbox.intersects(collisionTarget) && !dinosaur.hasCollided) {
dinosaur.hasCollided = true;
hasGameStopped = true;
gameSpeedBeforeCollision = gameSpeed;
gameSpeed = 0;
LK.stopMusic();
// Play defeat sound
LK.getSound('defeat').play();
// Throw dinosaur up and to the right
dinosaur.velocityY = -50;
dinosaur.isGrounded = false;
// Add spinning animation
tween(dinosaur, {
rotation: Math.PI * 4
}, {
duration: 1500,
easing: tween.easeOut
});
return; // Stop processing other collisions
}
}
// Collision detection with coins
for (var coinIndex = coins.length - 1; coinIndex >= 0; coinIndex--) {
var coin = coins[coinIndex];
if (dinosaur.hitbox.intersects(coin)) {
coinCount++;
coinTxt.setText('Coins: ' + coinCount);
// Increase score by 10 when collecting a coin
distanceScore += 1000; // Add 1000 to distanceScore since display score is 1/10 of actual
var displayScore = Math.floor(distanceScore / 100);
LK.setScore(displayScore);
scoreTxt.setText(displayScore);
LK.getSound('coin').play();
coin.destroy();
coins.splice(coinIndex, 1);
}
}
// Collision detection with flying obstacle
var flyingCollisionTarget = flyingObstacle && flyingObstacle.hitbox ? flyingObstacle.hitbox : flyingObstacle;
if (flyingObstacle && dinosaur.hitbox.intersects(flyingCollisionTarget) && !dinosaur.hasCollided) {
dinosaur.hasCollided = true;
hasGameStopped = true;
gameSpeedBeforeCollision = gameSpeed;
gameSpeed = 0;
LK.stopMusic();
// Play defeat sound
LK.getSound('defeat').play();
// Throw dinosaur up and to the right
dinosaur.velocityY = -50;
dinosaur.isGrounded = false;
// Add spinning animation
tween(dinosaur, {
rotation: Math.PI * 4
}, {
duration: 1500,
easing: tween.easeOut
});
return; // Stop processing other collisions
}
// Gradually increase game speed for difficulty progression
if (!hasGameStopped && LK.ticks % 360 === 0) {
// Every 6 seconds at 60fps
gameSpeed += 0.8;
for (var j = 0; j < groundTiles.length; j++) {
groundTiles[j].scrollSpeed = -gameSpeed;
}
}
// Manage clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
// Remove clouds that have scrolled off screen
if (cloud.x < -200) {
cloud.destroy();
clouds.splice(c, 1);
}
}
// Sort clouds by scale so bigger ones are drawn on top
clouds.sort(function (a, b) {
return a.scaleX - b.scaleX; // Smaller clouds first (drawn behind), bigger clouds last (drawn on top)
});
// Reorder clouds in the display list based on sorted order
for (var i = 0; i < clouds.length; i++) {
game.removeChild(clouds[i]);
game.addChild(clouds[i]);
}
// Spawn new clouds
if (!hasGameStopped) {
cloudSpawnTimer++;
}
if (!hasGameStopped && cloudSpawnTimer > 180) {
// Spawn new cloud every 3 seconds
var cloudY = Math.random() * 800 + 200; // Upper portion of screen
var newCloud = game.addChild(createCloud(2048 + 150, cloudY));
clouds.push(newCloud);
cloudSpawnTimer = 0;
}
// Ensure ground tiles are behind obstacles
for (var g = 0; g < groundTiles.length; g++) {
if (game.children.indexOf(groundTiles[g]) !== -1) {
game.removeChild(groundTiles[g]);
game.addChildAt(groundTiles[g], 0);
}
}
// Ensure dinosaur is always drawn on top of everything
if (game.children.indexOf(dinosaur) !== -1) {
game.removeChild(dinosaur);
game.addChild(dinosaur);
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5
});
self.baseSpeed = Math.random() * 3 + 2; // Random base speed between 2 and 5
self.speed = self.baseSpeed; // Initialize speed
self.update = function () {
if (!hasGameStopped) {
// Update speed based on current game speed
self.speed = self.baseSpeed * (gameSpeed / 6); // Scale with game speed (6 is initial speed)
self.x -= self.speed;
}
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 1.5;
}
};
return self;
});
var Dinosaur = Container.expand(function () {
var self = Container.call(this);
var dinoGraphics = self.attachAsset('dino', {
anchorX: 0.5,
anchorY: 1.0
});
var dinoGraphics2 = self.attachAsset('dino2', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0,
scaleX: 2.4,
scaleY: 2.4
});
self.hitbox = self.attachAsset('dino-hitbox', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
// Start image cycling animation - 4 times per second = 250ms per cycle
self.currentImage = 0;
self.startImageCycling = function () {
var cycleDuration = 250; // 250ms = 4 times per second
function cycleImages() {
if (self.currentImage === 0) {
// Switch to image 2
dinoGraphics.alpha = 0;
dinoGraphics2.alpha = 1;
self.currentImage = 1;
} else {
// Switch to image 1
dinoGraphics2.alpha = 0;
dinoGraphics.alpha = 1;
self.currentImage = 0;
}
// Schedule next cycle
LK.setTimeout(cycleImages, cycleDuration);
}
// Start the cycling
cycleImages();
};
// Start cycling immediately
self.startImageCycling();
self.velocityY = 0;
self.gravity = 1;
self.jumpPower = -30;
self.isGrounded = false;
self.groundY = 0;
self.hasCollided = false;
// Jump is now handled by the input system
self.update = function () {
// Apply gravity
self.velocityY += self.gravity;
self.y += self.velocityY;
// If collided, add horizontal movement to simulate being thrown
if (self.hasCollided) {
self.x += 3; // Move right when thrown
}
// Check ground collision
if (self.y >= self.groundY && !self.hasCollided) {
self.y = self.groundY;
self.velocityY = 0;
self.isGrounded = true;
}
// Check if fallen off screen (game over condition) - only trigger if collided
if (self.y > 2732 + 100 && self.hasCollided) {
LK.showGameOver();
}
};
return self;
});
var FlyingObstacle = Container.expand(function () {
var self = Container.call(this);
var flyingGraphics = self.attachAsset('flying_obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
var flyingGraphics2 = self.attachAsset('flying_obstacle2', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.hitbox = self.attachAsset('flying_obstacle-hitbox', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Start image cycling animation - 4 times per second = 250ms per cycle
self.currentImage = 0;
self.startImageCycling = function () {
var cycleDuration = 250; // 250ms = 4 times per second
function cycleImages() {
if (self.currentImage === 0) {
// Switch to image 2
flyingGraphics.alpha = 0;
flyingGraphics2.alpha = 1;
self.currentImage = 1;
} else {
// Switch to image 1
flyingGraphics2.alpha = 0;
flyingGraphics.alpha = 1;
self.currentImage = 0;
}
// Schedule next cycle
LK.setTimeout(cycleImages, cycleDuration);
}
// Start the cycling
cycleImages();
};
// Start cycling immediately
self.startImageCycling();
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 2 * 1.5;
}
};
return self;
});
var GroundTile = Container.expand(function () {
var self = Container.call(this);
var groundGraphics = self.attachAsset('ground', {
anchorX: 0,
anchorY: 0
});
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 1.5;
}
};
return self;
});
var Obstacle = Container.expand(function (size) {
var self = Container.call(this);
// Determine which asset to use based on size parameter
var assetId = size === 'large' ? 'obstacle_large' : 'obstacle_small';
var obstacleGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 1.0
});
// Add hitbox for obstacles
if (size === 'large') {
self.hitbox = self.attachAsset('obstacle_large-hitbox', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
} else if (size === 'small') {
self.hitbox = self.attachAsset('obstacle_small-hitbox', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0
});
}
self.size = size;
self.update = function () {
if (!hasGameStopped) {
self.x += -gameSpeed * 1.5;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var dinosaur;
var groundTiles = [];
var obstacles = [];
var coins = [];
var coinCount = 0;
var flyingObstacle = null;
var flyingObstacleSpawnTimer = 0;
var flyingObstacleHeight = 2040; // Just above ground obstacles (flying obstacle height is 60)
var groundY = 2732 - 120; // Ground level - position ground tiles so they fill to bottom of screen
var gameSpeed = 6;
var distanceScore = 0;
var gameSpeedBeforeCollision = 6;
var hasGameStopped = false;
var obstacleSpawnTimer = 0;
var minObstacleSpacing = 600;
var maxObstacles = 3;
var clouds = [];
var cloudSpawnTimer = 0;
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0x333333
});
scoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreTxt);
// Create coin count display
var coinTxt = new Text2('Coins: 0', {
size: 60,
fill: 0x333333
});
coinTxt.anchor.set(1, 0);
coinTxt.y = 90; // Position below score
LK.gui.topRight.addChild(coinTxt);
// Create dinosaur
dinosaur = game.addChild(new Dinosaur());
dinosaur.x = 400;
dinosaur.y = groundY;
dinosaur.groundY = groundY;
// Create initial ground tiles
function createGroundTile(x) {
var tile = new GroundTile();
tile.x = x;
tile.y = groundY;
return tile;
}
// Create obstacle function
function createObstacle(x) {
var sizes = ['small', 'large'];
var randomSize = sizes[Math.floor(Math.random() * sizes.length)];
var obstacle = new Obstacle(randomSize);
obstacle.x = x;
obstacle.y = groundY + 20;
// Create coin above obstacle
var coinY = obstacle.y - (randomSize === 'large' ? 350 : 250);
var coin = game.addChild(createCoin(x, coinY));
coins.push(coin);
return obstacle;
}
// Create flying obstacle function
function createFlyingObstacle(x) {
var obstacle = new FlyingObstacle();
obstacle.x = x;
obstacle.y = flyingObstacleHeight + 20;
return obstacle;
}
// Create cloud function
function createCloud(x, y) {
var cloud = new Cloud();
cloud.x = x;
cloud.y = y;
var randomScale = 0.6 + Math.random() * 0.8; // Random scale between 0.6 and 1.4
cloud.scaleX = randomScale;
cloud.scaleY = randomScale;
return cloud;
}
// Create coin function
function createCoin(x, y) {
var coin = new Coin();
coin.x = x;
coin.y = y;
return coin;
}
// Create initial ground tiles to cover screen width plus extra for scrolling
for (var i = 0; i < 15; i++) {
var tile = game.addChild(createGroundTile(i * 200));
groundTiles.push(tile);
}
// Create initial background clouds
for (var c = 0; c < 8; c++) {
var cloudX = Math.random() * (2048 + 400) - 200; // Spread across screen width
var cloudY = Math.random() * 800 + 200; // Upper portion of screen
var cloud = game.addChild(createCloud(cloudX, cloudY));
clouds.push(cloud);
}
// Play main theme music
LK.playMusic('main-theme');
// Override LK.showGameOver to show meters travelled and coins collected
LK.showGameOver = function () {
// Calculate meters travelled (using display score which is already 1/10 of actual)
var metersText = "Meters travelled: " + Math.floor(distanceScore / 100);
var coinsText = "Coins collected: " + coinCount;
// Display custom game over with meters and coins
console.log(metersText);
console.log(coinsText);
// Call original game over but with custom score display
var originalScore = LK.getScore();
LK.setScore(Math.floor(distanceScore / 100)); // Ensure score shows meters
// Override the default game over text
var originalGameOverElement = document.querySelector('.game-over-score-label');
if (originalGameOverElement) {
originalGameOverElement.textContent = 'Meters travelled';
}
// Show standard game over which will display the meters as score
LK.Game.prototype.showGameOver.call(this);
};
// Game input handling - variable jump system
var isHolding = false;
var jumpHoldTime = 0;
var maxJumpHoldTime = 20; // Maximum frames to hold for full jump
var minJumpPower = -20; // Minimum jump power for taps
var maxJumpPower = -35; // Maximum jump power for full hold
game.down = function (x, y, obj) {
if (dinosaur.isGrounded && !hasGameStopped) {
isHolding = true;
jumpHoldTime = 0;
// Start with minimum jump
dinosaur.velocityY = minJumpPower;
dinosaur.isGrounded = false;
LK.getSound('jump').play();
}
};
game.up = function (x, y, obj) {
isHolding = false;
};
// Main game update loop
game.update = function () {
// Handle variable jump height
if (isHolding && !dinosaur.isGrounded && jumpHoldTime < maxJumpHoldTime && !hasGameStopped) {
jumpHoldTime++;
// Apply additional upward force while holding
var holdForce = -0.8; // Additional upward force per frame
dinosaur.velocityY += holdForce;
// Ensure we don't exceed maximum jump power
if (dinosaur.velocityY < maxJumpPower) {
dinosaur.velocityY = maxJumpPower;
}
}
// Only update score and spawn objects if game hasn't stopped
if (!hasGameStopped) {
// Update distance score
distanceScore += gameSpeed;
var displayScore = Math.floor(distanceScore / 100);
LK.setScore(displayScore);
scoreTxt.setText(displayScore);
}
// Manage ground tiles
for (var i = groundTiles.length - 1; i >= 0; i--) {
var tile = groundTiles[i];
// Remove tiles that have scrolled off screen
if (tile.x < -250) {
tile.destroy();
groundTiles.splice(i, 1);
}
}
// Add new ground tiles as needed
var lastTile = groundTiles[groundTiles.length - 1];
if (lastTile && lastTile.x + 200 < 2048 + 200) {
var newTile = game.addChild(createGroundTile(lastTile.x + 200));
groundTiles.push(newTile);
}
// Manage obstacles
for (var k = obstacles.length - 1; k >= 0; k--) {
var obstacle = obstacles[k];
// Remove obstacles that have scrolled off screen
if (obstacle.x < -200) {
obstacle.destroy();
obstacles.splice(k, 1);
}
}
// Manage coins
for (var c = coins.length - 1; c >= 0; c--) {
var coin = coins[c];
// Remove coins that have scrolled off screen
if (coin.x < -200) {
coin.destroy();
coins.splice(c, 1);
}
}
// Manage flying obstacle
if (flyingObstacle) {
// Remove flying obstacle if it's off screen
if (flyingObstacle.x < -200) {
flyingObstacle.destroy();
flyingObstacle = null;
}
}
// Spawn flying obstacle
if (!hasGameStopped) {
flyingObstacleSpawnTimer++;
}
if (!hasGameStopped && !flyingObstacle && flyingObstacleSpawnTimer > 300) {
// Spawn every 5 seconds
flyingObstacle = game.addChild(createFlyingObstacle(2048 + 100));
flyingObstacleSpawnTimer = 0;
}
// Spawn new obstacles
if (!hasGameStopped) {
obstacleSpawnTimer++;
var baseSpawnTime = 120; // Base spawn time (2 seconds at 60fps)
var spawnVariation = 120; // ±2 second variation for more varied spacing
var currentSpawnTime = baseSpawnTime + Math.floor(Math.random() * spawnVariation * 2) - spawnVariation;
}
if (!hasGameStopped && obstacles.length < maxObstacles && obstacleSpawnTimer > currentSpawnTime) {
var canSpawn = true;
var spawnX = 2048 + 200; // Spawn well off-screen to the right
// Check if there's enough space from last obstacle
if (obstacles.length > 0) {
var lastObstacle = obstacles[obstacles.length - 1];
if (lastObstacle.x > spawnX - 600) {
// Ensure minimum 600px spacing
canSpawn = false;
}
}
if (canSpawn) {
// Add random horizontal offset while maintaining minimum spacing
var offsetRange = 100; // Reduced range to ensure proper spacing
var horizontalOffset = Math.floor(Math.random() * offsetRange);
var newObstacle = game.addChild(createObstacle(spawnX + horizontalOffset));
obstacles.push(newObstacle);
// Reset timer with additional random offset for next spawn
obstacleSpawnTimer = -Math.floor(Math.random() * 60); // Start next timer with up to 1 second head start
}
}
// Collision detection with ground obstacles
for (var o = 0; o < obstacles.length; o++) {
var obstacle = obstacles[o];
var collisionTarget = obstacle.hitbox || obstacle;
if (dinosaur.hitbox.intersects(collisionTarget) && !dinosaur.hasCollided) {
dinosaur.hasCollided = true;
hasGameStopped = true;
gameSpeedBeforeCollision = gameSpeed;
gameSpeed = 0;
LK.stopMusic();
// Play defeat sound
LK.getSound('defeat').play();
// Throw dinosaur up and to the right
dinosaur.velocityY = -50;
dinosaur.isGrounded = false;
// Add spinning animation
tween(dinosaur, {
rotation: Math.PI * 4
}, {
duration: 1500,
easing: tween.easeOut
});
return; // Stop processing other collisions
}
}
// Collision detection with coins
for (var coinIndex = coins.length - 1; coinIndex >= 0; coinIndex--) {
var coin = coins[coinIndex];
if (dinosaur.hitbox.intersects(coin)) {
coinCount++;
coinTxt.setText('Coins: ' + coinCount);
// Increase score by 10 when collecting a coin
distanceScore += 1000; // Add 1000 to distanceScore since display score is 1/10 of actual
var displayScore = Math.floor(distanceScore / 100);
LK.setScore(displayScore);
scoreTxt.setText(displayScore);
LK.getSound('coin').play();
coin.destroy();
coins.splice(coinIndex, 1);
}
}
// Collision detection with flying obstacle
var flyingCollisionTarget = flyingObstacle && flyingObstacle.hitbox ? flyingObstacle.hitbox : flyingObstacle;
if (flyingObstacle && dinosaur.hitbox.intersects(flyingCollisionTarget) && !dinosaur.hasCollided) {
dinosaur.hasCollided = true;
hasGameStopped = true;
gameSpeedBeforeCollision = gameSpeed;
gameSpeed = 0;
LK.stopMusic();
// Play defeat sound
LK.getSound('defeat').play();
// Throw dinosaur up and to the right
dinosaur.velocityY = -50;
dinosaur.isGrounded = false;
// Add spinning animation
tween(dinosaur, {
rotation: Math.PI * 4
}, {
duration: 1500,
easing: tween.easeOut
});
return; // Stop processing other collisions
}
// Gradually increase game speed for difficulty progression
if (!hasGameStopped && LK.ticks % 360 === 0) {
// Every 6 seconds at 60fps
gameSpeed += 0.8;
for (var j = 0; j < groundTiles.length; j++) {
groundTiles[j].scrollSpeed = -gameSpeed;
}
}
// Manage clouds
for (var c = clouds.length - 1; c >= 0; c--) {
var cloud = clouds[c];
// Remove clouds that have scrolled off screen
if (cloud.x < -200) {
cloud.destroy();
clouds.splice(c, 1);
}
}
// Sort clouds by scale so bigger ones are drawn on top
clouds.sort(function (a, b) {
return a.scaleX - b.scaleX; // Smaller clouds first (drawn behind), bigger clouds last (drawn on top)
});
// Reorder clouds in the display list based on sorted order
for (var i = 0; i < clouds.length; i++) {
game.removeChild(clouds[i]);
game.addChild(clouds[i]);
}
// Spawn new clouds
if (!hasGameStopped) {
cloudSpawnTimer++;
}
if (!hasGameStopped && cloudSpawnTimer > 180) {
// Spawn new cloud every 3 seconds
var cloudY = Math.random() * 800 + 200; // Upper portion of screen
var newCloud = game.addChild(createCloud(2048 + 150, cloudY));
clouds.push(newCloud);
cloudSpawnTimer = 0;
}
// Ensure ground tiles are behind obstacles
for (var g = 0; g < groundTiles.length; g++) {
if (game.children.indexOf(groundTiles[g]) !== -1) {
game.removeChild(groundTiles[g]);
game.addChildAt(groundTiles[g], 0);
}
}
// Ensure dinosaur is always drawn on top of everything
if (game.children.indexOf(dinosaur) !== -1) {
game.removeChild(dinosaur);
game.addChild(dinosaur);
}
};
dont crop parts of the image, show full image, give black outline
make him be flying with both wings, dont crop the image
tall rock, brown, very solid, really thick black outline
smaller rock, more rounded, really thick black outline, same brown color
white rounded cloud, really thick black outline
Simple golden coin, rounded, shiny, big black outline, funny
Same dinosaur but with wings down
Same dinosaur but legs running