User prompt
The round position should be underneath the penguin.
User prompt
Change the penguin's position to a slightly forward location, and make sure it returns to the same spot at the end of the round.
User prompt
The platform where the penguin is placed should be a bit further ahead, so I can easily drag the penguin with the mouse.
User prompt
penguenin olduğu konumu biraz daha ileri al
User prompt
The penguin and the arrow should work inversely — when you click and drag the penguin backwards, the arrow should point in the direction the penguin will travel. The farther you pull it back, the faster it should go. As soon as you release it, the penguin should start sliding toward the pins. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
A directional arrow should appear while dragging the penguin, showing the direction it will move once released.
User prompt
A directional arrow should appear while dragging the penguin, showing the direction it will move once released.
User prompt
The pins are still positioned off to the side. Move them to the center of the screen and make sure they are aligned with the penguin.
User prompt
Align the pins with the penguin.
User prompt
You need to arrange the pins in the center, just like in a real bowling game.
User prompt
labutları üçgen bir şekilde ekranın tam ortasına getir
User prompt
labutlar pengueni saldığımda penguenin çarpması gereken objeler ve tam ortaya hizalaman gerekiyor
User prompt
labutların ortada olması gerekiyor ve tam ortadan labutlara geçen bir yol olması gerekiyor
Code edit (1 edits merged)
Please save this source code
User prompt
Penguin Bowling: Ice Slide Strike
Initial prompt
I want to make a bowling game where, instead of a bowling ball, you launch a penguin. The ground is made of ice, and the penguin slides across it.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ 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.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; self.velocityX = 0; self.velocityY = 0; self.active = false; self.hasCollided = false; 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 })); // 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; // 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); LK.gui.top.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 aim, release to power up', { 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 a triangle formation at the center var centerX = 2048 / 2; // Center of the screen X var startY = 400; // Starting Y position var pinSpacingX = 80; // Horizontal spacing var pinSpacingY = 90; // Vertical spacing var pinCount = 0; // Traditional bowling triangle formation: 1-2-3-4 rows // First row (top of triangle) - 1 pin var pin = new BowlingPin(); pin.x = centerX; pin.y = startY; pins.push(pin); game.addChild(pin); pinCount++; // Second row - 2 pins for (var i = 0; i < 2; i++) { var pin = new BowlingPin(); pin.x = centerX + (i === 0 ? -0.5 : 0.5) * pinSpacingX; pin.y = startY + pinSpacingY; pins.push(pin); game.addChild(pin); pinCount++; } // Third row - 3 pins for (var i = 0; i < 3; i++) { var pin = new BowlingPin(); pin.x = centerX + (i - 1) * pinSpacingX; pin.y = startY + 2 * pinSpacingY; pins.push(pin); game.addChild(pin); pinCount++; } // Fourth row (bottom of triangle) - 4 pins for (var i = 0; i < 4; i++) { var pin = new BowlingPin(); pin.x = centerX + (i - 1.5) * pinSpacingX; pin.y = startY + 3 * pinSpacingY; pins.push(pin); game.addChild(pin); pinCount++; } 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 meter var power = powerMeter.getPowerRatio() * MAX_POWER; penguin.launch(aimAngle, 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 to aim, release to power up"); } } 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 = true; } }; game.move = function (x, y, obj) { if (aiming) { // Calculate aim angle from touch position to penguin var dx = x - launchArea.x; var dy = y - launchArea.y; // Only allow aiming upward (top half of the screen) if (dy < 0) { aimAngle = Math.atan2(dy, dx); updateAimLine(); } } }; game.up = function (x, y, obj) { if (aiming) { aiming = false; // Transition to power meter stage powerMeter.reset(); powerMeter.visible = true; gameState = "powering"; instructionText.setText("Tap to set power"); } else if (gameState === "powering") { // Launch the penguin with current power launchPenguin(); } }; // Game update loop game.update = function () { if (gameState === "powering") { powerMeter.update(); } 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');
===================================================================
--- original.js
+++ change.js
@@ -256,56 +256,45 @@
for (var i = 0; i < pins.length; i++) {
pins[i].destroy();
}
pins = [];
- // Create pin layout with a path in the middle
- var startX = bowlingLane.x + bowlingLane.width / 2;
- var startY = 400;
- var pinSpacingX = 80;
- var pinSpacingY = 90;
+ // Create pin layout in a triangle formation at the center
+ var centerX = 2048 / 2; // Center of the screen X
+ var startY = 400; // Starting Y position
+ var pinSpacingX = 80; // Horizontal spacing
+ var pinSpacingY = 90; // Vertical spacing
var pinCount = 0;
- // Set up pins in a traditional bowling triangle formation with a clear center path
- // Triangle formation: 4-3-2-1 (standard bowling)
- // But with a path cleared through the middle
- // Fourth row (front) - 1 pin on each side
+ // Traditional bowling triangle formation: 1-2-3-4 rows
+ // First row (top of triangle) - 1 pin
+ var pin = new BowlingPin();
+ pin.x = centerX;
+ pin.y = startY;
+ pins.push(pin);
+ game.addChild(pin);
+ pinCount++;
+ // Second row - 2 pins
for (var i = 0; i < 2; i++) {
var pin = new BowlingPin();
- // Position on left or right of center
- pin.x = startX + (i === 0 ? -1 : 1) * pinSpacingX;
- pin.y = startY + 3 * pinSpacingY;
+ pin.x = centerX + (i === 0 ? -0.5 : 0.5) * pinSpacingX;
+ pin.y = startY + pinSpacingY;
pins.push(pin);
game.addChild(pin);
pinCount++;
}
- // Third row - 2 pins on each side
- for (var i = 0; i < 4; i++) {
- // Skip middle two positions to create path
- if (i === 1 || i === 2) continue;
+ // Third row - 3 pins
+ for (var i = 0; i < 3; i++) {
var pin = new BowlingPin();
- pin.x = startX + (i - 1.5) * pinSpacingX;
+ pin.x = centerX + (i - 1) * pinSpacingX;
pin.y = startY + 2 * pinSpacingY;
pins.push(pin);
game.addChild(pin);
pinCount++;
}
- // Second row - 3 pins with a gap in the middle
- for (var i = 0; i < 3; i++) {
- // Skip the middle position
- if (i === 1) continue;
- var pin = new BowlingPin();
- pin.x = startX + (i - 1) * pinSpacingX;
- pin.y = startY + pinSpacingY;
- pins.push(pin);
- game.addChild(pin);
- pinCount++;
- }
- // First row (back) - 4 pins with a center gap
+ // Fourth row (bottom of triangle) - 4 pins
for (var i = 0; i < 4; i++) {
- // Skip the two middle positions
- if (i === 1 || i === 2) continue;
var pin = new BowlingPin();
- pin.x = startX + (i - 1.5) * pinSpacingX;
- pin.y = startY;
+ pin.x = centerX + (i - 1.5) * pinSpacingX;
+ pin.y = startY + 3 * pinSpacingY;
pins.push(pin);
game.addChild(pin);
pinCount++;
}
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