User prompt
her strike yapıldığında ortadaki engel biraz daha uzasın ve penguenin hızını biraz daha düşür, penguenin ateşe çarpıp yandığı yere başka bir ses eklemek istiyorum
User prompt
penguen yanarken başka bir resim olsun
User prompt
penguen ortada çıkan engele değdiğinde yansın
User prompt
penguen çok hızlı fırlıyor biraz yavaşlatalım
User prompt
eğer ortadaki engele 3 kere çarparsa penguen yanarak ölsün ve yandığı zamanki resmini değiştirebileyim
User prompt
ortada çıkan engel çizgisinin resmini değiştiremiyorum
User prompt
ortadaki çizginin arkasına ışınlanıyor , o şekilde olmasını istemiyorum çizginin bir duvar gibi olduğunu düşün aynı çerçevede olduğu gibi görev görsün ona vurursa penguen geriye seksin ve pengueni biraz yavaşlat çok hızlı gidiyor
User prompt
strike yaptıktan sonra çıkan engel hala geçirgen , o çizgi geçirgen olmasın aynı duvar gibi ona vurulduğunda geri sekilsin
User prompt
ekranın ortasında çıkan engel geçilmez olsun yani duvar gibi ona dokununca penguen seksin
User prompt
penguen mouse ile itme hızımıza göre hızını alsın her seferinde aynı hızda gitmesin örneğin yavaş fırlatırsak yavaş hızlı fırlatırsak hızlı gitsin
User prompt
penguenin hızı biraz yavaşlasın ve engel yatay olarak karşımıza çıksın
User prompt
labutlara sadece önden vurunca yıkılması ister arkadan ister sağdan ister soldan nereden vurursan vur gerçek fizik kurallarına uygun olarak yıkılsınlar , her levelde labutların arasının açılması mekaniğini iptal et yen bir mekanik ekliyoruz her strike yapışta ekranın ortasında ya sağdan ya da soldan bir engel çıksın ve bu engelin olmadığı boş alandan pengueni atıp labutları yıkabilelim ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
eğer penguen duvardan sekerek labutlara gelirse de labutları yıkabilsin
User prompt
eğer strike yapamazsa labutlar sıfırdan dizilmesin kaldığı yerden devam etsin
User prompt
penguenin hızını biraz arttır bu sefer hiç gitmiyor
User prompt
penguenin sürtünme hızı daha biraz daha yavaşlasın gerçek bir buzun üzerinde kayıyomuş hissiyatı versin, oyuncu her strike yaptığında labutlar etrafa daha fazla açılsın ve vurması zorlaşsın 2 kere strike yapamazsa game over olsun ve oyun tekrar başlasın
User prompt
labutların arasını biraz daha aç ve penguen çarpar çarpmaz hepsi yıkılmasın gerçek fizik kurallarına uygun yıkılsınlar , duvardan çarptırarak atarsan daha fazla puan versin
User prompt
When the penguin hits the wall, calculate the reflection vector based on a 90-degree bounce logic and apply reduced velocity. The penguin should continue moving in that new direction.
User prompt
The light blue area should also act like a wall, and when the penguin hits it, it should bounce off.
User prompt
Make the entire frame of the game act like a wall, so that when the penguin hits it, it bounces off.
User prompt
The edges should be walls, but when the penguin hits them, its speed should decrease, and it should continue moving at a perfect 90-degree angle.
User prompt
Only the front pins should fall over, and there should be a mechanic where the pins disappear by colliding with each other. If the penguin goes straight, it should knock all the pins over.
User prompt
When the penguin is released, at the maximum speed, it should definitely reach the pins. However, if it is thrown more slowly, it shouldn't reach the pins.
User prompt
The penguin should move a bit faster, and the arrow should be removed. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The arrow should start from where the penguin is being held, and the farther I pull the penguin, the farther it should be launched.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var AimArrow = Container.expand(function () { var self = Container.call(this); // Create arrow components var arrowLine = self.attachAsset('aimLine', { anchorX: 0.5, anchorY: 1.0, width: 10, height: 150 }); // Set initial visibility self.visible = false; // Update arrow position and rotation based on angle self.updateArrow = function (startX, startY, angle) { self.x = startX; self.y = startY; self.rotation = angle; self.visible = true; }; self.hide = function () { self.visible = false; }; return self; }); var BowlingPin = Container.expand(function () { var self = Container.call(this); var pinGraphics = self.attachAsset('bowlingPin', { anchorX: 0.5, anchorY: 0.5 }); self.isKnockedDown = false; self.velocityX = 0; self.velocityY = 0; self.friction = 0.95; self.knockDown = function () { if (!self.isKnockedDown) { self.isKnockedDown = true; // Randomize the pin's fall direction slightly self.velocityX = (Math.random() - 0.5) * 10; self.velocityY = Math.random() * 5; LK.getSound('pinHit').play(); return true; } return false; }; self.update = function () { if (self.isKnockedDown) { // Apply velocity self.x += self.velocityX; self.y += self.velocityY; // Apply friction self.velocityX *= self.friction; self.velocityY *= self.friction; // Rotation effect as the pin falls pinGraphics.rotation += 0.1; // Fade out effect pinGraphics.alpha *= 0.98; // Remove from game when almost invisible if (pinGraphics.alpha < 0.1) { self.visible = false; } } }; self.reset = function () { self.isKnockedDown = false; self.velocityX = 0; self.velocityY = 0; pinGraphics.rotation = 0; pinGraphics.alpha = 1; self.visible = true; }; return self; }); var Penguin = Container.expand(function () { var self = Container.call(this); var penguinGraphics = self.attachAsset('penguin', { anchorX: 0.5, anchorY: 0.5 }); // Physics properties self.velocityX = 0; self.velocityY = 0; self.friction = 0.98; // Ice friction self.active = false; self.hasCollided = false; self.pullDistance = 0; // Store the pull distance for power calculation self.launch = function (angle, power) { self.velocityX = Math.cos(angle) * power; self.velocityY = Math.sin(angle) * power; self.active = true; self.hasCollided = false; LK.getSound('slide').play(); }; self.update = function () { if (!self.active) return; // Apply velocity self.x += self.velocityX; self.y += self.velocityY; // Apply friction self.velocityX *= self.friction; self.velocityY *= self.friction; // Slight rotation effect for realism penguinGraphics.rotation += self.velocityX * 0.01; // Stop if velocity is very small if (Math.abs(self.velocityX) < 0.1 && Math.abs(self.velocityY) < 0.1) { self.active = false; self.velocityX = 0; self.velocityY = 0; } // Boundary checks for the bowling lane if (self.x < bowlingLane.x) { self.x = bowlingLane.x; self.velocityX *= -0.8; // Bounce off wall with some energy loss } else if (self.x > bowlingLane.x + bowlingLane.width) { self.x = bowlingLane.x + bowlingLane.width; self.velocityX *= -0.8; } // Top boundary check if (self.y < bowlingLane.y) { self.y = bowlingLane.y; self.velocityY *= -0.8; } // Bottom boundary (out of bounds) if (self.y > 2732) { self.active = false; self.reset(); } }; self.reset = function () { self.x = launchArea.x; self.y = launchArea.y - 250; // Move penguin further up the lane self.velocityX = 0; self.velocityY = 0; self.active = false; self.hasCollided = false; self.pullDistance = 0; // Reset pull distance penguinGraphics.rotation = 0; }; return self; }); var PowerMeter = Container.expand(function () { var self = Container.call(this); var meterBG = self.attachAsset('powerMeterBG', { anchorX: 0.5, anchorY: 0.5 }); var meter = self.attachAsset('powerMeter', { anchorX: 0.5, anchorY: 1.0, height: 0 // Start with no power }); var maxPower = 300; self.power = 0; self.increasing = true; self.update = function () { if (self.visible) { if (self.increasing) { self.power += 5; if (self.power >= maxPower) { self.power = maxPower; self.increasing = false; } } else { self.power -= 5; if (self.power <= 0) { self.power = 0; self.increasing = true; } } // Update meter height based on power meter.height = self.power; meter.y = meterBG.y + meterBG.height / 2 - meter.height / 2; } }; self.getPowerRatio = function () { return self.power / maxPower; }; self.reset = function () { self.power = 0; self.increasing = true; meter.height = 0; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xC7E6F7 }); /**** * Game Code ****/ // Game constants var MAX_POWER = 20; var PIN_ROWS = 4; var FRAMES = 10; var PINS_PER_FRAME = 10; // Game state variables var currentFrame = 1; var pinsKnockedDown = 0; var totalScore = 0; var aiming = false; var powering = false; var gameState = "aiming"; // States: aiming, powering, sliding, scoring, gameover var aimAngle = -Math.PI / 2; // Start aiming straight up // Create background var background = game.addChild(LK.getAsset('background', { anchorX: 0, anchorY: 0 })); // Create bowling lane var bowlingLane = game.addChild(LK.getAsset('bowlingLane', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 100 })); // Create launch area var launchArea = game.addChild(LK.getAsset('launchArea', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2400 })); // Create the aiming line var aimLine = game.addChild(LK.getAsset('aimLine', { anchorX: 0.5, anchorY: 1.0, x: launchArea.x, y: launchArea.y, visible: false })); // Create the directional arrow var aimArrow = game.addChild(new AimArrow()); aimArrow.x = launchArea.x; aimArrow.y = launchArea.y; // Create the power meter var powerMeter = game.addChild(new PowerMeter()); powerMeter.x = 1900; powerMeter.y = 1400; powerMeter.visible = false; // Create the penguin var penguin = game.addChild(new Penguin()); penguin.x = launchArea.x; penguin.y = launchArea.y - 250; // Move penguin further up the lane // Create bowling pins var pins = []; setupPins(); // Create UI elements var frameText = new Text2('Frame: 1/10', { size: 70, fill: 0x000000 }); frameText.anchor.set(0.5, 0); // Position frame text under the penguin's position frameText.y = penguin.y + 150; LK.gui.center.addChild(frameText); var scoreText = new Text2('Score: 0', { size: 70, fill: 0x000000 }); scoreText.anchor.set(0.5, 0); scoreText.y = 80; LK.gui.top.addChild(scoreText); var instructionText = new Text2('Tap and drag to pull penguin back, release to launch', { size: 50, fill: 0x000000 }); instructionText.anchor.set(0.5, 0); instructionText.y = 180; LK.gui.top.addChild(instructionText); // Helper functions function setupPins() { // Clear any existing pins for (var i = 0; i < pins.length; i++) { pins[i].destroy(); } pins = []; // Create pin layout in traditional bowling triangle formation // Ensure pins are exactly centered on the lane var startX = 2048 / 2; // Center of screen var startY = 400; // Position from top var pinSpacingX = 80; var pinSpacingY = 90; // Standard bowling pin layout (4-3-2-1 triangle) // First row (back) - 4 pins for (var i = 0; i < 4; i++) { var pin = new BowlingPin(); pin.x = startX + (i - 1.5) * pinSpacingX; // Perfectly centered pin.y = startY; pins.push(pin); game.addChild(pin); } // Second row - 3 pins for (var i = 0; i < 3; i++) { var pin = new BowlingPin(); pin.x = startX + (i - 1) * pinSpacingX; // Centered relative to first row pin.y = startY + pinSpacingY; pins.push(pin); game.addChild(pin); } // Third row - 2 pins for (var i = 0; i < 2; i++) { var pin = new BowlingPin(); pin.x = startX + (i - 0.5) * pinSpacingX; // Centered relative to second row pin.y = startY + 2 * pinSpacingY; pins.push(pin); game.addChild(pin); } // Fourth row (front) - 1 pin var pin = new BowlingPin(); pin.x = startX; // Center pin pin.y = startY + 3 * pinSpacingY; pins.push(pin); game.addChild(pin); pinsKnockedDown = 0; } function updateAimLine() { aimLine.rotation = aimAngle; // Ensure the aim line points from the penguin position aimLine.x = launchArea.x; aimLine.y = launchArea.y; } function launchPenguin() { // Calculate power based on the pull distance var power = Math.min(penguin.pullDistance / 50, 1) * MAX_POWER; // Launch penguin from current position toward the launch area var launchAngle = aimAngle + Math.PI; // Reverse the angle to launch toward the pins penguin.launch(launchAngle, power); gameState = "sliding"; powerMeter.visible = false; instructionText.setText("Watch the penguin slide!"); } function checkCollisions() { if (!penguin.active || penguin.hasCollided) return; var newKnockdowns = 0; for (var i = 0; i < pins.length; i++) { var pin = pins[i]; if (!pin.isKnockedDown && penguin.intersects(pin)) { if (pin.knockDown()) { newKnockdowns++; pinsKnockedDown++; // Update score totalScore += 1; updateScoreDisplay(); // Create a chain reaction with nearby pins for (var j = 0; j < pins.length; j++) { if (i !== j && !pins[j].isKnockedDown) { var dx = pins[j].x - pin.x; var dy = pins[j].y - pin.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100) { // Pins are close enough to affect each other pins[j].knockDown(); pinsKnockedDown++; totalScore += 1; updateScoreDisplay(); } } } } } } if (newKnockdowns > 0) { penguin.hasCollided = true; // Play strike sound if all pins are knocked down if (pinsKnockedDown === PINS_PER_FRAME) { LK.getSound('strike').play(); LK.effects.flashScreen(0xFFFFFF, 500); instructionText.setText("STRIKE!"); } } } function updateScoreDisplay() { scoreText.setText("Score: " + totalScore); // Update high score if needed if (totalScore > storage.highScore) { storage.highScore = totalScore; } } function nextFrame() { currentFrame++; if (currentFrame > FRAMES) { // Game over gameState = "gameover"; instructionText.setText("Game Over! Final Score: " + totalScore); // Show game over screen after a brief delay LK.setTimeout(function () { LK.showGameOver(); }, 2000); } else { // Setup for next frame frameText.setText("Frame: " + currentFrame + "/10"); setupPins(); penguin.reset(); gameState = "aiming"; instructionText.setText("Tap and drag backward to aim, release to launch"); } } function checkGameStateTransition() { if (gameState === "sliding") { // Check if penguin has stopped if (!penguin.active) { // Wait a bit for pins to settle and then move to next frame LK.setTimeout(function () { nextFrame(); }, 2000); gameState = "scoring"; } } } // Event handlers game.down = function (x, y, obj) { if (gameState === "aiming") { aiming = true; aimLine.visible = false; // Store original penguin position penguin.originalX = penguin.x; penguin.originalY = penguin.y; // Hide arrow when starting to aim aimArrow.hide(); } }; game.move = function (x, y, obj) { if (aiming) { // Calculate aim angle from penguin to opposite of pull direction var dx = launchArea.x - x; var dy = launchArea.y - y; // Calculate the distance of the pull for power var distance = Math.sqrt(dx * dx + dy * dy); // Limit the maximum drag distance var maxDrag = 300; distance = Math.min(distance, maxDrag); // Calculate the angle aimAngle = Math.atan2(dy, dx); // Move the penguin to the drag position penguin.x = launchArea.x - Math.cos(aimAngle) * distance; penguin.y = launchArea.y - Math.sin(aimAngle) * distance; // Update the directional arrow - start from penguin position pointing toward launch area aimArrow.updateArrow(penguin.x, penguin.y, aimAngle + Math.PI); // Store the pull distance for calculating power later penguin.pullDistance = distance; } }; game.up = function (x, y, obj) { if (aiming) { aiming = false; // Hide the directional arrow aimArrow.hide(); // Only launch if penguin was actually pulled back if (penguin.pullDistance > 10) { // Launch immediately after release launchPenguin(); } else { // Reset penguin position if not pulled back enough penguin.x = penguin.originalX; penguin.y = penguin.originalY; } } }; // Game update loop game.update = function () { if (gameState === "sliding") { penguin.update(); // Update pin physics for (var i = 0; i < pins.length; i++) { pins[i].update(); } checkCollisions(); checkGameStateTransition(); } }; // Start background music LK.playMusic('gameMusic');
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var AimArrow = Container.expand(function () {
var self = Container.call(this);
// Create arrow components
var arrowLine = self.attachAsset('aimLine', {
anchorX: 0.5,
anchorY: 1.0,
width: 10,
height: 150
});
// Set initial visibility
self.visible = false;
// Update arrow position and rotation based on angle
self.updateArrow = function (startX, startY, angle) {
self.x = startX;
self.y = startY;
self.rotation = angle;
self.visible = true;
};
self.hide = function () {
self.visible = false;
};
return self;
});
var BowlingPin = Container.expand(function () {
var self = Container.call(this);
var pinGraphics = self.attachAsset('bowlingPin', {
anchorX: 0.5,
anchorY: 0.5
});
self.isKnockedDown = false;
self.velocityX = 0;
self.velocityY = 0;
self.friction = 0.95;
self.knockDown = function () {
if (!self.isKnockedDown) {
self.isKnockedDown = true;
// Randomize the pin's fall direction slightly
self.velocityX = (Math.random() - 0.5) * 10;
self.velocityY = Math.random() * 5;
LK.getSound('pinHit').play();
return true;
}
return false;
};
self.update = function () {
if (self.isKnockedDown) {
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= self.friction;
self.velocityY *= self.friction;
// Rotation effect as the pin falls
pinGraphics.rotation += 0.1;
// Fade out effect
pinGraphics.alpha *= 0.98;
// Remove from game when almost invisible
if (pinGraphics.alpha < 0.1) {
self.visible = false;
}
}
};
self.reset = function () {
self.isKnockedDown = false;
self.velocityX = 0;
self.velocityY = 0;
pinGraphics.rotation = 0;
pinGraphics.alpha = 1;
self.visible = true;
};
return self;
});
var Penguin = Container.expand(function () {
var self = Container.call(this);
var penguinGraphics = self.attachAsset('penguin', {
anchorX: 0.5,
anchorY: 0.5
});
// Physics properties
self.velocityX = 0;
self.velocityY = 0;
self.friction = 0.98; // Ice friction
self.active = false;
self.hasCollided = false;
self.pullDistance = 0; // Store the pull distance for power calculation
self.launch = function (angle, power) {
self.velocityX = Math.cos(angle) * power;
self.velocityY = Math.sin(angle) * power;
self.active = true;
self.hasCollided = false;
LK.getSound('slide').play();
};
self.update = function () {
if (!self.active) return;
// Apply velocity
self.x += self.velocityX;
self.y += self.velocityY;
// Apply friction
self.velocityX *= self.friction;
self.velocityY *= self.friction;
// Slight rotation effect for realism
penguinGraphics.rotation += self.velocityX * 0.01;
// Stop if velocity is very small
if (Math.abs(self.velocityX) < 0.1 && Math.abs(self.velocityY) < 0.1) {
self.active = false;
self.velocityX = 0;
self.velocityY = 0;
}
// Boundary checks for the bowling lane
if (self.x < bowlingLane.x) {
self.x = bowlingLane.x;
self.velocityX *= -0.8; // Bounce off wall with some energy loss
} else if (self.x > bowlingLane.x + bowlingLane.width) {
self.x = bowlingLane.x + bowlingLane.width;
self.velocityX *= -0.8;
}
// Top boundary check
if (self.y < bowlingLane.y) {
self.y = bowlingLane.y;
self.velocityY *= -0.8;
}
// Bottom boundary (out of bounds)
if (self.y > 2732) {
self.active = false;
self.reset();
}
};
self.reset = function () {
self.x = launchArea.x;
self.y = launchArea.y - 250; // Move penguin further up the lane
self.velocityX = 0;
self.velocityY = 0;
self.active = false;
self.hasCollided = false;
self.pullDistance = 0; // Reset pull distance
penguinGraphics.rotation = 0;
};
return self;
});
var PowerMeter = Container.expand(function () {
var self = Container.call(this);
var meterBG = self.attachAsset('powerMeterBG', {
anchorX: 0.5,
anchorY: 0.5
});
var meter = self.attachAsset('powerMeter', {
anchorX: 0.5,
anchorY: 1.0,
height: 0 // Start with no power
});
var maxPower = 300;
self.power = 0;
self.increasing = true;
self.update = function () {
if (self.visible) {
if (self.increasing) {
self.power += 5;
if (self.power >= maxPower) {
self.power = maxPower;
self.increasing = false;
}
} else {
self.power -= 5;
if (self.power <= 0) {
self.power = 0;
self.increasing = true;
}
}
// Update meter height based on power
meter.height = self.power;
meter.y = meterBG.y + meterBG.height / 2 - meter.height / 2;
}
};
self.getPowerRatio = function () {
return self.power / maxPower;
};
self.reset = function () {
self.power = 0;
self.increasing = true;
meter.height = 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xC7E6F7
});
/****
* Game Code
****/
// Game constants
var MAX_POWER = 20;
var PIN_ROWS = 4;
var FRAMES = 10;
var PINS_PER_FRAME = 10;
// Game state variables
var currentFrame = 1;
var pinsKnockedDown = 0;
var totalScore = 0;
var aiming = false;
var powering = false;
var gameState = "aiming"; // States: aiming, powering, sliding, scoring, gameover
var aimAngle = -Math.PI / 2; // Start aiming straight up
// Create background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0
}));
// Create bowling lane
var bowlingLane = game.addChild(LK.getAsset('bowlingLane', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: 100
}));
// Create launch area
var launchArea = game.addChild(LK.getAsset('launchArea', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2400
}));
// Create the aiming line
var aimLine = game.addChild(LK.getAsset('aimLine', {
anchorX: 0.5,
anchorY: 1.0,
x: launchArea.x,
y: launchArea.y,
visible: false
}));
// Create the directional arrow
var aimArrow = game.addChild(new AimArrow());
aimArrow.x = launchArea.x;
aimArrow.y = launchArea.y;
// Create the power meter
var powerMeter = game.addChild(new PowerMeter());
powerMeter.x = 1900;
powerMeter.y = 1400;
powerMeter.visible = false;
// Create the penguin
var penguin = game.addChild(new Penguin());
penguin.x = launchArea.x;
penguin.y = launchArea.y - 250; // Move penguin further up the lane
// Create bowling pins
var pins = [];
setupPins();
// Create UI elements
var frameText = new Text2('Frame: 1/10', {
size: 70,
fill: 0x000000
});
frameText.anchor.set(0.5, 0);
// Position frame text under the penguin's position
frameText.y = penguin.y + 150;
LK.gui.center.addChild(frameText);
var scoreText = new Text2('Score: 0', {
size: 70,
fill: 0x000000
});
scoreText.anchor.set(0.5, 0);
scoreText.y = 80;
LK.gui.top.addChild(scoreText);
var instructionText = new Text2('Tap and drag to pull penguin back, release to launch', {
size: 50,
fill: 0x000000
});
instructionText.anchor.set(0.5, 0);
instructionText.y = 180;
LK.gui.top.addChild(instructionText);
// Helper functions
function setupPins() {
// Clear any existing pins
for (var i = 0; i < pins.length; i++) {
pins[i].destroy();
}
pins = [];
// Create pin layout in traditional bowling triangle formation
// Ensure pins are exactly centered on the lane
var startX = 2048 / 2; // Center of screen
var startY = 400; // Position from top
var pinSpacingX = 80;
var pinSpacingY = 90;
// Standard bowling pin layout (4-3-2-1 triangle)
// First row (back) - 4 pins
for (var i = 0; i < 4; i++) {
var pin = new BowlingPin();
pin.x = startX + (i - 1.5) * pinSpacingX; // Perfectly centered
pin.y = startY;
pins.push(pin);
game.addChild(pin);
}
// Second row - 3 pins
for (var i = 0; i < 3; i++) {
var pin = new BowlingPin();
pin.x = startX + (i - 1) * pinSpacingX; // Centered relative to first row
pin.y = startY + pinSpacingY;
pins.push(pin);
game.addChild(pin);
}
// Third row - 2 pins
for (var i = 0; i < 2; i++) {
var pin = new BowlingPin();
pin.x = startX + (i - 0.5) * pinSpacingX; // Centered relative to second row
pin.y = startY + 2 * pinSpacingY;
pins.push(pin);
game.addChild(pin);
}
// Fourth row (front) - 1 pin
var pin = new BowlingPin();
pin.x = startX; // Center pin
pin.y = startY + 3 * pinSpacingY;
pins.push(pin);
game.addChild(pin);
pinsKnockedDown = 0;
}
function updateAimLine() {
aimLine.rotation = aimAngle;
// Ensure the aim line points from the penguin position
aimLine.x = launchArea.x;
aimLine.y = launchArea.y;
}
function launchPenguin() {
// Calculate power based on the pull distance
var power = Math.min(penguin.pullDistance / 50, 1) * MAX_POWER;
// Launch penguin from current position toward the launch area
var launchAngle = aimAngle + Math.PI; // Reverse the angle to launch toward the pins
penguin.launch(launchAngle, power);
gameState = "sliding";
powerMeter.visible = false;
instructionText.setText("Watch the penguin slide!");
}
function checkCollisions() {
if (!penguin.active || penguin.hasCollided) return;
var newKnockdowns = 0;
for (var i = 0; i < pins.length; i++) {
var pin = pins[i];
if (!pin.isKnockedDown && penguin.intersects(pin)) {
if (pin.knockDown()) {
newKnockdowns++;
pinsKnockedDown++;
// Update score
totalScore += 1;
updateScoreDisplay();
// Create a chain reaction with nearby pins
for (var j = 0; j < pins.length; j++) {
if (i !== j && !pins[j].isKnockedDown) {
var dx = pins[j].x - pin.x;
var dy = pins[j].y - pin.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Pins are close enough to affect each other
pins[j].knockDown();
pinsKnockedDown++;
totalScore += 1;
updateScoreDisplay();
}
}
}
}
}
}
if (newKnockdowns > 0) {
penguin.hasCollided = true;
// Play strike sound if all pins are knocked down
if (pinsKnockedDown === PINS_PER_FRAME) {
LK.getSound('strike').play();
LK.effects.flashScreen(0xFFFFFF, 500);
instructionText.setText("STRIKE!");
}
}
}
function updateScoreDisplay() {
scoreText.setText("Score: " + totalScore);
// Update high score if needed
if (totalScore > storage.highScore) {
storage.highScore = totalScore;
}
}
function nextFrame() {
currentFrame++;
if (currentFrame > FRAMES) {
// Game over
gameState = "gameover";
instructionText.setText("Game Over! Final Score: " + totalScore);
// Show game over screen after a brief delay
LK.setTimeout(function () {
LK.showGameOver();
}, 2000);
} else {
// Setup for next frame
frameText.setText("Frame: " + currentFrame + "/10");
setupPins();
penguin.reset();
gameState = "aiming";
instructionText.setText("Tap and drag backward to aim, release to launch");
}
}
function checkGameStateTransition() {
if (gameState === "sliding") {
// Check if penguin has stopped
if (!penguin.active) {
// Wait a bit for pins to settle and then move to next frame
LK.setTimeout(function () {
nextFrame();
}, 2000);
gameState = "scoring";
}
}
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState === "aiming") {
aiming = true;
aimLine.visible = false;
// Store original penguin position
penguin.originalX = penguin.x;
penguin.originalY = penguin.y;
// Hide arrow when starting to aim
aimArrow.hide();
}
};
game.move = function (x, y, obj) {
if (aiming) {
// Calculate aim angle from penguin to opposite of pull direction
var dx = launchArea.x - x;
var dy = launchArea.y - y;
// Calculate the distance of the pull for power
var distance = Math.sqrt(dx * dx + dy * dy);
// Limit the maximum drag distance
var maxDrag = 300;
distance = Math.min(distance, maxDrag);
// Calculate the angle
aimAngle = Math.atan2(dy, dx);
// Move the penguin to the drag position
penguin.x = launchArea.x - Math.cos(aimAngle) * distance;
penguin.y = launchArea.y - Math.sin(aimAngle) * distance;
// Update the directional arrow - start from penguin position pointing toward launch area
aimArrow.updateArrow(penguin.x, penguin.y, aimAngle + Math.PI);
// Store the pull distance for calculating power later
penguin.pullDistance = distance;
}
};
game.up = function (x, y, obj) {
if (aiming) {
aiming = false;
// Hide the directional arrow
aimArrow.hide();
// Only launch if penguin was actually pulled back
if (penguin.pullDistance > 10) {
// Launch immediately after release
launchPenguin();
} else {
// Reset penguin position if not pulled back enough
penguin.x = penguin.originalX;
penguin.y = penguin.originalY;
}
}
};
// Game update loop
game.update = function () {
if (gameState === "sliding") {
penguin.update();
// Update pin physics
for (var i = 0; i < pins.length; i++) {
pins[i].update();
}
checkCollisions();
checkGameStateTransition();
}
};
// Start background music
LK.playMusic('gameMusic');
A cartoon-style penguin lying flat on its belly, facing forward with its body stretched out. In-Game asset. 2d. High contrast. No shadows
Bowling pin. In-Game asset. 2d. High contrast. No shadows
iglo. In-Game asset. 2d. High contrast. No shadows
Icy surface. In-Game asset. 2d. High contrast. No shadows
Snow gently falling from the sky in a peaceful winter scene. The snowflakes are soft and light, creating a calm atmosphere. The snow is falling in large, delicate flakes, covering the icy surface and creating a serene, magical ambiance.". In-Game asset. 2d. High contrast. No shadows
horizontal fire. In-Game asset. 2d. High contrast. No shadows
pişmiş tavuk. In-Game asset. 2d. High contrast. No shadows