/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Character (the slingshot ball) var SlingshotCharacter = Container.expand(function () { var self = Container.call(this); // Attach a circle asset for the character var charAsset = self.attachAsset('slingshotChar', { anchorX: 0.5, anchorY: 0.5 }); // For visual feedback when dragging self.setDragging = function (isDragging) { charAsset.alpha = isDragging ? 0.7 : 1; charAsset.scaleX = charAsset.scaleY = isDragging ? 1.15 : 1; }; // For visual feedback when shot self.flash = function () { LK.effects.flashObject(self, 0xffe066, 200); }; return self; }); // Target class var Target = Container.expand(function () { var self = Container.call(this); // Attach a target asset (circle) var targetAsset = self.attachAsset('targetCircle', { anchorX: 0.5, anchorY: 0.5 }); // For hit animation self.hit = function () { tween(self, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- CONFIGURABLES --- LK.playMusic('M'); var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var SLING_RADIUS = 350; // Max drag distance var SLING_CENTER_X = GAME_WIDTH / 2; var SLING_CENTER_Y = GAME_HEIGHT / 2; var CHARACTER_RADIUS = 80; var TARGET_RADIUS = 70; var NUM_TARGETS = 6; var MAX_SHOTS = NUM_TARGETS; var GAME_TIME = 20 * 1000; // 20 seconds // --- ASSETS --- // --- STATE --- var character; var targets = []; var shotsLeft = NUM_TARGETS; var misses = 0; var score = 0; var isDragging = false; var dragStart = null; var dragLine = null; var velocity = { x: 0, y: 0 }; var isFlying = false; var timerText, shotsText, missesText; var timeLeft = GAME_TIME; var timerInterval = null; var gameEnded = false; // --- GUI --- timerText = new Text2('20.0', { size: 100, fill: 0xFFFFFF }); timerText.anchor.set(0.5, 0); LK.gui.top.addChild(timerText); shotsText = new Text2('Atış: ' + NUM_TARGETS, { size: 80, fill: 0xFFFFFF }); shotsText.anchor.set(0.5, 0); LK.gui.top.addChild(shotsText); shotsText.y = 110; missesText = new Text2('Iska: 0', { size: 80, fill: 0xFFFFFF }); missesText.anchor.set(0.5, 0); LK.gui.top.addChild(missesText); missesText.y = 200; // --- SHOTS BAR REMOVED (bottom of scene) --- // --- INIT CHARACTER --- character = new SlingshotCharacter(); character.x = SLING_CENTER_X; character.y = SLING_CENTER_Y; game.addChild(character); // --- INIT TARGETS --- function randomTargetPos() { // Place targets randomly, but not too close to center or each other var minDistFromCenter = 400; var minDistFromOthers = 300; var tries = 0; while (tries < 100) { var x = 200 + Math.random() * (GAME_WIDTH - 400); var y = 300 + Math.random() * (GAME_HEIGHT - 600); var distToCenter = Math.sqrt((x - SLING_CENTER_X) * (x - SLING_CENTER_X) + (y - SLING_CENTER_Y) * (y - SLING_CENTER_Y)); if (distToCenter < minDistFromCenter) { tries++; continue; } var tooClose = false; for (var i = 0; i < targets.length; i++) { var t = targets[i]; var dx = t.x - x, dy = t.y - y; if (Math.sqrt(dx * dx + dy * dy) < minDistFromOthers) { tooClose = true; break; } } if (!tooClose) return { x: x, y: y }; tries++; } // fallback return { x: 200 + Math.random() * (GAME_WIDTH - 400), y: 300 + Math.random() * (GAME_HEIGHT - 600) }; } // Arrange targets in a circle around the character var circleRadius = 600; var angleStep = 2 * Math.PI / NUM_TARGETS; for (var i = 0; i < NUM_TARGETS; i++) { var t = new Target(); var angle = i * angleStep; t.x = SLING_CENTER_X + Math.cos(angle) * circleRadius; t.y = SLING_CENTER_Y + Math.sin(angle) * circleRadius; targets.push(t); game.addChild(t); } // --- DRAGGING & SLINGSHOT --- function drawDragLine(fromX, fromY, toX, toY) { if (!dragLine) { dragLine = LK.getAsset('dragLine', { width: 10, height: 10, color: 0xffffff, shape: 'box', anchorX: 0, anchorY: 0 }); dragLine.alpha = 0.5; game.addChild(dragLine); } var dx = toX - fromX, dy = toY - fromY; var len = Math.sqrt(dx * dx + dy * dy); dragLine.width = len; dragLine.height = 12; dragLine.x = fromX; dragLine.y = fromY - 6; dragLine.rotation = Math.atan2(dy, dx); dragLine.visible = true; } function hideDragLine() { if (dragLine) dragLine.visible = false; } // --- GAME EVENTS --- game.down = function (x, y, obj) { if (gameEnded || isFlying || shotsLeft <= 0) return; // Only allow drag if touch is on character var dx = x - character.x, dy = y - character.y; if (dx * dx + dy * dy <= CHARACTER_RADIUS * CHARACTER_RADIUS * 1.2) { isDragging = true; dragStart = { x: x, y: y }; character.setDragging(true); drawDragLine(character.x, character.y, x, y); } }; game.move = function (x, y, obj) { if (isDragging && !isFlying && !gameEnded) { // Limit drag distance var dx = x - SLING_CENTER_X, dy = y - SLING_CENTER_Y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > SLING_RADIUS) { var scale = SLING_RADIUS / dist; x = SLING_CENTER_X + dx * scale; y = SLING_CENTER_Y + dy * scale; } character.x = x; character.y = y; drawDragLine(SLING_CENTER_X, SLING_CENTER_Y, x, y); } }; game.up = function (x, y, obj) { if (isDragging && !isFlying && !gameEnded) { isDragging = false; character.setDragging(false); hideDragLine(); // Calculate velocity (opposite direction of drag) var dx = SLING_CENTER_X - character.x; var dy = SLING_CENTER_Y - character.y; var power = Math.sqrt(dx * dx + dy * dy); if (power < 40) { // Not enough drag, reset character.x = SLING_CENTER_X; character.y = SLING_CENTER_Y; return; } // Normalize and scale velocity var maxSpeed = 60; velocity.x = dx / power * Math.min(power, SLING_RADIUS) * 0.25; velocity.y = dy / power * Math.min(power, SLING_RADIUS) * 0.25; if (velocity.x > maxSpeed) velocity.x = maxSpeed; if (velocity.y > maxSpeed) velocity.y = maxSpeed; isFlying = true; shotsLeft--; shotsText.setText('Atış: ' + shotsLeft); // Shots bar update removed character.flash(); } }; // --- TIMER --- function updateTimerText() { var sec = Math.max(0, Math.ceil(timeLeft / 100) / 10); timerText.setText(sec.toFixed(1)); } function endGame(lost) { if (gameEnded) return; gameEnded = true; LK.setScore(score); if (lost) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } else { // Win only if all targets are hit, no misses, and shots used equals targets, and within 20 seconds if (score === NUM_TARGETS && misses === 0 && shotsLeft === 0 && timeLeft > 0) { // Show 'Kazandın' text in the center var winText = new Text2('Kazandın!', { size: 220, fill: 0xffe066, font: "'GillSans-Bold',Impact,'Arial Black',Tahoma" }); winText.anchor.set(0.5, 0.5); winText.x = GAME_WIDTH / 2; winText.y = GAME_HEIGHT / 2; game.addChild(winText); // Celebration effect: flash screen green, then confetti (simulate with multiple flashes) LK.effects.flashScreen(0x00ff00, 800); // Simulate confetti with multiple color flashes LK.setTimeout(function () { LK.effects.flashScreen(0xffe066, 200); }, 900); LK.setTimeout(function () { LK.effects.flashScreen(0x66ccff, 200); }, 1150); LK.setTimeout(function () { LK.effects.flashScreen(0xff66cc, 200); }, 1400); LK.setTimeout(function () { LK.effects.flashScreen(0xffffff, 120); }, 1650); // ShowYouWin after a short delay so player sees the celebration LK.setTimeout(function () { LK.showYouWin(); }, 2000); } else { // Not a perfect win, show game over LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); } } } timerInterval = LK.setInterval(function () { if (gameEnded) return; timeLeft -= 100; updateTimerText(); if (timeLeft <= 0) { endGame(true); } }, 100); // --- GAME UPDATE LOOP --- game.update = function () { if (gameEnded) return; // End game if out of shots or any miss occurs if (shotsLeft <= 0 || misses > 0) { endGame(true); return; } // Flying logic if (isFlying) { character.x += velocity.x; character.y += velocity.y; // Friction velocity.x *= 0.985; velocity.y *= 0.985; // Check collision with targets for (var i = targets.length - 1; i >= 0; i--) { var t = targets[i]; var dx = t.x - character.x, dy = t.y - character.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < CHARACTER_RADIUS + TARGET_RADIUS - 10) { // Hit! t.hit(); targets.splice(i, 1); score++; LK.setScore(score); // Animate character a bit tween(character, { scaleX: 1.3, scaleY: 1.3 }, { duration: 120, easing: tween.easeOut, onFinish: function onFinish() { tween(character, { scaleX: 1, scaleY: 1 }, { duration: 120 }); } }); // Reset character to center after short delay isFlying = false; LK.setTimeout(function () { character.x = SLING_CENTER_X; character.y = SLING_CENTER_Y; }, 180); // Win condition if (targets.length === 0) { endGame(false); } return; } } // Out of bounds or stopped if (character.x < -CHARACTER_RADIUS || character.x > GAME_WIDTH + CHARACTER_RADIUS || character.y < -CHARACTER_RADIUS || character.y > GAME_HEIGHT + CHARACTER_RADIUS || Math.abs(velocity.x) < 1 && Math.abs(velocity.y) < 1) { isFlying = false; misses++; missesText.setText('Iska: ' + misses); // Animate character back to center tween(character, { x: SLING_CENTER_X, y: SLING_CENTER_Y }, { duration: 300, easing: tween.easeOut }); if (misses > MAX_MISSES) { endGame(true); } } } // If not flying and not dragging, always reset to center if (!isFlying && !isDragging) { character.x = SLING_CENTER_X; character.y = SLING_CENTER_Y; } }; // --- CLEANUP ON GAME END --- game.destroy = function () { LK.clearInterval(timerInterval); }; // --- GUI POSITIONING --- // Place timer bar at the far right (en sağda) timerText.x = LK.gui.top.width - timerText.width / 2 - 20; shotsText.x = LK.gui.top.width / 2; missesText.x = 120 + missesText.width / 2; // Place misses bar at top left, leaving 120px margin for menu ; ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Character (the slingshot ball)
var SlingshotCharacter = Container.expand(function () {
var self = Container.call(this);
// Attach a circle asset for the character
var charAsset = self.attachAsset('slingshotChar', {
anchorX: 0.5,
anchorY: 0.5
});
// For visual feedback when dragging
self.setDragging = function (isDragging) {
charAsset.alpha = isDragging ? 0.7 : 1;
charAsset.scaleX = charAsset.scaleY = isDragging ? 1.15 : 1;
};
// For visual feedback when shot
self.flash = function () {
LK.effects.flashObject(self, 0xffe066, 200);
};
return self;
});
// Target class
var Target = Container.expand(function () {
var self = Container.call(this);
// Attach a target asset (circle)
var targetAsset = self.attachAsset('targetCircle', {
anchorX: 0.5,
anchorY: 0.5
});
// For hit animation
self.hit = function () {
tween(self, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- CONFIGURABLES ---
LK.playMusic('M');
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var SLING_RADIUS = 350; // Max drag distance
var SLING_CENTER_X = GAME_WIDTH / 2;
var SLING_CENTER_Y = GAME_HEIGHT / 2;
var CHARACTER_RADIUS = 80;
var TARGET_RADIUS = 70;
var NUM_TARGETS = 6;
var MAX_SHOTS = NUM_TARGETS;
var GAME_TIME = 20 * 1000; // 20 seconds
// --- ASSETS ---
// --- STATE ---
var character;
var targets = [];
var shotsLeft = NUM_TARGETS;
var misses = 0;
var score = 0;
var isDragging = false;
var dragStart = null;
var dragLine = null;
var velocity = {
x: 0,
y: 0
};
var isFlying = false;
var timerText, shotsText, missesText;
var timeLeft = GAME_TIME;
var timerInterval = null;
var gameEnded = false;
// --- GUI ---
timerText = new Text2('20.0', {
size: 100,
fill: 0xFFFFFF
});
timerText.anchor.set(0.5, 0);
LK.gui.top.addChild(timerText);
shotsText = new Text2('Atış: ' + NUM_TARGETS, {
size: 80,
fill: 0xFFFFFF
});
shotsText.anchor.set(0.5, 0);
LK.gui.top.addChild(shotsText);
shotsText.y = 110;
missesText = new Text2('Iska: 0', {
size: 80,
fill: 0xFFFFFF
});
missesText.anchor.set(0.5, 0);
LK.gui.top.addChild(missesText);
missesText.y = 200;
// --- SHOTS BAR REMOVED (bottom of scene) ---
// --- INIT CHARACTER ---
character = new SlingshotCharacter();
character.x = SLING_CENTER_X;
character.y = SLING_CENTER_Y;
game.addChild(character);
// --- INIT TARGETS ---
function randomTargetPos() {
// Place targets randomly, but not too close to center or each other
var minDistFromCenter = 400;
var minDistFromOthers = 300;
var tries = 0;
while (tries < 100) {
var x = 200 + Math.random() * (GAME_WIDTH - 400);
var y = 300 + Math.random() * (GAME_HEIGHT - 600);
var distToCenter = Math.sqrt((x - SLING_CENTER_X) * (x - SLING_CENTER_X) + (y - SLING_CENTER_Y) * (y - SLING_CENTER_Y));
if (distToCenter < minDistFromCenter) {
tries++;
continue;
}
var tooClose = false;
for (var i = 0; i < targets.length; i++) {
var t = targets[i];
var dx = t.x - x,
dy = t.y - y;
if (Math.sqrt(dx * dx + dy * dy) < minDistFromOthers) {
tooClose = true;
break;
}
}
if (!tooClose) return {
x: x,
y: y
};
tries++;
}
// fallback
return {
x: 200 + Math.random() * (GAME_WIDTH - 400),
y: 300 + Math.random() * (GAME_HEIGHT - 600)
};
}
// Arrange targets in a circle around the character
var circleRadius = 600;
var angleStep = 2 * Math.PI / NUM_TARGETS;
for (var i = 0; i < NUM_TARGETS; i++) {
var t = new Target();
var angle = i * angleStep;
t.x = SLING_CENTER_X + Math.cos(angle) * circleRadius;
t.y = SLING_CENTER_Y + Math.sin(angle) * circleRadius;
targets.push(t);
game.addChild(t);
}
// --- DRAGGING & SLINGSHOT ---
function drawDragLine(fromX, fromY, toX, toY) {
if (!dragLine) {
dragLine = LK.getAsset('dragLine', {
width: 10,
height: 10,
color: 0xffffff,
shape: 'box',
anchorX: 0,
anchorY: 0
});
dragLine.alpha = 0.5;
game.addChild(dragLine);
}
var dx = toX - fromX,
dy = toY - fromY;
var len = Math.sqrt(dx * dx + dy * dy);
dragLine.width = len;
dragLine.height = 12;
dragLine.x = fromX;
dragLine.y = fromY - 6;
dragLine.rotation = Math.atan2(dy, dx);
dragLine.visible = true;
}
function hideDragLine() {
if (dragLine) dragLine.visible = false;
}
// --- GAME EVENTS ---
game.down = function (x, y, obj) {
if (gameEnded || isFlying || shotsLeft <= 0) return;
// Only allow drag if touch is on character
var dx = x - character.x,
dy = y - character.y;
if (dx * dx + dy * dy <= CHARACTER_RADIUS * CHARACTER_RADIUS * 1.2) {
isDragging = true;
dragStart = {
x: x,
y: y
};
character.setDragging(true);
drawDragLine(character.x, character.y, x, y);
}
};
game.move = function (x, y, obj) {
if (isDragging && !isFlying && !gameEnded) {
// Limit drag distance
var dx = x - SLING_CENTER_X,
dy = y - SLING_CENTER_Y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > SLING_RADIUS) {
var scale = SLING_RADIUS / dist;
x = SLING_CENTER_X + dx * scale;
y = SLING_CENTER_Y + dy * scale;
}
character.x = x;
character.y = y;
drawDragLine(SLING_CENTER_X, SLING_CENTER_Y, x, y);
}
};
game.up = function (x, y, obj) {
if (isDragging && !isFlying && !gameEnded) {
isDragging = false;
character.setDragging(false);
hideDragLine();
// Calculate velocity (opposite direction of drag)
var dx = SLING_CENTER_X - character.x;
var dy = SLING_CENTER_Y - character.y;
var power = Math.sqrt(dx * dx + dy * dy);
if (power < 40) {
// Not enough drag, reset
character.x = SLING_CENTER_X;
character.y = SLING_CENTER_Y;
return;
}
// Normalize and scale velocity
var maxSpeed = 60;
velocity.x = dx / power * Math.min(power, SLING_RADIUS) * 0.25;
velocity.y = dy / power * Math.min(power, SLING_RADIUS) * 0.25;
if (velocity.x > maxSpeed) velocity.x = maxSpeed;
if (velocity.y > maxSpeed) velocity.y = maxSpeed;
isFlying = true;
shotsLeft--;
shotsText.setText('Atış: ' + shotsLeft);
// Shots bar update removed
character.flash();
}
};
// --- TIMER ---
function updateTimerText() {
var sec = Math.max(0, Math.ceil(timeLeft / 100) / 10);
timerText.setText(sec.toFixed(1));
}
function endGame(lost) {
if (gameEnded) return;
gameEnded = true;
LK.setScore(score);
if (lost) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
} else {
// Win only if all targets are hit, no misses, and shots used equals targets, and within 20 seconds
if (score === NUM_TARGETS && misses === 0 && shotsLeft === 0 && timeLeft > 0) {
// Show 'Kazandın' text in the center
var winText = new Text2('Kazandın!', {
size: 220,
fill: 0xffe066,
font: "'GillSans-Bold',Impact,'Arial Black',Tahoma"
});
winText.anchor.set(0.5, 0.5);
winText.x = GAME_WIDTH / 2;
winText.y = GAME_HEIGHT / 2;
game.addChild(winText);
// Celebration effect: flash screen green, then confetti (simulate with multiple flashes)
LK.effects.flashScreen(0x00ff00, 800);
// Simulate confetti with multiple color flashes
LK.setTimeout(function () {
LK.effects.flashScreen(0xffe066, 200);
}, 900);
LK.setTimeout(function () {
LK.effects.flashScreen(0x66ccff, 200);
}, 1150);
LK.setTimeout(function () {
LK.effects.flashScreen(0xff66cc, 200);
}, 1400);
LK.setTimeout(function () {
LK.effects.flashScreen(0xffffff, 120);
}, 1650);
// ShowYouWin after a short delay so player sees the celebration
LK.setTimeout(function () {
LK.showYouWin();
}, 2000);
} else {
// Not a perfect win, show game over
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
}
}
}
timerInterval = LK.setInterval(function () {
if (gameEnded) return;
timeLeft -= 100;
updateTimerText();
if (timeLeft <= 0) {
endGame(true);
}
}, 100);
// --- GAME UPDATE LOOP ---
game.update = function () {
if (gameEnded) return;
// End game if out of shots or any miss occurs
if (shotsLeft <= 0 || misses > 0) {
endGame(true);
return;
}
// Flying logic
if (isFlying) {
character.x += velocity.x;
character.y += velocity.y;
// Friction
velocity.x *= 0.985;
velocity.y *= 0.985;
// Check collision with targets
for (var i = targets.length - 1; i >= 0; i--) {
var t = targets[i];
var dx = t.x - character.x,
dy = t.y - character.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < CHARACTER_RADIUS + TARGET_RADIUS - 10) {
// Hit!
t.hit();
targets.splice(i, 1);
score++;
LK.setScore(score);
// Animate character a bit
tween(character, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 120,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(character, {
scaleX: 1,
scaleY: 1
}, {
duration: 120
});
}
});
// Reset character to center after short delay
isFlying = false;
LK.setTimeout(function () {
character.x = SLING_CENTER_X;
character.y = SLING_CENTER_Y;
}, 180);
// Win condition
if (targets.length === 0) {
endGame(false);
}
return;
}
}
// Out of bounds or stopped
if (character.x < -CHARACTER_RADIUS || character.x > GAME_WIDTH + CHARACTER_RADIUS || character.y < -CHARACTER_RADIUS || character.y > GAME_HEIGHT + CHARACTER_RADIUS || Math.abs(velocity.x) < 1 && Math.abs(velocity.y) < 1) {
isFlying = false;
misses++;
missesText.setText('Iska: ' + misses);
// Animate character back to center
tween(character, {
x: SLING_CENTER_X,
y: SLING_CENTER_Y
}, {
duration: 300,
easing: tween.easeOut
});
if (misses > MAX_MISSES) {
endGame(true);
}
}
}
// If not flying and not dragging, always reset to center
if (!isFlying && !isDragging) {
character.x = SLING_CENTER_X;
character.y = SLING_CENTER_Y;
}
};
// --- CLEANUP ON GAME END ---
game.destroy = function () {
LK.clearInterval(timerInterval);
};
// --- GUI POSITIONING ---
// Place timer bar at the far right (en sağda)
timerText.x = LK.gui.top.width - timerText.width / 2 - 20;
shotsText.x = LK.gui.top.width / 2;
missesText.x = 120 + missesText.width / 2; // Place misses bar at top left, leaving 120px margin for menu
;
;