/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Bowling Ball Class
var BowlingBall = Container.expand(function () {
var self = Container.call(this);
// Attach bowling ball asset (blue ellipse)
var ball = self.attachAsset('bowlingBall', {
anchorX: 0.5,
anchorY: 0.5
});
// Ball state
self.isMoving = false;
self.vx = 0;
self.vy = 0;
// Ball radius for collision
self.radius = ball.width / 2;
// Reset ball to initial position
self.reset = function () {
self.x = 2048 / 2;
self.y = 2732 - 350;
self.vx = 0;
self.vy = 0;
self.isMoving = false;
};
// Update ball position
self.update = function () {
if (self.isMoving) {
self.x += self.vx;
self.y += self.vy;
// Friction
self.vx *= 0.985;
self.vy *= 0.985;
// Stop if very slow
if (Math.abs(self.vx) < 0.5 && Math.abs(self.vy) < 0.5) {
self.vx = 0;
self.vy = 0;
self.isMoving = false;
}
// Clamp to game area
if (self.x < self.radius) self.x = self.radius;
if (self.x > 2048 - self.radius) self.x = 2048 - self.radius;
if (self.y < self.radius) self.y = self.radius;
if (self.y > 2732 - self.radius) self.y = 2732 - self.radius;
}
};
return self;
});
// Pin Class
var Pin = Container.expand(function () {
var self = Container.call(this);
// Attach pin asset (white box)
var pin = self.attachAsset('pin', {
anchorX: 0.5,
anchorY: 1.0
});
self.isStanding = true;
// Knock down pin
self.knockDown = function () {
if (self.isStanding) {
self.isStanding = false;
// Animate: fall down (rotate and fade)
tween(self, {
rotation: Math.PI / 2,
alpha: 0.3
}, {
duration: 400,
easing: tween.cubicOut
});
}
};
// Reset pin to standing
self.reset = function () {
self.isStanding = true;
self.rotation = 0;
self.alpha = 1;
};
// Get pin center for collision
self.getCenter = function () {
return {
x: self.x,
y: self.y - pin.height / 2
};
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// --- Game State Variables ---
// --- Asset Initialization ---
var ball;
var pins = [];
var currentFrame = 1;
var currentRoll = 1;
var frameScores = [];
var totalScore = 0;
var pinsDownThisFrame = 0;
var pinsDownThisRoll = 0;
var bestScore = storage.bestScore || 0;
var isAiming = false;
var aimStart = null;
var aimEnd = null;
var canThrow = true;
var isResetting = false;
// --- UI Elements ---
var scoreTxt = new Text2('Skor: 0', {
size: 90,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var frameTxt = new Text2('Tur: 1 / 10', {
size: 70,
fill: "#fff"
});
frameTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(frameTxt);
frameTxt.y = 110;
var bestScoreTxt = new Text2('En İyi: ' + bestScore, {
size: 60,
fill: 0xFFD700
});
bestScoreTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(bestScoreTxt);
// --- Helper Functions ---
// Arrange pins in triangle (10 pins)
function setupPins() {
// Remove old pins
for (var i = 0; i < pins.length; i++) {
pins[i].destroy();
}
pins = [];
// Triangle layout
var startX = 2048 / 2;
var startY = 600;
var rowSpacing = 90;
var colSpacing = 80;
var pinIdx = 0;
for (var row = 0; row < 4; row++) {
for (var col = 0; col <= row; col++) {
if (pinIdx >= 10) break;
var pin = new Pin();
pin.reset();
pin.x = startX + (col - row / 2) * colSpacing;
pin.y = startY + row * rowSpacing;
pins.push(pin);
game.addChild(pin);
pinIdx++;
}
}
}
// Reset ball and pins for new frame or roll
function resetForNextRoll() {
isResetting = true;
// Reset ball
ball.reset();
// Only reset pins if new frame
if (currentRoll === 1) {
setupPins();
} else {
// Only reset fallen pins if second roll
for (var i = 0; i < pins.length; i++) {
if (!pins[i].isStanding) {
pins[i].alpha = 0.15;
}
}
}
isResetting = false;
canThrow = true;
aimStart = null;
aimEnd = null;
}
// Count standing pins
function countStandingPins() {
var count = 0;
for (var i = 0; i < pins.length; i++) {
if (pins[i].isStanding) count++;
}
return count;
}
// Update UI
function updateUI() {
scoreTxt.setText('Skor: ' + totalScore);
frameTxt.setText('Tur: ' + currentFrame + ' / 10');
bestScoreTxt.setText('En İyi: ' + bestScore);
}
// Calculate score for a frame (simple: just sum pins knocked down)
function calcFrameScore(frameIdx) {
// For MVP, just sum pins knocked down in frame
return frameScores[frameIdx] || 0;
}
// End of game
function endGame() {
if (totalScore > bestScore) {
bestScore = totalScore;
storage.bestScore = bestScore;
}
updateUI();
// Show game over popup
LK.showGameOver();
}
// --- Game Setup ---
// Create ball
ball = new BowlingBall();
game.addChild(ball);
ball.reset();
// Create pins
setupPins();
// Initialize scores
frameScores = [];
totalScore = 0;
currentFrame = 1;
currentRoll = 1;
pinsDownThisFrame = 0;
pinsDownThisRoll = 0;
updateUI();
// --- Input Handling ---
// Drag/Swipe to throw
game.down = function (x, y, obj) {
if (!canThrow || ball.isMoving || isResetting) return;
// Only allow drag from ball area
var dx = x - ball.x;
var dy = y - ball.y;
if (dx * dx + dy * dy <= ball.radius * ball.radius * 1.2) {
isAiming = true;
aimStart = {
x: x,
y: y
};
aimEnd = null;
}
};
game.move = function (x, y, obj) {
if (isAiming && aimStart) {
aimEnd = {
x: x,
y: y
};
// Optionally: show aim line (not implemented in MVP)
}
};
game.up = function (x, y, obj) {
if (isAiming && aimStart && !ball.isMoving && canThrow) {
aimEnd = {
x: x,
y: y
};
// Calculate velocity
var dx = aimEnd.x - aimStart.x;
var dy = aimEnd.y - aimStart.y;
// Only allow upward throws
if (dy < -30) {
// Map swipe to velocity
var power = Math.min(Math.sqrt(dx * dx + dy * dy), 900);
var angle = Math.atan2(dy, dx);
var speed = 32 + power / 30; // min speed
ball.vx = Math.cos(angle) * speed;
ball.vy = Math.sin(angle) * speed;
ball.isMoving = true;
canThrow = false;
}
}
isAiming = false;
aimStart = null;
aimEnd = null;
};
// --- Game Loop ---
game.update = function () {
// Ball update
ball.update();
// Collision: Ball vs Pins
if (ball.isMoving) {
for (var i = 0; i < pins.length; i++) {
var pin = pins[i];
if (pin.isStanding) {
var c = pin.getCenter();
var dx = ball.x - c.x;
var dy = ball.y - c.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < ball.radius + 40) {
// 40: pin "radius"
pin.knockDown();
}
}
}
}
// Check if ball stopped or out of bounds
if (!ball.isMoving && !canThrow && !isResetting) {
// Wait a short moment before scoring
isResetting = true;
LK.setTimeout(function () {
// Count pins knocked down this roll
var pinsDown = 0;
for (var i = 0; i < pins.length; i++) {
if (!pins[i].isStanding && pins[i].alpha > 0.2) {
pinsDown++;
}
}
pinsDownThisRoll = pinsDown - pinsDownThisFrame;
pinsDownThisFrame = pinsDown;
// Add to frame score
if (!frameScores[currentFrame - 1]) frameScores[currentFrame - 1] = 0;
frameScores[currentFrame - 1] += pinsDownThisRoll;
totalScore = 0;
for (var f = 0; f < frameScores.length; f++) {
totalScore += calcFrameScore(f);
}
updateUI();
// Strike: all pins down in first roll
var allDown = countStandingPins() === 0;
if (allDown && currentRoll === 1) {
// Strike: skip second roll
currentFrame++;
currentRoll = 1;
pinsDownThisFrame = 0;
if (currentFrame > 10) {
endGame();
return;
}
resetForNextRoll();
} else if (currentRoll === 1) {
// Second roll
currentRoll = 2;
resetForNextRoll();
} else {
// End of frame
currentFrame++;
currentRoll = 1;
pinsDownThisFrame = 0;
if (currentFrame > 10) {
endGame();
return;
}
resetForNextRoll();
}
}, 700);
}
};
// --- Initial UI Update ---
updateUI(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,355 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+// Bowling Ball Class
+var BowlingBall = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach bowling ball asset (blue ellipse)
+ var ball = self.attachAsset('bowlingBall', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Ball state
+ self.isMoving = false;
+ self.vx = 0;
+ self.vy = 0;
+ // Ball radius for collision
+ self.radius = ball.width / 2;
+ // Reset ball to initial position
+ self.reset = function () {
+ self.x = 2048 / 2;
+ self.y = 2732 - 350;
+ self.vx = 0;
+ self.vy = 0;
+ self.isMoving = false;
+ };
+ // Update ball position
+ self.update = function () {
+ if (self.isMoving) {
+ self.x += self.vx;
+ self.y += self.vy;
+ // Friction
+ self.vx *= 0.985;
+ self.vy *= 0.985;
+ // Stop if very slow
+ if (Math.abs(self.vx) < 0.5 && Math.abs(self.vy) < 0.5) {
+ self.vx = 0;
+ self.vy = 0;
+ self.isMoving = false;
+ }
+ // Clamp to game area
+ if (self.x < self.radius) self.x = self.radius;
+ if (self.x > 2048 - self.radius) self.x = 2048 - self.radius;
+ if (self.y < self.radius) self.y = self.radius;
+ if (self.y > 2732 - self.radius) self.y = 2732 - self.radius;
+ }
+ };
+ return self;
+});
+// Pin Class
+var Pin = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach pin asset (white box)
+ var pin = self.attachAsset('pin', {
+ anchorX: 0.5,
+ anchorY: 1.0
+ });
+ self.isStanding = true;
+ // Knock down pin
+ self.knockDown = function () {
+ if (self.isStanding) {
+ self.isStanding = false;
+ // Animate: fall down (rotate and fade)
+ tween(self, {
+ rotation: Math.PI / 2,
+ alpha: 0.3
+ }, {
+ duration: 400,
+ easing: tween.cubicOut
+ });
+ }
+ };
+ // Reset pin to standing
+ self.reset = function () {
+ self.isStanding = true;
+ self.rotation = 0;
+ self.alpha = 1;
+ };
+ // Get pin center for collision
+ self.getCenter = function () {
+ return {
+ x: self.x,
+ y: self.y - pin.height / 2
+ };
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// --- Game State Variables ---
+// --- Asset Initialization ---
+var ball;
+var pins = [];
+var currentFrame = 1;
+var currentRoll = 1;
+var frameScores = [];
+var totalScore = 0;
+var pinsDownThisFrame = 0;
+var pinsDownThisRoll = 0;
+var bestScore = storage.bestScore || 0;
+var isAiming = false;
+var aimStart = null;
+var aimEnd = null;
+var canThrow = true;
+var isResetting = false;
+// --- UI Elements ---
+var scoreTxt = new Text2('Skor: 0', {
+ size: 90,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var frameTxt = new Text2('Tur: 1 / 10', {
+ size: 70,
+ fill: "#fff"
+});
+frameTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(frameTxt);
+frameTxt.y = 110;
+var bestScoreTxt = new Text2('En İyi: ' + bestScore, {
+ size: 60,
+ fill: 0xFFD700
+});
+bestScoreTxt.anchor.set(1, 0);
+LK.gui.topRight.addChild(bestScoreTxt);
+// --- Helper Functions ---
+// Arrange pins in triangle (10 pins)
+function setupPins() {
+ // Remove old pins
+ for (var i = 0; i < pins.length; i++) {
+ pins[i].destroy();
+ }
+ pins = [];
+ // Triangle layout
+ var startX = 2048 / 2;
+ var startY = 600;
+ var rowSpacing = 90;
+ var colSpacing = 80;
+ var pinIdx = 0;
+ for (var row = 0; row < 4; row++) {
+ for (var col = 0; col <= row; col++) {
+ if (pinIdx >= 10) break;
+ var pin = new Pin();
+ pin.reset();
+ pin.x = startX + (col - row / 2) * colSpacing;
+ pin.y = startY + row * rowSpacing;
+ pins.push(pin);
+ game.addChild(pin);
+ pinIdx++;
+ }
+ }
+}
+// Reset ball and pins for new frame or roll
+function resetForNextRoll() {
+ isResetting = true;
+ // Reset ball
+ ball.reset();
+ // Only reset pins if new frame
+ if (currentRoll === 1) {
+ setupPins();
+ } else {
+ // Only reset fallen pins if second roll
+ for (var i = 0; i < pins.length; i++) {
+ if (!pins[i].isStanding) {
+ pins[i].alpha = 0.15;
+ }
+ }
+ }
+ isResetting = false;
+ canThrow = true;
+ aimStart = null;
+ aimEnd = null;
+}
+// Count standing pins
+function countStandingPins() {
+ var count = 0;
+ for (var i = 0; i < pins.length; i++) {
+ if (pins[i].isStanding) count++;
+ }
+ return count;
+}
+// Update UI
+function updateUI() {
+ scoreTxt.setText('Skor: ' + totalScore);
+ frameTxt.setText('Tur: ' + currentFrame + ' / 10');
+ bestScoreTxt.setText('En İyi: ' + bestScore);
+}
+// Calculate score for a frame (simple: just sum pins knocked down)
+function calcFrameScore(frameIdx) {
+ // For MVP, just sum pins knocked down in frame
+ return frameScores[frameIdx] || 0;
+}
+// End of game
+function endGame() {
+ if (totalScore > bestScore) {
+ bestScore = totalScore;
+ storage.bestScore = bestScore;
+ }
+ updateUI();
+ // Show game over popup
+ LK.showGameOver();
+}
+// --- Game Setup ---
+// Create ball
+ball = new BowlingBall();
+game.addChild(ball);
+ball.reset();
+// Create pins
+setupPins();
+// Initialize scores
+frameScores = [];
+totalScore = 0;
+currentFrame = 1;
+currentRoll = 1;
+pinsDownThisFrame = 0;
+pinsDownThisRoll = 0;
+updateUI();
+// --- Input Handling ---
+// Drag/Swipe to throw
+game.down = function (x, y, obj) {
+ if (!canThrow || ball.isMoving || isResetting) return;
+ // Only allow drag from ball area
+ var dx = x - ball.x;
+ var dy = y - ball.y;
+ if (dx * dx + dy * dy <= ball.radius * ball.radius * 1.2) {
+ isAiming = true;
+ aimStart = {
+ x: x,
+ y: y
+ };
+ aimEnd = null;
+ }
+};
+game.move = function (x, y, obj) {
+ if (isAiming && aimStart) {
+ aimEnd = {
+ x: x,
+ y: y
+ };
+ // Optionally: show aim line (not implemented in MVP)
+ }
+};
+game.up = function (x, y, obj) {
+ if (isAiming && aimStart && !ball.isMoving && canThrow) {
+ aimEnd = {
+ x: x,
+ y: y
+ };
+ // Calculate velocity
+ var dx = aimEnd.x - aimStart.x;
+ var dy = aimEnd.y - aimStart.y;
+ // Only allow upward throws
+ if (dy < -30) {
+ // Map swipe to velocity
+ var power = Math.min(Math.sqrt(dx * dx + dy * dy), 900);
+ var angle = Math.atan2(dy, dx);
+ var speed = 32 + power / 30; // min speed
+ ball.vx = Math.cos(angle) * speed;
+ ball.vy = Math.sin(angle) * speed;
+ ball.isMoving = true;
+ canThrow = false;
+ }
+ }
+ isAiming = false;
+ aimStart = null;
+ aimEnd = null;
+};
+// --- Game Loop ---
+game.update = function () {
+ // Ball update
+ ball.update();
+ // Collision: Ball vs Pins
+ if (ball.isMoving) {
+ for (var i = 0; i < pins.length; i++) {
+ var pin = pins[i];
+ if (pin.isStanding) {
+ var c = pin.getCenter();
+ var dx = ball.x - c.x;
+ var dy = ball.y - c.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ if (dist < ball.radius + 40) {
+ // 40: pin "radius"
+ pin.knockDown();
+ }
+ }
+ }
+ }
+ // Check if ball stopped or out of bounds
+ if (!ball.isMoving && !canThrow && !isResetting) {
+ // Wait a short moment before scoring
+ isResetting = true;
+ LK.setTimeout(function () {
+ // Count pins knocked down this roll
+ var pinsDown = 0;
+ for (var i = 0; i < pins.length; i++) {
+ if (!pins[i].isStanding && pins[i].alpha > 0.2) {
+ pinsDown++;
+ }
+ }
+ pinsDownThisRoll = pinsDown - pinsDownThisFrame;
+ pinsDownThisFrame = pinsDown;
+ // Add to frame score
+ if (!frameScores[currentFrame - 1]) frameScores[currentFrame - 1] = 0;
+ frameScores[currentFrame - 1] += pinsDownThisRoll;
+ totalScore = 0;
+ for (var f = 0; f < frameScores.length; f++) {
+ totalScore += calcFrameScore(f);
+ }
+ updateUI();
+ // Strike: all pins down in first roll
+ var allDown = countStandingPins() === 0;
+ if (allDown && currentRoll === 1) {
+ // Strike: skip second roll
+ currentFrame++;
+ currentRoll = 1;
+ pinsDownThisFrame = 0;
+ if (currentFrame > 10) {
+ endGame();
+ return;
+ }
+ resetForNextRoll();
+ } else if (currentRoll === 1) {
+ // Second roll
+ currentRoll = 2;
+ resetForNextRoll();
+ } else {
+ // End of frame
+ currentFrame++;
+ currentRoll = 1;
+ pinsDownThisFrame = 0;
+ if (currentFrame > 10) {
+ endGame();
+ return;
+ }
+ resetForNextRoll();
+ }
+ }, 700);
+ }
+};
+// --- Initial UI Update ---
+updateUI();
\ No newline at end of file