User prompt
The gun should automatically fire in sync with the speed of the falling notes. The player, using head movements, only needs to aim the crosshair at the notes — no manual shooting is required. ↪💡 Consider importing and using the following plugins: @upit/facekit.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Nota Avcısı: Yüzle Nişan Al!
Initial prompt
*Game Concept:* Notes fall from the top of the screen in multiple columns. A fixed gun is placed at the bottom-left corner. The player controls the aim by moving their head (FaceKit integration), and the crosshair moves accordingly on the screen. When the player taps a note while aiming at it, the note is shot and triggers a musical sound. *Features:* - Multiple falling note columns, each representing different piano notes - Fixed gun in bottom-left corner - Crosshair follows player’s head movement (FaceKit) - Tap a note while aiming to shoot and play the corresponding sound - Notes fall in sync with different music tracks (randomly chosen each round) - Difficulty increases every 10 points by speeding up the notes - Game title includes buttons to select speed: Slow, Normal, Fast - Gameplay hint: “Move your head to aim and tap notes to shoot” displayed on screen Türkçe yap
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
// Ball class: the fixed shooter at bottom left
var Ball = Container.expand(function () {
var self = Container.call(this);
var ballAsset = self.attachAsset('ball', {
anchorX: 0.5,
anchorY: 0.5,
width: BALL_SIZE,
height: BALL_SIZE,
color: 0xffffff,
shape: 'ellipse'
});
return self;
});
// Bullet class: fired from ball towards crosshair
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5,
width: BULLET_SIZE,
height: BULLET_SIZE,
color: 0x00e6e6,
shape: 'ellipse'
});
self.vx = 0;
self.vy = 0;
self.update = function () {
self.x += self.vx;
self.y += self.vy;
};
return self;
});
// Crosshair class: follows facekit position
var Crosshair = Container.expand(function () {
var self = Container.call(this);
var crossAsset = self.attachAsset('crosshair', {
anchorX: 0.5,
anchorY: 0.5,
width: CROSS_SIZE,
height: CROSS_SIZE,
color: 0xff0000,
shape: 'ellipse'
});
return self;
});
// Note class: falling note
var Note = Container.expand(function () {
var self = Container.call(this);
// Randomly pick a color for the note
var color = NOTE_COLORS[Math.floor(Math.random() * NOTE_COLORS.length)];
var noteAsset = self.attachAsset('note', {
anchorX: 0.5,
anchorY: 0.5,
width: NOTE_WIDTH,
height: NOTE_HEIGHT,
color: color,
shape: 'ellipse'
});
self.column = 0; // which column this note is in
self.speed = noteFallSpeed; // will be set on spawn
self.hit = false; // has this note been hit
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181a20
});
/****
* Game Code
****/
// Note: All note assets will be ellipses with different colors for variety
// --- Constants ---
var NOTE_COLORS = [0xffe066, 0x66b3ff, 0xff66a3, 0x7cff66, 0xff8c66];
var GAME_W = 2048;
var GAME_H = 2732;
var BALL_SIZE = 120;
var NOTE_WIDTH = 160;
var NOTE_HEIGHT = 90;
var CROSS_SIZE = 90;
var BULLET_SIZE = 60;
var NOTE_COLS = 5;
var NOTE_MARGIN = 60;
var NOTE_AREA_W = GAME_W - 2 * NOTE_MARGIN;
var NOTE_COL_W = NOTE_AREA_W / NOTE_COLS;
var NOTE_START_Y = -NOTE_HEIGHT;
var BALL_X = 180;
var BALL_Y = GAME_H - 220;
var CROSS_MIN_X = 200;
var CROSS_MAX_X = GAME_W - 200;
var CROSS_MIN_Y = 200;
var CROSS_MAX_Y = GAME_H - 400;
var BULLET_SPEED = 48; // px per frame
// --- Game State ---
var notes = [];
var bullets = [];
var crosshair = null;
var ball = null;
var scoreTxt = null;
var tipTxt = null;
var lastNoteSpawnTick = 0;
var noteFallSpeed = 12; // will be set by difficulty
var noteSpawnInterval = 60; // ticks between notes, will be set by difficulty
var difficulty = null; // 'slow', 'normal', 'fast'
var gameStarted = false;
var canShoot = true;
var lastScore = 0;
var musicTracks = [{
id: 'music1',
name: 'Parça 1'
}, {
id: 'music2',
name: 'Parça 2'
}, {
id: 'music3',
name: 'Parça 3'
}];
var currentMusic = null;
// --- Difficulty Presets ---
var DIFFICULTY_PRESETS = {
'slow': {
noteFallSpeed: 10,
noteSpawnInterval: 80
},
'normal': {
noteFallSpeed: 14,
noteSpawnInterval: 60
},
'fast': {
noteFallSpeed: 20,
noteSpawnInterval: 40
}
};
// --- UI: Difficulty Selection ---
var diffBtns = [];
function showDifficultyMenu() {
var btnLabels = [{
key: 'slow',
label: 'Yavaş'
}, {
key: 'normal',
label: 'Normal'
}, {
key: 'fast',
label: 'Hızlı'
}];
var btnW = 500,
btnH = 180,
btnGap = 60;
var startY = GAME_H / 2 - (btnLabels.length * btnH + (btnLabels.length - 1) * btnGap) / 2;
for (var i = 0; i < btnLabels.length; i++) {
var btn = new Container();
var bg = btn.attachAsset('btnbg', {
anchorX: 0.5,
anchorY: 0.5,
width: btnW,
height: btnH,
color: 0x222a38,
shape: 'box'
});
var txt = new Text2(btnLabels[i].label, {
size: 90,
fill: "#fff"
});
txt.anchor.set(0.5, 0.5);
txt.x = 0;
txt.y = 0;
btn.addChild(txt);
btn.x = GAME_W / 2;
btn.y = startY + i * (btnH + btnGap);
btn.difficulty = btnLabels[i].key;
btn.down = function (x, y, obj) {
startGame(this.difficulty);
};
game.addChild(btn);
diffBtns.push(btn);
}
// Show tip
if (!tipTxt) {
tipTxt = new Text2("Başını hareket ettir, notalara dokun ve ateş et!", {
size: 70,
fill: 0xFFE066
});
tipTxt.anchor.set(0.5, 0);
}
tipTxt.x = GAME_W / 2;
tipTxt.y = 180;
game.addChild(tipTxt);
}
// Remove difficulty menu
function hideDifficultyMenu() {
for (var i = 0; i < diffBtns.length; i++) {
diffBtns[i].destroy();
}
diffBtns = [];
if (tipTxt) {
tipTxt.destroy();
tipTxt = null;
}
}
// --- Start Game ---
function startGame(diffKey) {
difficulty = diffKey;
noteFallSpeed = DIFFICULTY_PRESETS[diffKey].noteFallSpeed;
noteSpawnInterval = DIFFICULTY_PRESETS[diffKey].noteSpawnInterval;
gameStarted = true;
hideDifficultyMenu();
LK.setScore(0);
lastScore = 0;
notes = [];
bullets = [];
// Pick a random music
currentMusic = musicTracks[Math.floor(Math.random() * musicTracks.length)];
LK.playMusic(currentMusic.id);
// Ball
ball = new Ball();
ball.x = BALL_X;
ball.y = BALL_Y;
game.addChild(ball);
// Crosshair
crosshair = new Crosshair();
crosshair.x = BALL_X + 400;
crosshair.y = BALL_Y - 400;
game.addChild(crosshair);
// Score
if (!scoreTxt) {
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
}
scoreTxt.setText(0);
// Show tip for a few seconds
if (!tipTxt) {
tipTxt = new Text2("Başını hareket ettir, notalara dokun ve ateş et!", {
size: 70,
fill: 0xFFE066
});
tipTxt.anchor.set(0.5, 0);
}
tipTxt.x = GAME_W / 2;
tipTxt.y = 180;
game.addChild(tipTxt);
LK.setTimeout(function () {
if (tipTxt) {
tipTxt.destroy();
tipTxt = null;
}
}, 3000);
}
// --- End Game ---
function endGame(win) {
// Clean up
for (var i = 0; i < notes.length; i++) notes[i].destroy();
notes = [];
for (var i = 0; i < bullets.length; i++) bullets[i].destroy();
bullets = [];
if (ball) {
ball.destroy();
ball = null;
}
if (crosshair) {
crosshair.destroy();
crosshair = null;
}
gameStarted = false;
LK.stopMusic();
if (win) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}
// --- Note Spawning ---
function spawnNote() {
var note = new Note();
// Pick a random column
var col = Math.floor(Math.random() * NOTE_COLS);
note.column = col;
note.x = NOTE_MARGIN + NOTE_COL_W / 2 + col * NOTE_COL_W;
note.y = NOTE_START_Y;
note.speed = noteFallSpeed;
notes.push(note);
game.addChild(note);
}
// --- Difficulty Increase ---
function maybeIncreaseDifficulty() {
var score = LK.getScore();
if (score > 0 && score % 10 === 0 && score !== lastScore) {
// Increase speed and spawn rate
noteFallSpeed += 2;
if (noteSpawnInterval > 20) noteSpawnInterval -= 6;
lastScore = score;
}
}
// --- Facekit Crosshair Update ---
function updateCrosshair() {
if (!crosshair) return;
// Use facekit.noseTip or facekit.mouthCenter for aiming
var fx = facekit.noseTip ? facekit.noseTip.x : facekit.mouthCenter ? facekit.mouthCenter.x : GAME_W / 2;
var fy = facekit.noseTip ? facekit.noseTip.y : facekit.mouthCenter ? facekit.mouthCenter.y : GAME_H / 2;
// Clamp to play area
if (fx < CROSS_MIN_X) fx = CROSS_MIN_X;
if (fx > CROSS_MAX_X) fx = CROSS_MAX_X;
if (fy < CROSS_MIN_Y) fy = CROSS_MIN_Y;
if (fy > CROSS_MAX_Y) fy = CROSS_MAX_Y;
crosshair.x = fx;
crosshair.y = fy;
}
// --- Fire Bullet ---
function fireBullet() {
if (!canShoot || !gameStarted) return;
canShoot = false;
// Find if crosshair is over a note
var hitNote = null;
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
if (!n.hit && crosshair && crosshair.intersects(n)) {
hitNote = n;
break;
}
}
// Fire bullet towards crosshair
var b = new Bullet();
b.x = ball.x;
b.y = ball.y;
// Direction vector
var dx = crosshair.x - ball.x;
var dy = crosshair.y - ball.y;
var len = Math.sqrt(dx * dx + dy * dy);
if (len === 0) {
dx = 0;
dy = -1;
len = 1;
}
b.vx = BULLET_SPEED * dx / len;
b.vy = BULLET_SPEED * dy / len;
bullets.push(b);
game.addChild(b);
// If hitNote, mark as hit (so only one bullet per note)
if (hitNote) {
hitNote.hit = true;
}
// Play note sound (simulate: play a sound per note column)
var soundId = 'note' + (hitNote ? hitNote.column : Math.floor(Math.random() * NOTE_COLS));
LK.getSound(soundId).play();
// Allow next shot after short delay
LK.setTimeout(function () {
canShoot = true;
}, 250);
}
// --- Main Game Loop ---
game.update = function () {
if (!gameStarted) return;
// Update crosshair position from facekit
updateCrosshair();
// Spawn notes
if (LK.ticks - lastNoteSpawnTick >= noteSpawnInterval) {
spawnNote();
lastNoteSpawnTick = LK.ticks;
// Automatically fire a bullet every time a note spawns
fireBullet();
}
// Update notes
for (var i = notes.length - 1; i >= 0; i--) {
var n = notes[i];
n.update();
// If note is hit and bullet will reach it, handled below
// If note falls below screen, game over
if (n.y > GAME_H + NOTE_HEIGHT / 2) {
endGame(false);
return;
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Remove bullet if out of bounds
if (b.x < -100 || b.x > GAME_W + 100 || b.y < -100 || b.y > GAME_H + 100) {
b.destroy();
bullets.splice(i, 1);
continue;
}
// Check collision with notes
for (var j = notes.length - 1; j >= 0; j--) {
var n = notes[j];
if (n.hit && b.intersects(n)) {
// Hit!
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Remove note and bullet
n.destroy();
notes.splice(j, 1);
b.destroy();
bullets.splice(i, 1);
// Difficulty up
maybeIncreaseDifficulty();
// Win condition: 50 points
if (LK.getScore() >= 50) {
endGame(true);
return;
}
break;
}
}
}
};
// --- Show Difficulty Menu on Start ---
showDifficultyMenu();
/****
* Asset Initialization (for static analysis)
****/
// Notes (5 columns, 5 colors)
for (var i = 0; i < NOTE_COLS; i++) {}
// Ball
// Crosshair
// Bullet
// Button background
// Music tracks ===================================================================
--- original.js
+++ change.js
@@ -365,13 +365,8 @@
LK.setTimeout(function () {
canShoot = true;
}, 250);
}
-// --- Touch Handler: tap to fire if crosshair is over a note
-game.down = function (x, y, obj) {
- if (!gameStarted) return;
- fireBullet();
-};
// --- Main Game Loop ---
game.update = function () {
if (!gameStarted) return;
// Update crosshair position from facekit
@@ -379,8 +374,10 @@
// Spawn notes
if (LK.ticks - lastNoteSpawnTick >= noteSpawnInterval) {
spawnNote();
lastNoteSpawnTick = LK.ticks;
+ // Automatically fire a bullet every time a note spawns
+ fireBullet();
}
// Update notes
for (var i = notes.length - 1; i >= 0; i--) {
var n = notes[i];
Make a wallpaper that features small music notes and guns. The image should look good for the game and not appear pixelated.. In-Game asset. 2d. High contrast. No shadows
A rounded rectangle frame with both the inside and the border colored — no text inside. Colors can be yellow, blue, or white.. In-Game asset. 2d. High contrast. No shadows
I want a button box with rounded corners and a colorful design using blue, yellow, and white colors. In-Game asset. There should be no text inside the button.
dörtken şekilde olan üzerinde 🎵 simgesi olan bir nota. In-Game asset. 2d. High contrast. No shadows
Market sepeti sarı renk oyuncak gibi. In-Game asset. 2d. High contrast. No shadows
mavi sarı renkte kenarlaı düz dörtken olan bir kart ve ya çercive. In-Game asset. 2d. High contrast. No shadows
Mavi arka plan üzerinde sarı müzik notası simgeleri ve market arabası simgeleri olsun. In-Game asset. 2d. High contrast. No shadows
beyaz ev simgesi. In-Game asset. 2d. High contrast. No shadows
Yuvarlak altın para ortasında 🎶 müzik notası. In-Game asset. 2d. High contrast. No shadows
sarı dörtgen kenarkarı açık mavi. In-Game asset. 2d. High contrast. No shadows
beyaz bir İ buton görseli. In-Game asset. 2d. High contrast. No shadows
küçük bir kırmızı kalp ve içinde beyaz 🎶 notası. In-Game asset. 2d. High contrast. No shadows