/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Penguin class
var Penguin = Container.expand(function () {
var self = Container.call(this);
// Penguin id: 1 or 2
self.penguinId = 1;
// Attach penguin asset
var penguinGfx = self.attachAsset(self.penguinId === 1 ? 'penguin1' : 'penguin2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1 // Flip horizontally to show penguin's back
});
// Used for drag
self.isDragging = false;
// Used for aiming
self.aimLine = null;
// Used for touch start position
self.startDragX = 0;
self.startDragY = 0;
// Used for aiming vector
self.aimVX = 0;
self.aimVY = 0;
// Used for aiming bar
self.aimBar = null;
// Used for cooldown
self.canThrow = true;
// Used for tracking last position for drag
self.lastDragX = 0;
self.lastDragY = 0;
// Used for showing aim
self.showAim = function (x, y) {
// Not implemented: no line drawing in LK, so skip
};
// Used for hiding aim
self.hideAim = function () {
// Not implemented: no line drawing in LK, so skip
};
return self;
});
// Class for falling snowball (visual only, no collision)
var SnowShowerBall = Container.expand(function () {
var self = Container.call(this);
// Attach snowball asset
var gfx = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7 + Math.random() * 0.5,
scaleY: 0.7 + Math.random() * 0.5
});
// Random X across the screen, avoid top left 100x100
self.x = 120 + Math.random() * (GAME_WIDTH - 240);
self.y = -60 - Math.random() * 200;
// Random speed
self.vy = 7 + Math.random() * 4;
// Slight wind drift
self.vx = -2 + Math.random() * 4;
// Fade in/out
gfx.alpha = 0.7 + Math.random() * 0.3;
// Wobble
self.wobblePhase = Math.random() * Math.PI * 2;
self.update = function () {
self.y += self.vy;
self.x += self.vx + Math.sin(Date.now() / 300 + self.wobblePhase) * 1.2;
// Remove if out of bounds
if (self.y > GAME_HEIGHT + 80) {
self.destroy();
// Remove from array in main update
}
};
return self;
});
// Function to spawn a snowball shower ball
// Snowball class
var Snowball = Container.expand(function () {
var self = Container.call(this);
// Add black outline as a slightly larger ellipse behind the snowball
var outline = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.18,
scaleY: 1.18,
color: 0x000000
});
// Attach snowball asset (white, on top)
var snowballGfx = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5
});
// Who fired this snowball? 1 or 2
self.owner = 1;
// Velocity
self.vx = 0;
self.vy = 0;
// Used for bounce cooldown
self.bounced = false;
// Update method
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Light blue sky
});
/****
* Game Code
****/
// Flag asset for wind direction (simple colored box)
// Game constants
// Penguin (player 1)
// Penguin (player 2)
// Snowball
// Castle wall (center)
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Center wall
var wall = LK.getAsset('castleWall', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT / 2,
rotation: Math.PI / 2 // Rotate 90 degrees to make it horizontal
});
game.addChild(wall);
// --- Penguin selection screen ---
var selectedPenguinId = null;
var penguin1 = null;
var penguin2 = null;
var aiPenguin = null;
var playerPenguin = null;
var selectionScreen = new Container();
game.addChild(selectionScreen);
// Penguin 1 preview
var penguin1Preview = LK.getAsset('penguin1', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2 - 300,
y: GAME_HEIGHT / 2,
scaleX: 1,
scaleY: 1
});
selectionScreen.addChild(penguin1Preview);
// Penguin 2 preview
var penguin2Preview = LK.getAsset('penguin2', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2 + 300,
y: GAME_HEIGHT / 2,
scaleX: 1,
scaleY: 1
});
selectionScreen.addChild(penguin2Preview);
// Penguin 1 label
var penguin1Label = new Text2("Penguin 1", {
size: 90,
fill: 0x222222
});
penguin1Label.anchor.set(0.5, 0);
penguin1Label.x = penguin1Preview.x;
penguin1Label.y = penguin1Preview.y + 140;
selectionScreen.addChild(penguin1Label);
// Penguin 2 label
var penguin2Label = new Text2("Penguin 2", {
size: 90,
fill: 0x222222
});
penguin2Label.anchor.set(0.5, 0);
penguin2Label.x = penguin2Preview.x;
penguin2Label.y = penguin2Preview.y + 140;
selectionScreen.addChild(penguin2Label);
// Title
var selectTitle = new Text2("Choose your Penguin!", {
size: 120,
fill: 0x4fc3f7
});
selectTitle.anchor.set(0.5, 0.5);
selectTitle.x = GAME_WIDTH / 2;
selectTitle.y = GAME_HEIGHT / 2 - 300;
selectionScreen.addChild(selectTitle);
// Selection logic
selectionScreen.down = function (x, y, obj) {
// Check if touch is on penguin1Preview
var dx1 = x - penguin1Preview.x;
var dy1 = y - penguin1Preview.y;
var dx2 = x - penguin2Preview.x;
var dy2 = y - penguin2Preview.y;
var r = 120;
if (dx1 * dx1 + dy1 * dy1 < r * r) {
selectedPenguinId = 1;
} else if (dx2 * dx2 + dy2 * dy2 < r * r) {
selectedPenguinId = 2;
}
if (selectedPenguinId) {
// Remove selection screen
selectionScreen.destroy();
// Remove preview penguins from the game (ensure they are not left in the background)
if (penguin1Preview && penguin1Preview.parent) penguin1Preview.destroy();
if (penguin2Preview && penguin2Preview.parent) penguin2Preview.destroy();
if (penguin1Label && penguin1Label.parent) penguin1Label.destroy();
if (penguin2Label && penguin2Label.parent) penguin2Label.destroy();
if (selectTitle && selectTitle.parent) selectTitle.destroy();
// Setup penguins
penguin1 = new Penguin();
penguin1.penguinId = 1;
penguin1.x = GAME_WIDTH / 2;
penguin1.y = GAME_HEIGHT - 350;
game.addChild(penguin1);
penguin2 = new Penguin();
penguin2.penguinId = 2;
penguin2.x = GAME_WIDTH / 2;
penguin2.y = 350;
game.addChild(penguin2);
// Set correct asset for penguin2
penguin2.removeChildAt(0);
penguin2.attachAsset('penguin2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1
});
// Assign player and AI
if (selectedPenguinId === 1) {
playerPenguin = penguin1;
aiPenguin = penguin2;
} else {
playerPenguin = penguin2;
aiPenguin = penguin1;
}
// Mark for AI logic
aiPenguin.isAI = true;
playerPenguin.isAI = false;
// Set up initial canThrow
playerPenguin.canThrow = true;
aiPenguin.canThrow = true;
// (Optional) Add a little effect to show selection
LK.effects.flashObject(playerPenguin, 0x4fc3f7, 600);
}
};
selectionScreen.interactive = true;
selectionScreen.on('down', selectionScreen.down);
// The rest of the game logic will use playerPenguin and aiPenguin instead of penguin1/penguin2 directly.
// Score
var score1 = 0;
var score2 = 0;
// Score text
var scoreTxt = new Text2('0 : 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Snowballs array
var snowballs = [];
// --- Wind mechanic ---
// Wind directions: 0=left, 1=right, 2=up, 3=down
var windDirections = [{
name: "←",
dx: -1,
dy: 0
}, {
name: "→",
dx: 1,
dy: 0
}, {
name: "↑",
dx: 0,
dy: -1
}, {
name: "↓",
dx: 0,
dy: 1
}];
var windStrengthMin = 0; // minimum wind
var windStrengthMax = 22; // maximum wind
var windStrength = 0; // current wind strength (0-22)
var windDir = 0; // current wind direction index (0-3)
var windIndicator = null;
var windText = null;
// Helper to randomize wind before each throw
function setRandomWind() {
windDir = Math.floor(Math.random() * windDirections.length);
windStrength = Math.floor(Math.random() * (windStrengthMax + 1)); // 0 to max
// Remove old indicator
if (windIndicator) {
windIndicator.destroy();
windIndicator = null;
}
if (windText) {
windText.destroy();
windText = null;
}
if (typeof windFlag !== "undefined" && windFlag) {
windFlag.destroy();
windFlag = null;
}
// Show wind visually at top center (keep arrow for reference)
var arrowLen = 120 + windStrength * 3;
var arrowColor = 0x4fc3f7;
windIndicator = LK.getAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5,
width: 30,
height: arrowLen,
color: arrowColor
});
windIndicator.x = GAME_WIDTH / 2;
windIndicator.y = 160;
if (windDir === 0) windIndicator.rotation = Math.PI; // left
else if (windDir === 1) windIndicator.rotation = 0; // right
else if (windDir === 2) windIndicator.rotation = -Math.PI / 2; // up
else if (windDir === 3) windIndicator.rotation = Math.PI / 2; // down
game.addChild(windIndicator);
// Add flag to indicate wind direction and strength
windFlag = LK.getAsset('windFlag', {
anchorX: 0.1,
anchorY: 0.5,
width: 90 + windStrength * 2,
// flag length grows with wind
height: 60 + Math.floor(windStrength / 3),
// flag height grows a bit with wind
color: 0xffe066
});
// Place wind flag at the top right corner, leaving a margin from the edge
windFlag.x = GAME_WIDTH - 120;
windFlag.y = 120;
// Rotate flag to match wind direction
if (windDir === 0) windFlag.rotation = Math.PI; // left
else if (windDir === 1) windFlag.rotation = 0; // right
else if (windDir === 2) windFlag.rotation = -Math.PI / 2; // up
else if (windDir === 3) windFlag.rotation = Math.PI / 2; // down
game.addChild(windFlag);
// Animate flag waving (simple waving effect)
if (typeof windFlagTween !== "undefined" && windFlagTween) {
windFlagTween.stop();
windFlagTween = null;
}
// Animate flag waving (simple waving effect) using correct tween API
tween(windFlag, {
scaleY: 1.15
}, {
duration: 400,
easing: tween.sineInOut,
onFinish: function onFinish() {
// Reverse the tween for yoyo effect
tween(windFlag, {
scaleY: 1.0
}, {
duration: 400,
easing: tween.sineInOut,
onFinish: function onFinish() {
// Loop the waving animation
LK.setTimeout(function () {
if (windFlag && windFlag.parent) {
// Only continue if flag still exists
// Recursively start waving again
// (This is a simple infinite yoyo loop)
tween(windFlag, {
scaleY: 1.15
}, {
duration: 400,
easing: tween.sineInOut,
onFinish: arguments.callee
});
}
}, 0);
}
});
}
});
// Add wind text
var txt = windDirections[windDir].name + " " + windStrength;
windText = new Text2(txt, {
size: 80,
fill: 0x4fc3f7
});
windText.anchor.set(0.5, 0.5);
// Place wind text near the flag, but offset to the left to avoid overlap
windText.x = GAME_WIDTH - 260;
windText.y = 120;
LK.gui.top.addChild(windText);
}
// Call once at start
setRandomWind();
// Drag/aim state
var dragPenguin = null;
var dragStartX = 0;
var dragStartY = 0;
var dragCurrentX = 0;
var dragCurrentY = 0;
// Power bar state
var powerBar = null;
var powerBarBg = null;
var powerBarValue = 0;
var powerBarInterval = null;
var powerBarMax = 1.0; // max fill
var powerBarMin = 0.2; // min fill
var powerBarSpeed = 0.012; // fill per tick
// Turn-based state
var currentTurn = "player"; // "player" or "ai"
var turnInProgress = false; // Prevents double actions in a turn
// Only allow one penguin to be dragged at a time
function isTouchOnPenguin(x, y, penguin) {
if (!penguin) return false; // Defensive: penguin may be null
// Simple bounding box check
var px = penguin.x;
var py = penguin.y;
var w = penguin.width || 140;
var h = penguin.height || 180;
return x > px - w / 2 && x < px + w / 2 && y > py - h / 2 && y < py + h / 2;
}
// Only allow dragging own penguin (player 1: bottom, player 2: top)
game.down = function (x, y, obj) {
// Don't allow drag in top 100x100 (menu)
if (x < 100 && y < 100) return;
// Only allow drag on playerPenguin (single player) and only if it's player's turn and not in progress
if (typeof playerPenguin !== "undefined" && isTouchOnPenguin(x, y, playerPenguin) && currentTurn === "player" && !turnInProgress) {
turnInProgress = true;
dragPenguin = playerPenguin;
dragStartX = x;
dragStartY = y;
dragCurrentX = x;
dragCurrentY = y;
playerPenguin.isDragging = true;
// Show power bar next to playerPenguin
if (powerBarBg) {
powerBarBg.destroy();
powerBarBg = null;
}
if (powerBar) {
powerBar.destroy();
powerBar = null;
}
// Background bar
powerBarBg = LK.getAsset('snowball', {
anchorX: 0,
anchorY: 0.5,
width: 40,
height: 180,
color: 0xcccccc
});
powerBarBg.x = playerPenguin.x + 90;
powerBarBg.y = playerPenguin.y;
game.addChild(powerBarBg);
// Foreground (fill) bar
powerBar = LK.getAsset('snowball', {
anchorX: 0,
anchorY: 0.5,
width: 36,
height: 0,
// will be set by fill
color: 0x4fc3f7
});
powerBar.x = playerPenguin.x + 92;
powerBar.y = playerPenguin.y + 90; // start at bottom
game.addChild(powerBar);
powerBarValue = powerBarMin;
// Animate fill
if (powerBarInterval) LK.clearInterval(powerBarInterval);
powerBarInterval = LK.setInterval(function () {
if (!dragPenguin) return;
powerBarValue += powerBarSpeed;
if (powerBarValue > powerBarMax) powerBarValue = powerBarMax;
// Update bar height and position
var maxHeight = 180;
var fillHeight = Math.max(0, Math.floor(maxHeight * powerBarValue));
powerBar.height = fillHeight;
powerBar.y = playerPenguin.y + 90 - fillHeight;
}, 16);
}
};
game.move = function (x, y, obj) {
if (!dragPenguin) return;
// Clamp drag to own half (playerPenguin only)
if (dragPenguin === playerPenguin) {
if (playerPenguin.penguinId === 1 && y < GAME_HEIGHT / 2 + 100) y = GAME_HEIGHT / 2 + 100;
if (playerPenguin.penguinId === 2 && y > GAME_HEIGHT / 2 - 100) y = GAME_HEIGHT / 2 - 100;
}
// Clamp to game area
var minX = 120,
maxX = GAME_WIDTH - 120;
var minY = 120,
maxY = GAME_HEIGHT - 120;
x = Math.max(minX, Math.min(maxX, x));
y = Math.max(minY, Math.min(maxY, y));
dragCurrentX = x;
dragCurrentY = y;
// Move penguin
dragPenguin.x = x;
dragPenguin.y = y;
// --- Aiming bar logic ---
var penguin = dragPenguin;
if (penguin) {
// Remove old aimBar if exists
if (penguin.aimBar) {
penguin.aimBar.destroy();
penguin.aimBar = null;
}
// Only show aim bar if drag distance is enough
var dx = dragCurrentX - dragStartX;
var dy = dragCurrentY - dragStartY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 20) {
// Always aim toward the AI penguin
var target = aiPenguin;
var tx = target.x - penguin.x;
var ty = target.y - penguin.y;
var angle = Math.atan2(ty, tx);
// Bar length
var barLen = 220;
// Create bar as a thin tall rectangle (use a box shape)
var bar = LK.getAsset('snowball', {
anchorX: 0.5,
anchorY: 1,
width: 18,
height: barLen,
color: 0x4fc3f7
});
// Place under penguin
bar.x = penguin.x;
bar.y = penguin.y + 90;
// Rotate to aim direction
bar.rotation = angle + Math.PI / 2;
game.addChild(bar);
penguin.aimBar = bar;
}
}
// Move power bar if visible
if (powerBarBg && dragPenguin) {
powerBarBg.x = dragPenguin.x + 90;
powerBarBg.y = dragPenguin.y;
}
if (powerBar && dragPenguin) {
powerBar.x = dragPenguin.x + 92;
// keep y at bottom, height is set by interval
}
};
game.up = function (x, y, obj) {
if (!dragPenguin) return;
// Hide power bar
if (powerBarBg) {
powerBarBg.destroy();
powerBarBg = null;
}
if (powerBar) {
powerBar.destroy();
powerBar = null;
}
if (powerBarInterval) {
LK.clearInterval(powerBarInterval);
powerBarInterval = null;
}
// Only allow throw if drag distance is enough and cooldown is over
var dx = dragCurrentX - dragStartX;
var dy = dragCurrentY - dragStartY;
var dist = Math.sqrt(dx * dx + dy * dy);
// Only allow throw if drag is a "flick" (distance > 80)
if (dist > 80 && dragPenguin.canThrow && currentTurn === "player") {
// Set new wind before each throw
setRandomWind();
// Always throw toward the AI penguin, power only affects distance
var basePower = powerBarValue || powerBarMin;
var thrower = dragPenguin;
var target = aiPenguin;
// Calculate direction vector from thrower to target
var tx = target.x - thrower.x;
var ty = target.y - thrower.y;
var len = Math.sqrt(tx * tx + ty * ty);
// Normalize direction
var dirX = tx / len;
var dirY = ty / len;
// Set velocity magnitude based on power
var minV = 18;
var maxV = 55;
var velocity = minV + (maxV - minV) * ((basePower - powerBarMin) / (powerBarMax - powerBarMin));
// Clamp velocity
if (velocity < minV) velocity = minV;
if (velocity > maxV) velocity = maxV;
// Final velocity
var vx = dirX * velocity;
var vy = dirY * velocity;
// --- Apply wind effect ---
// Wind is a constant added to vx/vy, scaled by windStrength
var wind = windDirections[windDir];
var windEffect = windStrength * 0.18; // tune this for balance
vx += wind.dx * windEffect;
vy += wind.dy * windEffect;
// Create snowball
var snowball = new Snowball();
snowball.owner = playerPenguin.penguinId;
snowball.x = dragPenguin.x;
snowball.y = dragPenguin.y + (snowball.owner === 1 ? -90 : 90);
snowball.vx = vx;
snowball.vy = vy;
snowballs.push(snowball);
game.addChild(snowball);
// Play snowball throw sound
LK.getSound('kartopusesi').play();
// Cooldown: prevent spamming
dragPenguin.canThrow = false;
var cooldownPenguin = dragPenguin;
LK.setTimeout(function () {
if (cooldownPenguin) {
cooldownPenguin.canThrow = true;
}
}, 600);
// End player's turn, start AI's turn after a 2 second delay
currentTurn = "ai";
turnInProgress = true;
LK.setTimeout(function () {
turnInProgress = false;
}, 2000);
}
// Remove aim bar if exists
if (dragPenguin && dragPenguin.aimBar) {
dragPenguin.aimBar.destroy();
dragPenguin.aimBar = null;
}
dragPenguin.isDragging = false;
dragPenguin = null;
};
/**
* Helper: check collision between two containers (bounding box)
*/
function isIntersect(a, b) {
var ax = a.x,
ay = a.y,
aw = a.width || 100,
ah = a.height || 100;
var bx = b.x,
by = b.y,
bw = b.width || 100,
bh = b.height || 100;
return ax - aw / 2 < bx + bw / 2 && ax + aw / 2 > bx - bw / 2 && ay - ah / 2 < by + bh / 2 && ay + ah / 2 > by - bh / 2;
}
// Update score text
function updateScore() {
scoreTxt.setText(score1 + " : " + score2);
}
// Game update loop
game.update = function () {
// --- AI logic for non-player penguin ---
// AI only acts on its turn and if not in progress (wait for 2s after player)
if (typeof aiPenguin !== "undefined" && aiPenguin && aiPenguin.isAI && aiPenguin.canThrow && currentTurn === "ai" && !turnInProgress) {
// AI throws at intervals, only if no snowball is currently flying from AI
var aiHasActiveSnowball = false;
for (var aiCheck = 0; aiCheck < snowballs.length; aiCheck++) {
if (snowballs[aiCheck].owner === (aiPenguin.penguinId || 2)) {
aiHasActiveSnowball = true;
break;
}
}
if (!aiHasActiveSnowball) {
turnInProgress = true;
// Set new wind before each throw
setRandomWind();
// Aim at playerPenguin
var target = playerPenguin;
var thrower = aiPenguin;
// Add some random offset to aim for realism
var tx = target.x + (Math.random() - 0.5) * 80 - thrower.x;
var ty = target.y + (Math.random() - 0.5) * 80 - thrower.y;
var len = Math.sqrt(tx * tx + ty * ty);
var dirX = tx / len;
var dirY = ty / len;
// AI power: random between 0.5 and 1.0
var basePower = 0.5 + Math.random() * 0.5;
var minV = 18;
var maxV = 55;
var velocity = minV + (maxV - minV) * basePower;
if (velocity < minV) velocity = minV;
if (velocity > maxV) velocity = maxV;
var vx = dirX * velocity;
var vy = dirY * velocity;
// Apply wind
var wind = windDirections[windDir];
var windEffect = windStrength * 0.18;
vx += wind.dx * windEffect;
vy += wind.dy * windEffect;
// Create snowball
var snowball = new Snowball();
snowball.owner = aiPenguin.penguinId || 2;
snowball.x = aiPenguin.x;
snowball.y = aiPenguin.y + (snowball.owner === 1 ? -90 : 90);
snowball.vx = vx;
snowball.vy = vy;
snowballs.push(snowball);
game.addChild(snowball);
// Play snowball throw sound
LK.getSound('kartopusesi').play();
// Cooldown for AI
aiPenguin.canThrow = false;
var cooldownAI = aiPenguin;
LK.setTimeout(function () {
if (cooldownAI) {
cooldownAI.canThrow = true;
}
// After AI throw, switch back to player turn
currentTurn = "player";
turnInProgress = false;
}, 1200 + Math.random() * 800);
}
}
// Update snowballs
for (var i = snowballs.length - 1; i >= 0; i--) {
var sb = snowballs[i];
sb.update();
// Gravity
sb.vy += 0.7;
// Friction
sb.vx *= 0.99;
sb.vy *= 0.99;
// Out of bounds: remove
if (sb.x < -100 || sb.x > GAME_WIDTH + 100 || sb.y < -100 || sb.y > GAME_HEIGHT + 100) {
sb.destroy();
snowballs.splice(i, 1);
continue;
}
// No snowball-wall collision or bounce (disabled per requirements)
// Hit penguin (opponent only)
if (sb.owner === 1 && isIntersect(sb, penguin2)) {
// Score for player 1
score1 += 1;
updateScore();
LK.effects.flashObject(penguin2, 0xffffff, 400);
sb.destroy();
snowballs.splice(i, 1);
// Win condition
if (score1 >= 5) {
LK.showYouWin();
}
continue;
}
if (sb.owner === 2 && isIntersect(sb, penguin1)) {
// Score for player 2
score2 += 1;
updateScore();
LK.effects.flashObject(penguin1, 0xffffff, 400);
sb.destroy();
snowballs.splice(i, 1);
// Lose condition
if (score2 >= 5) {
LK.showGameOver();
}
continue;
}
}
};
// Initial score
updateScore();
// --- Snowball Shower Effect (Doğa olayı olarak kartopu yağma efekti) ---
// Array to hold falling snowballs for the effect
var snowShowerBalls = [];
// How often to spawn a new snowball (ms)
var snowShowerInterval = 220;
// How many snowballs at once (max)
var snowShowerMax = 18;
// Used to randomize spawn
var snowShowerTimer = null;
// Function to spawn a snowball shower ball
function spawnSnowShowerBall() {
if (snowShowerBalls.length >= snowShowerMax) return;
var ball = new SnowShowerBall();
snowShowerBalls.push(ball);
game.addChild(ball);
}
// Start the snowball shower effect
if (snowShowerTimer) LK.clearInterval(snowShowerTimer);
snowShowerTimer = LK.setInterval(function () {
spawnSnowShowerBall();
}, snowShowerInterval);
// Update snowShowerBalls in game.update
var oldGameUpdate = game.update;
game.update = function () {
// Update snow shower balls
for (var i = snowShowerBalls.length - 1; i >= 0; i--) {
var b = snowShowerBalls[i];
if (b && b.update) b.update();
if (b.y > GAME_HEIGHT + 80) {
if (b.parent) b.destroy();
snowShowerBalls.splice(i, 1);
}
}
// Call original game update logic
if (oldGameUpdate) oldGameUpdate.apply(this, arguments);
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Penguin class
var Penguin = Container.expand(function () {
var self = Container.call(this);
// Penguin id: 1 or 2
self.penguinId = 1;
// Attach penguin asset
var penguinGfx = self.attachAsset(self.penguinId === 1 ? 'penguin1' : 'penguin2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1 // Flip horizontally to show penguin's back
});
// Used for drag
self.isDragging = false;
// Used for aiming
self.aimLine = null;
// Used for touch start position
self.startDragX = 0;
self.startDragY = 0;
// Used for aiming vector
self.aimVX = 0;
self.aimVY = 0;
// Used for aiming bar
self.aimBar = null;
// Used for cooldown
self.canThrow = true;
// Used for tracking last position for drag
self.lastDragX = 0;
self.lastDragY = 0;
// Used for showing aim
self.showAim = function (x, y) {
// Not implemented: no line drawing in LK, so skip
};
// Used for hiding aim
self.hideAim = function () {
// Not implemented: no line drawing in LK, so skip
};
return self;
});
// Class for falling snowball (visual only, no collision)
var SnowShowerBall = Container.expand(function () {
var self = Container.call(this);
// Attach snowball asset
var gfx = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7 + Math.random() * 0.5,
scaleY: 0.7 + Math.random() * 0.5
});
// Random X across the screen, avoid top left 100x100
self.x = 120 + Math.random() * (GAME_WIDTH - 240);
self.y = -60 - Math.random() * 200;
// Random speed
self.vy = 7 + Math.random() * 4;
// Slight wind drift
self.vx = -2 + Math.random() * 4;
// Fade in/out
gfx.alpha = 0.7 + Math.random() * 0.3;
// Wobble
self.wobblePhase = Math.random() * Math.PI * 2;
self.update = function () {
self.y += self.vy;
self.x += self.vx + Math.sin(Date.now() / 300 + self.wobblePhase) * 1.2;
// Remove if out of bounds
if (self.y > GAME_HEIGHT + 80) {
self.destroy();
// Remove from array in main update
}
};
return self;
});
// Function to spawn a snowball shower ball
// Snowball class
var Snowball = Container.expand(function () {
var self = Container.call(this);
// Add black outline as a slightly larger ellipse behind the snowball
var outline = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.18,
scaleY: 1.18,
color: 0x000000
});
// Attach snowball asset (white, on top)
var snowballGfx = self.attachAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5
});
// Who fired this snowball? 1 or 2
self.owner = 1;
// Velocity
self.vx = 0;
self.vy = 0;
// Used for bounce cooldown
self.bounced = false;
// Update method
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Light blue sky
});
/****
* Game Code
****/
// Flag asset for wind direction (simple colored box)
// Game constants
// Penguin (player 1)
// Penguin (player 2)
// Snowball
// Castle wall (center)
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
// Center wall
var wall = LK.getAsset('castleWall', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2,
y: GAME_HEIGHT / 2,
rotation: Math.PI / 2 // Rotate 90 degrees to make it horizontal
});
game.addChild(wall);
// --- Penguin selection screen ---
var selectedPenguinId = null;
var penguin1 = null;
var penguin2 = null;
var aiPenguin = null;
var playerPenguin = null;
var selectionScreen = new Container();
game.addChild(selectionScreen);
// Penguin 1 preview
var penguin1Preview = LK.getAsset('penguin1', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2 - 300,
y: GAME_HEIGHT / 2,
scaleX: 1,
scaleY: 1
});
selectionScreen.addChild(penguin1Preview);
// Penguin 2 preview
var penguin2Preview = LK.getAsset('penguin2', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_WIDTH / 2 + 300,
y: GAME_HEIGHT / 2,
scaleX: 1,
scaleY: 1
});
selectionScreen.addChild(penguin2Preview);
// Penguin 1 label
var penguin1Label = new Text2("Penguin 1", {
size: 90,
fill: 0x222222
});
penguin1Label.anchor.set(0.5, 0);
penguin1Label.x = penguin1Preview.x;
penguin1Label.y = penguin1Preview.y + 140;
selectionScreen.addChild(penguin1Label);
// Penguin 2 label
var penguin2Label = new Text2("Penguin 2", {
size: 90,
fill: 0x222222
});
penguin2Label.anchor.set(0.5, 0);
penguin2Label.x = penguin2Preview.x;
penguin2Label.y = penguin2Preview.y + 140;
selectionScreen.addChild(penguin2Label);
// Title
var selectTitle = new Text2("Choose your Penguin!", {
size: 120,
fill: 0x4fc3f7
});
selectTitle.anchor.set(0.5, 0.5);
selectTitle.x = GAME_WIDTH / 2;
selectTitle.y = GAME_HEIGHT / 2 - 300;
selectionScreen.addChild(selectTitle);
// Selection logic
selectionScreen.down = function (x, y, obj) {
// Check if touch is on penguin1Preview
var dx1 = x - penguin1Preview.x;
var dy1 = y - penguin1Preview.y;
var dx2 = x - penguin2Preview.x;
var dy2 = y - penguin2Preview.y;
var r = 120;
if (dx1 * dx1 + dy1 * dy1 < r * r) {
selectedPenguinId = 1;
} else if (dx2 * dx2 + dy2 * dy2 < r * r) {
selectedPenguinId = 2;
}
if (selectedPenguinId) {
// Remove selection screen
selectionScreen.destroy();
// Remove preview penguins from the game (ensure they are not left in the background)
if (penguin1Preview && penguin1Preview.parent) penguin1Preview.destroy();
if (penguin2Preview && penguin2Preview.parent) penguin2Preview.destroy();
if (penguin1Label && penguin1Label.parent) penguin1Label.destroy();
if (penguin2Label && penguin2Label.parent) penguin2Label.destroy();
if (selectTitle && selectTitle.parent) selectTitle.destroy();
// Setup penguins
penguin1 = new Penguin();
penguin1.penguinId = 1;
penguin1.x = GAME_WIDTH / 2;
penguin1.y = GAME_HEIGHT - 350;
game.addChild(penguin1);
penguin2 = new Penguin();
penguin2.penguinId = 2;
penguin2.x = GAME_WIDTH / 2;
penguin2.y = 350;
game.addChild(penguin2);
// Set correct asset for penguin2
penguin2.removeChildAt(0);
penguin2.attachAsset('penguin2', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: -1
});
// Assign player and AI
if (selectedPenguinId === 1) {
playerPenguin = penguin1;
aiPenguin = penguin2;
} else {
playerPenguin = penguin2;
aiPenguin = penguin1;
}
// Mark for AI logic
aiPenguin.isAI = true;
playerPenguin.isAI = false;
// Set up initial canThrow
playerPenguin.canThrow = true;
aiPenguin.canThrow = true;
// (Optional) Add a little effect to show selection
LK.effects.flashObject(playerPenguin, 0x4fc3f7, 600);
}
};
selectionScreen.interactive = true;
selectionScreen.on('down', selectionScreen.down);
// The rest of the game logic will use playerPenguin and aiPenguin instead of penguin1/penguin2 directly.
// Score
var score1 = 0;
var score2 = 0;
// Score text
var scoreTxt = new Text2('0 : 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Snowballs array
var snowballs = [];
// --- Wind mechanic ---
// Wind directions: 0=left, 1=right, 2=up, 3=down
var windDirections = [{
name: "←",
dx: -1,
dy: 0
}, {
name: "→",
dx: 1,
dy: 0
}, {
name: "↑",
dx: 0,
dy: -1
}, {
name: "↓",
dx: 0,
dy: 1
}];
var windStrengthMin = 0; // minimum wind
var windStrengthMax = 22; // maximum wind
var windStrength = 0; // current wind strength (0-22)
var windDir = 0; // current wind direction index (0-3)
var windIndicator = null;
var windText = null;
// Helper to randomize wind before each throw
function setRandomWind() {
windDir = Math.floor(Math.random() * windDirections.length);
windStrength = Math.floor(Math.random() * (windStrengthMax + 1)); // 0 to max
// Remove old indicator
if (windIndicator) {
windIndicator.destroy();
windIndicator = null;
}
if (windText) {
windText.destroy();
windText = null;
}
if (typeof windFlag !== "undefined" && windFlag) {
windFlag.destroy();
windFlag = null;
}
// Show wind visually at top center (keep arrow for reference)
var arrowLen = 120 + windStrength * 3;
var arrowColor = 0x4fc3f7;
windIndicator = LK.getAsset('snowball', {
anchorX: 0.5,
anchorY: 0.5,
width: 30,
height: arrowLen,
color: arrowColor
});
windIndicator.x = GAME_WIDTH / 2;
windIndicator.y = 160;
if (windDir === 0) windIndicator.rotation = Math.PI; // left
else if (windDir === 1) windIndicator.rotation = 0; // right
else if (windDir === 2) windIndicator.rotation = -Math.PI / 2; // up
else if (windDir === 3) windIndicator.rotation = Math.PI / 2; // down
game.addChild(windIndicator);
// Add flag to indicate wind direction and strength
windFlag = LK.getAsset('windFlag', {
anchorX: 0.1,
anchorY: 0.5,
width: 90 + windStrength * 2,
// flag length grows with wind
height: 60 + Math.floor(windStrength / 3),
// flag height grows a bit with wind
color: 0xffe066
});
// Place wind flag at the top right corner, leaving a margin from the edge
windFlag.x = GAME_WIDTH - 120;
windFlag.y = 120;
// Rotate flag to match wind direction
if (windDir === 0) windFlag.rotation = Math.PI; // left
else if (windDir === 1) windFlag.rotation = 0; // right
else if (windDir === 2) windFlag.rotation = -Math.PI / 2; // up
else if (windDir === 3) windFlag.rotation = Math.PI / 2; // down
game.addChild(windFlag);
// Animate flag waving (simple waving effect)
if (typeof windFlagTween !== "undefined" && windFlagTween) {
windFlagTween.stop();
windFlagTween = null;
}
// Animate flag waving (simple waving effect) using correct tween API
tween(windFlag, {
scaleY: 1.15
}, {
duration: 400,
easing: tween.sineInOut,
onFinish: function onFinish() {
// Reverse the tween for yoyo effect
tween(windFlag, {
scaleY: 1.0
}, {
duration: 400,
easing: tween.sineInOut,
onFinish: function onFinish() {
// Loop the waving animation
LK.setTimeout(function () {
if (windFlag && windFlag.parent) {
// Only continue if flag still exists
// Recursively start waving again
// (This is a simple infinite yoyo loop)
tween(windFlag, {
scaleY: 1.15
}, {
duration: 400,
easing: tween.sineInOut,
onFinish: arguments.callee
});
}
}, 0);
}
});
}
});
// Add wind text
var txt = windDirections[windDir].name + " " + windStrength;
windText = new Text2(txt, {
size: 80,
fill: 0x4fc3f7
});
windText.anchor.set(0.5, 0.5);
// Place wind text near the flag, but offset to the left to avoid overlap
windText.x = GAME_WIDTH - 260;
windText.y = 120;
LK.gui.top.addChild(windText);
}
// Call once at start
setRandomWind();
// Drag/aim state
var dragPenguin = null;
var dragStartX = 0;
var dragStartY = 0;
var dragCurrentX = 0;
var dragCurrentY = 0;
// Power bar state
var powerBar = null;
var powerBarBg = null;
var powerBarValue = 0;
var powerBarInterval = null;
var powerBarMax = 1.0; // max fill
var powerBarMin = 0.2; // min fill
var powerBarSpeed = 0.012; // fill per tick
// Turn-based state
var currentTurn = "player"; // "player" or "ai"
var turnInProgress = false; // Prevents double actions in a turn
// Only allow one penguin to be dragged at a time
function isTouchOnPenguin(x, y, penguin) {
if (!penguin) return false; // Defensive: penguin may be null
// Simple bounding box check
var px = penguin.x;
var py = penguin.y;
var w = penguin.width || 140;
var h = penguin.height || 180;
return x > px - w / 2 && x < px + w / 2 && y > py - h / 2 && y < py + h / 2;
}
// Only allow dragging own penguin (player 1: bottom, player 2: top)
game.down = function (x, y, obj) {
// Don't allow drag in top 100x100 (menu)
if (x < 100 && y < 100) return;
// Only allow drag on playerPenguin (single player) and only if it's player's turn and not in progress
if (typeof playerPenguin !== "undefined" && isTouchOnPenguin(x, y, playerPenguin) && currentTurn === "player" && !turnInProgress) {
turnInProgress = true;
dragPenguin = playerPenguin;
dragStartX = x;
dragStartY = y;
dragCurrentX = x;
dragCurrentY = y;
playerPenguin.isDragging = true;
// Show power bar next to playerPenguin
if (powerBarBg) {
powerBarBg.destroy();
powerBarBg = null;
}
if (powerBar) {
powerBar.destroy();
powerBar = null;
}
// Background bar
powerBarBg = LK.getAsset('snowball', {
anchorX: 0,
anchorY: 0.5,
width: 40,
height: 180,
color: 0xcccccc
});
powerBarBg.x = playerPenguin.x + 90;
powerBarBg.y = playerPenguin.y;
game.addChild(powerBarBg);
// Foreground (fill) bar
powerBar = LK.getAsset('snowball', {
anchorX: 0,
anchorY: 0.5,
width: 36,
height: 0,
// will be set by fill
color: 0x4fc3f7
});
powerBar.x = playerPenguin.x + 92;
powerBar.y = playerPenguin.y + 90; // start at bottom
game.addChild(powerBar);
powerBarValue = powerBarMin;
// Animate fill
if (powerBarInterval) LK.clearInterval(powerBarInterval);
powerBarInterval = LK.setInterval(function () {
if (!dragPenguin) return;
powerBarValue += powerBarSpeed;
if (powerBarValue > powerBarMax) powerBarValue = powerBarMax;
// Update bar height and position
var maxHeight = 180;
var fillHeight = Math.max(0, Math.floor(maxHeight * powerBarValue));
powerBar.height = fillHeight;
powerBar.y = playerPenguin.y + 90 - fillHeight;
}, 16);
}
};
game.move = function (x, y, obj) {
if (!dragPenguin) return;
// Clamp drag to own half (playerPenguin only)
if (dragPenguin === playerPenguin) {
if (playerPenguin.penguinId === 1 && y < GAME_HEIGHT / 2 + 100) y = GAME_HEIGHT / 2 + 100;
if (playerPenguin.penguinId === 2 && y > GAME_HEIGHT / 2 - 100) y = GAME_HEIGHT / 2 - 100;
}
// Clamp to game area
var minX = 120,
maxX = GAME_WIDTH - 120;
var minY = 120,
maxY = GAME_HEIGHT - 120;
x = Math.max(minX, Math.min(maxX, x));
y = Math.max(minY, Math.min(maxY, y));
dragCurrentX = x;
dragCurrentY = y;
// Move penguin
dragPenguin.x = x;
dragPenguin.y = y;
// --- Aiming bar logic ---
var penguin = dragPenguin;
if (penguin) {
// Remove old aimBar if exists
if (penguin.aimBar) {
penguin.aimBar.destroy();
penguin.aimBar = null;
}
// Only show aim bar if drag distance is enough
var dx = dragCurrentX - dragStartX;
var dy = dragCurrentY - dragStartY;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 20) {
// Always aim toward the AI penguin
var target = aiPenguin;
var tx = target.x - penguin.x;
var ty = target.y - penguin.y;
var angle = Math.atan2(ty, tx);
// Bar length
var barLen = 220;
// Create bar as a thin tall rectangle (use a box shape)
var bar = LK.getAsset('snowball', {
anchorX: 0.5,
anchorY: 1,
width: 18,
height: barLen,
color: 0x4fc3f7
});
// Place under penguin
bar.x = penguin.x;
bar.y = penguin.y + 90;
// Rotate to aim direction
bar.rotation = angle + Math.PI / 2;
game.addChild(bar);
penguin.aimBar = bar;
}
}
// Move power bar if visible
if (powerBarBg && dragPenguin) {
powerBarBg.x = dragPenguin.x + 90;
powerBarBg.y = dragPenguin.y;
}
if (powerBar && dragPenguin) {
powerBar.x = dragPenguin.x + 92;
// keep y at bottom, height is set by interval
}
};
game.up = function (x, y, obj) {
if (!dragPenguin) return;
// Hide power bar
if (powerBarBg) {
powerBarBg.destroy();
powerBarBg = null;
}
if (powerBar) {
powerBar.destroy();
powerBar = null;
}
if (powerBarInterval) {
LK.clearInterval(powerBarInterval);
powerBarInterval = null;
}
// Only allow throw if drag distance is enough and cooldown is over
var dx = dragCurrentX - dragStartX;
var dy = dragCurrentY - dragStartY;
var dist = Math.sqrt(dx * dx + dy * dy);
// Only allow throw if drag is a "flick" (distance > 80)
if (dist > 80 && dragPenguin.canThrow && currentTurn === "player") {
// Set new wind before each throw
setRandomWind();
// Always throw toward the AI penguin, power only affects distance
var basePower = powerBarValue || powerBarMin;
var thrower = dragPenguin;
var target = aiPenguin;
// Calculate direction vector from thrower to target
var tx = target.x - thrower.x;
var ty = target.y - thrower.y;
var len = Math.sqrt(tx * tx + ty * ty);
// Normalize direction
var dirX = tx / len;
var dirY = ty / len;
// Set velocity magnitude based on power
var minV = 18;
var maxV = 55;
var velocity = minV + (maxV - minV) * ((basePower - powerBarMin) / (powerBarMax - powerBarMin));
// Clamp velocity
if (velocity < minV) velocity = minV;
if (velocity > maxV) velocity = maxV;
// Final velocity
var vx = dirX * velocity;
var vy = dirY * velocity;
// --- Apply wind effect ---
// Wind is a constant added to vx/vy, scaled by windStrength
var wind = windDirections[windDir];
var windEffect = windStrength * 0.18; // tune this for balance
vx += wind.dx * windEffect;
vy += wind.dy * windEffect;
// Create snowball
var snowball = new Snowball();
snowball.owner = playerPenguin.penguinId;
snowball.x = dragPenguin.x;
snowball.y = dragPenguin.y + (snowball.owner === 1 ? -90 : 90);
snowball.vx = vx;
snowball.vy = vy;
snowballs.push(snowball);
game.addChild(snowball);
// Play snowball throw sound
LK.getSound('kartopusesi').play();
// Cooldown: prevent spamming
dragPenguin.canThrow = false;
var cooldownPenguin = dragPenguin;
LK.setTimeout(function () {
if (cooldownPenguin) {
cooldownPenguin.canThrow = true;
}
}, 600);
// End player's turn, start AI's turn after a 2 second delay
currentTurn = "ai";
turnInProgress = true;
LK.setTimeout(function () {
turnInProgress = false;
}, 2000);
}
// Remove aim bar if exists
if (dragPenguin && dragPenguin.aimBar) {
dragPenguin.aimBar.destroy();
dragPenguin.aimBar = null;
}
dragPenguin.isDragging = false;
dragPenguin = null;
};
/**
* Helper: check collision between two containers (bounding box)
*/
function isIntersect(a, b) {
var ax = a.x,
ay = a.y,
aw = a.width || 100,
ah = a.height || 100;
var bx = b.x,
by = b.y,
bw = b.width || 100,
bh = b.height || 100;
return ax - aw / 2 < bx + bw / 2 && ax + aw / 2 > bx - bw / 2 && ay - ah / 2 < by + bh / 2 && ay + ah / 2 > by - bh / 2;
}
// Update score text
function updateScore() {
scoreTxt.setText(score1 + " : " + score2);
}
// Game update loop
game.update = function () {
// --- AI logic for non-player penguin ---
// AI only acts on its turn and if not in progress (wait for 2s after player)
if (typeof aiPenguin !== "undefined" && aiPenguin && aiPenguin.isAI && aiPenguin.canThrow && currentTurn === "ai" && !turnInProgress) {
// AI throws at intervals, only if no snowball is currently flying from AI
var aiHasActiveSnowball = false;
for (var aiCheck = 0; aiCheck < snowballs.length; aiCheck++) {
if (snowballs[aiCheck].owner === (aiPenguin.penguinId || 2)) {
aiHasActiveSnowball = true;
break;
}
}
if (!aiHasActiveSnowball) {
turnInProgress = true;
// Set new wind before each throw
setRandomWind();
// Aim at playerPenguin
var target = playerPenguin;
var thrower = aiPenguin;
// Add some random offset to aim for realism
var tx = target.x + (Math.random() - 0.5) * 80 - thrower.x;
var ty = target.y + (Math.random() - 0.5) * 80 - thrower.y;
var len = Math.sqrt(tx * tx + ty * ty);
var dirX = tx / len;
var dirY = ty / len;
// AI power: random between 0.5 and 1.0
var basePower = 0.5 + Math.random() * 0.5;
var minV = 18;
var maxV = 55;
var velocity = minV + (maxV - minV) * basePower;
if (velocity < minV) velocity = minV;
if (velocity > maxV) velocity = maxV;
var vx = dirX * velocity;
var vy = dirY * velocity;
// Apply wind
var wind = windDirections[windDir];
var windEffect = windStrength * 0.18;
vx += wind.dx * windEffect;
vy += wind.dy * windEffect;
// Create snowball
var snowball = new Snowball();
snowball.owner = aiPenguin.penguinId || 2;
snowball.x = aiPenguin.x;
snowball.y = aiPenguin.y + (snowball.owner === 1 ? -90 : 90);
snowball.vx = vx;
snowball.vy = vy;
snowballs.push(snowball);
game.addChild(snowball);
// Play snowball throw sound
LK.getSound('kartopusesi').play();
// Cooldown for AI
aiPenguin.canThrow = false;
var cooldownAI = aiPenguin;
LK.setTimeout(function () {
if (cooldownAI) {
cooldownAI.canThrow = true;
}
// After AI throw, switch back to player turn
currentTurn = "player";
turnInProgress = false;
}, 1200 + Math.random() * 800);
}
}
// Update snowballs
for (var i = snowballs.length - 1; i >= 0; i--) {
var sb = snowballs[i];
sb.update();
// Gravity
sb.vy += 0.7;
// Friction
sb.vx *= 0.99;
sb.vy *= 0.99;
// Out of bounds: remove
if (sb.x < -100 || sb.x > GAME_WIDTH + 100 || sb.y < -100 || sb.y > GAME_HEIGHT + 100) {
sb.destroy();
snowballs.splice(i, 1);
continue;
}
// No snowball-wall collision or bounce (disabled per requirements)
// Hit penguin (opponent only)
if (sb.owner === 1 && isIntersect(sb, penguin2)) {
// Score for player 1
score1 += 1;
updateScore();
LK.effects.flashObject(penguin2, 0xffffff, 400);
sb.destroy();
snowballs.splice(i, 1);
// Win condition
if (score1 >= 5) {
LK.showYouWin();
}
continue;
}
if (sb.owner === 2 && isIntersect(sb, penguin1)) {
// Score for player 2
score2 += 1;
updateScore();
LK.effects.flashObject(penguin1, 0xffffff, 400);
sb.destroy();
snowballs.splice(i, 1);
// Lose condition
if (score2 >= 5) {
LK.showGameOver();
}
continue;
}
}
};
// Initial score
updateScore();
// --- Snowball Shower Effect (Doğa olayı olarak kartopu yağma efekti) ---
// Array to hold falling snowballs for the effect
var snowShowerBalls = [];
// How often to spawn a new snowball (ms)
var snowShowerInterval = 220;
// How many snowballs at once (max)
var snowShowerMax = 18;
// Used to randomize spawn
var snowShowerTimer = null;
// Function to spawn a snowball shower ball
function spawnSnowShowerBall() {
if (snowShowerBalls.length >= snowShowerMax) return;
var ball = new SnowShowerBall();
snowShowerBalls.push(ball);
game.addChild(ball);
}
// Start the snowball shower effect
if (snowShowerTimer) LK.clearInterval(snowShowerTimer);
snowShowerTimer = LK.setInterval(function () {
spawnSnowShowerBall();
}, snowShowerInterval);
// Update snowShowerBalls in game.update
var oldGameUpdate = game.update;
game.update = function () {
// Update snow shower balls
for (var i = snowShowerBalls.length - 1; i >= 0; i--) {
var b = snowShowerBalls[i];
if (b && b.update) b.update();
if (b.y > GAME_HEIGHT + 80) {
if (b.parent) b.destroy();
snowShowerBalls.splice(i, 1);
}
}
// Call original game update logic
if (oldGameUpdate) oldGameUpdate.apply(this, arguments);
};
bir penguen çizmeni istiyorum bir eli havada olsun eli biraz uzun olsun çok tatlı bir penguen olsun
penguenin arkası dönük olsun. In-Game asset. 2d. High contrast. No shadows
kale duvarı kahverengi renkte olsun eski çağ surları gibi olsun ve ekranın ortasını full kaplasın yatay şekilde. In-Game asset. 2d. High contrast. No shadows
rüzgarın yönüne doğru değişen bir dalgalanan türk bayrağı resmi. In-Game asset. 2d. High contrast. No shadows