/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bomb class: Fired by the mortar, moves upward, explodes on contact with a note var Bomb = Container.expand(function () { var self = Container.call(this); var bombAsset = self.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 28; // Always positive, direction handled by dirX/dirY self.radius = bombAsset.width * 0.5; self.dirX = 0; self.dirY = -1; self.update = function () { if (typeof self.lastX === "undefined") self.lastX = self.x; if (typeof self.lastY === "undefined") self.lastY = self.y; self.x += self.dirX * self.speed; self.y += self.dirY * self.speed; self.lastX = self.x; self.lastY = self.y; }; return self; }); // Mortar class: Player's cannon, can be dragged horizontally and fires bombs var Mortar = Container.expand(function () { var self = Container.call(this); var mortarAsset = self.attachAsset('mortar', { anchorX: 0.5, anchorY: 1 }); self.width = mortarAsset.width; self.height = mortarAsset.height; // For a little animation on fire self.fireAnim = function () { tween(self, { scaleX: 1.2, scaleY: 0.85 }, { duration: 80, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { scaleX: 1, scaleY: 1 }, { duration: 120, easing: tween.cubicIn }); } }); }; return self; }); // Note class: Descends from the top, must be destroyed before reaching the wall var Note = Container.expand(function () { var self = Container.call(this); var noteAsset = self.attachAsset('note', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 4 + Math.random() * 2; // Slower speed for notes (enemies) self.radius = noteAsset.width * 0.5; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181c2c }); /**** * Game Code ****/ // --- Game constants --- var GAME_W = 2048; var GAME_H = 2732; var WALL_HEIGHT = 420; var MORTAR_Y = GAME_H - WALL_HEIGHT - 40; var NOTE_SPAWN_INTERVAL = 120; // frames (2 seconds at 60FPS) var NOTE_MIN_X = 180; var NOTE_MAX_X = GAME_W - 180; // --- Background image (fullscreen) --- var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, width: GAME_W, height: GAME_H, x: 0, y: 0 }); game.addChild(background); // --- Play Button Overlay --- var playOverlay = new Container(); var playText = new Text2('Play', { size: 220, fill: 0xFFF700 }); playText.anchor.set(0.5, 0.5); playText.x = 0; playText.y = 0; playOverlay.addChild(playText); // Center overlay playOverlay.x = GAME_W / 2; playOverlay.y = GAME_H / 2; // Add overlay to game game.addChild(playOverlay); // Block input until started var gameStarted = false; // Overlay tap handler var gameStartTick = 0; playOverlay.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; playOverlay.visible = false; playOverlay.interactive = false; LK.playMusic('yuksektempolumuzik'); if (typeof LK.ticks !== "undefined") { gameStartTick = LK.ticks; } else { gameStartTick = 0; } } }; playOverlay.interactive = true; // --- Game state --- var bombs = []; var notes = []; var canShoot = true; var dragNode = null; var lastGameOver = false; var noteSpawnTick = 0; var notesPerSpawn = 1; var notesPerSpawnTick = 0; // --- Wall (defense line) --- var wallWidth = GAME_W; var wall = LK.getAsset('wall', { anchorX: 0, anchorY: 0, width: wallWidth, height: WALL_HEIGHT, x: 0, y: GAME_H - WALL_HEIGHT }); game.addChild(wall); // --- Wall health --- var wallHealth = 10; var wallHealthTxt = new Text2('Hp: 10', { size: 100, fill: 0xFF4444 }); wallHealthTxt.anchor.set(1, 0); // right aligned, top LK.gui.topRight.addChild(wallHealthTxt); wallHealthTxt.x = -60; // 60px from the right edge (inside gui.topRight) wallHealthTxt.y = 60; // 60px from the top edge // --- Timer display (below HP, right aligned) --- var timerTxt = new Text2('00:00', { size: 100, fill: 0xFFFFFF }); timerTxt.anchor.set(1, 0); // right aligned, top LK.gui.topRight.addChild(timerTxt); timerTxt.x = -60; // align with HP timerTxt.y = wallHealthTxt.y + wallHealthTxt.height + 10; // 10px below HP // HP bar removed, only wall health number will be shown function updateHpBar() { // No-op, bar removed } updateHpBar(); // --- Mortar (player cannon) --- var mortar = new Mortar(); game.addChild(mortar); mortar.x = GAME_W / 2; mortar.y = MORTAR_Y; // --- Score display --- var scoreTxt = new Text2('0', { size: 120, fill: 0xFFF700 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // (Timer display now handled in top right, below HP) // Helper to format seconds as mm:ss function formatTime(secs) { var m = Math.floor(secs / 60); var s = Math.floor(secs % 60); return (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s; } var lastTimerUpdate = -1; // --- Helper: Clamp mortar movement within screen --- function clampMortarX(x) { var halfW = mortar.width * 0.5; if (x < halfW + 40) return halfW + 40; if (x > GAME_W - halfW - 40) return GAME_W - halfW - 40; return x; } // --- Mortar is fixed: disable dragging --- game.down = function (x, y, obj) { // Do nothing, mortar is fixed }; game.up = function (x, y, obj) { // Do nothing, mortar is fixed }; game.move = function (x, y, obj) { // Do nothing, mortar is fixed }; // --- Tap to fire bomb --- game.tap = function (x, y, obj) { // Only allow firing if game started if (!gameStarted) return; // Only allow firing if tap is above the mortar and not on the wall if (canShoot && y < mortar.y - 60) { lastTapTarget = { x: x, y: y }; fireBomb(); } }; // For mobile, treat 'down' as tap if not dragging game.down = function (origDown) { return function (x, y, obj) { origDown && origDown(x, y, obj); if (!gameStarted) return; if (!dragNode && canShoot && y < mortar.y - 60) { lastTapTarget = { x: x, y: y }; fireBomb(); } }; }(game.down); // --- Fire bomb logic --- // Store the last tap target for bomb direction var lastTapTarget = { x: mortar.x, y: mortar.y - 800 }; function fireBomb() { // Add cooldown: prevent shooting for 0.3 second (300ms) or 0.2s after 20s canShoot = false; var cooldown = 300; if (gameStarted && typeof gameStartTick !== "undefined" && typeof LK.ticks !== "undefined" && LK.ticks - gameStartTick >= 1200) { cooldown = 200; } LK.setTimeout(function () { canShoot = true; }, cooldown); // Fire 1 bomb straight toward the tap/click direction var baseX = mortar.x; var baseY = mortar.y - mortar.height * 0.7; var dx = lastTapTarget.x - baseX; var dy = lastTapTarget.y - baseY; var len = Math.sqrt(dx * dx + dy * dy); if (len === 0) { dx = 0; dy = -1; len = 1; } var angle = Math.atan2(dy, dx); var bomb = new Bomb(); bomb.x = baseX; bomb.y = baseY; bomb.dirX = Math.cos(angle); bomb.dirY = Math.sin(angle); bombs.push(bomb); game.addChild(bomb); mortar.fireAnim(); } // --- Spawn a note at random X --- function spawnNote() { var note = new Note(); note.x = NOTE_MIN_X + Math.random() * (NOTE_MAX_X - NOTE_MIN_X); note.y = -note.height * 0.5; notes.push(note); game.addChild(note); } // --- Main update loop --- game.update = function () { if (!gameStarted) return; // --- Update timer display --- if (typeof gameStartTick !== "undefined" && typeof LK.ticks !== "undefined") { var elapsed = Math.floor((LK.ticks - gameStartTick) / 60); if (elapsed !== lastTimerUpdate) { timerTxt.setText(formatTime(elapsed)); lastTimerUpdate = elapsed; } } // --- Bombs update --- for (var i = bombs.length - 1; i >= 0; i--) { var bomb = bombs[i]; bomb.update(); // Remove if off screen if (bomb.y < -bomb.height) { bomb.destroy(); bombs.splice(i, 1); continue; } // Check collision with notes for (var j = notes.length - 1; j >= 0; j--) { var note = notes[j]; var dx = bomb.x - note.x; var dy = bomb.y - note.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < bomb.radius + note.radius - 10) { // Hit! // Area damage: destroy all notes within explosion radius var explosionRadius = bomb.radius * 2.2; // Area effect radius (tweak as needed) var destroyedCount = 0; for (var m = notes.length - 1; m >= 0; m--) { var otherNote = notes[m]; var dx2 = bomb.x - otherNote.x; var dy2 = bomb.y - otherNote.y; var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2); if (dist2 < explosionRadius + otherNote.radius - 10) { otherNote.destroy(); notes.splice(m, 1); destroyedCount++; } } bomb.destroy(); bombs.splice(i, 1); // Score up for each destroyed note LK.setScore(LK.getScore() + destroyedCount); scoreTxt.setText(LK.getScore()); // Small explosion effect LK.effects.flashObject(mortar, 0xfff700, 200); // Optional: flash screen for area hit LK.effects.flashScreen(0xfff700, 120); break; } } } // --- Notes update --- for (var k = notes.length - 1; k >= 0; k--) { var note = notes[k]; note.update(); // If note hits the wall, decrease wall health and update display if (note.y + note.radius > wall.y) { note.destroy(); notes.splice(k, 1); wallHealth--; if (wallHealth < 0) wallHealth = 0; wallHealthTxt.setText('Hp: ' + wallHealth); // Optional: flash wall on hit LK.effects.flashObject(wall, 0xff4444, 200); // Game over if wall health reaches 0 if (wallHealth === 0 && !lastGameOver) { lastGameOver = true; LK.showGameOver(); } continue; } // Remove if off screen (shouldn't happen) if (note.y > GAME_H + note.height) { note.destroy(); notes.splice(k, 1); } } // --- Spawn notes at interval --- noteSpawnTick++; notesPerSpawnTick++; if (noteSpawnTick >= NOTE_SPAWN_INTERVAL) { for (var n = 0; n < notesPerSpawn; n++) { spawnNote(); } noteSpawnTick = 0; } // Every 10 seconds (600 frames), increase notesPerSpawn by 1 if (notesPerSpawnTick >= 600) { notesPerSpawn++; notesPerSpawnTick = 0; } }; // --- Reset state on new game --- LK.on('gameStart', function () { // Remove all bombs and notes for (var i = 0; i < bombs.length; i++) bombs[i].destroy(); for (var j = 0; j < notes.length; j++) notes[j].destroy(); bombs = []; notes = []; canShoot = true; lastGameOver = false; noteSpawnTick = 0; notesPerSpawn = 1; notesPerSpawnTick = 0; LK.setScore(0); scoreTxt.setText('0'); mortar.x = GAME_W / 2; wallHealth = 10; wallHealthTxt.setText('Hp: ' + wallHealth); // Show Play overlay again gameStarted = false; playOverlay.visible = true; playOverlay.interactive = true; gameStartTick = 0; timerTxt.setText('00:00'); lastTimerUpdate = -1; }); // --- Asset initialization (shapes) --- // Mortar: a simple ellipse/circle // Bomb: small dark circle // Note: yellow ellipse (music note) // Wall: wide rectangle /* End of gamecode.js */
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bomb class: Fired by the mortar, moves upward, explodes on contact with a note
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombAsset = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 28; // Always positive, direction handled by dirX/dirY
self.radius = bombAsset.width * 0.5;
self.dirX = 0;
self.dirY = -1;
self.update = function () {
if (typeof self.lastX === "undefined") self.lastX = self.x;
if (typeof self.lastY === "undefined") self.lastY = self.y;
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
// Mortar class: Player's cannon, can be dragged horizontally and fires bombs
var Mortar = Container.expand(function () {
var self = Container.call(this);
var mortarAsset = self.attachAsset('mortar', {
anchorX: 0.5,
anchorY: 1
});
self.width = mortarAsset.width;
self.height = mortarAsset.height;
// For a little animation on fire
self.fireAnim = function () {
tween(self, {
scaleX: 1.2,
scaleY: 0.85
}, {
duration: 80,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 120,
easing: tween.cubicIn
});
}
});
};
return self;
});
// Note class: Descends from the top, must be destroyed before reaching the wall
var Note = Container.expand(function () {
var self = Container.call(this);
var noteAsset = self.attachAsset('note', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 2; // Slower speed for notes (enemies)
self.radius = noteAsset.width * 0.5;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181c2c
});
/****
* Game Code
****/
// --- Game constants ---
var GAME_W = 2048;
var GAME_H = 2732;
var WALL_HEIGHT = 420;
var MORTAR_Y = GAME_H - WALL_HEIGHT - 40;
var NOTE_SPAWN_INTERVAL = 120; // frames (2 seconds at 60FPS)
var NOTE_MIN_X = 180;
var NOTE_MAX_X = GAME_W - 180;
// --- Background image (fullscreen) ---
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
width: GAME_W,
height: GAME_H,
x: 0,
y: 0
});
game.addChild(background);
// --- Play Button Overlay ---
var playOverlay = new Container();
var playText = new Text2('Play', {
size: 220,
fill: 0xFFF700
});
playText.anchor.set(0.5, 0.5);
playText.x = 0;
playText.y = 0;
playOverlay.addChild(playText);
// Center overlay
playOverlay.x = GAME_W / 2;
playOverlay.y = GAME_H / 2;
// Add overlay to game
game.addChild(playOverlay);
// Block input until started
var gameStarted = false;
// Overlay tap handler
var gameStartTick = 0;
playOverlay.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
playOverlay.visible = false;
playOverlay.interactive = false;
LK.playMusic('yuksektempolumuzik');
if (typeof LK.ticks !== "undefined") {
gameStartTick = LK.ticks;
} else {
gameStartTick = 0;
}
}
};
playOverlay.interactive = true;
// --- Game state ---
var bombs = [];
var notes = [];
var canShoot = true;
var dragNode = null;
var lastGameOver = false;
var noteSpawnTick = 0;
var notesPerSpawn = 1;
var notesPerSpawnTick = 0;
// --- Wall (defense line) ---
var wallWidth = GAME_W;
var wall = LK.getAsset('wall', {
anchorX: 0,
anchorY: 0,
width: wallWidth,
height: WALL_HEIGHT,
x: 0,
y: GAME_H - WALL_HEIGHT
});
game.addChild(wall);
// --- Wall health ---
var wallHealth = 10;
var wallHealthTxt = new Text2('Hp: 10', {
size: 100,
fill: 0xFF4444
});
wallHealthTxt.anchor.set(1, 0); // right aligned, top
LK.gui.topRight.addChild(wallHealthTxt);
wallHealthTxt.x = -60; // 60px from the right edge (inside gui.topRight)
wallHealthTxt.y = 60; // 60px from the top edge
// --- Timer display (below HP, right aligned) ---
var timerTxt = new Text2('00:00', {
size: 100,
fill: 0xFFFFFF
});
timerTxt.anchor.set(1, 0); // right aligned, top
LK.gui.topRight.addChild(timerTxt);
timerTxt.x = -60; // align with HP
timerTxt.y = wallHealthTxt.y + wallHealthTxt.height + 10; // 10px below HP
// HP bar removed, only wall health number will be shown
function updateHpBar() {
// No-op, bar removed
}
updateHpBar();
// --- Mortar (player cannon) ---
var mortar = new Mortar();
game.addChild(mortar);
mortar.x = GAME_W / 2;
mortar.y = MORTAR_Y;
// --- Score display ---
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFF700
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// (Timer display now handled in top right, below HP)
// Helper to format seconds as mm:ss
function formatTime(secs) {
var m = Math.floor(secs / 60);
var s = Math.floor(secs % 60);
return (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s;
}
var lastTimerUpdate = -1;
// --- Helper: Clamp mortar movement within screen ---
function clampMortarX(x) {
var halfW = mortar.width * 0.5;
if (x < halfW + 40) return halfW + 40;
if (x > GAME_W - halfW - 40) return GAME_W - halfW - 40;
return x;
}
// --- Mortar is fixed: disable dragging ---
game.down = function (x, y, obj) {
// Do nothing, mortar is fixed
};
game.up = function (x, y, obj) {
// Do nothing, mortar is fixed
};
game.move = function (x, y, obj) {
// Do nothing, mortar is fixed
};
// --- Tap to fire bomb ---
game.tap = function (x, y, obj) {
// Only allow firing if game started
if (!gameStarted) return;
// Only allow firing if tap is above the mortar and not on the wall
if (canShoot && y < mortar.y - 60) {
lastTapTarget = {
x: x,
y: y
};
fireBomb();
}
};
// For mobile, treat 'down' as tap if not dragging
game.down = function (origDown) {
return function (x, y, obj) {
origDown && origDown(x, y, obj);
if (!gameStarted) return;
if (!dragNode && canShoot && y < mortar.y - 60) {
lastTapTarget = {
x: x,
y: y
};
fireBomb();
}
};
}(game.down);
// --- Fire bomb logic ---
// Store the last tap target for bomb direction
var lastTapTarget = {
x: mortar.x,
y: mortar.y - 800
};
function fireBomb() {
// Add cooldown: prevent shooting for 0.3 second (300ms) or 0.2s after 20s
canShoot = false;
var cooldown = 300;
if (gameStarted && typeof gameStartTick !== "undefined" && typeof LK.ticks !== "undefined" && LK.ticks - gameStartTick >= 1200) {
cooldown = 200;
}
LK.setTimeout(function () {
canShoot = true;
}, cooldown);
// Fire 1 bomb straight toward the tap/click direction
var baseX = mortar.x;
var baseY = mortar.y - mortar.height * 0.7;
var dx = lastTapTarget.x - baseX;
var dy = lastTapTarget.y - baseY;
var len = Math.sqrt(dx * dx + dy * dy);
if (len === 0) {
dx = 0;
dy = -1;
len = 1;
}
var angle = Math.atan2(dy, dx);
var bomb = new Bomb();
bomb.x = baseX;
bomb.y = baseY;
bomb.dirX = Math.cos(angle);
bomb.dirY = Math.sin(angle);
bombs.push(bomb);
game.addChild(bomb);
mortar.fireAnim();
}
// --- Spawn a note at random X ---
function spawnNote() {
var note = new Note();
note.x = NOTE_MIN_X + Math.random() * (NOTE_MAX_X - NOTE_MIN_X);
note.y = -note.height * 0.5;
notes.push(note);
game.addChild(note);
}
// --- Main update loop ---
game.update = function () {
if (!gameStarted) return;
// --- Update timer display ---
if (typeof gameStartTick !== "undefined" && typeof LK.ticks !== "undefined") {
var elapsed = Math.floor((LK.ticks - gameStartTick) / 60);
if (elapsed !== lastTimerUpdate) {
timerTxt.setText(formatTime(elapsed));
lastTimerUpdate = elapsed;
}
}
// --- Bombs update ---
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
bomb.update();
// Remove if off screen
if (bomb.y < -bomb.height) {
bomb.destroy();
bombs.splice(i, 1);
continue;
}
// Check collision with notes
for (var j = notes.length - 1; j >= 0; j--) {
var note = notes[j];
var dx = bomb.x - note.x;
var dy = bomb.y - note.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < bomb.radius + note.radius - 10) {
// Hit!
// Area damage: destroy all notes within explosion radius
var explosionRadius = bomb.radius * 2.2; // Area effect radius (tweak as needed)
var destroyedCount = 0;
for (var m = notes.length - 1; m >= 0; m--) {
var otherNote = notes[m];
var dx2 = bomb.x - otherNote.x;
var dy2 = bomb.y - otherNote.y;
var dist2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
if (dist2 < explosionRadius + otherNote.radius - 10) {
otherNote.destroy();
notes.splice(m, 1);
destroyedCount++;
}
}
bomb.destroy();
bombs.splice(i, 1);
// Score up for each destroyed note
LK.setScore(LK.getScore() + destroyedCount);
scoreTxt.setText(LK.getScore());
// Small explosion effect
LK.effects.flashObject(mortar, 0xfff700, 200);
// Optional: flash screen for area hit
LK.effects.flashScreen(0xfff700, 120);
break;
}
}
}
// --- Notes update ---
for (var k = notes.length - 1; k >= 0; k--) {
var note = notes[k];
note.update();
// If note hits the wall, decrease wall health and update display
if (note.y + note.radius > wall.y) {
note.destroy();
notes.splice(k, 1);
wallHealth--;
if (wallHealth < 0) wallHealth = 0;
wallHealthTxt.setText('Hp: ' + wallHealth);
// Optional: flash wall on hit
LK.effects.flashObject(wall, 0xff4444, 200);
// Game over if wall health reaches 0
if (wallHealth === 0 && !lastGameOver) {
lastGameOver = true;
LK.showGameOver();
}
continue;
}
// Remove if off screen (shouldn't happen)
if (note.y > GAME_H + note.height) {
note.destroy();
notes.splice(k, 1);
}
}
// --- Spawn notes at interval ---
noteSpawnTick++;
notesPerSpawnTick++;
if (noteSpawnTick >= NOTE_SPAWN_INTERVAL) {
for (var n = 0; n < notesPerSpawn; n++) {
spawnNote();
}
noteSpawnTick = 0;
}
// Every 10 seconds (600 frames), increase notesPerSpawn by 1
if (notesPerSpawnTick >= 600) {
notesPerSpawn++;
notesPerSpawnTick = 0;
}
};
// --- Reset state on new game ---
LK.on('gameStart', function () {
// Remove all bombs and notes
for (var i = 0; i < bombs.length; i++) bombs[i].destroy();
for (var j = 0; j < notes.length; j++) notes[j].destroy();
bombs = [];
notes = [];
canShoot = true;
lastGameOver = false;
noteSpawnTick = 0;
notesPerSpawn = 1;
notesPerSpawnTick = 0;
LK.setScore(0);
scoreTxt.setText('0');
mortar.x = GAME_W / 2;
wallHealth = 10;
wallHealthTxt.setText('Hp: ' + wallHealth);
// Show Play overlay again
gameStarted = false;
playOverlay.visible = true;
playOverlay.interactive = true;
gameStartTick = 0;
timerTxt.setText('00:00');
lastTimerUpdate = -1;
});
// --- Asset initialization (shapes) ---
// Mortar: a simple ellipse/circle
// Bomb: small dark circle
// Note: yellow ellipse (music note)
// Wall: wide rectangle
/* End of gamecode.js */
bu duvar geniş olsun
müzik notası olsun gözü ve keskin dişleri olsun. In-Game asset. 2d. High contrast. No shadows
gitar teli. In-Game asset. 2d. High contrast. No shadows
oyun background olacak.tam ekran olsun.bir konser sahnesine bakan koltuk bakış açısında olsun. In-Game asset. 2d. High contrast. No shadows
yüksek çözünürlüklü topdown bakış açısı makineli tüfek olsun. In-Game asset. 2d. High contrast. No shadows