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