/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
unlockedCows: [0]
});
/****
* Classes
****/
var Collectible = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'coin';
self.value = self.type === 'coin' ? 10 : 50;
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = graphics.width;
self.height = graphics.height;
self.active = true;
self.reset = function (y) {
self.y = y || -self.height;
// Position collectible between river banks
var minX = 250;
var maxX = 2048 - 250 - self.width;
self.x = minX + Math.random() * (maxX - minX);
};
self.update = function () {
self.y += river.speed;
// Rotate coins
if (self.type === 'coin') {
graphics.rotation += 0.05;
}
// Flash power-ups
if (self.type === 'powerup' && LK.ticks % 10 === 0) {
tween(graphics, {
alpha: graphics.alpha < 1 ? 1 : 0.6
}, {
duration: 200
});
}
// Check if collectible is off screen
if (self.y > 2732 + self.height) {
self.active = false;
}
};
self.collect = function () {
self.active = false;
if (self.type === 'powerup') {
// Apply power-up effect
player.invincible = true;
// Set player to flash
var flashInterval = LK.setInterval(function () {
player.alpha = player.alpha < 1 ? 1 : 0.5;
}, 200);
// End invincibility after 5 seconds
LK.setTimeout(function () {
player.invincible = false;
player.alpha = 1;
LK.clearInterval(flashInterval);
}, 5000);
}
// Play collection sound
LK.getSound('collect').play();
// Add points
LK.setScore(LK.getScore() + self.value);
updateScoreText();
};
self.reset();
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'rock';
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = graphics.width;
self.height = graphics.height;
self.active = true;
self.reset = function (y) {
self.y = y || -self.height;
// Position obstacle between river banks
var minX = 250;
var maxX = 2048 - 250 - self.width;
self.x = minX + Math.random() * (maxX - minX);
};
self.update = function () {
self.lastType = self.type; // Track the type of obstacle for jump scare
self.y += river.speed;
// Add behavior for enemy cow
if (self.type === 'enemyCow') {
self.x += Math.sin(LK.ticks / 20) * 5; // Move enemy cow in a wave pattern
}
// Check if obstacle is off screen
if (self.y > 2732 + self.height) {
self.active = false;
}
};
self.reset();
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
// Create kayak
var kayak = self.attachAsset('kayak', {
anchorX: 0.5,
anchorY: 0.5,
y: 20
});
// Create cow
var cow = self.attachAsset('cow', {
anchorX: 0.5,
anchorY: 0.5,
y: -10
});
self.width = kayak.width;
self.height = kayak.height + cow.height - 20; // Overlap adjustment
self.invincible = false;
self.dead = false;
self.reset = function () {
self.x = 2048 / 2;
self.y = 2732 - 300;
self.dead = false;
self.invincible = false;
self.alpha = 1;
};
self.die = function () {
if (self.invincible || self.dead) {
return;
}
self.dead = true;
LK.getSound('hit').play();
// Jump scare effect with obstacle asset
var jumpScare = LK.getAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3,
scaleY: 3
});
game.addChild(jumpScare);
LK.effects.flashObject(jumpScare, 0xFFFFFF, 500, function () {
jumpScare.destroy();
});
LK.effects.flashScreen(0xFF0000, 500);
// Show game over after a short delay
LK.setTimeout(function () {
// Save high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
LK.showGameOver();
}, 1000);
};
return self;
});
var River = Container.expand(function () {
var self = Container.call(this);
var waterGraphics = self.attachAsset('water', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var leftBank = self.attachAsset('riverbank', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
var rightBank = self.attachAsset('riverbank', {
anchorX: 1,
anchorY: 0,
x: 2048,
y: 0
});
self.speed = 5;
self.maxSpeed = 15;
self.increaseSpeed = function (amount) {
self.speed = Math.min(self.maxSpeed, self.speed + amount);
};
return self;
});
var SpeedBoost = Container.expand(function () {
var self = Container.call(this);
self.type = 'speedBoost';
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = graphics.width;
self.height = graphics.height;
self.active = true;
self.reset = function (y) {
self.y = y || -self.height;
var minX = 250;
var maxX = 2048 - 250 - self.width;
self.x = minX + Math.random() * (maxX - minX);
};
self.update = function () {
self.y += river.speed;
if (LK.ticks % 10 === 0) {
tween(graphics, {
alpha: graphics.alpha < 1 ? 1 : 0.6
}, {
duration: 200
});
}
if (self.y > 2732 + self.height) {
self.active = false;
}
};
self.collect = function () {
self.active = false;
river.increaseSpeed(5);
LK.setTimeout(function () {
river.increaseSpeed(-5);
}, 5000);
LK.getSound('collect').play();
LK.setScore(LK.getScore() + 100);
updateScoreText();
};
self.reset();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1E90FF
});
/****
* Game Code
****/
var player;
var river;
var obstacles = [];
var collectibles = [];
var dragNode = null;
var gameStarted = false;
var difficultyTimer;
var obstacleTimer;
var collectibleTimer;
var scoreText;
var highScoreText;
var distanceText;
var distance = 0;
function initGame() {
// Create river
river = game.addChild(new River());
// Create player
player = game.addChild(new Player());
player.reset();
// Reset game variables
LK.setScore(0);
obstacles = [];
collectibles = [];
gameStarted = false;
distance = 0;
// Create interface
createInterface();
// Start river sound
LK.playMusic('riverSound');
}
function createInterface() {
// Create score text
scoreText = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -scoreText.width - 20;
scoreText.y = 20;
// Create high score text
highScoreText = new Text2('HIGH SCORE: ' + storage.highScore, {
size: 40,
fill: 0xFFFFFF
});
highScoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreText);
highScoreText.x = -highScoreText.width - 20;
highScoreText.y = scoreText.y + scoreText.height + 10;
// Create distance text
distanceText = new Text2('DISTANCE: 0m', {
size: 50,
fill: 0xFFFFFF
});
distanceText.anchor.set(0, 0);
LK.gui.top.addChild(distanceText);
distanceText.y = 20;
// Create start message
if (!gameStarted) {
var startMessage = new Text2('TAP TO START PADDLING!', {
size: 80,
fill: 0xFFFFFF
});
startMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startMessage);
// Animate start message
tween(startMessage, {
alpha: 0.5
}, {
duration: 800,
easing: tween.sinInOut,
onFinish: function onFinish() {
tween(startMessage, {
alpha: 1
}, {
duration: 800,
easing: tween.sinInOut,
onFinish: function onFinish() {
if (!gameStarted) {
// Recursively continue animation until game starts
tween(startMessage, {
alpha: 0.5
}, {
duration: 800,
easing: tween.sinInOut
});
} else {
startMessage.destroy();
}
}
});
}
});
}
}
function updateScoreText() {
scoreText.setText('SCORE: ' + LK.getScore());
}
function startGame() {
if (gameStarted) {
return;
}
gameStarted = true;
// Start spawning obstacles
obstacleTimer = LK.setInterval(function () {
spawnObstacle();
}, 1500);
// Start spawning collectibles
collectibleTimer = LK.setInterval(function () {
var rand = Math.random();
if (rand < 0.6) {
spawnCollectible('coin');
} else if (rand < 0.9) {
spawnCollectible('powerup');
} else {
spawnCollectible('speedBoost');
}
}, 2000);
// Increase difficulty over time
difficultyTimer = LK.setInterval(function () {
river.increaseSpeed(0.5);
}, 10000);
}
function spawnObstacle() {
var types = ['rock', 'log', 'predator', 'enemyCow'];
var type = types[Math.floor(Math.random() * types.length)];
var obstacle = new Obstacle(type);
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnCollectible(type) {
var collectible = new Collectible(type);
collectibles.push(collectible);
game.addChild(collectible);
}
function handleMove(x, y) {
if (dragNode) {
// Constrain player to river
var minX = 250 + player.width / 2;
var maxX = 2048 - 250 - player.width / 2;
dragNode.x = Math.max(minX, Math.min(maxX, x));
}
}
function checkCollisions() {
if (player.dead) {
return;
}
// Check obstacle collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.active && player.intersects(obstacle)) {
player.type = obstacle.type; // Pass obstacle type to player for jump scare
player.die();
break;
}
}
// Check collectible collisions
for (var j = collectibles.length - 1; j >= 0; j--) {
var collectible = collectibles[j];
if (collectible.active && player.intersects(collectible)) {
collectible.collect();
collectibles.splice(j, 1);
}
}
// Check SpeedBoost collisions
for (var k = collectibles.length - 1; k >= 0; k--) {
var speedBoost = collectibles[k];
if (speedBoost.type === 'speedBoost' && speedBoost.active && player.intersects(speedBoost)) {
speedBoost.collect();
collectibles.splice(k, 1);
}
}
}
function cleanupInactiveObjects() {
// Remove inactive obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
if (!obstacles[i].active) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
}
// Remove inactive collectibles
for (var j = collectibles.length - 1; j >= 0; j--) {
if (!collectibles[j].active) {
collectibles[j].destroy();
collectibles.splice(j, 1);
}
}
}
// Event handlers
game.down = function (x, y) {
if (!gameStarted) {
startGame();
}
dragNode = player;
handleMove(x, y);
};
game.up = function () {
dragNode = null;
};
game.move = function (x, y) {
handleMove(x, y);
};
// Game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Update obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
// Update collectibles
for (var j = 0; j < collectibles.length; j++) {
collectibles[j].update();
}
// Check collisions
checkCollisions();
// Clean up inactive objects
cleanupInactiveObjects();
// Update distance traveled
distance += river.speed / 20;
distanceText.setText('DISTANCE: ' + Math.floor(distance) + 'm');
};
// Initialize game
initGame(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
unlockedCows: [0]
});
/****
* Classes
****/
var Collectible = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'coin';
self.value = self.type === 'coin' ? 10 : 50;
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = graphics.width;
self.height = graphics.height;
self.active = true;
self.reset = function (y) {
self.y = y || -self.height;
// Position collectible between river banks
var minX = 250;
var maxX = 2048 - 250 - self.width;
self.x = minX + Math.random() * (maxX - minX);
};
self.update = function () {
self.y += river.speed;
// Rotate coins
if (self.type === 'coin') {
graphics.rotation += 0.05;
}
// Flash power-ups
if (self.type === 'powerup' && LK.ticks % 10 === 0) {
tween(graphics, {
alpha: graphics.alpha < 1 ? 1 : 0.6
}, {
duration: 200
});
}
// Check if collectible is off screen
if (self.y > 2732 + self.height) {
self.active = false;
}
};
self.collect = function () {
self.active = false;
if (self.type === 'powerup') {
// Apply power-up effect
player.invincible = true;
// Set player to flash
var flashInterval = LK.setInterval(function () {
player.alpha = player.alpha < 1 ? 1 : 0.5;
}, 200);
// End invincibility after 5 seconds
LK.setTimeout(function () {
player.invincible = false;
player.alpha = 1;
LK.clearInterval(flashInterval);
}, 5000);
}
// Play collection sound
LK.getSound('collect').play();
// Add points
LK.setScore(LK.getScore() + self.value);
updateScoreText();
};
self.reset();
return self;
});
var Obstacle = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'rock';
var graphics = self.attachAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5
});
self.width = graphics.width;
self.height = graphics.height;
self.active = true;
self.reset = function (y) {
self.y = y || -self.height;
// Position obstacle between river banks
var minX = 250;
var maxX = 2048 - 250 - self.width;
self.x = minX + Math.random() * (maxX - minX);
};
self.update = function () {
self.lastType = self.type; // Track the type of obstacle for jump scare
self.y += river.speed;
// Add behavior for enemy cow
if (self.type === 'enemyCow') {
self.x += Math.sin(LK.ticks / 20) * 5; // Move enemy cow in a wave pattern
}
// Check if obstacle is off screen
if (self.y > 2732 + self.height) {
self.active = false;
}
};
self.reset();
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
// Create kayak
var kayak = self.attachAsset('kayak', {
anchorX: 0.5,
anchorY: 0.5,
y: 20
});
// Create cow
var cow = self.attachAsset('cow', {
anchorX: 0.5,
anchorY: 0.5,
y: -10
});
self.width = kayak.width;
self.height = kayak.height + cow.height - 20; // Overlap adjustment
self.invincible = false;
self.dead = false;
self.reset = function () {
self.x = 2048 / 2;
self.y = 2732 - 300;
self.dead = false;
self.invincible = false;
self.alpha = 1;
};
self.die = function () {
if (self.invincible || self.dead) {
return;
}
self.dead = true;
LK.getSound('hit').play();
// Jump scare effect with obstacle asset
var jumpScare = LK.getAsset(self.type, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3,
scaleY: 3
});
game.addChild(jumpScare);
LK.effects.flashObject(jumpScare, 0xFFFFFF, 500, function () {
jumpScare.destroy();
});
LK.effects.flashScreen(0xFF0000, 500);
// Show game over after a short delay
LK.setTimeout(function () {
// Save high score if needed
if (LK.getScore() > storage.highScore) {
storage.highScore = LK.getScore();
}
LK.showGameOver();
}, 1000);
};
return self;
});
var River = Container.expand(function () {
var self = Container.call(this);
var waterGraphics = self.attachAsset('water', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var leftBank = self.attachAsset('riverbank', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
var rightBank = self.attachAsset('riverbank', {
anchorX: 1,
anchorY: 0,
x: 2048,
y: 0
});
self.speed = 5;
self.maxSpeed = 15;
self.increaseSpeed = function (amount) {
self.speed = Math.min(self.maxSpeed, self.speed + amount);
};
return self;
});
var SpeedBoost = Container.expand(function () {
var self = Container.call(this);
self.type = 'speedBoost';
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = graphics.width;
self.height = graphics.height;
self.active = true;
self.reset = function (y) {
self.y = y || -self.height;
var minX = 250;
var maxX = 2048 - 250 - self.width;
self.x = minX + Math.random() * (maxX - minX);
};
self.update = function () {
self.y += river.speed;
if (LK.ticks % 10 === 0) {
tween(graphics, {
alpha: graphics.alpha < 1 ? 1 : 0.6
}, {
duration: 200
});
}
if (self.y > 2732 + self.height) {
self.active = false;
}
};
self.collect = function () {
self.active = false;
river.increaseSpeed(5);
LK.setTimeout(function () {
river.increaseSpeed(-5);
}, 5000);
LK.getSound('collect').play();
LK.setScore(LK.getScore() + 100);
updateScoreText();
};
self.reset();
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1E90FF
});
/****
* Game Code
****/
var player;
var river;
var obstacles = [];
var collectibles = [];
var dragNode = null;
var gameStarted = false;
var difficultyTimer;
var obstacleTimer;
var collectibleTimer;
var scoreText;
var highScoreText;
var distanceText;
var distance = 0;
function initGame() {
// Create river
river = game.addChild(new River());
// Create player
player = game.addChild(new Player());
player.reset();
// Reset game variables
LK.setScore(0);
obstacles = [];
collectibles = [];
gameStarted = false;
distance = 0;
// Create interface
createInterface();
// Start river sound
LK.playMusic('riverSound');
}
function createInterface() {
// Create score text
scoreText = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -scoreText.width - 20;
scoreText.y = 20;
// Create high score text
highScoreText = new Text2('HIGH SCORE: ' + storage.highScore, {
size: 40,
fill: 0xFFFFFF
});
highScoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreText);
highScoreText.x = -highScoreText.width - 20;
highScoreText.y = scoreText.y + scoreText.height + 10;
// Create distance text
distanceText = new Text2('DISTANCE: 0m', {
size: 50,
fill: 0xFFFFFF
});
distanceText.anchor.set(0, 0);
LK.gui.top.addChild(distanceText);
distanceText.y = 20;
// Create start message
if (!gameStarted) {
var startMessage = new Text2('TAP TO START PADDLING!', {
size: 80,
fill: 0xFFFFFF
});
startMessage.anchor.set(0.5, 0.5);
LK.gui.center.addChild(startMessage);
// Animate start message
tween(startMessage, {
alpha: 0.5
}, {
duration: 800,
easing: tween.sinInOut,
onFinish: function onFinish() {
tween(startMessage, {
alpha: 1
}, {
duration: 800,
easing: tween.sinInOut,
onFinish: function onFinish() {
if (!gameStarted) {
// Recursively continue animation until game starts
tween(startMessage, {
alpha: 0.5
}, {
duration: 800,
easing: tween.sinInOut
});
} else {
startMessage.destroy();
}
}
});
}
});
}
}
function updateScoreText() {
scoreText.setText('SCORE: ' + LK.getScore());
}
function startGame() {
if (gameStarted) {
return;
}
gameStarted = true;
// Start spawning obstacles
obstacleTimer = LK.setInterval(function () {
spawnObstacle();
}, 1500);
// Start spawning collectibles
collectibleTimer = LK.setInterval(function () {
var rand = Math.random();
if (rand < 0.6) {
spawnCollectible('coin');
} else if (rand < 0.9) {
spawnCollectible('powerup');
} else {
spawnCollectible('speedBoost');
}
}, 2000);
// Increase difficulty over time
difficultyTimer = LK.setInterval(function () {
river.increaseSpeed(0.5);
}, 10000);
}
function spawnObstacle() {
var types = ['rock', 'log', 'predator', 'enemyCow'];
var type = types[Math.floor(Math.random() * types.length)];
var obstacle = new Obstacle(type);
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnCollectible(type) {
var collectible = new Collectible(type);
collectibles.push(collectible);
game.addChild(collectible);
}
function handleMove(x, y) {
if (dragNode) {
// Constrain player to river
var minX = 250 + player.width / 2;
var maxX = 2048 - 250 - player.width / 2;
dragNode.x = Math.max(minX, Math.min(maxX, x));
}
}
function checkCollisions() {
if (player.dead) {
return;
}
// Check obstacle collisions
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
if (obstacle.active && player.intersects(obstacle)) {
player.type = obstacle.type; // Pass obstacle type to player for jump scare
player.die();
break;
}
}
// Check collectible collisions
for (var j = collectibles.length - 1; j >= 0; j--) {
var collectible = collectibles[j];
if (collectible.active && player.intersects(collectible)) {
collectible.collect();
collectibles.splice(j, 1);
}
}
// Check SpeedBoost collisions
for (var k = collectibles.length - 1; k >= 0; k--) {
var speedBoost = collectibles[k];
if (speedBoost.type === 'speedBoost' && speedBoost.active && player.intersects(speedBoost)) {
speedBoost.collect();
collectibles.splice(k, 1);
}
}
}
function cleanupInactiveObjects() {
// Remove inactive obstacles
for (var i = obstacles.length - 1; i >= 0; i--) {
if (!obstacles[i].active) {
obstacles[i].destroy();
obstacles.splice(i, 1);
}
}
// Remove inactive collectibles
for (var j = collectibles.length - 1; j >= 0; j--) {
if (!collectibles[j].active) {
collectibles[j].destroy();
collectibles.splice(j, 1);
}
}
}
// Event handlers
game.down = function (x, y) {
if (!gameStarted) {
startGame();
}
dragNode = player;
handleMove(x, y);
};
game.up = function () {
dragNode = null;
};
game.move = function (x, y) {
handleMove(x, y);
};
// Game update function
game.update = function () {
if (!gameStarted) {
return;
}
// Update obstacles
for (var i = 0; i < obstacles.length; i++) {
obstacles[i].update();
}
// Update collectibles
for (var j = 0; j < collectibles.length; j++) {
collectibles[j].update();
}
// Check collisions
checkCollisions();
// Clean up inactive objects
cleanupInactiveObjects();
// Update distance traveled
distance += river.speed / 20;
distanceText.setText('DISTANCE: ' + Math.floor(distance) + 'm');
};
// Initialize game
initGame();
yellow kayak. Single Game Texture. In-Game asset. High contrast. No shadows
log, 250x60. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
wolf. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
cow. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Rock in water. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
angry cow. Side portrait. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows