Code edit (9 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
yanlış font seçmişsin. celebration messages fontu ile aynı olsun rüzgar yçönü tekrar dene ve gol sayacı
User prompt
tekrar dene yazısı pixelart bir tarzda olsun rüzgar yönü yazısı ve gol sayacı da pixelart bir tarzda fontla yazılsın
User prompt
tekrar dene butonu 300x300 olsun
User prompt
retryimage yerine startbutton çıkıyor düzelt. ayrıca bir tekar dene değil TEKRAR DENE! yazsın. shadow u olsun yazının pixelart bir fontta olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
asla game over verme. bir tekrar dene yazııs çıkar ve altına bir resim koy. resme tıkalyınca yeniden başlasın oyun menüye dönmeden. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
oyuncuların topla kesişecek şekilde spawn olmasına engel oş
User prompt
çok hızlı dönüyor yavaşlat biraz ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
top yavaşça dönsün hareket halindeyken ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yaızlar iki satırdan oluşsun -volleytics kısmı da 3. satırda sağa yaslı olsun. daha pixeart görünen bri fontla yaz. ayrıca shadow koy ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
image gelmesin sadece rastgele mesajlar gelsina nimasyonlu şekilde ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yaızlar celebretion image ile birlikte önünd egelsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AimArrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 1
});
self.visible = false;
self.updateArrow = function (startX, startY, endX, endY) {
var deltaX = endX - startX;
var deltaY = endY - startY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var angle = Math.atan2(deltaY, deltaX) + Math.PI / 2;
self.x = startX;
self.y = startY;
self.rotation = angle;
self.scaleY = Math.min(distance / 40, 5);
self.visible = true;
};
return self;
});
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
self.windResistance = 0.98;
self.update = function () {
// Calculate ball scale based on Y position
var fieldTop = 400;
var fieldBottom = 2732;
var minScale = 1.2; // Smallest scale at top
var maxScale = 2.5; // Largest scale at bottom
var fieldProgress = (self.y - fieldTop) / (fieldBottom - fieldTop);
fieldProgress = Math.max(0, Math.min(1, fieldProgress));
var targetScale = minScale + (maxScale - minScale) * fieldProgress;
// Apply smooth scaling with tween
if (self.lastScale === undefined) {
self.lastScale = targetScale;
}
if (Math.abs(targetScale - self.lastScale) > 0.05) {
tween(self, {
scaleX: targetScale,
scaleY: targetScale
}, {
duration: 100
});
self.lastScale = targetScale;
}
if (self.isMoving) {
// Apply wind effect with moderate influence
self.velocityX += windX * 0.1;
self.velocityY += windY * 0.1;
// Apply movement
self.x += self.velocityX;
self.y += self.velocityY;
// Apply less friction for smoother movement
self.velocityX *= 0.995;
self.velocityY *= 0.995;
// Stop if velocity is very low
if (Math.abs(self.velocityX) < 0.3 && Math.abs(self.velocityY) < 0.3) {
self.isMoving = false;
self.velocityX = 0;
self.velocityY = 0;
checkRoundEnd();
}
// Check boundaries and bounce off walls - trapezoidal field
// Calculate field width at current Y position for trapezoid shape
var fieldTop = 400;
var fieldBottom = 2732; // Full screen height at bottom
var fieldTopWidth = 1200; // Narrower at top
var fieldBottomWidth = 2048; // Full width at bottom
var fieldProgress = (self.y - fieldTop) / (fieldBottom - fieldTop);
fieldProgress = Math.max(0, Math.min(1, fieldProgress));
var currentFieldWidth = fieldTopWidth + (fieldBottomWidth - fieldTopWidth) * fieldProgress;
var leftBoundary = (2048 - currentFieldWidth) / 2;
var rightBoundary = leftBoundary + currentFieldWidth;
// Left wall bounce
if (self.x < leftBoundary) {
self.x = leftBoundary;
self.velocityX = -self.velocityX * 0.8; // Bounce with some energy loss
}
// Right wall bounce
if (self.x > rightBoundary) {
self.x = rightBoundary;
self.velocityX = -self.velocityX * 0.8; // Bounce with some energy loss
}
// Top wall - game over
if (self.y < fieldTop) {
LK.getSound('blocked').play();
self.isMoving = false;
checkRoundEnd();
}
// Banner collision - prevent ball from passing through banner area
var bannerTop = 2612; // Banner y position (2672) minus half banner height (60)
if (self.y > bannerTop) {
self.y = bannerTop;
self.velocityY = -self.velocityY * 0.8; // Bounce with some energy loss
}
// Bottom wall bounce
if (self.y > fieldBottom) {
self.y = fieldBottom;
self.velocityY = -self.velocityY * 0.8; // Bounce with some energy loss
}
}
};
self.shoot = function (targetX, targetY, power) {
var deltaX = targetX - self.x;
var deltaY = targetY - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
self.velocityX = deltaX / distance * power * 1.5;
self.velocityY = deltaY / distance * power * 1.5;
self.isMoving = true;
LK.getSound('kick').play();
}
};
return self;
});
var Defender = Container.expand(function () {
var self = Container.call(this);
var defenderGraphics = self.attachAsset('defender', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game over customization is handled automatically by LK.showGameOver()
// The engine does not provide APIs to customize game over text or add custom links
// Current implementation correctly uses LK.showGameOver() which handles all game over UX
// Array of random celebration messages
var celebrationMessages = ["Güzel şuttu. Takımını yönetmeye ne dersin? – volleytics", "Şutunu çektin, şimdi sahayı yönet! – volleytics", "Vaay, antrenman şimdi başlıyor. – volleytics", "Gol senin, yönetim bizim işimiz. – volleytics", "İyi oynuyorsun. Peki takımın geri kalanı? – volleytics", "Spor sahada başlar, volleytics'te tamamlanır.", "Şut çekmesi kolay, ya spor okulu yönetmek? – volleytics"];
var ball;
var defenders = [];
var goal;
var aimArrow;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
var windX = 0;
var windY = 0;
var windIndicator;
var roundNumber = 1;
var gameState = 'menu'; // 'menu', 'aiming', 'shooting', 'roundEnd'
var menuContainer;
var startButton;
// Create field - full width at bottom, narrowing toward top
var field = game.addChild(LK.getAsset('field', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 400,
width: 2048,
height: 2332
}));
// Create field boundary lines for trapezoidal shape
var fieldLines = [];
// Left boundary line - angled using rotation
var leftLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0,
x: 424,
// Left edge at top
y: 400,
width: 4,
height: 2332
}));
leftLine.rotation = 0.19; // Angle for trapezoid shape
fieldLines.push(leftLine);
// Right boundary line - angled using rotation
var rightLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0,
x: 1624,
// Right edge at top
y: 400,
width: 4,
height: 2332
}));
rightLine.rotation = -0.19; // Angle for trapezoid shape
fieldLines.push(rightLine);
// Top boundary line
var topLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0,
anchorY: 0.5,
x: 424,
y: 400,
width: 1200,
height: 4
}));
fieldLines.push(topLine);
// Bottom boundary line
var bottomLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 2732,
width: 2048,
height: 4
}));
fieldLines.push(bottomLine);
// Create goal at top center - half extending above field
goal = game.addChild(LK.getAsset('goal', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: 300
}));
// Create UI elements
var scoreTxt = new Text2('Gol: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false; // Hide in menu initially
LK.gui.top.addChild(scoreTxt);
var windTxt = new Text2('Rüzgar Yönü: →', {
size: 60,
fill: 0x00FFFF
});
windTxt.anchor.set(0, 0);
windTxt.x = 100;
windTxt.y = 100;
windTxt.visible = false; // Hide in menu initially
LK.gui.topLeft.addChild(windTxt);
// Create aim arrow
aimArrow = game.addChild(new AimArrow());
function spawnBall() {
if (ball) {
ball.destroy();
}
ball = game.addChild(new Ball());
// Spawn ball in bottom half of trapezoidal field, but above banner
ball.x = 400 + Math.random() * 1248;
ball.y = 2000 + Math.random() * 612; // Reduced from 732 to 612 to stay above banner (2612)
// Set initial scale based on spawn position
var fieldTop = 400;
var fieldBottom = 2732;
var minScale = 1.2;
var maxScale = 2.5;
var fieldProgress = (ball.y - fieldTop) / (fieldBottom - fieldTop);
fieldProgress = Math.max(0, Math.min(1, fieldProgress));
var initialScale = minScale + (maxScale - minScale) * fieldProgress;
ball.scaleX = initialScale;
ball.scaleY = initialScale;
ball.lastScale = initialScale;
}
function spawnDefenders() {
// Clear existing defenders
for (var i = 0; i < defenders.length; i++) {
defenders[i].destroy();
}
defenders = [];
// Spawn defenders based on round number
var defenderCount = Math.min(2 + Math.floor(roundNumber / 2), 6);
for (var i = 0; i < defenderCount; i++) {
var defender = game.addChild(new Defender());
var validPosition = false;
var attempts = 0;
var maxAttempts = 50;
// Keep trying to find a valid position at least 50 pixels from ball
while (!validPosition && attempts < maxAttempts) {
// Spawn defenders within trapezoidal field bounds
var spawnY = 500 + Math.random() * 1900;
var fieldProgress = (spawnY - 400) / 2332;
var fieldWidthAtY = 1200 + 848 * fieldProgress;
var leftBound = (2048 - fieldWidthAtY) / 2;
var spawnX = leftBound + Math.random() * fieldWidthAtY;
// Check distance from ball
if (ball) {
var distanceFromBall = Math.sqrt((spawnX - ball.x) * (spawnX - ball.x) + (spawnY - ball.y) * (spawnY - ball.y));
if (distanceFromBall >= 50) {
validPosition = true;
defender.x = spawnX;
defender.y = spawnY;
}
} else {
// If no ball exists, accept any position
validPosition = true;
defender.x = spawnX;
defender.y = spawnY;
}
attempts++;
}
// If we couldn't find a valid position after max attempts, use the last generated position
if (!validPosition) {
var spawnY = 500 + Math.random() * 1900;
var fieldProgress = (spawnY - 400) / 2332;
var fieldWidthAtY = 1200 + 848 * fieldProgress;
var leftBound = (2048 - fieldWidthAtY) / 2;
defender.x = leftBound + Math.random() * fieldWidthAtY;
defender.y = spawnY;
}
defenders.push(defender);
}
}
function generateWind() {
var windStrength = 0.4 + roundNumber * 0.05;
var windAngle = Math.random() * Math.PI * 2;
windX = Math.cos(windAngle) * windStrength;
windY = Math.sin(windAngle) * windStrength;
// Update wind indicator
var windDirection = '';
if (Math.abs(windX) > Math.abs(windY)) {
windDirection = windX > 0 ? '→' : '←';
} else {
windDirection = windY > 0 ? '↓' : '↑';
}
windTxt.setText('Rüzgar Yönü: ' + windDirection);
}
function checkCollisions() {
if (!ball || !ball.isMoving) {
return;
}
// Check defender collisions
for (var i = 0; i < defenders.length; i++) {
if (ball.intersects(defenders[i])) {
ball.isMoving = false;
LK.getSound('blocked').play();
LK.effects.flashScreen(0xff0000, 500);
// Wait for blocked sound to finish before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
// Check goal collision
if (ball.intersects(goal) && ball.y < goal.y + 200) {
ball.isMoving = false;
LK.getSound('goal').play();
LK.effects.flashScreen(0x00ff00, 500);
// Create sliding celebration message
var celebrationMsg = game.addChild(LK.getAsset('celebrationMessage', {
anchorX: 0.5,
anchorY: 0.5,
x: -400,
// Start off-screen left
y: 1366 // Center of screen vertically
}));
// Add random text overlay on celebration message
var randomMessage = celebrationMessages[Math.floor(Math.random() * celebrationMessages.length)];
var celebrationText = new Text2(randomMessage, {
size: 80,
fill: 0x000000,
font: "Kanit"
});
celebrationText.anchor.set(0.5, 0.5);
celebrationText.x = 0; // Relative to celebrationMsg
celebrationText.y = 0; // Relative to celebrationMsg
celebrationMsg.addChild(celebrationText);
// Slide in from left to center - text moves with the image automatically since it's a child
tween(celebrationMsg, {
x: 1024
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Wait a moment, then slide out to the right
LK.setTimeout(function () {
tween(celebrationMsg, {
x: 2448
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
celebrationMsg.destroy();
}
});
}, 1500);
}
});
// Increment goal count
var currentText = scoreTxt.text || 'Gol: 0';
var goalCount = 1;
if (currentText && currentText.indexOf(': ') !== -1) {
goalCount = parseInt(currentText.split(': ')[1]) + 1;
}
scoreTxt.setText('Gol: ' + goalCount);
// Check win condition
if (goalCount >= 10) {
LK.showYouWin();
} else {
// Next round
roundNumber++;
// Delay starting new round to allow celebration message to complete
LK.setTimeout(function () {
startNewRound();
}, 3100);
}
}
}
function checkRoundEnd() {
if (gameState === 'shooting' && ball && !ball.isMoving) {
// Ball stopped without scoring
LK.getSound('blocked').play();
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
function startNewRound() {
gameState = 'aiming';
spawnBall();
spawnDefenders();
generateWind();
windTxt.visible = true; // Show wind indicator when game starts
scoreTxt.visible = true; // Show score when game starts
aimArrow.visible = false;
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState === 'menu' && startButton) {
var buttonPos = game.toLocal(startButton.parent.toGlobal(startButton.position));
var distance = Math.sqrt((x - buttonPos.x) * (x - buttonPos.x) + (y - buttonPos.y) * (y - buttonPos.y));
if (distance < 200) {
LK.getSound('kick').play();
gameState = 'aiming';
hideMenu();
startNewRound();
}
} else if (gameState === 'aiming' && ball) {
var ballPos = game.toLocal(ball.parent.toGlobal(ball.position));
var distance = Math.sqrt((x - ballPos.x) * (x - ballPos.x) + (y - ballPos.y) * (y - ballPos.y));
if (distance < 60) {
isDragging = true;
dragStartX = x;
dragStartY = y;
}
}
};
game.move = function (x, y, obj) {
if (gameState === 'aiming' && isDragging && ball) {
aimArrow.updateArrow(ball.x, ball.y, x, y);
}
};
game.up = function (x, y, obj) {
if (gameState === 'aiming' && isDragging && ball) {
var distance = Math.sqrt((x - ball.x) * (x - ball.x) + (y - ball.y) * (y - ball.y));
var power = Math.min(distance / 3, 20);
ball.shoot(x, y, power);
gameState = 'shooting';
aimArrow.visible = false;
isDragging = false;
}
};
game.update = function () {
checkCollisions();
};
// Create banner at bottom of screen
var banner = new Container();
game.addChild(banner);
// Position banner at very bottom center
banner.x = 1024;
banner.y = 2672; // Move to very bottom (2732 - 60 for half banner height)
// Create banner background
var bannerBg = LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 120
});
bannerBg.tint = 0x333333;
banner.addChild(bannerBg);
// Create main text
var bannerText1 = new Text2('Gerçek Hayatta spora devam etmek için:', {
size: 50,
fill: 0xFFFFFF
});
bannerText1.anchor.set(0.5, 0.5);
bannerText1.y = -25;
banner.addChild(bannerText1);
// Create link text (no longer clickable)
var bannerText2 = new Text2('volleytics.com', {
size: 55,
fill: 0xb63147
});
bannerText2.anchor.set(0.5, 0.5);
bannerText2.y = 30;
banner.addChild(bannerText2);
function createMenu() {
menuContainer = new Container();
game.addChild(menuContainer);
// Menu background
var menuBg = menuContainer.attachAsset('menuBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Game title image in upper half of menu
var titleImage = menuContainer.attachAsset('titleImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800,
width: 600,
height: 600
});
// Start button
startButton = menuContainer.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500,
width: 800,
height: 400
});
// Title text shadow
var titleShadow = new Text2('Volleytics ile sporun verimli olsun', {
size: 120,
fill: 0x000000,
font: "Kanit"
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1027;
titleShadow.y = 2403;
menuContainer.addChild(titleShadow);
// Title text
var titleText = new Text2('Volleytics ile sporun verimli olsun', {
size: 120,
fill: 0xFFFFFF,
font: "Kanit"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 2400;
menuContainer.addChild(titleText);
// Link text shadow
var linkShadow = new Text2('volleytics.com', {
size: 90,
fill: 0x000000,
font: "Kanit"
});
linkShadow.anchor.set(0.5, 0.5);
linkShadow.x = 1027;
linkShadow.y = 2553;
menuContainer.addChild(linkShadow);
// Link text
var linkText = new Text2('volleytics.com', {
size: 90,
fill: 0xb63147,
font: "Kanit"
});
linkText.anchor.set(0.5, 0.5);
linkText.x = 1024;
linkText.y = 2550;
menuContainer.addChild(linkText);
}
function hideMenu() {
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
startButton = null;
}
scoreTxt.visible = true; // Show score when leaving menu
}
// Initialize menu
createMenu(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AimArrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 1
});
self.visible = false;
self.updateArrow = function (startX, startY, endX, endY) {
var deltaX = endX - startX;
var deltaY = endY - startY;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
var angle = Math.atan2(deltaY, deltaX) + Math.PI / 2;
self.x = startX;
self.y = startY;
self.rotation = angle;
self.scaleY = Math.min(distance / 40, 5);
self.visible = true;
};
return self;
});
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballGraphics = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.isMoving = false;
self.windResistance = 0.98;
self.update = function () {
// Calculate ball scale based on Y position
var fieldTop = 400;
var fieldBottom = 2732;
var minScale = 1.2; // Smallest scale at top
var maxScale = 2.5; // Largest scale at bottom
var fieldProgress = (self.y - fieldTop) / (fieldBottom - fieldTop);
fieldProgress = Math.max(0, Math.min(1, fieldProgress));
var targetScale = minScale + (maxScale - minScale) * fieldProgress;
// Apply smooth scaling with tween
if (self.lastScale === undefined) {
self.lastScale = targetScale;
}
if (Math.abs(targetScale - self.lastScale) > 0.05) {
tween(self, {
scaleX: targetScale,
scaleY: targetScale
}, {
duration: 100
});
self.lastScale = targetScale;
}
if (self.isMoving) {
// Apply wind effect with moderate influence
self.velocityX += windX * 0.1;
self.velocityY += windY * 0.1;
// Apply movement
self.x += self.velocityX;
self.y += self.velocityY;
// Apply less friction for smoother movement
self.velocityX *= 0.995;
self.velocityY *= 0.995;
// Stop if velocity is very low
if (Math.abs(self.velocityX) < 0.3 && Math.abs(self.velocityY) < 0.3) {
self.isMoving = false;
self.velocityX = 0;
self.velocityY = 0;
checkRoundEnd();
}
// Check boundaries and bounce off walls - trapezoidal field
// Calculate field width at current Y position for trapezoid shape
var fieldTop = 400;
var fieldBottom = 2732; // Full screen height at bottom
var fieldTopWidth = 1200; // Narrower at top
var fieldBottomWidth = 2048; // Full width at bottom
var fieldProgress = (self.y - fieldTop) / (fieldBottom - fieldTop);
fieldProgress = Math.max(0, Math.min(1, fieldProgress));
var currentFieldWidth = fieldTopWidth + (fieldBottomWidth - fieldTopWidth) * fieldProgress;
var leftBoundary = (2048 - currentFieldWidth) / 2;
var rightBoundary = leftBoundary + currentFieldWidth;
// Left wall bounce
if (self.x < leftBoundary) {
self.x = leftBoundary;
self.velocityX = -self.velocityX * 0.8; // Bounce with some energy loss
}
// Right wall bounce
if (self.x > rightBoundary) {
self.x = rightBoundary;
self.velocityX = -self.velocityX * 0.8; // Bounce with some energy loss
}
// Top wall - game over
if (self.y < fieldTop) {
LK.getSound('blocked').play();
self.isMoving = false;
checkRoundEnd();
}
// Banner collision - prevent ball from passing through banner area
var bannerTop = 2612; // Banner y position (2672) minus half banner height (60)
if (self.y > bannerTop) {
self.y = bannerTop;
self.velocityY = -self.velocityY * 0.8; // Bounce with some energy loss
}
// Bottom wall bounce
if (self.y > fieldBottom) {
self.y = fieldBottom;
self.velocityY = -self.velocityY * 0.8; // Bounce with some energy loss
}
}
};
self.shoot = function (targetX, targetY, power) {
var deltaX = targetX - self.x;
var deltaY = targetY - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 0) {
self.velocityX = deltaX / distance * power * 1.5;
self.velocityY = deltaY / distance * power * 1.5;
self.isMoving = true;
LK.getSound('kick').play();
}
};
return self;
});
var Defender = Container.expand(function () {
var self = Container.call(this);
var defenderGraphics = self.attachAsset('defender', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game over customization is handled automatically by LK.showGameOver()
// The engine does not provide APIs to customize game over text or add custom links
// Current implementation correctly uses LK.showGameOver() which handles all game over UX
// Array of random celebration messages
var celebrationMessages = ["Güzel şuttu. Takımını yönetmeye ne dersin? – volleytics", "Şutunu çektin, şimdi sahayı yönet! – volleytics", "Vaay, antrenman şimdi başlıyor. – volleytics", "Gol senin, yönetim bizim işimiz. – volleytics", "İyi oynuyorsun. Peki takımın geri kalanı? – volleytics", "Spor sahada başlar, volleytics'te tamamlanır.", "Şut çekmesi kolay, ya spor okulu yönetmek? – volleytics"];
var ball;
var defenders = [];
var goal;
var aimArrow;
var isDragging = false;
var dragStartX = 0;
var dragStartY = 0;
var windX = 0;
var windY = 0;
var windIndicator;
var roundNumber = 1;
var gameState = 'menu'; // 'menu', 'aiming', 'shooting', 'roundEnd'
var menuContainer;
var startButton;
// Create field - full width at bottom, narrowing toward top
var field = game.addChild(LK.getAsset('field', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 400,
width: 2048,
height: 2332
}));
// Create field boundary lines for trapezoidal shape
var fieldLines = [];
// Left boundary line - angled using rotation
var leftLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0,
x: 424,
// Left edge at top
y: 400,
width: 4,
height: 2332
}));
leftLine.rotation = 0.19; // Angle for trapezoid shape
fieldLines.push(leftLine);
// Right boundary line - angled using rotation
var rightLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0,
x: 1624,
// Right edge at top
y: 400,
width: 4,
height: 2332
}));
rightLine.rotation = -0.19; // Angle for trapezoid shape
fieldLines.push(rightLine);
// Top boundary line
var topLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0,
anchorY: 0.5,
x: 424,
y: 400,
width: 1200,
height: 4
}));
fieldLines.push(topLine);
// Bottom boundary line
var bottomLine = game.addChild(LK.getAsset('fieldLine', {
anchorX: 0,
anchorY: 0.5,
x: 0,
y: 2732,
width: 2048,
height: 4
}));
fieldLines.push(bottomLine);
// Create goal at top center - half extending above field
goal = game.addChild(LK.getAsset('goal', {
anchorX: 0.5,
anchorY: 0,
x: 1024,
y: 300
}));
// Create UI elements
var scoreTxt = new Text2('Gol: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.visible = false; // Hide in menu initially
LK.gui.top.addChild(scoreTxt);
var windTxt = new Text2('Rüzgar Yönü: →', {
size: 60,
fill: 0x00FFFF
});
windTxt.anchor.set(0, 0);
windTxt.x = 100;
windTxt.y = 100;
windTxt.visible = false; // Hide in menu initially
LK.gui.topLeft.addChild(windTxt);
// Create aim arrow
aimArrow = game.addChild(new AimArrow());
function spawnBall() {
if (ball) {
ball.destroy();
}
ball = game.addChild(new Ball());
// Spawn ball in bottom half of trapezoidal field, but above banner
ball.x = 400 + Math.random() * 1248;
ball.y = 2000 + Math.random() * 612; // Reduced from 732 to 612 to stay above banner (2612)
// Set initial scale based on spawn position
var fieldTop = 400;
var fieldBottom = 2732;
var minScale = 1.2;
var maxScale = 2.5;
var fieldProgress = (ball.y - fieldTop) / (fieldBottom - fieldTop);
fieldProgress = Math.max(0, Math.min(1, fieldProgress));
var initialScale = minScale + (maxScale - minScale) * fieldProgress;
ball.scaleX = initialScale;
ball.scaleY = initialScale;
ball.lastScale = initialScale;
}
function spawnDefenders() {
// Clear existing defenders
for (var i = 0; i < defenders.length; i++) {
defenders[i].destroy();
}
defenders = [];
// Spawn defenders based on round number
var defenderCount = Math.min(2 + Math.floor(roundNumber / 2), 6);
for (var i = 0; i < defenderCount; i++) {
var defender = game.addChild(new Defender());
var validPosition = false;
var attempts = 0;
var maxAttempts = 50;
// Keep trying to find a valid position at least 50 pixels from ball
while (!validPosition && attempts < maxAttempts) {
// Spawn defenders within trapezoidal field bounds
var spawnY = 500 + Math.random() * 1900;
var fieldProgress = (spawnY - 400) / 2332;
var fieldWidthAtY = 1200 + 848 * fieldProgress;
var leftBound = (2048 - fieldWidthAtY) / 2;
var spawnX = leftBound + Math.random() * fieldWidthAtY;
// Check distance from ball
if (ball) {
var distanceFromBall = Math.sqrt((spawnX - ball.x) * (spawnX - ball.x) + (spawnY - ball.y) * (spawnY - ball.y));
if (distanceFromBall >= 50) {
validPosition = true;
defender.x = spawnX;
defender.y = spawnY;
}
} else {
// If no ball exists, accept any position
validPosition = true;
defender.x = spawnX;
defender.y = spawnY;
}
attempts++;
}
// If we couldn't find a valid position after max attempts, use the last generated position
if (!validPosition) {
var spawnY = 500 + Math.random() * 1900;
var fieldProgress = (spawnY - 400) / 2332;
var fieldWidthAtY = 1200 + 848 * fieldProgress;
var leftBound = (2048 - fieldWidthAtY) / 2;
defender.x = leftBound + Math.random() * fieldWidthAtY;
defender.y = spawnY;
}
defenders.push(defender);
}
}
function generateWind() {
var windStrength = 0.4 + roundNumber * 0.05;
var windAngle = Math.random() * Math.PI * 2;
windX = Math.cos(windAngle) * windStrength;
windY = Math.sin(windAngle) * windStrength;
// Update wind indicator
var windDirection = '';
if (Math.abs(windX) > Math.abs(windY)) {
windDirection = windX > 0 ? '→' : '←';
} else {
windDirection = windY > 0 ? '↓' : '↑';
}
windTxt.setText('Rüzgar Yönü: ' + windDirection);
}
function checkCollisions() {
if (!ball || !ball.isMoving) {
return;
}
// Check defender collisions
for (var i = 0; i < defenders.length; i++) {
if (ball.intersects(defenders[i])) {
ball.isMoving = false;
LK.getSound('blocked').play();
LK.effects.flashScreen(0xff0000, 500);
// Wait for blocked sound to finish before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
return;
}
}
// Check goal collision
if (ball.intersects(goal) && ball.y < goal.y + 200) {
ball.isMoving = false;
LK.getSound('goal').play();
LK.effects.flashScreen(0x00ff00, 500);
// Create sliding celebration message
var celebrationMsg = game.addChild(LK.getAsset('celebrationMessage', {
anchorX: 0.5,
anchorY: 0.5,
x: -400,
// Start off-screen left
y: 1366 // Center of screen vertically
}));
// Add random text overlay on celebration message
var randomMessage = celebrationMessages[Math.floor(Math.random() * celebrationMessages.length)];
var celebrationText = new Text2(randomMessage, {
size: 80,
fill: 0x000000,
font: "Kanit"
});
celebrationText.anchor.set(0.5, 0.5);
celebrationText.x = 0; // Relative to celebrationMsg
celebrationText.y = 0; // Relative to celebrationMsg
celebrationMsg.addChild(celebrationText);
// Slide in from left to center - text moves with the image automatically since it's a child
tween(celebrationMsg, {
x: 1024
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Wait a moment, then slide out to the right
LK.setTimeout(function () {
tween(celebrationMsg, {
x: 2448
}, {
duration: 800,
easing: tween.easeIn,
onFinish: function onFinish() {
celebrationMsg.destroy();
}
});
}, 1500);
}
});
// Increment goal count
var currentText = scoreTxt.text || 'Gol: 0';
var goalCount = 1;
if (currentText && currentText.indexOf(': ') !== -1) {
goalCount = parseInt(currentText.split(': ')[1]) + 1;
}
scoreTxt.setText('Gol: ' + goalCount);
// Check win condition
if (goalCount >= 10) {
LK.showYouWin();
} else {
// Next round
roundNumber++;
// Delay starting new round to allow celebration message to complete
LK.setTimeout(function () {
startNewRound();
}, 3100);
}
}
}
function checkRoundEnd() {
if (gameState === 'shooting' && ball && !ball.isMoving) {
// Ball stopped without scoring
LK.getSound('blocked').play();
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
function startNewRound() {
gameState = 'aiming';
spawnBall();
spawnDefenders();
generateWind();
windTxt.visible = true; // Show wind indicator when game starts
scoreTxt.visible = true; // Show score when game starts
aimArrow.visible = false;
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState === 'menu' && startButton) {
var buttonPos = game.toLocal(startButton.parent.toGlobal(startButton.position));
var distance = Math.sqrt((x - buttonPos.x) * (x - buttonPos.x) + (y - buttonPos.y) * (y - buttonPos.y));
if (distance < 200) {
LK.getSound('kick').play();
gameState = 'aiming';
hideMenu();
startNewRound();
}
} else if (gameState === 'aiming' && ball) {
var ballPos = game.toLocal(ball.parent.toGlobal(ball.position));
var distance = Math.sqrt((x - ballPos.x) * (x - ballPos.x) + (y - ballPos.y) * (y - ballPos.y));
if (distance < 60) {
isDragging = true;
dragStartX = x;
dragStartY = y;
}
}
};
game.move = function (x, y, obj) {
if (gameState === 'aiming' && isDragging && ball) {
aimArrow.updateArrow(ball.x, ball.y, x, y);
}
};
game.up = function (x, y, obj) {
if (gameState === 'aiming' && isDragging && ball) {
var distance = Math.sqrt((x - ball.x) * (x - ball.x) + (y - ball.y) * (y - ball.y));
var power = Math.min(distance / 3, 20);
ball.shoot(x, y, power);
gameState = 'shooting';
aimArrow.visible = false;
isDragging = false;
}
};
game.update = function () {
checkCollisions();
};
// Create banner at bottom of screen
var banner = new Container();
game.addChild(banner);
// Position banner at very bottom center
banner.x = 1024;
banner.y = 2672; // Move to very bottom (2732 - 60 for half banner height)
// Create banner background
var bannerBg = LK.getAsset('fieldLine', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 120
});
bannerBg.tint = 0x333333;
banner.addChild(bannerBg);
// Create main text
var bannerText1 = new Text2('Gerçek Hayatta spora devam etmek için:', {
size: 50,
fill: 0xFFFFFF
});
bannerText1.anchor.set(0.5, 0.5);
bannerText1.y = -25;
banner.addChild(bannerText1);
// Create link text (no longer clickable)
var bannerText2 = new Text2('volleytics.com', {
size: 55,
fill: 0xb63147
});
bannerText2.anchor.set(0.5, 0.5);
bannerText2.y = 30;
banner.addChild(bannerText2);
function createMenu() {
menuContainer = new Container();
game.addChild(menuContainer);
// Menu background
var menuBg = menuContainer.attachAsset('menuBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
// Game title image in upper half of menu
var titleImage = menuContainer.attachAsset('titleImage', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 800,
width: 600,
height: 600
});
// Start button
startButton = menuContainer.attachAsset('startButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1500,
width: 800,
height: 400
});
// Title text shadow
var titleShadow = new Text2('Volleytics ile sporun verimli olsun', {
size: 120,
fill: 0x000000,
font: "Kanit"
});
titleShadow.anchor.set(0.5, 0.5);
titleShadow.x = 1027;
titleShadow.y = 2403;
menuContainer.addChild(titleShadow);
// Title text
var titleText = new Text2('Volleytics ile sporun verimli olsun', {
size: 120,
fill: 0xFFFFFF,
font: "Kanit"
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 2400;
menuContainer.addChild(titleText);
// Link text shadow
var linkShadow = new Text2('volleytics.com', {
size: 90,
fill: 0x000000,
font: "Kanit"
});
linkShadow.anchor.set(0.5, 0.5);
linkShadow.x = 1027;
linkShadow.y = 2553;
menuContainer.addChild(linkShadow);
// Link text
var linkText = new Text2('volleytics.com', {
size: 90,
fill: 0xb63147,
font: "Kanit"
});
linkText.anchor.set(0.5, 0.5);
linkText.x = 1024;
linkText.y = 2550;
menuContainer.addChild(linkText);
}
function hideMenu() {
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
startButton = null;
}
scoreTxt.visible = true; // Show score when leaving menu
}
// Initialize menu
createMenu();
pixerlart soccer ball. In-Game asset. 2d. High contrast. No shadows
pixelart soccer goal. In-Game asset. 2d. High contrast. No shadows
pixelart grass texture low quality. have soccer field half center circle at bottom. In-Game asset. 2d. High contrast. No shadows
pixelart arrow up. In-Game asset. 2d. High contrast. No shadows
pixelart football shoot scene cinematic. In-Game asset. 2d. High contrast. No shadows
pixelart button. have text in middle "BAŞLA". In-Game asset. 2d. High contrast. No shadows
fancy pixelart title have shadow and white letters. text is "ŞUT ve GOL". In-Game asset. 2d. High contrast. No shadows
pixelart roling arrow button orange color. In-Game asset. 2d. High contrast. No shadows