/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Balloon = Container.expand(function (type) {
var self = Container.call(this);
// Define balloon types and properties
var types = {
'red': {
color: 'balloon_red',
points: 10,
speed: 2
},
'blue': {
color: 'balloon_blue',
points: 20,
speed: 3
},
'yellow': {
color: 'balloon_yellow',
points: 30,
speed: 4
},
'green': {
color: 'balloon_green',
points: 50,
speed: 5
},
'spiky': {
color: 'spiky_balloon',
points: -10,
speed: 6
},
'purple': {
color: 'balloon_purple',
points: 40,
speed: 4.5
}
};
var balloonType = types[type] || types['red'];
self.type = type;
self.points = balloonType.points;
self.baseSpeed = balloonType.speed;
self.speed = self.baseSpeed;
self.active = true;
// Create balloon body
var balloonBody = self.attachAsset(balloonType.color, {
anchorX: 0.5,
anchorY: 0.5
});
// Create balloon string
var balloonString = self.attachAsset('balloon_string', {
anchorX: 0.5,
anchorY: 0,
y: balloonBody.height / 2
});
// Add a small random horizontal drift
self.driftSpeed = (Math.random() * 2 - 1) * 0.5;
self.update = function () {
if (self.active) {
self.y -= self.speed;
self.x += self.driftSpeed;
// Check if balloon is off-screen
if (self.y < -200) {
self.active = false;
}
}
};
self.pop = function () {
if (self.active) {
self.active = false;
LK.getSound('pop').play();
// Visual pop effect
tween(balloonBody, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Nothing needed here as cleanup happens in game loop
}
});
// Make string fall
tween(balloonString, {
rotation: Math.PI / 4,
alpha: 0
}, {
duration: 500,
easing: tween.easeIn
});
// Additional blast effect for spiky balloon
if (self.type === 'spiky') {
tween(balloonBody, {
scaleX: 2.5,
// Increase scale for more dramatic effect
scaleY: 2.5,
// Increase scale for more dramatic effect
alpha: 0
}, {
duration: 700,
// Increase duration for a slower blast
easing: tween.elasticOut,
onFinish: function onFinish() {
// Additional effect or cleanup if needed
balloonBody.destroy(); // Ensure the balloon body is removed after the effect
}
});
}
return self.points;
}
return 0;
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.speed = 0.3 + Math.random() * 0.3;
self.active = true;
// Make clouds different sizes
var scale = 0.8 + Math.random() * 1.2;
cloudGraphics.scaleX = scale;
cloudGraphics.scaleY = scale * 0.7;
self.update = function () {
if (self.active) {
self.x += self.speed;
// Loop cloud back to left side when it goes off screen
if (self.x > 2200) {
self.x = -200;
self.y = 200 + Math.random() * 300;
}
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.active = true;
self.type = Math.random() > 0.5 ? 'rapid' : 'spread';
// Set different color based on powerup type
if (self.type === 'rapid') {
powerupGraphics.tint = 0xff0000;
} else {
powerupGraphics.tint = 0x00ff00;
}
// Animate the powerup
tween(powerupGraphics, {
rotation: Math.PI * 2
}, {
duration: 3000,
easing: tween.linear
});
self.update = function () {
if (self.active) {
self.y -= self.speed;
// Check if powerup is off-screen
if (self.y < -100) {
self.active = false;
}
}
};
self.collect = function () {
if (self.active) {
self.active = false;
LK.getSound('powerup_collect').play();
// Visual collect effect
tween(powerupGraphics, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
return self.type;
}
return null;
};
return self;
});
var Seagull = Container.expand(function () {
var self = Container.call(this);
var seagullGraphics = self.attachAsset('seagull', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 2;
self.active = true;
self.direction = Math.random() > 0.5 ? 1 : -1;
// Set initial direction
if (self.direction < 0) {
seagullGraphics.scaleX = -1;
}
self.update = function () {
if (self.active) {
self.x += self.speed * self.direction;
// Ensure wing flapping animation is applied
if (!self.flapping) {
self.flapping = true;
tween(seagullGraphics, {
scaleY: 0.8
}, {
duration: 200,
yoyo: true,
repeat: Infinity,
easing: tween.easeInOut
});
}
// Check if seagull is off-screen
if (self.direction > 0 && self.x > 2100 || self.direction < 0 && self.x < -50) {
self.active = false;
}
}
};
return self;
});
var Seagull2 = Container.expand(function () {
var self = Container.call(this);
var seagullGraphics = self.attachAsset('seagull2', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 2;
self.active = true;
self.direction = Math.random() > 0.5 ? 1 : -1;
// Set initial direction
if (self.direction < 0) {
seagullGraphics.scaleX = -1;
}
self.update = function () {
if (self.active) {
self.x += self.speed * self.direction;
// Ensure wing flapping animation is applied
if (!self.flapping) {
self.flapping = true;
tween(seagullGraphics, {
scaleY: 0.8
}, {
duration: 200,
yoyo: true,
repeat: Infinity,
easing: tween.easeInOut
});
}
// Check if seagull is off-screen
if (self.direction > 0 && self.x > 2100 || self.direction < 0 && self.x < -50) {
self.active = false;
}
}
};
return self;
});
var WaterBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.active = true;
self.update = function () {
if (self.active) {
self.y += self.speed;
// Check if bullet is off-screen
if (self.y < -50) {
self.active = false;
}
}
};
return self;
});
var WaterGun = Container.expand(function () {
var self = Container.call(this);
var gunGraphics = self.attachAsset('watergun', {
anchorX: 0.5,
anchorY: 0.5
});
self.canShoot = true;
self.cooldown = 500; // ms between shots
self.powerupActive = false;
self.powerupType = null;
self.powerupTimer = null;
self.shoot = function () {
if (!self.canShoot) {
return null;
}
LK.getSound('shoot').play();
var bullets = [];
// Create main bullet
var bullet = new WaterBullet();
bullet.x = self.x;
bullet.y = self.y - 30;
bullets.push(bullet);
// If spread powerup is active, create side bullets
if (self.powerupActive && self.powerupType === 'spread') {
var bulletLeft = new WaterBullet();
bulletLeft.x = self.x - 30;
bulletLeft.y = self.y - 20;
bullets.push(bulletLeft);
var bulletRight = new WaterBullet();
bulletRight.x = self.x + 30;
bulletRight.y = self.y - 20;
bullets.push(bulletRight);
}
// Set cooldown unless rapid fire powerup is active
if (!(self.powerupActive && self.powerupType === 'rapid')) {
self.canShoot = false;
LK.setTimeout(function () {
self.canShoot = true;
}, self.cooldown);
}
return bullets;
};
self.activatePowerup = function (type) {
// Clear existing powerup if any
if (self.powerupTimer) {
LK.clearTimeout(self.powerupTimer);
}
self.powerupActive = true;
self.powerupType = type;
// Visual feedback
tween(gunGraphics, {
tint: type === 'rapid' ? 0xff0000 : 0x00ff00
}, {
duration: 300,
easing: tween.easeOut
});
// Set powerup duration
self.powerupTimer = LK.setTimeout(function () {
self.powerupActive = false;
self.powerupType = null;
// Reset gun appearance
tween(gunGraphics, {
tint: 0x2299cc
}, {
duration: 300,
easing: tween.easeIn
});
}, 8000); // 8 seconds
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x99ddff
});
/****
* Game Code
****/
function createSeagull2() {
var seagull2 = new Seagull2();
// Start from either left or right edge based on direction
seagull2.x = seagull2.direction > 0 ? -50 : 2100;
seagull2.y = 400 + Math.random() * 600;
seagulls.push(seagull2);
game.addChild(seagull2);
}
// Game variables
var score = 0;
var waterGun;
var bullets = [];
var balloons = [];
var seagulls = [];
var powerups = [];
var clouds = [];
var windEffect = 0;
var gameActive = true;
var lastBalloonSpawn = 0;
var lastSeagullSpawn = 0;
var lastPowerupSpawn = 0;
var balloonSpawnRate = 1500; // ms
var seagullSpawnRate = 5000; // ms
var powerupSpawnRate = 10000; // ms
var touchPoint = null;
// Background elements
var skyBackground = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Add some clouds
for (var i = 0; i < 5; i++) {
var cloud = new Cloud();
cloud.x = Math.random() * 2048;
cloud.y = 200 + Math.random() * 300;
clouds.push(cloud);
game.addChild(cloud);
}
// Water
var water = game.addChild(LK.getAsset('water', {
anchorX: 0,
anchorY: 1,
x: 0,
y: 2732
}));
// Sand
var sand = game.addChild(LK.getAsset('sand', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - water.height
}));
// Create water gun
waterGun = new WaterGun();
waterGun.x = 1024;
waterGun.y = 2732 - 200; // Position above the sand
game.addChild(waterGun);
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -200; // Offset from right edge
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 40,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -200;
highScoreTxt.y = 60;
// Wind indicator
var windTxt = new Text2('Wind: 0', {
size: 40,
fill: 0xFFFFFF
});
windTxt.anchor.set(0, 0);
LK.gui.top.addChild(windTxt);
windTxt.y = 60;
// Game functions
function createBalloon() {
var types = ['red', 'blue', 'yellow', 'green', 'spiky', 'purple'];
// Weight probabilities toward easier balloons
var type = types[Math.floor(Math.pow(Math.random(), 1.5) * types.length)];
var balloon = new Balloon(type);
balloon.x = 200 + Math.random() * (2048 - 400);
balloon.y = 2732 + 100;
// Apply wind effect to drift speed
balloon.driftSpeed += windEffect;
balloons.push(balloon);
game.addChild(balloon);
}
function createSeagull() {
var seagull = new Seagull();
// Start from either left or right edge based on direction
seagull.x = seagull.direction > 0 ? -50 : 2100;
seagull.y = 400 + Math.random() * 600;
seagulls.push(seagull);
game.addChild(seagull);
}
function createPowerup() {
var powerup = new PowerUp();
powerup.x = 200 + Math.random() * (2048 - 400);
powerup.y = 2732 + 50;
powerups.push(powerup);
game.addChild(powerup);
}
function checkCollisions() {
// Check bullet-balloon collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (!bullet.active) {
continue;
}
for (var j = balloons.length - 1; j >= 0; j--) {
var balloon = balloons[j];
if (!balloon.active) {
continue;
}
if (bullet.intersects(balloon)) {
if (bullet.intersects(powerup)) {
powerup.collect(); // Collect the powerup
// Burst multiple nearby balloons
for (var n = balloons.length - 1; n >= 0; n--) {
var nearbyBalloon = balloons[n];
if (nearbyBalloon.active && Math.abs(nearbyBalloon.x - bullet.x) < 200 && Math.abs(nearbyBalloon.y - bullet.y) < 200) {
nearbyBalloon.pop();
score += nearbyBalloon.points;
scoreTxt.setText('Score: ' + score);
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
}
}
}
if (balloon.type === 'spiky') {
gameActive = false;
LK.showGameOver();
return;
}
// Score points for popping balloon
var points = balloon.pop();
score += points;
scoreTxt.setText('Score: ' + score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
// Deactivate bullet
bullet.active = false;
break;
}
}
// Check bullet-seagull collisions (no points, but deactivates bullet)
for (var k = seagulls.length - 1; k >= 0; k--) {
var seagull = seagulls[k];
if (!seagull.active || !bullet.active) {
continue;
}
if (bullet.intersects(seagull)) {
// Trigger game over
gameActive = false;
LK.showGameOver();
return;
}
}
}
// Check watergun-powerup collisions
for (var m = powerups.length - 1; m >= 0; m--) {
var powerup = powerups[m];
if (!powerup.active) {
continue;
}
if (waterGun.intersects(powerup)) {
var powerupType = powerup.collect();
if (powerupType) {
waterGun.activatePowerup(powerupType);
}
}
}
}
function updateWind() {
// Change wind every 10 seconds
if (LK.ticks % 600 === 0) {
windEffect = (Math.random() * 2 - 1) * 1.5;
windTxt.setText('Wind: ' + (windEffect > 0 ? '→' : '←').repeat(Math.abs(Math.round(windEffect))));
}
}
function cleanupInactiveObjects() {
// Clean up inactive bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (!bullets[i].active) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
// Clean up inactive balloons
for (var j = balloons.length - 1; j >= 0; j--) {
if (!balloons[j].active) {
balloons[j].destroy();
balloons.splice(j, 1);
}
}
// Clean up inactive seagulls
for (var k = seagulls.length - 1; k >= 0; k--) {
if (!seagulls[k].active) {
seagulls[k].destroy();
seagulls.splice(k, 1);
}
}
// Clean up inactive powerups
for (var m = powerups.length - 1; m >= 0; m--) {
if (!powerups[m].active) {
powerups[m].destroy();
powerups.splice(m, 1);
}
}
}
function handleTouch(x, y) {
// Move water gun to touch position (with limits)
waterGun.x = Math.max(100, Math.min(2048 - 100, x));
// Shoot water
var newBullets = waterGun.shoot();
if (newBullets) {
for (var i = 0; i < newBullets.length; i++) {
game.addChild(newBullets[i]);
bullets.push(newBullets[i]);
}
}
}
// Touch events
game.down = function (x, y) {
touchPoint = {
x: x,
y: y
};
handleTouch(x, y);
};
game.move = function (x, y) {
if (touchPoint) {
touchPoint = {
x: x,
y: y
};
handleTouch(x, y);
}
};
game.up = function () {
touchPoint = null;
};
// Main game loop
game.update = function () {
if (!gameActive) {
return;
}
// Spawn objects based on time
var currentTime = LK.ticks * (1000 / 60); // Convert ticks to milliseconds
// Spawn balloons
if (currentTime - lastBalloonSpawn > balloonSpawnRate) {
createBalloon();
lastBalloonSpawn = currentTime;
// Gradually increase balloon spawn rate
balloonSpawnRate = Math.max(700, balloonSpawnRate - 10);
}
// Spawn seagulls
if (currentTime - lastSeagullSpawn > seagullSpawnRate) {
createSeagull();
createSeagull2(); // Add seagull2 spawning
lastSeagullSpawn = currentTime;
}
// Spawn powerups
if (currentTime - lastPowerupSpawn > powerupSpawnRate) {
createPowerup();
lastPowerupSpawn = currentTime;
}
// Update wind
updateWind();
// Check for collisions
checkCollisions();
// Clean up inactive objects
cleanupInactiveObjects();
// Shooting if touch is held
if (touchPoint && LK.ticks % 10 === 0 && waterGun.powerupActive && waterGun.powerupType === 'rapid') {
handleTouch(touchPoint.x, touchPoint.y);
}
// Game over condition: If too many balloons escape
// Count escaped balloons (moved off the top of the screen)
var escapedCount = 0;
for (var i = 0; i < balloons.length; i++) {
if (!balloons[i].active && balloons[i].y < 0) {
escapedCount++;
}
}
// If score reaches 500, player wins
if (score >= 500) {
gameActive = false;
LK.showYouWin();
}
};
// Start background music
LK.playMusic('beach_music'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Balloon = Container.expand(function (type) {
var self = Container.call(this);
// Define balloon types and properties
var types = {
'red': {
color: 'balloon_red',
points: 10,
speed: 2
},
'blue': {
color: 'balloon_blue',
points: 20,
speed: 3
},
'yellow': {
color: 'balloon_yellow',
points: 30,
speed: 4
},
'green': {
color: 'balloon_green',
points: 50,
speed: 5
},
'spiky': {
color: 'spiky_balloon',
points: -10,
speed: 6
},
'purple': {
color: 'balloon_purple',
points: 40,
speed: 4.5
}
};
var balloonType = types[type] || types['red'];
self.type = type;
self.points = balloonType.points;
self.baseSpeed = balloonType.speed;
self.speed = self.baseSpeed;
self.active = true;
// Create balloon body
var balloonBody = self.attachAsset(balloonType.color, {
anchorX: 0.5,
anchorY: 0.5
});
// Create balloon string
var balloonString = self.attachAsset('balloon_string', {
anchorX: 0.5,
anchorY: 0,
y: balloonBody.height / 2
});
// Add a small random horizontal drift
self.driftSpeed = (Math.random() * 2 - 1) * 0.5;
self.update = function () {
if (self.active) {
self.y -= self.speed;
self.x += self.driftSpeed;
// Check if balloon is off-screen
if (self.y < -200) {
self.active = false;
}
}
};
self.pop = function () {
if (self.active) {
self.active = false;
LK.getSound('pop').play();
// Visual pop effect
tween(balloonBody, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Nothing needed here as cleanup happens in game loop
}
});
// Make string fall
tween(balloonString, {
rotation: Math.PI / 4,
alpha: 0
}, {
duration: 500,
easing: tween.easeIn
});
// Additional blast effect for spiky balloon
if (self.type === 'spiky') {
tween(balloonBody, {
scaleX: 2.5,
// Increase scale for more dramatic effect
scaleY: 2.5,
// Increase scale for more dramatic effect
alpha: 0
}, {
duration: 700,
// Increase duration for a slower blast
easing: tween.elasticOut,
onFinish: function onFinish() {
// Additional effect or cleanup if needed
balloonBody.destroy(); // Ensure the balloon body is removed after the effect
}
});
}
return self.points;
}
return 0;
};
return self;
});
var Cloud = Container.expand(function () {
var self = Container.call(this);
var cloudGraphics = self.attachAsset('cloud', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.speed = 0.3 + Math.random() * 0.3;
self.active = true;
// Make clouds different sizes
var scale = 0.8 + Math.random() * 1.2;
cloudGraphics.scaleX = scale;
cloudGraphics.scaleY = scale * 0.7;
self.update = function () {
if (self.active) {
self.x += self.speed;
// Loop cloud back to left side when it goes off screen
if (self.x > 2200) {
self.x = -200;
self.y = 200 + Math.random() * 300;
}
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2;
self.active = true;
self.type = Math.random() > 0.5 ? 'rapid' : 'spread';
// Set different color based on powerup type
if (self.type === 'rapid') {
powerupGraphics.tint = 0xff0000;
} else {
powerupGraphics.tint = 0x00ff00;
}
// Animate the powerup
tween(powerupGraphics, {
rotation: Math.PI * 2
}, {
duration: 3000,
easing: tween.linear
});
self.update = function () {
if (self.active) {
self.y -= self.speed;
// Check if powerup is off-screen
if (self.y < -100) {
self.active = false;
}
}
};
self.collect = function () {
if (self.active) {
self.active = false;
LK.getSound('powerup_collect').play();
// Visual collect effect
tween(powerupGraphics, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
return self.type;
}
return null;
};
return self;
});
var Seagull = Container.expand(function () {
var self = Container.call(this);
var seagullGraphics = self.attachAsset('seagull', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 2;
self.active = true;
self.direction = Math.random() > 0.5 ? 1 : -1;
// Set initial direction
if (self.direction < 0) {
seagullGraphics.scaleX = -1;
}
self.update = function () {
if (self.active) {
self.x += self.speed * self.direction;
// Ensure wing flapping animation is applied
if (!self.flapping) {
self.flapping = true;
tween(seagullGraphics, {
scaleY: 0.8
}, {
duration: 200,
yoyo: true,
repeat: Infinity,
easing: tween.easeInOut
});
}
// Check if seagull is off-screen
if (self.direction > 0 && self.x > 2100 || self.direction < 0 && self.x < -50) {
self.active = false;
}
}
};
return self;
});
var Seagull2 = Container.expand(function () {
var self = Container.call(this);
var seagullGraphics = self.attachAsset('seagull2', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 2;
self.active = true;
self.direction = Math.random() > 0.5 ? 1 : -1;
// Set initial direction
if (self.direction < 0) {
seagullGraphics.scaleX = -1;
}
self.update = function () {
if (self.active) {
self.x += self.speed * self.direction;
// Ensure wing flapping animation is applied
if (!self.flapping) {
self.flapping = true;
tween(seagullGraphics, {
scaleY: 0.8
}, {
duration: 200,
yoyo: true,
repeat: Infinity,
easing: tween.easeInOut
});
}
// Check if seagull is off-screen
if (self.direction > 0 && self.x > 2100 || self.direction < 0 && self.x < -50) {
self.active = false;
}
}
};
return self;
});
var WaterBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.active = true;
self.update = function () {
if (self.active) {
self.y += self.speed;
// Check if bullet is off-screen
if (self.y < -50) {
self.active = false;
}
}
};
return self;
});
var WaterGun = Container.expand(function () {
var self = Container.call(this);
var gunGraphics = self.attachAsset('watergun', {
anchorX: 0.5,
anchorY: 0.5
});
self.canShoot = true;
self.cooldown = 500; // ms between shots
self.powerupActive = false;
self.powerupType = null;
self.powerupTimer = null;
self.shoot = function () {
if (!self.canShoot) {
return null;
}
LK.getSound('shoot').play();
var bullets = [];
// Create main bullet
var bullet = new WaterBullet();
bullet.x = self.x;
bullet.y = self.y - 30;
bullets.push(bullet);
// If spread powerup is active, create side bullets
if (self.powerupActive && self.powerupType === 'spread') {
var bulletLeft = new WaterBullet();
bulletLeft.x = self.x - 30;
bulletLeft.y = self.y - 20;
bullets.push(bulletLeft);
var bulletRight = new WaterBullet();
bulletRight.x = self.x + 30;
bulletRight.y = self.y - 20;
bullets.push(bulletRight);
}
// Set cooldown unless rapid fire powerup is active
if (!(self.powerupActive && self.powerupType === 'rapid')) {
self.canShoot = false;
LK.setTimeout(function () {
self.canShoot = true;
}, self.cooldown);
}
return bullets;
};
self.activatePowerup = function (type) {
// Clear existing powerup if any
if (self.powerupTimer) {
LK.clearTimeout(self.powerupTimer);
}
self.powerupActive = true;
self.powerupType = type;
// Visual feedback
tween(gunGraphics, {
tint: type === 'rapid' ? 0xff0000 : 0x00ff00
}, {
duration: 300,
easing: tween.easeOut
});
// Set powerup duration
self.powerupTimer = LK.setTimeout(function () {
self.powerupActive = false;
self.powerupType = null;
// Reset gun appearance
tween(gunGraphics, {
tint: 0x2299cc
}, {
duration: 300,
easing: tween.easeIn
});
}, 8000); // 8 seconds
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x99ddff
});
/****
* Game Code
****/
function createSeagull2() {
var seagull2 = new Seagull2();
// Start from either left or right edge based on direction
seagull2.x = seagull2.direction > 0 ? -50 : 2100;
seagull2.y = 400 + Math.random() * 600;
seagulls.push(seagull2);
game.addChild(seagull2);
}
// Game variables
var score = 0;
var waterGun;
var bullets = [];
var balloons = [];
var seagulls = [];
var powerups = [];
var clouds = [];
var windEffect = 0;
var gameActive = true;
var lastBalloonSpawn = 0;
var lastSeagullSpawn = 0;
var lastPowerupSpawn = 0;
var balloonSpawnRate = 1500; // ms
var seagullSpawnRate = 5000; // ms
var powerupSpawnRate = 10000; // ms
var touchPoint = null;
// Background elements
var skyBackground = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Add some clouds
for (var i = 0; i < 5; i++) {
var cloud = new Cloud();
cloud.x = Math.random() * 2048;
cloud.y = 200 + Math.random() * 300;
clouds.push(cloud);
game.addChild(cloud);
}
// Water
var water = game.addChild(LK.getAsset('water', {
anchorX: 0,
anchorY: 1,
x: 0,
y: 2732
}));
// Sand
var sand = game.addChild(LK.getAsset('sand', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 2732 - water.height
}));
// Create water gun
waterGun = new WaterGun();
waterGun.x = 1024;
waterGun.y = 2732 - 200; // Position above the sand
game.addChild(waterGun);
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -200; // Offset from right edge
var highScoreTxt = new Text2('High Score: ' + storage.highScore, {
size: 40,
fill: 0xFFFFFF
});
highScoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(highScoreTxt);
highScoreTxt.x = -200;
highScoreTxt.y = 60;
// Wind indicator
var windTxt = new Text2('Wind: 0', {
size: 40,
fill: 0xFFFFFF
});
windTxt.anchor.set(0, 0);
LK.gui.top.addChild(windTxt);
windTxt.y = 60;
// Game functions
function createBalloon() {
var types = ['red', 'blue', 'yellow', 'green', 'spiky', 'purple'];
// Weight probabilities toward easier balloons
var type = types[Math.floor(Math.pow(Math.random(), 1.5) * types.length)];
var balloon = new Balloon(type);
balloon.x = 200 + Math.random() * (2048 - 400);
balloon.y = 2732 + 100;
// Apply wind effect to drift speed
balloon.driftSpeed += windEffect;
balloons.push(balloon);
game.addChild(balloon);
}
function createSeagull() {
var seagull = new Seagull();
// Start from either left or right edge based on direction
seagull.x = seagull.direction > 0 ? -50 : 2100;
seagull.y = 400 + Math.random() * 600;
seagulls.push(seagull);
game.addChild(seagull);
}
function createPowerup() {
var powerup = new PowerUp();
powerup.x = 200 + Math.random() * (2048 - 400);
powerup.y = 2732 + 50;
powerups.push(powerup);
game.addChild(powerup);
}
function checkCollisions() {
// Check bullet-balloon collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (!bullet.active) {
continue;
}
for (var j = balloons.length - 1; j >= 0; j--) {
var balloon = balloons[j];
if (!balloon.active) {
continue;
}
if (bullet.intersects(balloon)) {
if (bullet.intersects(powerup)) {
powerup.collect(); // Collect the powerup
// Burst multiple nearby balloons
for (var n = balloons.length - 1; n >= 0; n--) {
var nearbyBalloon = balloons[n];
if (nearbyBalloon.active && Math.abs(nearbyBalloon.x - bullet.x) < 200 && Math.abs(nearbyBalloon.y - bullet.y) < 200) {
nearbyBalloon.pop();
score += nearbyBalloon.points;
scoreTxt.setText('Score: ' + score);
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
}
}
}
if (balloon.type === 'spiky') {
gameActive = false;
LK.showGameOver();
return;
}
// Score points for popping balloon
var points = balloon.pop();
score += points;
scoreTxt.setText('Score: ' + score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
highScoreTxt.setText('High Score: ' + storage.highScore);
}
// Deactivate bullet
bullet.active = false;
break;
}
}
// Check bullet-seagull collisions (no points, but deactivates bullet)
for (var k = seagulls.length - 1; k >= 0; k--) {
var seagull = seagulls[k];
if (!seagull.active || !bullet.active) {
continue;
}
if (bullet.intersects(seagull)) {
// Trigger game over
gameActive = false;
LK.showGameOver();
return;
}
}
}
// Check watergun-powerup collisions
for (var m = powerups.length - 1; m >= 0; m--) {
var powerup = powerups[m];
if (!powerup.active) {
continue;
}
if (waterGun.intersects(powerup)) {
var powerupType = powerup.collect();
if (powerupType) {
waterGun.activatePowerup(powerupType);
}
}
}
}
function updateWind() {
// Change wind every 10 seconds
if (LK.ticks % 600 === 0) {
windEffect = (Math.random() * 2 - 1) * 1.5;
windTxt.setText('Wind: ' + (windEffect > 0 ? '→' : '←').repeat(Math.abs(Math.round(windEffect))));
}
}
function cleanupInactiveObjects() {
// Clean up inactive bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (!bullets[i].active) {
bullets[i].destroy();
bullets.splice(i, 1);
}
}
// Clean up inactive balloons
for (var j = balloons.length - 1; j >= 0; j--) {
if (!balloons[j].active) {
balloons[j].destroy();
balloons.splice(j, 1);
}
}
// Clean up inactive seagulls
for (var k = seagulls.length - 1; k >= 0; k--) {
if (!seagulls[k].active) {
seagulls[k].destroy();
seagulls.splice(k, 1);
}
}
// Clean up inactive powerups
for (var m = powerups.length - 1; m >= 0; m--) {
if (!powerups[m].active) {
powerups[m].destroy();
powerups.splice(m, 1);
}
}
}
function handleTouch(x, y) {
// Move water gun to touch position (with limits)
waterGun.x = Math.max(100, Math.min(2048 - 100, x));
// Shoot water
var newBullets = waterGun.shoot();
if (newBullets) {
for (var i = 0; i < newBullets.length; i++) {
game.addChild(newBullets[i]);
bullets.push(newBullets[i]);
}
}
}
// Touch events
game.down = function (x, y) {
touchPoint = {
x: x,
y: y
};
handleTouch(x, y);
};
game.move = function (x, y) {
if (touchPoint) {
touchPoint = {
x: x,
y: y
};
handleTouch(x, y);
}
};
game.up = function () {
touchPoint = null;
};
// Main game loop
game.update = function () {
if (!gameActive) {
return;
}
// Spawn objects based on time
var currentTime = LK.ticks * (1000 / 60); // Convert ticks to milliseconds
// Spawn balloons
if (currentTime - lastBalloonSpawn > balloonSpawnRate) {
createBalloon();
lastBalloonSpawn = currentTime;
// Gradually increase balloon spawn rate
balloonSpawnRate = Math.max(700, balloonSpawnRate - 10);
}
// Spawn seagulls
if (currentTime - lastSeagullSpawn > seagullSpawnRate) {
createSeagull();
createSeagull2(); // Add seagull2 spawning
lastSeagullSpawn = currentTime;
}
// Spawn powerups
if (currentTime - lastPowerupSpawn > powerupSpawnRate) {
createPowerup();
lastPowerupSpawn = currentTime;
}
// Update wind
updateWind();
// Check for collisions
checkCollisions();
// Clean up inactive objects
cleanupInactiveObjects();
// Shooting if touch is held
if (touchPoint && LK.ticks % 10 === 0 && waterGun.powerupActive && waterGun.powerupType === 'rapid') {
handleTouch(touchPoint.x, touchPoint.y);
}
// Game over condition: If too many balloons escape
// Count escaped balloons (moved off the top of the screen)
var escapedCount = 0;
for (var i = 0; i < balloons.length; i++) {
if (!balloons[i].active && balloons[i].y < 0) {
escapedCount++;
}
}
// If score reaches 500, player wins
if (score >= 500) {
gameActive = false;
LK.showYouWin();
}
};
// Start background music
LK.playMusic('beach_music');
A soft gradient sky transitioning from light blue to white, with subtle fluffy clouds scattered across. The style should be cartoonish and visually appealing.". Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A glowing, floating power-up icon shaped like a lightning bolt, rotating in mid-air. Colors include blue, green, and red variants.". Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A cartoon-style toy gun with a futuristic design, mainly blue with white and black details, a large trigger, and a barrel that shoots darts.". Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
A cartoon-style seagull in mid-flight, white feathers with a light gray beak and wings slightly spread out. Expressions should be fun and mischievous.". Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows