/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Cactus obstacle var Cactus = Container.expand(function () { var self = Container.call(this); var cactusSprite = self.attachAsset('cactus', { anchorX: 0.5, anchorY: 1 }); self.width = cactusSprite.width; self.height = cactusSprite.height; self.speed = 0; // Set by game self.update = function () { self.x -= self.speed; }; return self; }); // Dino (player) class var Dino = Container.expand(function () { var self = Container.call(this); var dinoSprite = self.attachAsset('dino', { anchorX: 0.5, anchorY: 1 }); self.width = dinoSprite.width; self.height = dinoSprite.height; // State self.isJumping = false; self.velocityY = 0; self.gravity = 2.2 * 1; // gravity is positive, pulls dino down self.jumpStrength = -48; // negative jumpStrength makes dino go up (y decreases) self.groundY = 0; // Set after adding to game // Jump self.jump = function () { if (!self.isJumping) { self.isJumping = true; self.velocityY = self.jumpStrength; LK.getSound('jump').play(); } }; // Update per frame self.update = function () { if (self.isJumping) { self.y += self.velocityY; self.velocityY += self.gravity; if (self.y >= self.groundY) { self.y = self.groundY; self.isJumping = false; self.velocityY = 0; } } }; return self; }); // Pterodactyl obstacle var Ptero = Container.expand(function () { var self = Container.call(this); var pteroSprite = self.attachAsset('ptero', { anchorX: 0.5, anchorY: 0.5 }); self.width = pteroSprite.width; self.height = pteroSprite.height; self.speed = 0; // Set by game self.update = function () { self.x -= self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xf5f5f5 }); /**** * Game Code ****/ // Game constants // Dinosaur (player) // Cactus (obstacle) // Pterodactyl (obstacle) // Ground // Jump sound var GROUND_Y = 2200; var DINO_START_X = 400; var OBSTACLE_MIN_GAP = 700; var OBSTACLE_MAX_GAP = 1200; var PTERO_MIN_Y = GROUND_Y - 400; var PTERO_MAX_Y = GROUND_Y - 700; var GAME_SPEED_START = 22; var GAME_SPEED_MAX = 60; var GAME_SPEEDUP_EVERY = 600; // ticks var GAME_SPEEDUP_AMOUNT = 1.2; // Game state var dino; var ground; var obstacles = []; var gameSpeed = GAME_SPEED_START; var ticksSinceLastObstacle = 0; var nextObstacleGap = 0; var score = 0; var scoreTxt; var dragNode = null; var isTouching = false; var ducking = false; var lastObstacleType = null; // Add ground ground = LK.getAsset('ground', { anchorX: 0, anchorY: 0, x: 0, y: GROUND_Y + 1 }); game.addChild(ground); // Add dino dino = new Dino(); game.addChild(dino); dino.x = DINO_START_X; dino.groundY = GROUND_Y; dino.y = GROUND_Y; // Score text scoreTxt = new Text2('0', { size: 120, fill: "#222" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Helper: spawn obstacle function spawnObstacle() { // Increase obstacle variety as score increases var availableTypes = ['cactus', 'ptero']; if (score > 500) { availableTypes.push('double_cactus'); } if (score > 1200) { availableTypes.push('low_ptero'); } if (score > 2000) { availableTypes.push('triple_cactus'); } // Randomly pick type, but avoid two pteros in a row var type = availableTypes[Math.floor(Math.random() * availableTypes.length)]; if ((type === 'ptero' || type === 'low_ptero') && lastObstacleType && (lastObstacleType === 'ptero' || lastObstacleType === 'low_ptero')) { type = 'cactus'; } lastObstacleType = type; var obs; if (type === 'cactus') { obs = new Cactus(); obs.x = 2048 + obs.width + Math.floor(Math.random() * 120); // randomize spawn x obs.y = GROUND_Y; obs.speed = gameSpeed; obstacles.push(obs); game.addChild(obs); } else if (type === 'double_cactus') { // Two cacti close together for (var i = 0; i < 2; i++) { obs = new Cactus(); obs.x = 2048 + obs.width + i * (obs.width + 60 + Math.floor(Math.random() * 40)); obs.y = GROUND_Y; obs.speed = gameSpeed; obstacles.push(obs); game.addChild(obs); } } else if (type === 'triple_cactus') { // Three cacti close together for (var i = 0; i < 3; i++) { obs = new Cactus(); obs.x = 2048 + obs.width + i * (obs.width + 50 + Math.floor(Math.random() * 30)); obs.y = GROUND_Y; obs.speed = gameSpeed; obstacles.push(obs); game.addChild(obs); } } else if (type === 'ptero') { obs = new Ptero(); obs.x = 2048 + obs.width + Math.floor(Math.random() * 120); // Randomize ptero height obs.y = PTERO_MIN_Y + Math.floor(Math.random() * (PTERO_MAX_Y - PTERO_MIN_Y)); obs.speed = gameSpeed + 2; obstacles.push(obs); game.addChild(obs); } else if (type === 'low_ptero') { obs = new Ptero(); obs.x = 2048 + obs.width + Math.floor(Math.random() * 120); // Lower flying ptero, forces jump obs.y = GROUND_Y - 120 - Math.floor(Math.random() * 60); obs.speed = gameSpeed + 2.5; obstacles.push(obs); game.addChild(obs); } } // Helper: reset game state function resetGame() { // Remove obstacles for (var i = 0; i < obstacles.length; i++) { obstacles[i].destroy(); } obstacles = []; gameSpeed = GAME_SPEED_START; ticksSinceLastObstacle = 0; // Reset with dynamic gap scaling var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10)); var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8)); nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap)); score = 0; scoreTxt.setText(score); dino.x = DINO_START_X; dino.y = GROUND_Y; dino.isJumping = false; dino.velocityY = 0; lastObstacleType = null; } // Touch/drag controls game.down = function (x, y, obj) { isTouching = true; dino.jump(); }; game.up = function (x, y, obj) { isTouching = false; }; game.move = function (x, y, obj) {}; // Main game loop game.update = function () { // Speed up over time if (LK.ticks % GAME_SPEEDUP_EVERY === 0 && gameSpeed < GAME_SPEED_MAX) { gameSpeed += GAME_SPEEDUP_AMOUNT; if (gameSpeed > GAME_SPEED_MAX) { gameSpeed = GAME_SPEED_MAX; } } // Update dino dino.update(); // Update obstacles for (var i = obstacles.length - 1; i >= 0; i--) { var obs = obstacles[i]; obs.speed = gameSpeed + (obs instanceof Ptero ? 2 : 0); obs.update(); // Remove if off screen if (obs.x < -300) { obs.destroy(); obstacles.splice(i, 1); continue; } // Collision detection if (dino.intersects(obs)) { LK.getSound('hit').play(); LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } // Obstacle spawning ticksSinceLastObstacle += gameSpeed; // Make gap smaller as score increases (min 350) var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10)); var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8)); if (ticksSinceLastObstacle >= nextObstacleGap) { spawnObstacle(); ticksSinceLastObstacle = 0; nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap)); } // Score increases with distance score += Math.floor(gameSpeed / 6); scoreTxt.setText(score); LK.setScore(score); }; // Reset game state on game start resetGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Cactus obstacle
var Cactus = Container.expand(function () {
var self = Container.call(this);
var cactusSprite = self.attachAsset('cactus', {
anchorX: 0.5,
anchorY: 1
});
self.width = cactusSprite.width;
self.height = cactusSprite.height;
self.speed = 0; // Set by game
self.update = function () {
self.x -= self.speed;
};
return self;
});
// Dino (player) class
var Dino = Container.expand(function () {
var self = Container.call(this);
var dinoSprite = self.attachAsset('dino', {
anchorX: 0.5,
anchorY: 1
});
self.width = dinoSprite.width;
self.height = dinoSprite.height;
// State
self.isJumping = false;
self.velocityY = 0;
self.gravity = 2.2 * 1; // gravity is positive, pulls dino down
self.jumpStrength = -48; // negative jumpStrength makes dino go up (y decreases)
self.groundY = 0; // Set after adding to game
// Jump
self.jump = function () {
if (!self.isJumping) {
self.isJumping = true;
self.velocityY = self.jumpStrength;
LK.getSound('jump').play();
}
};
// Update per frame
self.update = function () {
if (self.isJumping) {
self.y += self.velocityY;
self.velocityY += self.gravity;
if (self.y >= self.groundY) {
self.y = self.groundY;
self.isJumping = false;
self.velocityY = 0;
}
}
};
return self;
});
// Pterodactyl obstacle
var Ptero = Container.expand(function () {
var self = Container.call(this);
var pteroSprite = self.attachAsset('ptero', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = pteroSprite.width;
self.height = pteroSprite.height;
self.speed = 0; // Set by game
self.update = function () {
self.x -= self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf5f5f5
});
/****
* Game Code
****/
// Game constants
// Dinosaur (player)
// Cactus (obstacle)
// Pterodactyl (obstacle)
// Ground
// Jump sound
var GROUND_Y = 2200;
var DINO_START_X = 400;
var OBSTACLE_MIN_GAP = 700;
var OBSTACLE_MAX_GAP = 1200;
var PTERO_MIN_Y = GROUND_Y - 400;
var PTERO_MAX_Y = GROUND_Y - 700;
var GAME_SPEED_START = 22;
var GAME_SPEED_MAX = 60;
var GAME_SPEEDUP_EVERY = 600; // ticks
var GAME_SPEEDUP_AMOUNT = 1.2;
// Game state
var dino;
var ground;
var obstacles = [];
var gameSpeed = GAME_SPEED_START;
var ticksSinceLastObstacle = 0;
var nextObstacleGap = 0;
var score = 0;
var scoreTxt;
var dragNode = null;
var isTouching = false;
var ducking = false;
var lastObstacleType = null;
// Add ground
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: GROUND_Y + 1
});
game.addChild(ground);
// Add dino
dino = new Dino();
game.addChild(dino);
dino.x = DINO_START_X;
dino.groundY = GROUND_Y;
dino.y = GROUND_Y;
// Score text
scoreTxt = new Text2('0', {
size: 120,
fill: "#222"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Helper: spawn obstacle
function spawnObstacle() {
// Increase obstacle variety as score increases
var availableTypes = ['cactus', 'ptero'];
if (score > 500) {
availableTypes.push('double_cactus');
}
if (score > 1200) {
availableTypes.push('low_ptero');
}
if (score > 2000) {
availableTypes.push('triple_cactus');
}
// Randomly pick type, but avoid two pteros in a row
var type = availableTypes[Math.floor(Math.random() * availableTypes.length)];
if ((type === 'ptero' || type === 'low_ptero') && lastObstacleType && (lastObstacleType === 'ptero' || lastObstacleType === 'low_ptero')) {
type = 'cactus';
}
lastObstacleType = type;
var obs;
if (type === 'cactus') {
obs = new Cactus();
obs.x = 2048 + obs.width + Math.floor(Math.random() * 120); // randomize spawn x
obs.y = GROUND_Y;
obs.speed = gameSpeed;
obstacles.push(obs);
game.addChild(obs);
} else if (type === 'double_cactus') {
// Two cacti close together
for (var i = 0; i < 2; i++) {
obs = new Cactus();
obs.x = 2048 + obs.width + i * (obs.width + 60 + Math.floor(Math.random() * 40));
obs.y = GROUND_Y;
obs.speed = gameSpeed;
obstacles.push(obs);
game.addChild(obs);
}
} else if (type === 'triple_cactus') {
// Three cacti close together
for (var i = 0; i < 3; i++) {
obs = new Cactus();
obs.x = 2048 + obs.width + i * (obs.width + 50 + Math.floor(Math.random() * 30));
obs.y = GROUND_Y;
obs.speed = gameSpeed;
obstacles.push(obs);
game.addChild(obs);
}
} else if (type === 'ptero') {
obs = new Ptero();
obs.x = 2048 + obs.width + Math.floor(Math.random() * 120);
// Randomize ptero height
obs.y = PTERO_MIN_Y + Math.floor(Math.random() * (PTERO_MAX_Y - PTERO_MIN_Y));
obs.speed = gameSpeed + 2;
obstacles.push(obs);
game.addChild(obs);
} else if (type === 'low_ptero') {
obs = new Ptero();
obs.x = 2048 + obs.width + Math.floor(Math.random() * 120);
// Lower flying ptero, forces jump
obs.y = GROUND_Y - 120 - Math.floor(Math.random() * 60);
obs.speed = gameSpeed + 2.5;
obstacles.push(obs);
game.addChild(obs);
}
}
// Helper: reset game state
function resetGame() {
// Remove obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].destroy();
}
obstacles = [];
gameSpeed = GAME_SPEED_START;
ticksSinceLastObstacle = 0;
// Reset with dynamic gap scaling
var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10));
var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8));
nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap));
score = 0;
scoreTxt.setText(score);
dino.x = DINO_START_X;
dino.y = GROUND_Y;
dino.isJumping = false;
dino.velocityY = 0;
lastObstacleType = null;
}
// Touch/drag controls
game.down = function (x, y, obj) {
isTouching = true;
dino.jump();
};
game.up = function (x, y, obj) {
isTouching = false;
};
game.move = function (x, y, obj) {};
// Main game loop
game.update = function () {
// Speed up over time
if (LK.ticks % GAME_SPEEDUP_EVERY === 0 && gameSpeed < GAME_SPEED_MAX) {
gameSpeed += GAME_SPEEDUP_AMOUNT;
if (gameSpeed > GAME_SPEED_MAX) {
gameSpeed = GAME_SPEED_MAX;
}
}
// Update dino
dino.update();
// Update obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
var obs = obstacles[i];
obs.speed = gameSpeed + (obs instanceof Ptero ? 2 : 0);
obs.update();
// Remove if off screen
if (obs.x < -300) {
obs.destroy();
obstacles.splice(i, 1);
continue;
}
// Collision detection
if (dino.intersects(obs)) {
LK.getSound('hit').play();
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
}
// Obstacle spawning
ticksSinceLastObstacle += gameSpeed;
// Make gap smaller as score increases (min 350)
var minGap = Math.max(350, OBSTACLE_MIN_GAP - Math.floor(score / 10));
var maxGap = Math.max(minGap + 200, OBSTACLE_MAX_GAP - Math.floor(score / 8));
if (ticksSinceLastObstacle >= nextObstacleGap) {
spawnObstacle();
ticksSinceLastObstacle = 0;
nextObstacleGap = minGap + Math.floor(Math.random() * (maxGap - minGap));
}
// Score increases with distance
score += Math.floor(gameSpeed / 6);
scoreTxt.setText(score);
LK.setScore(score);
};
// Reset game state on game start
resetGame();