Code edit (1 edits merged)
Please save this source code
User prompt
diyalog ekranındaki yazıyı kendim manuel olarak satırlara ayırabileceğim bir kod yaz.
User prompt
diyalogu satırlara hayır dialoguebackground'ın içinden taşmayacak şekilde ayarlar
User prompt
walkie talkie'yi 100 piksel daha sağa taşı, diyalogun içindeki yazıları satırlara ayır ben kendim manuel düzelteyim
User prompt
diyalogtaki ??? yazısını 50 piksel sağa taşı, walkie talkie'yi 200 piksel sağa taşı, ekranın içinde yazan diyalog yazısının boyutunu küçült ve satırlara ayır.
Code edit (1 edits merged)
Please save this source code
User prompt
walkie talkie'nin boyu ço küçük yazı satır satır değil click to continue yazısı çok küçük ??? yazısı ekranın dışında
User prompt
diyalogun satır satır olmasını sağla sağ tarafında walkie talkie'yi geri ekle ve diyalogun sol üstüne ??? yazısını tekrardan ekle ve click to continue.. yazısını da geri ekle tekrardan 0.3 alphadan 1.0 alphaya gidip gelsin ve sonrasında ekran gittikten sonra chapter 1'in ilk bölümü başlasın
User prompt
diyalog ekranını geri getir
User prompt
Please fix the bug: 'Uncaught ReferenceError: startChapter1Bullets is not defined' in or related to this line: 'startChapter1Bullets();' Line Number: 381
User prompt
startgame'de oyuna eski chapter 1 ile değil yeni chapter 1'in ilk bölümüyle başlanmasını sağla fakat eski chapter 1'in diyalog fonksiyonunu oyundan sakın kaldırma
User prompt
Please fix the bug: 'Uncaught ReferenceError: startChapter1Bullets is not defined' in or related to this line: 'startChapter1Bullets();' Line Number: 379
User prompt
bizim en başta yaptığımız diyalog ekranının aynısını yap
User prompt
lütfen bu diyalog ekranını eski düzende yarat
User prompt
şuan start game denilince ekrana diyalog background'ı yazılar, walkie talki görseli, vb. click to continue falan hiçbiri yazmıyor
User prompt
Please fix the bug: 'Uncaught ReferenceError: startChapter1Bullets is not defined' in or related to this line: 'startChapter1Bullets();' Line Number: 379
User prompt
tamamdır bunu yap
User prompt
start game butonuna basıldığında sadece eski chapter 1'i kaldır çünkü şuan eski chapter 1'in diyalog ekranı geliyor ekrana onun gelmemesi lazım
User prompt
şuanda start game butonuna bastığımda chapter 1'in 1. bölümünün diyalog ekranı ekrana gelmiyor bu yüzden oyun takılıyor.
User prompt
şuan start game dendiğinde ilk önce bir diyalog çıkıyor 25 mermilik olan oyun sonra bir anda 50 mermilik olan oyunun diyalogu çıkıyor yani eski chapter 1 ile şuanki chapter 1'in 1.bölümü karışmış bunu düzeltir misin
User prompt
ekstradan isteğim her bölümde farklı şeyler yaşanacak sana söylediğim şeyleri yapacaksın mesela ilk bölümün bitişinde de diyalog ekranı çıkacak ve busefer ekranda yine aynı düzen olacak ve sadece yazı değişecek yazıda busefer: “You’re alive... For now. But the enemy will hit harder. Prepare.” yazacak ekranda ve sonra chapter 1'in ikinci aşamasına geçilecek ikinci aşamanın introsunda yine bir diyalog gelecek ve busefer içinde: “The enemy’s tracking you, Shadow. Trick them with your Shadow Clone. Move.” yazacak ve busefer de etraftan dikine bir şekilde gelen mermiler yerine oyuncunun o anlık konumuna giden mermiler (takip etmeyecek sadece 1 kere oyuncuya doğru gidecek) atılacak. ve eğer oyuncu geçerse bölümü yine bir diyalog ekranı gelecek ve busefer diyalog ekranında “Your clone worked. But these enemies don’t quit. More are coming.” yazacak
User prompt
chapter 1'i 5 farklı aşamaya ayır. ve bu yaptığımız chapter 1'ın birinci aşaması olacak
User prompt
chapter 1'deki gelen mermi sayısını 50 mermi yap
User prompt
şuanda mermilerin rotasyonu sağa doğru oldu
User prompt
şuanda da rotasyonu yukarı doğru oldu
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
chapter: 1,
endlessHighScore: 0
});
/****
* Classes
****/
// Takipçi ışık mermisi (ChasingLightBullet) sınıfı
var ChasingLightBullet = Container.expand(function () {
var self = Container.call(this);
// Mermi grafiği
var bulletAsset = self.attachAsset('lightBullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Hız vektörü
self.speed = 10 + Math.random() * 3;
// Çarpışma kontrolü için son intersect durumu
self.lastIntersecting = false;
// Mermi boyutu
self.width = bulletAsset.width;
self.height = bulletAsset.height;
// Parlama animasyonu için tween
var pulseTween = null;
// Parlama animasyonu başlat
function startPulse() {
if (pulseTween) {
tween.stop(bulletAsset, {
alpha: true
});
pulseTween = null;
}
bulletAsset.alpha = 0.5 + Math.random() * 0.2;
// Tween ile alpha'yı 1'e çıkar, sonra tekrar 0.5-0.7 arası değere geri döndür, sonsuz döngü
function pulseUp() {
pulseTween = tween(bulletAsset, {
alpha: 1
}, {
duration: 350,
easing: tween.easeInOut,
onFinish: function onFinish() {
var min = 0.5,
max = 0.7;
var target = min + Math.random() * (max - min);
pulseTween = tween(bulletAsset, {
alpha: target
}, {
duration: 350,
easing: tween.easeInOut,
onFinish: pulseUp
});
}
});
}
pulseUp();
}
startPulse();
// Güncelleme fonksiyonu
self.update = function () {
// Son pozisyonları güncelle
if (self.lastX === undefined) {
self.lastX = self.x;
}
if (self.lastY === undefined) {
self.lastY = self.y;
}
// Hedefe doğru yönel
if (typeof shadow !== "undefined") {
var dx = shadow.x - self.x;
var dy = shadow.y - self.y;
var angle = Math.atan2(dy, dx);
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
// Merminin ucunu oyuncuya bakacak şekilde döndür
self.rotation = angle + Math.PI / 2;
}
self.lastX = self.x;
self.lastY = self.y;
};
// Ekran dışına çıktı mı?
self.isOutOfBounds = function () {
return self.x < -self.width || self.x > 2048 + self.width || self.y < -self.height || self.y > 2732 + self.height;
};
// Yok edilirken animasyonu durdur
var _destroy = self.destroy;
self.destroy = function () {
if (pulseTween) {
pulseTween.stop();
}
_destroy.call(self);
};
return self;
});
// Işık mermisi (LightBullet) sınıfı
var LightBullet = Container.expand(function () {
var self = Container.call(this);
// Mermi grafiği
var bulletAsset = self.attachAsset('lightBullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Hız vektörü
self.speedX = 0;
self.speedY = 0;
// Çarpışma kontrolü için son intersect durumu
self.lastIntersecting = false;
// Mermi boyutu
self.width = bulletAsset.width;
self.height = bulletAsset.height;
// Mermi güncelleme fonksiyonu
self.update = function () {
// Son pozisyonları güncelle
if (self.lastX === undefined) {
self.lastX = self.x;
}
if (self.lastY === undefined) {
self.lastY = self.y;
}
self.x += self.speedX;
self.y += self.speedY;
self.lastX = self.x;
self.lastY = self.y;
};
// Ekran dışına çıktı mı?
self.isOutOfBounds = function () {
return self.x < -self.width || self.x > 2048 + self.width || self.y < -self.height || self.y > 2732 + self.height;
};
return self;
});
// Gölge karakter (Shadow) sınıfı
var Shadow = Container.expand(function () {
var self = Container.call(this);
// Gölge karakter grafiği olarak shadowbox kullan
var shadowBoxAsset = self.attachAsset('shadowbox', {
anchorX: 0.5,
anchorY: 0.5
});
// Gözler: shadowredeye assetini ekle
var eyeAsset = LK.getAsset('shadowredeye', {
anchorX: 0.5,
anchorY: 0.5
});
// Gözleri kutunun ortasına ve biraz yukarıya yerleştir
// shadowbox'ın yüksekliğine göre orantılı konumlandır
eyeAsset.x = 0;
eyeAsset.y = -shadowBoxAsset.height * 0.18;
// Gözleri kutunun içine ekle
self.addChild(eyeAsset);
// Yarıçapı döndür (kenar çarpışma için)
self.getRadius = function () {
// Kutu genişliğinin yarısı
return shadowBoxAsset.width / 2;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181a1b
});
/****
* Game Code
****/
// Oyun alanı boyutları
var GAME_W = 2048;
var GAME_H = 2732;
// Storage eklentisini başlat
// Menü ekranı için değişkenler
var menuContainer = null;
var menuButtons = [];
var menuActive = true;
var currentMode = null; // "chapter" veya "endless"
// Oyun içi değişkenler
var shadow = null;
var bullets = [];
var chasingBullets = [];
var score = 0;
var scoreTxt = null;
var dragNode = null;
var isGameActive = false;
var controlPanel = null;
var joystick = null;
var joystickRadius = 180 * 2;
var joystickKnobRadius = 60 * 1.2;
var isPanelActive = false;
var panelStartX = 0;
var panelStartY = 0;
var knobStartX = 0;
var knobStartY = 0;
var bulletInterval = 700;
var bulletTimer = null;
var chasingBulletInterval = 1200;
var chasingBulletTimer = null;
// Menü ekranı oluşturma fonksiyonu
function showMenu() {
menuActive = true;
isGameActive = false;
// Menü zaten varsa kaldır
if (menuContainer) {
menuContainer.destroy();
menuContainer = null;
menuButtons = [];
}
menuContainer = new Container();
// --- Main menu background (fills screen) ---
var bg = LK.getAsset('mainmenubackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: GAME_W,
height: GAME_H
});
menuContainer.addChild(bg);
// --- Animated white bar (mainmenuwhite) ---
var whiteBar = LK.getAsset('mainmenuwhite', {
anchorX: 0.5,
anchorY: 0,
x: GAME_W / 2,
y: 0,
width: GAME_W * 0.9,
height: 220
});
menuContainer.addChild(whiteBar);
// Animate whiteBar up and down forever
function animateWhiteBarDown() {
tween(whiteBar, {
y: GAME_H - whiteBar.height
}, {
duration: 2200,
easing: tween.easeInOut,
onFinish: animateWhiteBarUp
});
}
function animateWhiteBarUp() {
tween(whiteBar, {
y: 0
}, {
duration: 2200,
easing: tween.easeInOut,
onFinish: animateWhiteBarDown
});
}
animateWhiteBarDown();
// --- Logo (original scale, moved 400px down) ---
var logo = LK.getAsset('agentshadowlogo', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_W / 2,
y: 800,
scaleX: 1,
scaleY: 1
});
menuContainer.addChild(logo);
// Butonlar arası dikey boşluk
var btnSpacing = 80;
var btnW = 600;
var btnH = 180;
var startY = 1300; // 900 + 400
// Buton isimleri ve fonksiyonları
var btnDefs = [{
label: "Start Game",
onClick: function onClick() {
currentMode = "chapter";
menuActive = false;
menuContainer.visible = false;
startGameFromChapter();
}
}, {
label: "Endless Run",
onClick: function onClick() {
currentMode = "endless";
menuActive = false;
menuContainer.visible = false;
startEndlessRun();
}
}, {
label: "Reset Game",
onClick: function onClick() {
storage.chapter = 1;
// Geri bildirim için kısa bir animasyon veya renk değişimi yapılabilir
if (menuButtons[2] && menuButtons[2].bg) {
LK.effects.flashObject(menuButtons[2].bg, 0xff0000, 300);
}
}
}];
// Butonları oluştur
for (var i = 0; i < btnDefs.length; i++) {
var btnY = startY + i * (btnH + btnSpacing);
// Buton arka planı
var btnBg = LK.getAsset('blackbutton', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_W / 2,
y: btnY,
width: btnW,
height: btnH
});
// Buton metni
var btnText = new Text2(btnDefs[i].label, {
size: 80,
fill: "#fff"
});
btnText.anchor.set(0.5, 0.5);
btnText.x = GAME_W / 2;
btnText.y = btnY;
// Buton Container'ı
var btnContainer = new Container();
btnContainer.bg = btnBg;
btnContainer.addChild(btnBg);
btnContainer.addChild(btnText);
// Buton tıklama alanı
btnContainer.interactive = true;
btnContainer.buttonMode = true;
// Basit dokunma olayı
(function (def, btn) {
btnContainer.down = function (x, y, obj) {
if (!menuActive) {
return;
}
def.onClick();
};
})(btnDefs[i], btnContainer);
menuContainer.addChild(btnContainer);
menuButtons.push(btnContainer);
}
// Menü sahneye ekle
game.addChild(menuContainer);
}
// Menüden chapter modunda oyunu başlat
function startGameFromChapter() {
// Temizle
clearGameObjects();
// Chapter bilgisini storage'dan al
var chapter = storage.chapter || 1;
// Karakteri oluştur ve ortala
shadow = new Shadow();
shadow.x = GAME_W / 2;
shadow.y = GAME_H * 0.8;
game.addChild(shadow);
// Skor (chapter modunda skor kullanılmaz, sadece kalan mermi sayısı gösterilir)
score = 0;
if (scoreTxt) {
scoreTxt.destroy();
}
// Chapter 1 bullet sayacı (skor yerine)
var chapter1BulletCount = 25;
scoreTxt = new Text2(chapter1BulletCount + "", {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
isGameActive = false; // Oyun başlatılmadan önce false
menuActive = false;
// --- CHAPTER 1: 5 aşamalı sistem ---
// Her aşama için parametreler
var chapter1Stages = [
// Stage 1: Şu anki mevcut sistem (50 dikine mermi)
{
bulletCount: 50,
bulletInterval: 1200,
bulletScale: 0.7,
speedBase: 7,
speedRand: 2,
speedStep: 2.5,
stepEvery: 5,
pattern: "vertical"
},
// Stage 2: Daha hızlı, daha küçük mermiler
{
bulletCount: 40,
bulletInterval: 900,
bulletScale: 0.6,
speedBase: 9,
speedRand: 2,
speedStep: 3,
stepEvery: 4,
pattern: "vertical"
},
// Stage 3: Çapraz mermiler (sağdan ve soldan da gelebilir)
{
bulletCount: 35,
bulletInterval: 800,
bulletScale: 0.6,
speedBase: 10,
speedRand: 3,
speedStep: 3.5,
stepEvery: 4,
pattern: "mixed"
},
// Stage 4: Daha hızlı ve karışık
{
bulletCount: 30,
bulletInterval: 700,
bulletScale: 0.55,
speedBase: 12,
speedRand: 4,
speedStep: 4,
stepEvery: 3,
pattern: "mixed"
},
// Stage 5: Son aşama, çok hızlı ve yoğun
{
bulletCount: 25,
bulletInterval: 600,
bulletScale: 0.5,
speedBase: 14,
speedRand: 5,
speedStep: 5,
stepEvery: 2,
pattern: "mixed"
}];
function startChapter1Bullets() {
isGameActive = true;
var currentStage = 0;
// Diyalog ekranı gösterici
function showDialogue(options, onContinue) {
// options: { lines: [], speaker: "", walkie: true/false, continueText: string }
var dialogueBg = LK.getAsset('dialoguebackground', {
anchorX: 0.5,
anchorY: 0.5,
x: GAME_W / 2,
y: GAME_H / 2,
scaleX: 1,
scaleY: 1
});
game.addChild(dialogueBg);
var dialogueText = new Text2(options.lines.join('\n'), {
size: 60,
fill: "#000"
});
dialogueText.anchor.set(0.5, 0.5);
dialogueText.x = dialogueBg.x;
dialogueText.y = dialogueBg.y;
dialogueText.maxWidth = dialogueBg.width * 0.85;
game.addChild(dialogueText);
var speakerText = null;
if (options.speaker) {
speakerText = new Text2(options.speaker, {
size: 90,
fill: "#000"
});
speakerText.anchor.set(0, 0);
speakerText.x = dialogueBg.x - dialogueBg.width / 2 + 40 + 100;
speakerText.y = dialogueBg.y - dialogueBg.height / 2 + 30 + 100;
game.addChild(speakerText);
}
var walkieTalkie = null;
if (options.walkie) {
walkieTalkie = LK.getAsset('walkietalkie', {
anchorX: 0.5,
anchorY: 0.5,
x: dialogueBg.x + dialogueBg.width / 2,
y: dialogueBg.y - dialogueBg.height / 4
});
game.addChild(walkieTalkie);
}
var continueText = new Text2(options.continueText || "click to continue..", {
size: 72,
fill: "#000"
});
continueText.anchor.set(0.5, 0);
continueText.x = dialogueBg.x;
continueText.y = dialogueBg.y + dialogueBg.height / 2 - 60 - 150;
continueText.alpha = 0.3;
game.addChild(continueText);
// Animate alpha between 0.3 and 0.1 forever using tween
function animateAlphaDown() {
tween(continueText, {
alpha: 0.1
}, {
duration: 700,
easing: tween.easeInOut,
onFinish: animateAlphaUp
});
}
function animateAlphaUp() {
tween(continueText, {
alpha: 0.3
}, {
duration: 700,
easing: tween.easeInOut,
onFinish: animateAlphaDown
});
}
animateAlphaDown();
// Diyalog ekranında tıklandığında diyalogu kaldır
function closeDialogue() {
if (dialogueBg && !dialogueBg._destroyed) dialogueBg.destroy();
if (dialogueText && !dialogueText._destroyed) dialogueText.destroy();
if (speakerText && !speakerText._destroyed) speakerText.destroy();
if (walkieTalkie && !walkieTalkie._destroyed) walkieTalkie.destroy();
if (continueText && !continueText._destroyed) continueText.destroy();
game.down = originalGameDown;
if (onContinue) onContinue();
}
var originalGameDown = game.down;
game.down = function (x, y, obj) {
closeDialogue();
};
}
// Stage parametreleri ve diyalogları
var chapter1Stages = [
// Stage 1: Dikey mermiler, intro ve bitiş diyalogları
{
bulletCount: 50,
bulletInterval: 1200,
bulletScale: 0.7,
speedBase: 7,
speedRand: 2,
speedStep: 2.5,
stepEvery: 5,
pattern: "vertical",
introDialogue: {
lines: ["*khkhkhhht* Agent Shadow, you’re ", "active. The Light’s forces are hunting", "you. Stay unseen, move fast. *khkht*"],
speaker: "???",
walkie: true,
continueText: "click to continue.."
},
outroDialogue: {
lines: ["You’re alive… For now. But the enemy will hit harder. Prepare."],
speaker: "",
walkie: false,
continueText: "click to continue.."
}
},
// Stage 2: Oyuncuya doğru giden mermiler, intro ve bitiş diyalogları
{
bulletCount: 40,
bulletInterval: 900,
bulletScale: 0.7,
speedBase: 13,
speedRand: 5,
speedStep: 0,
stepEvery: 999,
// hızlanma yok
pattern: "targeted",
introDialogue: {
lines: ["The enemy’s tracking you, Shadow. Trick them with your Shadow Clone. Move."],
speaker: "",
walkie: false,
continueText: "click to continue.."
},
outroDialogue: {
lines: ["Your clone worked. But these enemies don’t quit. More are coming."],
speaker: "",
walkie: false,
continueText: "click to continue.."
}
},
// Stage 3: Çapraz mermiler (sağdan ve soldan da gelebilir)
{
bulletCount: 35,
bulletInterval: 800,
bulletScale: 0.6,
speedBase: 10,
speedRand: 3,
speedStep: 3.5,
stepEvery: 4,
pattern: "mixed",
introDialogue: null,
outroDialogue: null
},
// Stage 4: Daha hızlı ve karışık
{
bulletCount: 30,
bulletInterval: 700,
bulletScale: 0.55,
speedBase: 12,
speedRand: 4,
speedStep: 4,
stepEvery: 3,
pattern: "mixed",
introDialogue: null,
outroDialogue: null
},
// Stage 5: Son aşama, çok hızlı ve yoğun
{
bulletCount: 25,
bulletInterval: 600,
bulletScale: 0.5,
speedBase: 14,
speedRand: 5,
speedStep: 5,
stepEvery: 2,
pattern: "mixed",
introDialogue: null,
outroDialogue: null
}];
// Stage başlatıcı
function startStage(stageIdx) {
if (stageIdx >= chapter1Stages.length) {
// Tüm aşamalar bitti, ekrandaki mermiler bitince win yaz
var _checkAllBulletsGone = function checkAllBulletsGone() {
if (bullets.length === 0) {
if (scoreTxt) scoreTxt.setText("WIN");
isGameActive = false;
} else {
LK.setTimeout(_checkAllBulletsGone, 100);
}
};
_checkAllBulletsGone();
return;
}
var stage = chapter1Stages[stageIdx];
var bulletsFired = 0;
var maxBullets = stage.bulletCount;
var bulletInterval = stage.bulletInterval;
var bulletsToGo = maxBullets;
var bulletScale = stage.bulletScale;
// Skor yazısı yerine kalan mermi sayısını göster
if (scoreTxt) {
scoreTxt.setText(bulletsToGo + "");
}
// Stage intro diyalogu varsa göster, yoksa direkt başlat
function beginStage() {
function fireBullet() {
if (!isGameActive) return;
var bullet;
var startX, startY, angle;
if (stage.pattern === "vertical") {
bullet = new LightBullet();
bullet.scale.x = bulletScale;
bullet.scale.y = bulletScale;
// Sadece üst kenardan, rastgele X ile başlat
startX = Math.random() * GAME_W;
startY = -bullet.height;
bullet.x = startX;
bullet.y = startY;
bullet.speedX = 0;
bullet.speedY = stage.speedBase + Math.random() * stage.speedRand + Math.floor(bulletsFired / stage.stepEvery) * stage.speedStep;
bullet.rotation = Math.PI;
} else if (stage.pattern === "targeted") {
// Oyuncunun o anki konumuna giden mermiler (takip etmeyecek, sadece 1 kere hedefe gidecek)
bullet = new LightBullet();
bullet.scale.x = bulletScale;
bullet.scale.y = bulletScale;
// Kenarı rastgele seç (üst, alt, sol, sağ)
var edge = Math.floor(Math.random() * 4);
var targetX = shadow.x;
var targetY = shadow.y;
if (edge === 0) {
// üst
startX = Math.random() * GAME_W;
startY = -bullet.height;
} else if (edge === 1) {
// sağ
startX = GAME_W + bullet.width;
startY = Math.random() * GAME_H;
} else if (edge === 2) {
// alt
startX = Math.random() * GAME_W;
startY = GAME_H + bullet.height;
} else {
// sol
startX = -bullet.width;
startY = Math.random() * GAME_H;
}
// Hedefe doğru vektör
var dx = targetX - startX;
var dy = targetY - startY;
angle = Math.atan2(dy, dx);
var speed = stage.speedBase + Math.random() * stage.speedRand;
bullet.x = startX;
bullet.y = startY;
bullet.speedX = Math.cos(angle) * speed;
bullet.speedY = Math.sin(angle) * speed;
bullet.rotation = angle + Math.PI / 2;
} else {
// Karışık: sağdan veya soldan da gelebilir
bullet = new LightBullet();
bullet.scale.x = bulletScale;
bullet.scale.y = bulletScale;
var side = Math.random() < 0.5 ? "left" : "right";
startY = Math.random() * (GAME_H * 0.5); // üst yarıdan gelsin
if (side === "left") {
startX = -bullet.width;
bullet.x = startX;
bullet.y = startY;
bullet.speedX = stage.speedBase + Math.random() * stage.speedRand + Math.floor(bulletsFired / stage.stepEvery) * stage.speedStep;
bullet.speedY = stage.speedBase * 0.5 + Math.random() * (stage.speedRand * 0.5);
bullet.rotation = Math.PI / 2;
} else {
startX = GAME_W + bullet.width;
bullet.x = startX;
bullet.y = startY;
bullet.speedX = -stage.speedBase - Math.random() * stage.speedRand - Math.floor(bulletsFired / stage.stepEvery) * stage.speedStep;
bullet.speedY = stage.speedBase * 0.5 + Math.random() * (stage.speedRand * 0.5);
bullet.rotation = -Math.PI / 2;
}
}
bullets.push(bullet);
game.addChild(bullet);
bulletsFired++;
bulletsToGo--;
// Kalan mermi sayısını güncelle
if (scoreTxt) {
scoreTxt.setText(bulletsToGo > 0 ? bulletsToGo + "" : "0");
}
if (bulletsFired < maxBullets) {
// Her stepEvery mermide bir hızlan
if (bulletsFired % stage.stepEvery === 0) {
bulletInterval = Math.max(300, bulletInterval - 120);
}
LK.setTimeout(fireBullet, bulletInterval);
} else {
// Son mermi atıldı, ekrandaki mermiler bitince bir sonraki aşamaya geç
var _checkAllBulletsGone = function checkAllBulletsGone() {
if (bullets.length === 0) {
// Stage outro diyalogu varsa göster, yoksa direkt sonraki aşamaya geç
if (stage.outroDialogue) {
showDialogue(stage.outroDialogue, function () {
startStage(stageIdx + 1);
});
} else {
startStage(stageIdx + 1);
}
} else {
LK.setTimeout(_checkAllBulletsGone, 100);
}
};
_checkAllBulletsGone();
}
}
fireBullet();
}
// Stage intro diyalogu varsa önce onu göster
if (stage.introDialogue) {
showDialogue(stage.introDialogue, function () {
// Stage başlığı ve countdown sadece ilk aşamada gösterilsin
if (stageIdx === 0) {
// Chapter başlığı
var chapterTitle = new Text2("Chapter 1: Shadow’s Awakening", {
size: 100,
fill: "#fff"
});
chapterTitle.anchor.set(0.5, 0);
chapterTitle.x = GAME_W / 2;
chapterTitle.y = 220;
game.addChild(chapterTitle);
LK.setTimeout(function () {
if (chapterTitle && !chapterTitle._destroyed) {
chapterTitle.destroy();
}
// 3-2-1 countdown
var countdownVals = [3, 2, 1];
var countdownText = new Text2("", {
size: 200,
fill: "#fff",
fontWeight: "bold"
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = GAME_W / 2;
countdownText.y = GAME_H / 2;
game.addChild(countdownText);
var idx = 0;
function nextCountdown() {
if (idx < countdownVals.length) {
countdownText.setText(countdownVals[idx]);
idx++;
LK.setTimeout(nextCountdown, 800);
} else {
countdownText.destroy();
beginStage();
}
}
nextCountdown();
}, 2500);
} else {
beginStage();
}
});
} else {
beginStage();
}
}
// İlk aşamadan başla
startStage(currentStage);
}
}
// Endless Run başlat
function startEndlessRun() {
clearGameObjects();
// Karakteri oluştur ve ortala
shadow = new Shadow();
shadow.x = GAME_W / 2;
shadow.y = GAME_H * 0.8;
game.addChild(shadow);
// Skor (endless modda skor gösterilir)
score = 0;
if (scoreTxt) {
scoreTxt.destroy();
}
scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
isGameActive = true;
menuActive = false;
startBulletTimer();
startChasingBulletTimer();
}
// Oyun objelerini temizle
function clearGameObjects() {
// Karakteri sil
if (shadow) {
shadow.destroy();
shadow = null;
}
// Mermileri sil
for (var i = 0; i < bullets.length; i++) {
if (bullets[i]) {
bullets[i].destroy();
}
}
bullets = [];
for (var i = 0; i < chasingBullets.length; i++) {
if (chasingBullets[i]) {
chasingBullets[i].destroy();
}
}
chasingBullets = [];
// Skor metni sil
if (scoreTxt) {
scoreTxt.destroy();
scoreTxt = null;
}
// Joystick ve paneli sil
if (controlPanel) {
controlPanel.destroy();
controlPanel = null;
}
joystick = null;
isPanelActive = false;
dragNode = null;
joystickDirX = 0;
joystickDirY = 0;
joystickActive = false;
}
// Oyun ilk açıldığında menüyü göster
showMenu();
// Mermi oluşturma fonksiyonu
function spawnBullet() {
// Merminin çıkacağı kenarı rastgele seç (üst, alt, sol, sağ)
var edge = Math.floor(Math.random() * 4);
var bullet = new LightBullet();
var angle, startX, startY, targetX, targetY, speed;
// Hedef karakterin anlık pozisyonu
targetX = shadow.x;
targetY = shadow.y;
// Kenara göre başlangıç pozisyonu ve yönü belirle
if (edge === 0) {
// üst
startX = Math.random() * GAME_W;
startY = -bullet.height;
} else if (edge === 1) {
// sağ
startX = GAME_W + bullet.width;
startY = Math.random() * GAME_H;
} else if (edge === 2) {
// alt
startX = Math.random() * GAME_W;
startY = GAME_H + bullet.height;
} else {
// sol
startX = -bullet.width;
startY = Math.random() * GAME_H;
}
// Hedefe doğru vektör
var dx = targetX - startX;
var dy = targetY - startY;
angle = Math.atan2(dy, dx);
// Hız (her mermi için rastgele küçük bir varyasyon)
speed = 13 + Math.random() * 5;
bullet.x = startX;
bullet.y = startY;
bullet.speedX = Math.cos(angle) * speed;
bullet.speedY = Math.sin(angle) * speed;
// Merminin ucunu oyuncuya bakacak şekilde döndür
bullet.rotation = angle + Math.PI / 2;
bullets.push(bullet);
game.addChild(bullet);
}
// Takipçi mermi oluşturma fonksiyonu
function spawnChasingBullet() {
// Sadece skor 10 veya üstü ise oluştur
if (score < 10) {
return;
}
// Kenardan rastgele bir yerden başlat
var edge = Math.floor(Math.random() * 4);
var bullet = new ChasingLightBullet();
var startX, startY;
if (edge === 0) {
startX = Math.random() * GAME_W;
startY = -bullet.height;
} else if (edge === 1) {
startX = GAME_W + bullet.width;
startY = Math.random() * GAME_H;
} else if (edge === 2) {
startX = Math.random() * GAME_W;
startY = GAME_H + bullet.height;
} else {
startX = -bullet.width;
startY = Math.random() * GAME_H;
}
bullet.x = startX;
bullet.y = startY;
// Başlangıçta oyuncuya bakacak şekilde döndür
var dx = shadow.x - bullet.x;
var dy = shadow.y - bullet.y;
bullet.rotation = Math.atan2(dy, dx) + Math.PI / 2;
chasingBullets.push(bullet);
game.addChild(bullet);
}
// Mermi oluşturma zamanlayıcısı başlat
function startBulletTimer() {
if (bulletTimer) {
LK.clearInterval(bulletTimer);
}
bulletTimer = LK.setInterval(function () {
if (isGameActive) {
spawnBullet();
}
}, bulletInterval);
}
// startBulletTimer(); // Chapter 1'de otomatik mermi spawn edilmesin
// Takipçi mermi zamanlayıcısı başlat
function startChasingBulletTimer() {
if (chasingBulletTimer) {
LK.clearInterval(chasingBulletTimer);
}
chasingBulletTimer = LK.setInterval(function () {
if (isGameActive && score >= 10) {
spawnChasingBullet();
}
}, chasingBulletInterval);
}
// startChasingBulletTimer(); // Chapter 1'de otomatik takipçi mermi spawn edilmesin
// Skoru güncelle
function updateScore(val) {
// Sadece endless modda skor güncellensin
if (currentMode === "endless") {
score = val;
if (scoreTxt) scoreTxt.setText(score);
}
}
// Oyun bittiğinde
function gameOver() {
isGameActive = false;
// Ekranı kırmızıya flashla
LK.effects.flashScreen(0xff2222, 800);
// Chapter modunda ise ilerlemeyi kaydet
if (currentMode === "chapter") {
// Skora göre chapter ilerletme örneği (ileride özelleştirilebilir)
if (score > 0) {
var nextChapter = (storage.chapter || 1) + 1;
storage.chapter = nextChapter;
}
}
// Endless modda high score zaten update'de kaydediliyor
// Oyun bitişini göster
LK.showGameOver();
// Kısa bir gecikmeden sonra menüyü tekrar göster
LK.setTimeout(function () {
showMenu();
}, 1200);
}
// Sürükleme işlemleri
// Joystick yönünü ve mesafesini globalde tut
var joystickDirX = 0;
var joystickDirY = 0;
var joystickActive = false;
function handleMove(x, y, obj) {
if (!isGameActive || menuActive) {
return;
}
if (isPanelActive && controlPanel && joystick) {
// Joystick merkezine göre delta
var dx = x - panelStartX;
var dy = y - panelStartY;
var dist = Math.sqrt(dx * dx + dy * dy);
// Knob'u panel sınırında tut
var maxDist = joystickRadius - joystickKnobRadius;
if (dist > maxDist) {
var angle = Math.atan2(dy, dx);
dx = Math.cos(angle) * maxDist;
dy = Math.sin(angle) * maxDist;
}
joystick.x = dx;
joystick.y = dy;
// Joystick yönünü ve oranını kaydet
if (dist > 10) {
// ölü bölge
joystickDirX = dx / maxDist;
joystickDirY = dy / maxDist;
joystickActive = true;
} else {
joystickDirX = 0;
joystickDirY = 0;
joystickActive = false;
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (!isGameActive || menuActive) {
return;
}
// Kontrol paneli zaten varsa kaldır
if (controlPanel) {
controlPanel.destroy();
controlPanel = null;
joystick = null;
isPanelActive = false;
}
// Kontrol panelini oluştur
controlPanel = new Container();
controlPanel.x = x;
controlPanel.y = y;
// Panel arka planı (şeffaf daire)
var panelBg = LK.getAsset('centerCircle', {
width: joystickRadius * 2,
height: joystickRadius * 2,
color: 0x222222,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.25
});
controlPanel.addChild(panelBg);
// Joystick knob'u (küçük daire)
joystick = LK.getAsset('centerCircle', {
width: joystickKnobRadius * 2,
height: joystickKnobRadius * 2,
color: 0xffffff,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
joystick.x = 0;
joystick.y = 0;
controlPanel.addChild(joystick);
// Paneli oyuna ekle
game.addChild(controlPanel);
isPanelActive = true;
panelStartX = x;
panelStartY = y;
knobStartX = 0;
knobStartY = 0;
};
game.up = function (x, y, obj) {
if (menuActive) {
return;
}
// Kontrol panelini kaldır
if (controlPanel) {
controlPanel.destroy();
controlPanel = null;
joystick = null;
isPanelActive = false;
}
dragNode = null;
// Joystick bırakıldığında hareketi durdur
joystickDirX = 0;
joystickDirY = 0;
joystickActive = false;
};
// Oyun güncelleme döngüsü
game.update = function () {
if (!isGameActive || menuActive) {
return;
}
// Karakteri joystick yönünde sürekli hareket ettir
if (joystickActive) {
var moveSpeed = 22;
shadow.x += joystickDirX * moveSpeed;
shadow.y += joystickDirY * moveSpeed;
var r = shadow.getRadius();
if (shadow.x < r) {
shadow.x = r;
}
if (shadow.x > GAME_W - r) {
shadow.x = GAME_W - r;
}
if (shadow.y < r) {
shadow.y = r;
}
if (shadow.y > GAME_H - r) {
shadow.y = GAME_H - r;
}
}
// Mermileri güncelle
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
if (b.isOutOfBounds()) {
b.destroy();
bullets.splice(i, 1);
continue;
}
var intersecting = b.intersects(shadow);
if (!b.lastIntersecting && intersecting) {
// Oyun biter
gameOver();
return;
}
b.lastIntersecting = intersecting;
}
// Takipçi mermileri güncelle
for (var i = chasingBullets.length - 1; i >= 0; i--) {
var cb = chasingBullets[i];
cb.update();
if (cb.isOutOfBounds()) {
cb.destroy();
chasingBullets.splice(i, 1);
continue;
}
var intersecting = cb.intersects(shadow);
if (!cb.lastIntersecting && intersecting) {
gameOver();
return;
}
cb.lastIntersecting = intersecting;
}
// Işık mermileri birbirine çarptı mı kontrol et ve patlat
for (var i = bullets.length - 1; i >= 0; i--) {
var b1 = bullets[i];
for (var j = i - 1; j >= 0; j--) {
var b2 = bullets[j];
if (!b1._destroyed && !b2._destroyed && b1.intersects(b2)) {
b1.destroy();
b2.destroy();
bullets.splice(i, 1);
bullets.splice(j, 1);
i--;
break;
}
}
}
// Takipçi mermiler ile normal mermiler çarpışırsa patlat
for (var i = chasingBullets.length - 1; i >= 0; i--) {
var cb = chasingBullets[i];
for (var j = bullets.length - 1; j >= 0; j--) {
var b = bullets[j];
if (!cb._destroyed && !b._destroyed && cb.intersects(b)) {
cb.destroy();
b.destroy();
chasingBullets.splice(i, 1);
bullets.splice(j, 1);
i--;
break;
}
}
}
// Takipçi mermiler birbirine çarparsa patlat
for (var i = chasingBullets.length - 1; i >= 0; i--) {
var cb1 = chasingBullets[i];
for (var j = i - 1; j >= 0; j--) {
var cb2 = chasingBullets[j];
if (!cb1._destroyed && !cb2._destroyed && cb1.intersects(cb2)) {
cb1.destroy();
cb2.destroy();
chasingBullets.splice(i, 1);
chasingBullets.splice(j, 1);
i--;
break;
}
}
}
// Skoru güncelle (hayatta kalma süresi) - sadece endless modda
if (currentMode === "endless" && LK.ticks % 30 === 0) {
updateScore(score + 1);
// Endless modda high score kaydet
if (score > (storage.endlessHighScore || 0)) {
storage.endlessHighScore = score;
}
}
};
// Oyun yeniden başladığında sıfırla
game.on('reset', function () {
// Tüm oyun objelerini temizle
clearGameObjects();
// Menüye dön
showMenu();
}); ===================================================================
--- original.js
+++ change.js
@@ -350,100 +350,79 @@
score = 0;
if (scoreTxt) {
scoreTxt.destroy();
}
- // Skor metni (chapter modunda kalan mermi sayısı olarak kullanılacak)
- scoreTxt = new Text2('0', {
+ // Chapter 1 bullet sayacı (skor yerine)
+ var chapter1BulletCount = 25;
+ scoreTxt = new Text2(chapter1BulletCount + "", {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
isGameActive = false; // Oyun başlatılmadan önce false
menuActive = false;
// --- CHAPTER 1: 5 aşamalı sistem ---
- // Her aşama için parametreler ve diyaloglar
- // (chapter1Stages tekrar tanımlanmasın, sadece startChapter1Bullets fonksiyonu kullanılacak)
+ // Her aşama için parametreler
+ var chapter1Stages = [
+ // Stage 1: Şu anki mevcut sistem (50 dikine mermi)
+ {
+ bulletCount: 50,
+ bulletInterval: 1200,
+ bulletScale: 0.7,
+ speedBase: 7,
+ speedRand: 2,
+ speedStep: 2.5,
+ stepEvery: 5,
+ pattern: "vertical"
+ },
+ // Stage 2: Daha hızlı, daha küçük mermiler
+ {
+ bulletCount: 40,
+ bulletInterval: 900,
+ bulletScale: 0.6,
+ speedBase: 9,
+ speedRand: 2,
+ speedStep: 3,
+ stepEvery: 4,
+ pattern: "vertical"
+ },
+ // Stage 3: Çapraz mermiler (sağdan ve soldan da gelebilir)
+ {
+ bulletCount: 35,
+ bulletInterval: 800,
+ bulletScale: 0.6,
+ speedBase: 10,
+ speedRand: 3,
+ speedStep: 3.5,
+ stepEvery: 4,
+ pattern: "mixed"
+ },
+ // Stage 4: Daha hızlı ve karışık
+ {
+ bulletCount: 30,
+ bulletInterval: 700,
+ bulletScale: 0.55,
+ speedBase: 12,
+ speedRand: 4,
+ speedStep: 4,
+ stepEvery: 3,
+ pattern: "mixed"
+ },
+ // Stage 5: Son aşama, çok hızlı ve yoğun
+ {
+ bulletCount: 25,
+ bulletInterval: 600,
+ bulletScale: 0.5,
+ speedBase: 14,
+ speedRand: 5,
+ speedStep: 5,
+ stepEvery: 2,
+ pattern: "mixed"
+ }];
function startChapter1Bullets() {
isGameActive = true;
var currentStage = 0;
- // İlk aşama başlamadan önce intro diyalogunu göster
- var chapter1Stages = [{
- bulletCount: 50,
- bulletInterval: 1200,
- bulletScale: 0.7,
- speedBase: 7,
- speedRand: 2,
- speedStep: 2.5,
- stepEvery: 5,
- pattern: "vertical",
- introDialogue: {
- lines: ["*khkhkhhht* Agent Shadow, you’re ", "active. The Light’s forces are hunting", "you. Stay unseen, move fast. *khkht*"],
- speaker: "???",
- walkie: true,
- continueText: "click to continue.."
- },
- outroDialogue: {
- lines: ["You’re alive… For now. But the enemy will hit harder. Prepare."],
- speaker: "",
- walkie: false,
- continueText: "click to continue.."
- }
- }, {
- bulletCount: 40,
- bulletInterval: 900,
- bulletScale: 0.7,
- speedBase: 13,
- speedRand: 5,
- speedStep: 0,
- stepEvery: 999,
- pattern: "targeted",
- introDialogue: {
- lines: ["The enemy’s tracking you, Shadow. Trick them with your Shadow Clone. Move."],
- speaker: "",
- walkie: false,
- continueText: "click to continue.."
- },
- outroDialogue: {
- lines: ["Your clone worked. But these enemies don’t quit. More are coming."],
- speaker: "",
- walkie: false,
- continueText: "click to continue.."
- }
- }, {
- bulletCount: 35,
- bulletInterval: 800,
- bulletScale: 0.6,
- speedBase: 10,
- speedRand: 3,
- speedStep: 3.5,
- stepEvery: 4,
- pattern: "mixed",
- introDialogue: null,
- outroDialogue: null
- }, {
- bulletCount: 30,
- bulletInterval: 700,
- bulletScale: 0.55,
- speedBase: 12,
- speedRand: 4,
- speedStep: 4,
- stepEvery: 3,
- pattern: "mixed",
- introDialogue: null,
- outroDialogue: null
- }, {
- bulletCount: 25,
- bulletInterval: 600,
- bulletScale: 0.5,
- speedBase: 14,
- speedRand: 5,
- speedStep: 5,
- stepEvery: 2,
- pattern: "mixed",
- introDialogue: null,
- outroDialogue: null
- }];
// Diyalog ekranı gösterici
function showDialogue(options, onContinue) {
// options: { lines: [], speaker: "", walkie: true/false, continueText: string }
var dialogueBg = LK.getAsset('dialoguebackground', {
gri bir yuvarlak. In-Game asset. 2d. High contrast. No shadows
white bullet. In-Game asset. 2d. High contrast. No shadows
kırmızı gözler, gözler sadece kırmızı, gözden başka hiçbir şey olmayacak ve 2 tane göz olacak yan yana aynı boyutta, dümdüz kırmızı gözleri ekstra efekt yok, yazı yok, gözler dikine dikdörtgen şeklinde olacak gerçek göz gibi olmayacaklar, gözlerin boşlukları olmayacak gözler köşeli olacak dikine dikdörtgen ve köşeli. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
white color circle. In-Game asset. 2d. High contrast. No shadows
rectangle with rounded edges (color white) (the edges will white too). In-Game asset. 2d. High contrast. No shadows
black walkie talkie. In-Game asset. 2d. High contrast. No shadows
only text no image, agent shadow text logo for agent game. In-Game asset. 2d. High contrast. No shadows
black rectangle (rounded corners). In-Game asset. 2d. High contrast. No shadows
lock icon. no text. only white color. In-Game asset. 2d. High contrast. No shadows
ünlem işareti kırmızı. In-Game asset. 2d. High contrast. No shadows
game skill logo, skill name is "shadow". no text. only image.. In-Game asset. 2d. High contrast. No shadows