Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
add new assets specialboss_locked specialboss_unlocked
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 359
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '0')' in or related to this line: 'return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;' Line Number: 359
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (18 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ggame is not defined' in or related to this line: 'ggame.update = function () {' Line Number: 1468
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (4 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'height')' in or related to this line: 'LK.gui.top.add(new Text2('SONG ENDED', {' Line Number: 920
Code edit (11 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'height')' in or related to this line: 'playerHpBarContainer.y = LK.data.height - 80; // Pozycja Y na dole (LK.data.height to wysokość ekranu)' Line Number: 698
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'stringify')' in or related to this line: 'console.log("Swipe BBox:", JSON.stringify(swipeBoundingBox));' Line Number: 497
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Note = Container.expand(function (noteType, swipeDir, targetHitTimeFull, centerXVal) {
var self = Container.call(this);
self.noteType = noteType || 'tap';
self.swipeDir = swipeDir || null;
self.targetHitTime = targetHitTimeFull;
self.visualSpawnTime = self.targetHitTime - noteTravelTime;
self.hit = false;
self.judged = false;
self.scaleStart = 0.3;
self.scaleEnd = 1.2;
self.centerX = centerXVal;
self.centerY = 1800;
self.startY = 600;
self.noteAsset = null;
self.isWiderSwipePart = false; // Flag for wider swipe rendering if needed later
// Store original columnIndex if available, for potential debugging or advanced logic
if (this.mapData && this.mapData.originalColumnHint !== undefined) {
self.originalColumnHint = this.mapData.originalColumnHint;
}
if (self.noteType === 'tap') {
self.noteAsset = self.attachAsset('tapNote', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.noteType === 'swipe') {
self.noteAsset = self.attachAsset('swipeNote', {
anchorX: 0.5,
anchorY: 0.5
});
if (self.swipeDir) {
var arrow = new Text2('', {
size: 80,
fill: 0xFFFFFF
});
arrow.anchor.set(0.5, 0.5);
if (self.swipeDir === 'left') {
arrow.setText('←');
} else if (self.swipeDir === 'right') {
arrow.setText('→');
} else if (self.swipeDir === 'up') {
arrow.setText('↑');
} else if (self.swipeDir === 'down') {
arrow.setText('↓');
}
self.addChild(arrow);
self.arrow = arrow;
}
} else if (self.noteType === 'trap') {
self.noteAsset = self.attachAsset('trapNote', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.alpha = 0;
self.showHitFeedback = function (result) {
// Existing circular feedback
var feedbackCircle = LK.getAsset('hitFeedback', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
// Relative to the note's center
y: 0,
// Relative to the note's center
scaleX: 0.7,
scaleY: 0.7,
alpha: 0.7
});
var feedbackTextContent = "";
var feedbackTextColor = 0xFFFFFF; // Default white
if (result === 'perfect') {
feedbackCircle.tint = 0xffff00; // Yellow
feedbackTextContent = "Perfect!"; // Or "+100"
feedbackTextColor = 0xffff00;
} else if (result === 'good') {
feedbackCircle.tint = 0x00ff00; // Green
feedbackTextContent = "Good!"; // Or "+50"
feedbackTextColor = 0x00ff00;
} else {
// 'miss'
feedbackCircle.tint = 0xff0000; // Red
feedbackTextContent = "Miss";
feedbackTextColor = 0xff0000;
}
self.addChild(feedbackCircle); // Add circle to the note container
tween(feedbackCircle, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 350,
easing: tween.easeOut,
onFinish: function onFinish() {
if (feedbackCircle.parent) {
feedbackCircle.destroy();
}
}
});
// New text feedback
if (feedbackTextContent) {
var scorePopup = new Text2(feedbackTextContent, {
size: 60,
// Możemy dostosować rozmiar
fill: feedbackTextColor,
stroke: 0x000000,
// Czarny kontur dla lepszej czytelności
strokeThickness: 3
});
scorePopup.anchor.set(0.5, 0.5);
scorePopup.x = 0; // W centrum notatki (tam gdzie feedbackCircle)
scorePopup.y = -SWIPE_NOTE_WIDTH / 2 - 30; // Trochę nad notatką (zakładając, że notatka ma środek w 0,0)
// Możemy potrzebować dostosować Y, jeśli anchor notatki jest inny
// Add to the main game layer (or LK.gui.top) so it's not affected by note's alpha/scale changes later
// If added to self (note), it would disappear if note is quickly destroyed.
// Let's add it to the note's parent (which should be 'game')
if (self.parent) {
// Ensure note has a parent
// Position needs to be absolute if added to game layer
scorePopup.x = self.x + 0; // (self.x (Note's absolute X) + relative X (0))
scorePopup.y = self.y - SWIPE_NOTE_WIDTH * self.scale.y / 2 - 30; // (self.y (Note's absolute Y) + relative Y)
self.parent.addChild(scorePopup); // Add to the same layer as the note
}
tween(scorePopup, {
y: scorePopup.y - 80,
// Animacja w górę
alpha: 0
}, {
duration: 700,
// Dłuższy czas trwania animacji
easing: tween.easeOut,
onFinish: function onFinish() {
if (scorePopup.parent) {
scorePopup.destroy();
}
}
});
}
};
self.update = function () {
var now = Date.now();
if (self.judged) {
// If judged (hit or missed), it might still be moving for a bit
if (now > self.targetHitTime + 500) {// Time after hit/miss to be fully removed by removeOldNotes
// This note is done, removeOldNotes will handle it.
// If it was hit, its alpha might be 0 from feedback animation.
// If it was missed and had flash, it's visible.
// We can explicitly hide it here if we want it to disappear sooner than removeOldNotes.
// self.alpha = 0; // Opcjonalnie, aby szybciej zniknęła po ocenie
}
// Allow it to continue moving based on original trajectory if needed for visual effect
// For simplicity, if judged, we mostly let removeOldNotes handle it.
// However, if we want it to continue moving PAST the hit line visibly:
if (this.alpha > 0) {
// Only update position if visible
var elapsedTimeSinceSpawn = now - self.visualSpawnTime;
var currentProgress = elapsedTimeSinceSpawn / noteTravelTime;
// No clamping progress to 1 here, so it can go beyond
self.x = self.centerX;
self.y = self.startY + (self.centerY - self.startY) * currentProgress;
// Keep scale at max after passing hit line
var currentScale = currentProgress >= 1 ? self.scaleEnd : self.scaleStart + (self.scaleEnd - self.scaleStart) * currentProgress;
self.scale.x = Math.max(0.01, currentScale);
self.scale.y = Math.max(0.01, currentScale);
}
return;
}
if (now < self.visualSpawnTime) {
self.alpha = 0;
return;
}
if (self.alpha === 0 && !self.judged) {
self.alpha = 1;
}
var elapsedTimeSinceSpawn = now - self.visualSpawnTime;
var progress = elapsedTimeSinceSpawn / noteTravelTime;
// Notatka leci dalej, więc progress może być > 1
// Nie ograniczamy już progress do 1 tutaj dla pozycji i skali
// Skala osiąga self.scaleEnd przy progress = 1 i tak pozostaje
var scale;
if (progress >= 1) {
scale = self.scaleEnd;
} else if (progress < 0) {
// Powinno być obsłużone przez visualSpawnTime check, ale dla pewności
scale = self.scaleStart;
progress = 0; // Clamp progress for position if it was somehow negative
} else {
scale = self.scaleStart + (self.scaleEnd - self.scaleStart) * progress;
}
self.scale.x = Math.max(0.01, scale);
self.scale.y = Math.max(0.01, scale);
self.x = self.centerX;
self.y = self.startY + (self.centerY - self.startY) * progress; // Pozwalamy Y iść dalej
// Oznacz jako miss, jeśli nie została oceniona i minął czas + okno tolerancji
if (!self.judged && now > self.targetHitTime + hitWindowGood) {
self.judged = true; // Oznaczona jako oceniona (w tym przypadku jako miss)
if (self.noteType !== 'trap') {
game.onNoteMiss(self); // Wywołaj logikę miss
}
// Notatka będzie dalej widoczna i usuwana przez removeOldNotes
}
};
self.isInHitWindow = function () {
var now = Date.now();
var dt = Math.abs(now - self.targetHitTime);
return dt <= hitWindowGood;
};
self.getHitAccuracy = function () {
var now = Date.now();
var dt = Math.abs(now - self.targetHitTime);
if (dt <= hitWindowPerfect) {
return 'perfect';
}
if (dt <= hitWindowGood) {
return 'good';
}
return 'miss';
};
return self;
});
var PowerUpItem = Container.expand(function (powerUpType, centerXVal) {
var self = Container.call(this);
self.itemType = powerUpType;
self.centerX = centerXVal;
self.startY = 600;
self.centerY = 1800; // Linia uderzenia/zbierania
self.visualAsset = null;
self.collected = false;
self.spawnTime = Date.now();
self.isAtDestinationAndPotentiallyMissed = false; // Nowa flaga
if (self.itemType === 'potion') {
self.visualAsset = self.attachAsset('hpPotionAsset', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.itemType === 'shield') {
self.visualAsset = self.attachAsset('shieldAsset', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (self.itemType === 'swipeToTap') {
self.visualAsset = self.attachAsset('swipeToTapBuffAsset', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
console.log("Error: Nieznany typ PowerUpa przy tworzeniu assetu: " + self.itemType);
self.visualAsset = self.attachAsset('hpPotionAsset', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.alpha = 1;
self.scale.set(1);
self.x = self.centerX; // Ustawienie początkowej pozycji X
self.y = self.startY; // Ustawienie początkowej pozycji Y
self.update = function () {
if (self.collected) {
// Jeśli zebrany, nic więcej nie rób (zostanie usunięty przez managePowerUpItems)
return;
}
// Jeśli w poprzedniej klatce dotarł do celu i nie został zebrany, teraz go usuwamy
if (self.isAtDestinationAndPotentiallyMissed) {
if (!self.collected) {
// Podwójne sprawdzenie, na wszelki wypadek
console.log("PowerUp " + self.itemType + " ostatecznie minięty i niszczony");
if (self.parent) {
self.destroy();
}
}
return; // Kończymy update dla tego obiektu
}
var now = Date.now();
var progress = (now - self.spawnTime) / noteTravelTime;
if (progress >= 1) {
self.y = self.centerY; // Ustawiamy dokładnie na linii uderzenia
// Dotarł do linii. Ustawiamy flagę, ale nie niszczymy od razu.
// Zniszczenie (jeśli nie zebrany) nastąpi w następnej klatce update().
// Daje to szansę na zarejestrowanie kliknięcia w tej klatce.
self.isAtDestinationAndPotentiallyMissed = true;
// Na tym etapie jeszcze nie logujemy "minięty", bo może zostać kliknięty w tej klatce.
} else {
// Nadal w ruchu
self.y = self.startY + (self.centerY - self.startY) * progress;
}
};
self.collect = function () {
if (self.collected) {
return;
}
self.collected = true;
console.log("PowerUp " + self.itemType + " zebrany!");
if (collectedPowerUps.hasOwnProperty(self.itemType)) {
collectedPowerUps[self.itemType]++;
console.log("Masz teraz " + collectedPowerUps[self.itemType] + " x " + self.itemType);
updatePowerUpDisplayCounts(); // NOWE: Aktualizuj UI po zebraniu
}
if (self.parent) {
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181828
});
/****
* Game Code
****/
function _typeof2(o) {
"@babel/helpers - typeof";
return _typeof2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof2(o);
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function showStartScreen() {
currentScreenState = 'start';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
hitZoneLine.visible = false;
}
// Usunięte linie ukrywające shieldTimerDisplayContainer i swipeToTapTimerDisplayContainer,
// ponieważ teraz nie powinny być w ogóle tworzone w tym stanie.
game.setBackgroundColor(0x000000);
var startButton = new Text2("MAKE SOME NOISEE", {
size: 150,
fill: 0xFFFFFF
});
startButton.anchor.set(0.5, 0.5);
startButton.x = gameScreenWidth / 2;
startButton.y = gameScreenHeight / 2;
startButton.interactive = true;
startButton.cursor = "pointer";
game.addChild(startButton);
startButton.down = function () {
if (startButton.parent) {
startButton.destroy();
}
showIntro();
};
}
function showMainMenu() {
currentScreenState = 'mainmenu';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
hitZoneLine.visible = false;
}
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
}
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
game.setBackgroundColor(0x2a2a2a); // Inny kolor tła dla menu głównego
var menuItems = []; // Tablica do przechowywania elementów menu dla łatwego czyszczenia
var titleText = new Text2("MAIN MENU", {
// Dodajmy tytuł ekranu
size: 180,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = gameScreenWidth / 2;
titleText.y = 300; // Na górze ekranu
game.addChild(titleText);
menuItems.push(titleText);
var buttonYStart = 700;
var buttonYSpacing = 250;
var buttonFontSize = 120;
// Przycisk "Music Battle"
var musicBattleButton = new Text2("Music Battle", {
size: buttonFontSize,
fill: 0xFFD700 // Złoty kolor dla wyróżnienia
});
musicBattleButton.anchor.set(0.5, 0.5);
musicBattleButton.x = gameScreenWidth / 2;
musicBattleButton.y = buttonYStart;
musicBattleButton.interactive = true;
musicBattleButton.cursor = "pointer";
game.addChild(musicBattleButton);
menuItems.push(musicBattleButton);
musicBattleButton.down = function () {
menuItems.forEach(function (item) {
if (item.parent) {
item.destroy();
}
});
showBossSelectionScreen();
};
// Przycisk "How To Play"
var howToPlayButton = new Text2("How To Play", {
size: buttonFontSize,
fill: 0xFFFFFF
});
howToPlayButton.anchor.set(0.5, 0.5);
howToPlayButton.x = gameScreenWidth / 2;
howToPlayButton.y = buttonYStart + buttonYSpacing;
howToPlayButton.interactive = true;
howToPlayButton.cursor = "pointer";
game.addChild(howToPlayButton);
menuItems.push(howToPlayButton);
howToPlayButton.down = function () {
menuItems.forEach(function (item) {
if (item.parent) {
item.destroy();
}
});
showTutorial();
};
// Przycisk "Credits"
var creditsButton = new Text2("Credits", {
size: buttonFontSize,
fill: 0xFFFFFF
});
creditsButton.anchor.set(0.5, 0.5);
creditsButton.x = gameScreenWidth / 2;
creditsButton.y = buttonYStart + buttonYSpacing * 2;
creditsButton.interactive = true;
creditsButton.cursor = "pointer";
game.addChild(creditsButton);
menuItems.push(creditsButton);
creditsButton.down = function () {
menuItems.forEach(function (item) {
if (item.parent) {
item.destroy();
}
});
showCreditsScreen();
};
}
var allBossData = [];
var currentBossViewStartIndex = 0;
var visibleBossCards = [null, null, null, null];
var selectedCardSlotIndex = 0;
var currentlyPlayingMusic = null;
var placeholderMusicKey = 'test1';
var placeholderSongMapKey = 'defaultTestTrack';
function initializeBossData() {
allBossData = [{
id: 'boss1',
displayName: 'Boss 1',
cardAssetKey: 'boss1',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss2',
displayName: 'Boss 2',
cardAssetKey: 'boss2',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss3',
displayName: 'Boss 3',
cardAssetKey: 'boss3',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss4',
displayName: 'Boss 4',
cardAssetKey: 'boss4',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss5',
displayName: 'Boss 5',
cardAssetKey: 'boss5',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss6',
displayName: 'Boss 6',
cardAssetKey: 'boss6',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss7',
displayName: 'Boss 7',
cardAssetKey: 'boss7',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}, {
id: 'boss8',
displayName: 'Boss 8',
cardAssetKey: 'boss8',
musicAssetKey: placeholderMusicKey,
songMapKey: placeholderSongMapKey
}];
}
function updateSelectedCardVisual() {
for (var i = 0; i < visibleBossCards.length; i++) {
var cardContainer = visibleBossCards[i];
if (cardContainer && cardContainer.visualAsset) {
if (i === selectedCardSlotIndex) {
cardContainer.visualAsset.tint = 0xFFFF00;
cardContainer.scale.set(1.05);
} else {
cardContainer.visualAsset.tint = 0xFFFFFF;
cardContainer.scale.set(1.0);
}
}
}
}
function displayBossCards(newStartIndex, isInitialDisplay) {
currentBossViewStartIndex = newStartIndex;
var cardSlotsPositions = [{
x: gameScreenWidth / 2 - 220,
y: gameScreenHeight / 2 - 300
}, {
x: gameScreenWidth / 2 + 20,
y: gameScreenHeight / 2 - 300
}, {
x: gameScreenWidth / 2 - 220,
y: gameScreenHeight / 2 + 20
}, {
x: gameScreenWidth / 2 + 20,
y: gameScreenHeight / 2 + 20
}];
for (var i = 0; i < visibleBossCards.length; i++) {
if (visibleBossCards[i] && visibleBossCards[i].parent) {
visibleBossCards[i].destroy();
}
visibleBossCards[i] = null;
}
for (var i = 0; i < 4; i++) {
var dataIndex = currentBossViewStartIndex + i;
if (dataIndex < allBossData.length) {
var bossData = allBossData[dataIndex];
var cardContainer = new Container();
cardContainer.x = cardSlotsPositions[i].x;
cardContainer.y = cardSlotsPositions[i].y;
cardContainer.bossData = bossData;
cardContainer.slotIndex = i;
var cardAsset = LK.getAsset(bossData.cardAssetKey, {});
cardAsset.anchor.set(0.5, 0.5);
cardContainer.visualAsset = cardAsset;
cardContainer.addChild(cardAsset);
var nameText = new Text2(bossData.displayName, {
size: 30,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 2
});
nameText.anchor.set(0.5, 0);
nameText.x = 0;
nameText.y = cardAsset.height / 2 + 5;
cardContainer.addChild(nameText);
cardContainer.interactive = true;
cardContainer.cursor = "pointer";
cardContainer.down = function () {
selectedCardSlotIndex = this.slotIndex;
updateSelectedCardVisual();
console.log("Zaznaczono kartę: " + this.bossData.displayName + " w slocie " + this.slotIndex);
};
game.addChild(cardContainer);
visibleBossCards[i] = cardContainer;
}
}
if (isInitialDisplay) {
selectedCardSlotIndex = 0;
} else {
var maxSlotOnNewPage = Math.min(3, allBossData.length - 1 - currentBossViewStartIndex);
if (selectedCardSlotIndex > maxSlotOnNewPage) {
selectedCardSlotIndex = maxSlotOnNewPage;
}
}
updateSelectedCardVisual();
}
function showBossSelectionScreen() {
currentScreenState = 'bossGallery_paged';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
hitZoneLine.visible = false;
}
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
}
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
game.setBackgroundColor(0x101020);
initializeBossData();
var screenElements = [];
// --- GŁÓWNA RAMKA WIZUALNA ---
var mainFrame = LK.getAsset('galleryFrame', {});
mainFrame.width = 920; // PRZYKŁADOWA szerokość ramki (aby objąć karty 200+30+200 = 430, plus margines)
mainFrame.height = 970; // PRZYKŁADOWA wysokość ramki (aby objąć karty 280+30+280 = 590, plus margines)
mainFrame.x = gameScreenWidth / 2; // Ramka wyśrodkowana
mainFrame.y = gameScreenHeight / 2 - 50; // Ramka wyśrodkowana pionowo z tym samym offsetem co karty
mainFrame.anchor.set(0.5, 0.5);
game.addChild(mainFrame);
screenElements.push(mainFrame);
// --- Przyciski Nawigacyjne (lewa strona) ---
var upButton = LK.getAsset('upbutton', {});
upButton.x = 500; // SZTYWNA POZYCJA X
upButton.y = gameScreenHeight / 2 - 50; // SZTYWNA POZYCJA Y
upButton.anchor.set(0.5, 0.5);
upButton.interactive = true;
upButton.cursor = "pointer";
upButton.down = function () {
var newIndex = Math.max(0, currentBossViewStartIndex - 4);
if (newIndex !== currentBossViewStartIndex) {
displayBossCards(newIndex, false);
}
};
game.addChild(upButton);
screenElements.push(upButton);
var downButton = LK.getAsset('downbutton', {});
downButton.x = 500; // SZTYWNA POZYCJA X
downButton.y = gameScreenHeight / 2 + 70; // SZTYWNA POZYCJA Y
downButton.anchor.set(0.5, 0.5);
downButton.interactive = true;
downButton.cursor = "pointer";
downButton.down = function () {
var newIndex = currentBossViewStartIndex + 4;
if (newIndex < allBossData.length) {
displayBossCards(newIndex, false);
}
};
game.addChild(downButton);
screenElements.push(downButton);
// --- Przyciski Akcji (prawa strona) ---
var playButton = LK.getAsset('play', {});
playButton.x = gameScreenWidth - 600; // SZTYWNA POZYCJA X
playButton.y = gameScreenHeight / 2 - 120; // SZTYWNA POZYCJA Y
playButton.anchor.set(0.5, 0.5);
playButton.interactive = true;
playButton.cursor = "pointer";
playButton.down = function () {
var selectedBossData = allBossData[currentBossViewStartIndex + selectedCardSlotIndex];
if (selectedBossData) {
if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
currentlyPlayingMusic.stop();
}
currentlyPlayingMusic = LK.getSound(selectedBossData.musicAssetKey);
if (currentlyPlayingMusic && typeof currentlyPlayingMusic.play === 'function') {
currentlyPlayingMusic.play();
}
}
};
game.addChild(playButton);
screenElements.push(playButton);
var stopButton = LK.getAsset('stop', {});
stopButton.x = gameScreenWidth - 600; // SZTYWNA POZYCJA X
stopButton.y = gameScreenHeight / 2; // SZTYWNA POZYCJA Y
stopButton.anchor.set(0.5, 0.5);
stopButton.interactive = true;
stopButton.cursor = "pointer";
stopButton.down = function () {
if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
currentlyPlayingMusic.stop();
currentlyPlayingMusic = null;
}
};
game.addChild(stopButton);
screenElements.push(stopButton);
var fightButton = LK.getAsset('fight', {});
fightButton.x = gameScreenWidth - 600; // SZTYWNA POZYCJA X
fightButton.y = gameScreenHeight / 2 + 120; // SZTYWNA POZYCJA Y
fightButton.anchor.set(0.5, 0.5);
fightButton.interactive = true;
fightButton.cursor = "pointer";
fightButton.down = function () {
var selectedBossData = allBossData[currentBossViewStartIndex + selectedCardSlotIndex];
if (selectedBossData) {
if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
currentlyPlayingMusic.stop();
currentlyPlayingMusic = null;
}
screenElements.forEach(function (el) {
if (el && el.parent) {
el.destroy();
}
});
screenElements = [];
for (var i = 0; i < visibleBossCards.length; i++) {
if (visibleBossCards[i] && visibleBossCards[i].parent) {
visibleBossCards[i].destroy();
}
visibleBossCards[i] = null;
}
loadSong(selectedBossData.songMapKey);
}
};
game.addChild(fightButton);
screenElements.push(fightButton);
// --- Przycisk "Special Boss" ---
var specialBossButtonAsset = LK.getAsset('specialBossArea', {});
specialBossButtonAsset.width = 400; // SZTYWNA SZEROKOŚĆ (szeroki)
specialBossButtonAsset.height = 70; // SZTYWNA WYSOKOŚĆ (wąski)
specialBossButtonAsset.x = gameScreenWidth / 2; // SZTYWNA POZYCJA X (na środku)
specialBossButtonAsset.y = gameScreenHeight * 0.70; // SZTYWNA POZYCJA Y (np. 80% wysokości ekranu)
specialBossButtonAsset.anchor.set(0.5, 0.5);
var specialBossText = new Text2("SPECIAL BOSS", {
size: 30,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 2
});
specialBossText.anchor.set(0.5, 0.5);
if (typeof specialBossButtonAsset.addChild === 'function') {
specialBossButtonAsset.addChild(specialBossText);
} else {
specialBossText.x = specialBossButtonAsset.x;
specialBossText.y = specialBossButtonAsset.y;
game.addChild(specialBossText);
screenElements.push(specialBossText);
}
specialBossButtonAsset.interactive = true;
specialBossButtonAsset.cursor = "pointer";
specialBossButtonAsset.down = function () {
var infoPopup = new Text2("Pokonaj wszystkich pozostałych bossów!", {
size: 40,
fill: 0xFF0000,
stroke: 0x000000,
strokeThickness: 2,
align: 'center',
wordWrap: true,
wordWrapWidth: gameScreenWidth * 0.8
});
infoPopup.anchor.set(0.5, 0.5);
infoPopup.x = gameScreenWidth / 2;
infoPopup.y = gameScreenHeight / 2;
game.addChild(infoPopup);
LK.setTimeout(function () {
if (infoPopup.parent) {
infoPopup.destroy();
}
}, 3500);
};
game.addChild(specialBossButtonAsset);
screenElements.push(specialBossButtonAsset);
// --- Przycisk Powrotu ---
var backToMainButton = new Text2("Back to Main Menu", {
size: 50,
fill: 0xDDDDDD
});
backToMainButton.anchor.set(0.5, 1);
backToMainButton.x = gameScreenWidth / 2;
backToMainButton.y = gameScreenHeight - 20;
backToMainButton.interactive = true;
backToMainButton.cursor = "pointer";
backToMainButton.down = function () {
if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
currentlyPlayingMusic.stop();
currentlyPlayingMusic = null;
}
screenElements.forEach(function (el) {
if (el && el.parent) {
el.destroy();
}
});
screenElements = [];
for (var i = 0; i < visibleBossCards.length; i++) {
if (visibleBossCards[i] && visibleBossCards[i].parent) {
visibleBossCards[i].destroy();
}
visibleBossCards[i] = null;
}
currentBossViewStartIndex = 0;
selectedCardSlotIndex = 0;
showMainMenu();
};
game.addChild(backToMainButton);
screenElements.push(backToMainButton);
displayBossCards(0, true); // Wyświetla karty na środku
}
// Pamiętaj, aby wywołaċ initializeBossData(); gdzieś na początku, np. po deklaracjach zmiennych globalnych.
// Aby uruchomiċ ten ekran, wywołaj showBossSelectionScreen();
function showCreditsScreen() {
currentScreenState = 'credits';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
hitZoneLine.visible = false;
}
game.setBackgroundColor(0x1a1a1a); // Ciemnoszary dla creditsów
var elements = [];
var creditsText = new Text2("Gra stworzona przez:\nNasz Wspaniały Duet!", {
size: 90,
fill: 0xFFFFFF,
align: 'center' // Wyśrodkowanie tekstu wieloliniowego
});
creditsText.anchor.set(0.5, 0.5);
creditsText.x = gameScreenWidth / 2;
creditsText.y = gameScreenHeight / 2 - 100;
game.addChild(creditsText);
elements.push(creditsText);
var backButton = new Text2("Back to Menu", {
size: 80,
fill: 0xCCCCCC
});
backButton.anchor.set(0.5, 0.5);
backButton.x = gameScreenWidth / 2;
backButton.y = gameScreenHeight - 200;
backButton.interactive = true;
backButton.cursor = "pointer";
game.addChild(backButton);
elements.push(backButton);
backButton.down = function () {
elements.forEach(function (item) {
if (item.parent) {
item.destroy();
}
});
showMainMenu();
};
}
function showIntro() {
currentScreenState = 'intro';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
hitZoneLine.visible = false;
}
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
}
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
game.setBackgroundColor(0x111111);
var introPlaceholderText = new Text2("Intro Sequence Placeholder", {
size: 100,
fill: 0xFFFFFF
});
introPlaceholderText.anchor.set(0.5, 0.5);
introPlaceholderText.x = gameScreenWidth / 2;
introPlaceholderText.y = gameScreenHeight / 2;
game.addChild(introPlaceholderText);
LK.setTimeout(function () {
if (introPlaceholderText.parent) {
introPlaceholderText.destroy();
}
showMainMenu(); // <<<< ZMIANA TUTAJ
}, 1000);
}
function showTutorial() {
currentScreenState = 'tutorial';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
hitZoneLine.visible = false;
}
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
} // Pozostawiam na wszelki wypadek
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
} // Pozostawiam na wszelki wypadek
game.setBackgroundColor(0x222222);
var elements = [];
var tutorialPlaceholderText = new Text2("Tutorial Placeholder\n(Tu będzie super tutorial!)", {
size: 100,
fill: 0xFFFFFF,
align: 'center'
});
tutorialPlaceholderText.anchor.set(0.5, 0.5);
tutorialPlaceholderText.x = gameScreenWidth / 2;
tutorialPlaceholderText.y = gameScreenHeight / 2 - 100;
game.addChild(tutorialPlaceholderText);
elements.push(tutorialPlaceholderText);
var backButton = new Text2("Back to Menu", {
size: 80,
fill: 0xCCCCCC
});
backButton.anchor.set(0.5, 0.5);
backButton.x = gameScreenWidth / 2;
backButton.y = gameScreenHeight - 200;
backButton.interactive = true;
backButton.cursor = "pointer";
game.addChild(backButton);
elements.push(backButton);
backButton.down = function () {
elements.forEach(function (item) {
if (item.parent) {
item.destroy();
}
});
showMainMenu();
};
}
var currentScreenState = '';
var gameScreenWidth = 2048;
var gameScreenHeight = Math.round(gameScreenWidth * (2732 / 2048)); // iPad-like proportions
var playfieldWidth = 1408;
var playfieldStartX = (gameScreenWidth - playfieldWidth) / 2;
var NUM_COLUMNS = 4;
var columnWidth = playfieldWidth / NUM_COLUMNS;
var columnCenterXs = [];
for (var i = 0; i < NUM_COLUMNS; i++) {
columnCenterXs.push(playfieldStartX + i * columnWidth + columnWidth / 2);
}
var SWIPE_NOTE_WIDTH = 160;
// HP System Variables
var playerMaxHP = 10;
var playerCurrentHP = 10;
var bossMaxHP = 30;
var bossCurrentHP = 30;
var gameOverFlag = false;
// HP Bar UI Elements Configuration (actual elements created in setupHpBars)
var hpBarWidth = 400;
var hpBarHeight = 30;
// UI Container
var gameUIContainer; // Declare gameUIContainer
// HP Bar Containers (will be initialized in setupHpBars)
var playerHpBarContainer;
var playerHpBarFill;
var bossHpBarContainer;
var bossHpBarFill;
var POWERUP_SPAWN_INTERVAL = 2000; // Co 6 sekund
var lastPowerUpSpawnAttemptTime = 0;
var POWERUP_SPAWN_CHANCE = 0.75; // 15% szansy
var POTION_HEAL_AMOUNT = 2;
var activePowerUpItems = [];
var SHIELD_DURATION = 6000;
var isShieldActive = false;
var shieldEndTime = 0;
var SWIPE_TO_TAP_BUFF_DURATION = 5000; // Czas trwania buffa w ms (5 sekund)
var isSwipeToTapBuffActive = false;
var swipeToTapBuffEndTime = 0;
var shieldTimerDisplayContainer;
var smallShieldIconDisplay;
var shieldTimerTextDisplay;
var shieldTimerDisplayContainer;
var smallShieldIconDisplay;
var shieldTimerTextDisplay;
var swipeToTapTimerDisplayContainer; // Kontener na ikonkę timera i tekst dla buffa
var smallSwipeToTapIconDisplay; // Mniejsza ikonka buffa dla timera
var swipeToTapTimerTextDisplay;
var currentBossSprite;
var powerUpDisplayContainer; // Główny kontener na UI power-upów
var hpPotionIcon, shieldIcon, swipeToTapIcon; // Referencje do ikon
var hpPotionCountText, shieldCountText, swipeToTapCountText; // Referencje do tekstów z ilością
var collectedPowerUps = {
potion: 0,
shield: 0,
swipeToTap: 0 // Klucz 'swipeToTap' dla spójności
};
// Game State & Rhythm Logic Variables
var allSongData = {
"defaultTestTrack": {
musicAsset: null,
bossAssetKey: 'Boss1_Asset',
// <<--- NOWA WŁAŚCIWOŚĆ
config: {
playerMaxHP: 10,
//
bossMaxHP: 20 //
},
rawRhythmMap: [
// Istniejące nuty
{
time: 1000,
type: 'tap',
columnIndex: 0
}, {
time: 1800,
type: 'tap',
columnIndex: 1
}, {
time: 2600,
type: 'swipe',
swipeDir: 'left',
columnIndex: 2
}, {
time: 3400,
type: 'tap',
columnIndex: 3
}, {
time: 4200,
type: 'swipe',
swipeDir: 'right',
columnIndex: 0
}, {
time: 5000,
type: 'trap',
columnIndex: 1
}, {
time: 5800,
type: 'tap',
columnIndex: 2
}, {
time: 6600,
type: 'swipe',
swipeDir: 'right',
columnIndex: 1
}, {
time: 6600,
type: 'swipe',
swipeDir: 'right',
columnIndex: 2
}, {
time: 7400,
type: 'tap',
columnIndex: 0
},
// Dodatkowe nuty dla przedłużenia mapy
{
time: 9000,
type: 'tap',
columnIndex: 1
}, {
time: 10000,
type: 'swipe',
swipeDir: 'left',
columnIndex: 2
}, {
time: 11000,
type: 'tap',
columnIndex: 3
}, {
time: 12000,
type: 'swipe',
swipeDir: 'right',
columnIndex: 0
}, {
time: 13000,
type: 'tap',
columnIndex: 1
}, {
time: 14000,
type: 'trap',
columnIndex: 2
}, {
time: 15000,
type: 'tap',
columnIndex: 3
}, {
time: 16000,
type: 'swipe',
swipeDir: 'up',
columnIndex: 0
}, {
time: 17000,
type: 'swipe',
swipeDir: 'down',
columnIndex: 1
}, {
time: 18000,
type: 'tap',
columnIndex: 2
}, {
time: 19000,
type: 'swipe',
swipeDir: 'left',
columnIndex: 3
}, {
time: 20000,
type: 'tap',
columnIndex: 0
}, {
time: 21000,
type: 'tap',
columnIndex: 1
}, {
time: 22000,
type: 'swipe',
swipeDir: 'right',
columnIndex: 2
}, {
time: 23000,
type: 'tap',
columnIndex: 3
}, {
time: 24000,
type: 'swipe',
swipeDir: 'up',
columnIndex: 1
}, {
time: 25000,
type: 'swipe',
swipeDir: 'down',
columnIndex: 2
}, {
time: 26000,
type: 'tap',
columnIndex: 0
}, {
time: 27000,
type: 'tap',
columnIndex: 3
}]
},
"test3": {
// Pozostaje bez zmian, chyba że też chcesz go modyfikować
musicAsset: "test3",
config: {
playerMaxHP: 10,
bossMaxHP: 30
}
}
};
var currentActiveRhythmMap = null;
var currentMusic = null;
var noteTravelTime = 2200;
var hitWindowPerfect = 190;
var hitWindowGood = 260;
var MIN_SWIPE_DISTANCE = 60;
var notes = [];
var nextNoteIdx = 0;
var gameStartTime = 0;
var score = 0;
var combo = 0;
var maxCombo = 0;
var swipeStart = null;
var inputLocked = false;
var hpBarsInitialized = false;
// Initialize and add gameUIContainer to the game scene
gameUIContainer = new Container();
game.addChild(gameUIContainer);
// Function to process raw rhythm map data (remains unchanged, ensure it's here)
function processRawRhythmMap(rawMapData, songKeyForLogging) {
console.log("Processing raw map for: " + songKeyForLogging + " with " + rawMapData.length + " initial notes.");
var processedMap = [];
var tempMap = [];
for (var k = 0; k < rawMapData.length; k++) {
var originalNote = rawMapData[k];
var copiedNote = {};
for (var key in originalNote) {
if (originalNote.hasOwnProperty(key)) {
copiedNote[key] = originalNote[key];
}
}
tempMap.push(copiedNote);
}
for (var i = 0; i < tempMap.length; i++) {
var note = tempMap[i];
if (note.type === 'swipe' && note.swipeDir) {
var dir = note.swipeDir.toLowerCase();
if (dir.includes('right')) {
note.swipeDir = 'right';
} else if (dir.includes('left')) {
note.swipeDir = 'left';
} else if (dir.includes('up')) {
note.swipeDir = 'up';
} else if (dir.includes('down')) {
note.swipeDir = 'down';
}
}
}
var timeGroupedNotes = {};
tempMap.forEach(function (note) {
if (!timeGroupedNotes[note.time]) {
timeGroupedNotes[note.time] = [];
}
timeGroupedNotes[note.time].push(note);
});
var finalMapNotes = [];
var sortedTimes = Object.keys(timeGroupedNotes).map(Number).sort(function (a, b) {
return a - b;
});
for (var tIdx = 0; tIdx < sortedTimes.length; tIdx++) {
var time = sortedTimes[tIdx];
var notesAtThisTime = timeGroupedNotes[time];
var notesToKeepAtThisTime = [];
var processedForWiderSwipeConversion = [];
var colsWithVerticalSwipes = [null, null, null, null];
notesAtThisTime.forEach(function (note) {
if (note.type === 'swipe' && (note.swipeDir === 'up' || note.swipeDir === 'down')) {
if (note.columnIndex >= 0 && note.columnIndex < NUM_COLUMNS) {
var alreadyConverted = false;
for (var convIdx = 0; convIdx < processedForWiderSwipeConversion.length; convIdx++) {
if (processedForWiderSwipeConversion[convIdx].originalTime === note.time && processedForWiderSwipeConversion[convIdx].originalColumn === note.columnIndex) {
alreadyConverted = true;
break;
}
}
if (!alreadyConverted) {
colsWithVerticalSwipes[note.columnIndex] = note.swipeDir;
}
}
}
});
for (var c = 0; c < NUM_COLUMNS - 1; c++) {
if (colsWithVerticalSwipes[c] && colsWithVerticalSwipes[c + 1] && colsWithVerticalSwipes[c] === colsWithVerticalSwipes[c + 1]) {
var randomHorizontalDir = Math.random() < 0.5 ? 'left' : 'right';
var pairCenterX = (columnCenterXs[c] + columnCenterXs[c + 1]) / 2;
notesToKeepAtThisTime.push({
time: time,
type: 'swipe',
swipeDir: randomHorizontalDir,
partOfWiderSwipe: 'leftHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: c
});
notesToKeepAtThisTime.push({
time: time,
type: 'swipe',
swipeDir: randomHorizontalDir,
partOfWiderSwipe: 'rightHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: c + 1
});
processedForWiderSwipeConversion.push({
originalTime: time,
originalColumn: c
});
processedForWiderSwipeConversion.push({
originalTime: time,
originalColumn: c + 1
});
colsWithVerticalSwipes[c] = null;
colsWithVerticalSwipes[c + 1] = null;
c++;
}
}
notesAtThisTime.forEach(function (note) {
var wasConverted = false;
for (var convIdx = 0; convIdx < processedForWiderSwipeConversion.length; convIdx++) {
if (processedForWiderSwipeConversion[convIdx].originalTime === note.time && processedForWiderSwipeConversion[convIdx].originalColumn === note.columnIndex && (note.swipeDir === 'up' || note.swipeDir === 'down')) {
wasConverted = true;
break;
}
}
if (!wasConverted) {
notesToKeepAtThisTime.push(note);
}
});
var horizontalWiderSwipePairs = {};
var notesForFinalProcessing = [];
var uniqueNotesAtThisTime = [];
var seenNotesKeysAtThisTime = {};
notesToKeepAtThisTime.forEach(function (note) {
var key = "" + note.type + "_" + (note.columnIndex !== undefined ? note.columnIndex : note.partOfWiderSwipe ? note.widerSwipePairCenterX + note.partOfWiderSwipe : '') + "_" + (note.swipeDir || '');
if (!seenNotesKeysAtThisTime[key]) {
uniqueNotesAtThisTime.push(note);
seenNotesKeysAtThisTime[key] = true;
}
});
uniqueNotesAtThisTime.sort(function (a, b) {
var valA = a.originalColumnHint !== undefined ? a.originalColumnHint : a.columnIndex !== undefined ? a.columnIndex : a.widerSwipePairCenterX || 0;
var valB = b.originalColumnHint !== undefined ? b.originalColumnHint : b.columnIndex !== undefined ? b.columnIndex : b.widerSwipePairCenterX || 0;
return valA - valB;
});
for (var nIdx = 0; nIdx < uniqueNotesAtThisTime.length; nIdx++) {
var note = uniqueNotesAtThisTime[nIdx];
if (note.partOfWiderSwipe) {
notesForFinalProcessing.push(note);
continue;
}
var potentialPartner = null;
if (nIdx + 1 < uniqueNotesAtThisTime.length) {
potentialPartner = uniqueNotesAtThisTime[nIdx + 1];
}
if (note.type === 'swipe' && (note.swipeDir === 'left' || note.swipeDir === 'right') && potentialPartner && potentialPartner.type === 'swipe' && potentialPartner.time === note.time && potentialPartner.swipeDir === note.swipeDir && potentialPartner.columnIndex === note.columnIndex + 1) {
var pairCenterX = (columnCenterXs[note.columnIndex] + columnCenterXs[potentialPartner.columnIndex]) / 2;
notesForFinalProcessing.push({
time: note.time,
type: 'swipe',
swipeDir: note.swipeDir,
partOfWiderSwipe: 'leftHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: note.columnIndex
});
notesForFinalProcessing.push({
time: potentialPartner.time,
type: 'swipe',
swipeDir: potentialPartner.swipeDir,
partOfWiderSwipe: 'rightHalf',
widerSwipePairCenterX: pairCenterX,
originalColumnHint: potentialPartner.columnIndex
});
nIdx++;
} else {
notesForFinalProcessing.push(note);
}
}
finalMapNotes.push.apply(finalMapNotes, notesForFinalProcessing);
}
var uniqueNotesOverall = [];
var seenNotesOverall = {};
finalMapNotes.sort(function (a, b) {
return a.time - b.time;
});
finalMapNotes.forEach(function (note) {
var cX;
var keyPartForColumn;
if (note.partOfWiderSwipe) {
cX = note.widerSwipePairCenterX + (note.partOfWiderSwipe === 'leftHalf' ? -(SWIPE_NOTE_WIDTH / 2) : SWIPE_NOTE_WIDTH / 2);
keyPartForColumn = "pC" + note.widerSwipePairCenterX + "h" + (note.partOfWiderSwipe === 'leftHalf' ? 'L' : 'R');
} else if (note.columnIndex !== undefined) {
cX = columnCenterXs[note.columnIndex];
keyPartForColumn = "c" + note.columnIndex;
} else {
cX = gameScreenWidth / 2;
keyPartForColumn = "cX" + cX;
}
var key = "" + note.time + "_" + note.type + "_" + keyPartForColumn + "_" + (note.swipeDir || '');
if (!seenNotesOverall[key]) {
uniqueNotesOverall.push(note);
seenNotesOverall[key] = true;
} else {
// console.log("Filtered final duplicate note: " + key);
}
});
console.log("Processed map for: " + songKeyForLogging + " FINALLY contains " + uniqueNotesOverall.length + " notes.");
return uniqueNotesOverall;
}
var hpBarsInitialized = false;
var scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF,
alpha: 1
});
scoreTxt.anchor.set(1, 0); // Anchor center-top
scoreTxt.x = gameScreenWidth / 1;
scoreTxt.y = 20; // Position from the top of its container (gameUIContainer)
gameUIContainer.addChild(scoreTxt);
console.log("Restored scoreTxt: X=" + scoreTxt.x + " Y=" + scoreTxt.y + " Visible:" + scoreTxt.visible + " Parent: gameUIContainer");
var comboTxt = new Text2('Combo: 0', {
size: 50,
// Możesz dostosować rozmiar tekstu combo
fill: 0xFFFF00,
// Żółty kolor
alpha: 0.5
});
comboTxt.anchor.set(0, 0.5);
comboTxt.x = 100;
comboTxt.y = 1000;
comboTxt.rotation = -0.26;
gameUIContainer.addChild(comboTxt);
console.log("ComboTxt positioned: X=" + comboTxt.x + " Y=" + comboTxt.y + " Visible:" + comboTxt.visible + " Parent: gameUIContainer");
var hitZoneY = 1800;
var hitZoneVisualWidth = playfieldWidth;
var hitZoneLine = LK.getAsset('lineAsset', {
anchorX: 0.5,
anchorY: 0.5,
x: gameScreenWidth / 2,
y: hitZoneY,
width: hitZoneVisualWidth,
height: 4,
alpha: 0.6
});
game.addChild(hitZoneLine);
function rectsIntersect(r1, r2) {
return !(r2.x > r1.x + r1.width || r2.x + r2.width < r1.x || r2.y > r1.y + r1.height || r2.y + r2.height < r1.y);
}
function resetGameState() {
notes.forEach(function (n) {
if (n && n.parent) {
n.destroy();
}
});
notes = [];
nextNoteIdx = 0;
score = 0;
combo = 0;
maxCombo = 0;
swipeStart = null;
inputLocked = false;
scoreTxt.setText('Score: 0');
comboTxt.setText('Combo: 0');
gameOverFlag = false;
playerCurrentHP = playerMaxHP;
bossCurrentHP = bossMaxHP;
collectedPowerUps.potion = 0;
collectedPowerUps.shield = 0;
collectedPowerUps.swipeToTap = 0;
hpBarsInitialized = false;
if (hpBarsInitialized) {
updatePowerUpDisplayCounts();
}
if (isShieldActive) {
isShieldActive = false;
if (shieldIcon) {
shieldIcon.alpha = 1.0;
}
}
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
}
if (isSwipeToTapBuffActive) {
isSwipeToTapBuffActive = false;
if (swipeToTapIcon) {
swipeToTapIcon.alpha = 1.0;
}
}
// NOWE: Ukryj timer buffa Swipe-to-Tap przy resecie
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
// Koniec NOWE
if (playerHpBarFill && bossHpBarFill) {
updatePlayerHpDisplay();
updateBossHpDisplay();
}
}
function loadSong(songKey) {
if (gameUIContainer) {
gameUIContainer.visible = true;
}
if (gameUIContainer) {
gameUIContainer.visible = true;
}
if (hitZoneLine) {
hitZoneLine.visible = true;
}
var songData = allSongData[songKey]; //
if (!songData) {
//
console.log("Error: Song data not found for key: " + songKey); //
if (allSongData["defaultTestTrack"]) {
//
songData = allSongData["defaultTestTrack"]; //
console.log("Fallback to defaultTestTrack"); //
} else {
//
currentActiveRhythmMap = []; //
console.log("No fallback song data found."); //
return; //
}
}
if (songData.config) {
//
playerMaxHP = songData.config.playerMaxHP || 10; //
bossMaxHP = songData.config.bossMaxHP || 50; //
} else {
//
playerMaxHP = 10; //
bossMaxHP = 50; //
}
if (currentMusic && typeof currentMusic.stop === 'function') {
//
currentMusic.stop(); //
}
currentMusic = null; //
// hpBarsInitialized = false; // Tę linię prawdopodobnie chcemy zostawić, aby UI się odświeżało poprawnie dla nowej piosenki, ale paski HP bossa/gracza są resetowane w resetGameState
resetGameState();
if (gameUIContainer) {
gameUIContainer.visible = true;
}
hpBarsInitialized = false; // Resetujemy flagę, aby paski HP i UI power-upów mogły się poprawnie zainicjalizować na nowo w game.update
nextNoteIdx = 0; //
// NOWA SEKCJA: Ładowanie i wyświetlanie Bossa
if (currentBossSprite && currentBossSprite.parent) {
currentBossSprite.destroy(); // Usuń poprzedniego bossa, jeśli istnieje
currentBossSprite = null;
}
if (songData.bossAssetKey) {
currentBossSprite = LK.getAsset(songData.bossAssetKey, {
anchorX: 0.5,
anchorY: 0.5
});
currentBossSprite.x = gameScreenWidth / 2;
currentBossSprite.y = 350; // Możesz dostosować tę pozycję Y
currentBossSprite.alpha = 0.8; // Możesz dostosować alpha
game.addChildAt(currentBossSprite, 0); // Dodajemy na spód sceny gry
console.log("Boss sprite '" + songData.bossAssetKey + "' loaded and added to scene.");
} else {
console.log("No bossAssetKey defined for song: " + songKey);
}
// KONIEC NOWEJ SEKCJI
if (songData.rawRhythmMap) {
//
currentActiveRhythmMap = processRawRhythmMap(songData.rawRhythmMap, songKey); //
} else {
//
currentActiveRhythmMap = []; //
console.log("Warning: No rawRhythmMap for song: " + songKey + ". Game will have no notes."); //
}
gameStartTime = Date.now(); //
if (songData.musicAsset) {
//
currentMusic = LK.getSound(songData.musicAsset); //
if (currentMusic && typeof currentMusic.play === 'function') {
//
currentMusic.play(); //
console.log("Music asset for " + songKey + " PLAYING. gameStartTime: " + gameStartTime); //
} else {
//
console.log("Warning: Music asset '" + songData.musicAsset + "' not found or not playable."); //
}
} else {
//
console.log("No musicAsset defined for " + songKey + ". Map will run on system time only."); //
}
console.log("Loaded and processed song: " + songKey + " PlayerHP: " + playerMaxHP + " BossHP: " + bossMaxHP); //
}
function setupHpBars() {
if (bossHpBarContainer) {
bossHpBarContainer.destroy();
}
bossHpBarContainer = new Container();
bossHpBarContainer.x = gameScreenWidth / 2;
bossHpBarContainer.y = 100; // Adjusted Y slightly lower than scoreTxt for clarity
gameUIContainer.addChild(bossHpBarContainer); // Add to gameUIContainer
var bossBg = LK.getAsset('hpBarBackground', {
width: hpBarWidth,
height: hpBarHeight,
anchorX: 0.5,
anchorY: 0.5
});
bossHpBarContainer.addChild(bossBg);
bossHpBarFill = LK.getAsset('bossHpFill', {
width: hpBarWidth,
height: hpBarHeight,
anchorX: 0,
anchorY: 0.5,
x: -hpBarWidth / 2
});
bossHpBarContainer.addChild(bossHpBarFill);
if (playerHpBarContainer) {
playerHpBarContainer.destroy();
}
playerHpBarContainer = new Container();
playerHpBarContainer.x = gameScreenWidth / 2;
playerHpBarContainer.y = gameScreenHeight - 80;
gameUIContainer.addChild(playerHpBarContainer); // Add to gameUIContainer
var playerBg = LK.getAsset('hpBarBackground', {
width: hpBarWidth,
height: hpBarHeight,
anchorX: 0.5,
anchorY: 0.5
});
playerHpBarContainer.addChild(playerBg);
playerHpBarFill = LK.getAsset('playerHpFill', {
width: hpBarWidth,
height: hpBarHeight,
anchorX: 0,
anchorY: 0.5,
x: -hpBarWidth / 2
});
playerHpBarContainer.addChild(playerHpBarFill);
updateBossHpDisplay();
updatePlayerHpDisplay();
console.log("HP Bars setup and added to gameUIContainer. PlayerHP Y: " + playerHpBarContainer.y + " BossHP Y: " + bossHpBarContainer.y);
}
function setupPowerUpDisplay() {
powerUpDisplayContainer = new Container();
powerUpDisplayContainer.x = gameScreenWidth / 2;
powerUpDisplayContainer.y = 2450; // Twoja ustawiona wartość
gameUIContainer.addChild(powerUpDisplayContainer);
var iconSize = 150; // Twoja ustawiona wartość
var iconSpacing = 450; // Twoja ustawiona wartość
var textOffsetY = iconSize / 2 + 15;
// 1. Mikstura HP (bez zmian)
hpPotionIcon = LK.getAsset('hpPotionAsset', {
anchorX: 0.5,
anchorY: 0.5,
width: iconSize,
height: iconSize * 1.2
});
hpPotionIcon.x = -iconSpacing;
powerUpDisplayContainer.addChild(hpPotionIcon);
hpPotionCountText = new Text2("x0", {
size: 40,
fill: 0xFFFFFF,
anchorX: 0.5,
anchorY: 0
});
hpPotionCountText.x = hpPotionIcon.x;
hpPotionCountText.y = textOffsetY;
powerUpDisplayContainer.addChild(hpPotionCountText);
hpPotionIcon.interactive = true;
hpPotionIcon.down = function () {
if (collectedPowerUps.potion > 0 && !gameOverFlag) {
collectedPowerUps.potion--;
updatePowerUpDisplayCounts();
playerCurrentHP += POTION_HEAL_AMOUNT;
if (playerCurrentHP > playerMaxHP) {
playerCurrentHP = playerMaxHP;
}
updatePlayerHpDisplay();
console.log("Użyto Mikstury HP! Aktualne HP gracza: " + playerCurrentHP);
} else if (collectedPowerUps.potion <= 0 && !gameOverFlag) {
console.log("Brak mikstur HP do użycia.");
}
};
// 2. Tarcza (bez zmian)
shieldIcon = LK.getAsset('shieldAsset', {
anchorX: 0.5,
anchorY: 0.5,
width: iconSize,
height: iconSize
});
shieldIcon.x = 0;
powerUpDisplayContainer.addChild(shieldIcon);
shieldCountText = new Text2("x0", {
size: 40,
fill: 0xFFFFFF,
anchorX: 0.5,
anchorY: 0
});
shieldCountText.x = shieldIcon.x;
shieldCountText.y = textOffsetY;
powerUpDisplayContainer.addChild(shieldCountText);
shieldIcon.interactive = true;
shieldIcon.down = function () {
if (collectedPowerUps.shield > 0 && !isShieldActive && !gameOverFlag) {
collectedPowerUps.shield--;
updatePowerUpDisplayCounts();
isShieldActive = true;
shieldEndTime = Date.now() + SHIELD_DURATION;
shieldIcon.alpha = 0.5;
console.log("Tarcza AKTYWOWANA na " + SHIELD_DURATION / 1000 + " sekund!");
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = true;
var remainingSeconds = SHIELD_DURATION / 1000;
shieldTimerTextDisplay.setText(remainingSeconds.toFixed(1) + "s");
}
} else if (isShieldActive && !gameOverFlag) {
console.log("Tarcza jest już aktywna.");
} else if (collectedPowerUps.shield <= 0 && !gameOverFlag) {
console.log("Brak Tarcz do użycia.");
}
};
// 3. Buff Swipe-to-Tap
swipeToTapIcon = LK.getAsset('swipeToTapBuffAsset', {
anchorX: 0.5,
anchorY: 0.5,
width: iconSize * 1.1,
height: iconSize * 1.1
});
swipeToTapIcon.x = iconSpacing;
powerUpDisplayContainer.addChild(swipeToTapIcon);
swipeToTapCountText = new Text2("x0", {
size: 40,
fill: 0xFFFFFF,
anchorX: 0.5,
anchorY: 0
});
swipeToTapCountText.x = swipeToTapIcon.x;
swipeToTapCountText.y = textOffsetY;
powerUpDisplayContainer.addChild(swipeToTapCountText);
swipeToTapIcon.interactive = true;
swipeToTapIcon.down = function () {
console.log("--- SwipeToTap Icon (pełna logika) KLIKNIĘTA! ---");
console.log("Stan przed aktywacją: collected=" + collectedPowerUps.swipeToTap + ", isActive=" + isSwipeToTapBuffActive + ", gameOver=" + gameOverFlag);
if (collectedPowerUps.swipeToTap > 0 && !isSwipeToTapBuffActive && !gameOverFlag) {
collectedPowerUps.swipeToTap--;
updatePowerUpDisplayCounts();
isSwipeToTapBuffActive = true;
swipeToTapBuffEndTime = Date.now() + SWIPE_TO_TAP_BUFF_DURATION;
swipeToTapIcon.alpha = 0.5;
console.log("Buff Swipe-to-Tap AKTYWOWANY na " + SWIPE_TO_TAP_BUFF_DURATION / 1000 + " sekund!");
// NOWE: Pokaż timer buffa Swipe-to-Tap
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = true;
var remainingSecondsBuff = SWIPE_TO_TAP_BUFF_DURATION / 1000;
swipeToTapTimerTextDisplay.setText(remainingSecondsBuff.toFixed(1) + "s");
}
} else {
console.log("Buff Swipe-to-Tap NIE został aktywowany. Analiza warunków:");
if (!(collectedPowerUps.swipeToTap > 0)) {
console.log(" - Powód: Brak zebranych buffów (ilość: " + collectedPowerUps.swipeToTap + ")");
}
if (isSwipeToTapBuffActive) {
console.log(" - Powód: Buff Swipe-to-Tap jest już aktywny.");
}
if (gameOverFlag) {
console.log(" - Powód: Gra jest zakończona (gameOverFlag = " + gameOverFlag + ")");
}
}
};
// UI dla timera tarczy (bez zmian)
shieldTimerDisplayContainer = new Container();
shieldTimerDisplayContainer.x = gameScreenWidth - 120;
shieldTimerDisplayContainer.y = 150;
gameUIContainer.addChild(shieldTimerDisplayContainer);
var smallIconSize = 60; // Wspólny rozmiar dla małych ikon w timerach
smallShieldIconDisplay = LK.getAsset('shieldAsset', {
anchorX: 0.5,
anchorY: 0.5,
width: smallIconSize,
height: smallIconSize
});
shieldTimerDisplayContainer.addChild(smallShieldIconDisplay);
shieldTimerTextDisplay = new Text2("", {
size: 35,
fill: 0xFFFFFF,
anchorX: 0.5,
anchorY: 0
});
shieldTimerTextDisplay.y = smallIconSize / 2 + 5;
shieldTimerDisplayContainer.addChild(shieldTimerTextDisplay);
shieldTimerDisplayContainer.visible = false;
// NOWE: Tworzenie UI dla timera buffa Swipe-to-Tap (początkowo niewidoczne)
swipeToTapTimerDisplayContainer = new Container();
swipeToTapTimerDisplayContainer.x = gameScreenWidth - 120; // Ta sama pozycja X co timer tarczy
// Pozycja Y poniżej timera tarczy (wysokość timera tarczy to ok. smallIconSize + wysokość tekstu + odstęp)
// Zakładając, że shieldTimerDisplayContainer ma ok. 100-110px wysokości:
swipeToTapTimerDisplayContainer.y = shieldTimerDisplayContainer.y + smallIconSize + 40 + 10; // np. 150 + 60 + 40 + 10 = 260
gameUIContainer.addChild(swipeToTapTimerDisplayContainer);
smallSwipeToTapIconDisplay = LK.getAsset('swipeToTapBuffAsset', {
anchorX: 0.5,
anchorY: 0.5,
width: smallIconSize * 1.1,
// Zachowujemy proporcje jak dla dużej ikony
height: smallIconSize * 1.1
});
swipeToTapTimerDisplayContainer.addChild(smallSwipeToTapIconDisplay);
swipeToTapTimerTextDisplay = new Text2("", {
// Początkowo pusty tekst
size: 35,
fill: 0xFFFFFF,
anchorX: 0.5,
anchorY: 0
});
swipeToTapTimerTextDisplay.y = smallIconSize * 1.1 / 2 + 5; // Umiejscowienie pod małą ikonką buffa
swipeToTapTimerDisplayContainer.addChild(swipeToTapTimerTextDisplay);
swipeToTapTimerDisplayContainer.visible = false; // Początkowo niewidoczny
console.log("PowerUp Display UI created. All PowerUp Icons are interactive. Shield & SwipeToTap Timer UI created.");
}
function updatePowerUpDisplayCounts() {
if (hpPotionCountText) {
// Sprawdzamy, czy UI zostało już zainicjalizowane
hpPotionCountText.setText("x" + collectedPowerUps.potion);
shieldCountText.setText("x" + collectedPowerUps.shield);
swipeToTapCountText.setText("x" + collectedPowerUps.swipeToTap);
}
}
function updatePlayerHpDisplay() {
if (playerHpBarFill) {
var healthPercent = playerCurrentHP / playerMaxHP;
playerHpBarFill.width = hpBarWidth * Math.max(0, healthPercent);
}
}
function updateBossHpDisplay() {
if (bossHpBarFill) {
var healthPercent = bossCurrentHP / bossMaxHP;
bossHpBarFill.width = hpBarWidth * Math.max(0, healthPercent);
}
}
function spawnNotes() {
var now = Date.now();
if (!currentActiveRhythmMap) {
return;
}
while (nextNoteIdx < currentActiveRhythmMap.length) {
var noteData = currentActiveRhythmMap[nextNoteIdx];
var noteTargetHitTime = gameStartTime + noteData.time;
if (noteTargetHitTime - noteTravelTime <= now) {
var targetCenterX;
// ... (logika ustalania targetCenterX pozostaje bez zmian, linie ) ...
if (noteData.partOfWiderSwipe && noteData.widerSwipePairCenterX !== undefined) {
if (noteData.partOfWiderSwipe === 'leftHalf') {
targetCenterX = noteData.widerSwipePairCenterX - SWIPE_NOTE_WIDTH / 2;
} else if (noteData.partOfWiderSwipe === 'rightHalf') {
targetCenterX = noteData.widerSwipePairCenterX + SWIPE_NOTE_WIDTH / 2;
} else {
targetCenterX = columnCenterXs[noteData.originalColumnHint !== undefined ? noteData.originalColumnHint : Math.floor(NUM_COLUMNS / 2)];
}
} else if (noteData.columnIndex !== undefined && noteData.columnIndex >= 0 && noteData.columnIndex < NUM_COLUMNS) {
targetCenterX = columnCenterXs[noteData.columnIndex];
} else {
targetCenterX = playfieldStartX + playfieldWidth / 2;
}
// NOWE: Logika zmiany typu nuty, jeśli buff Swipe-to-Tap jest aktywny
var finalNoteType = noteData.type;
var finalSwipeDir = noteData.swipeDir;
if (isSwipeToTapBuffActive && noteData.type === 'swipe') {
finalNoteType = 'tap'; // Zmień typ na 'tap'
finalSwipeDir = null; // Tap nie ma kierunku swipe'a
console.log("Buff aktywny: Zmieniono swipe na tap dla nuty o czasie " + noteData.time);
}
// Koniec NOWE
var n = new Note(finalNoteType, finalSwipeDir, noteTargetHitTime, targetCenterX); // Używamy finalNoteType i finalSwipeDir
n.mapData = noteData;
if (noteData.partOfWiderSwipe) {
n.isWiderSwipePart = true;
}
n.alpha = 0;
notes.push(n);
game.addChild(n);
nextNoteIdx++;
} else {
break;
}
}
}
function removeOldNotes() {
var now = Date.now();
for (var i = notes.length - 1; i >= 0; i--) {
var n = notes[i];
var timeToRemoveAfterJudged = 700; // ms po targetHitTime dla ocenionych notatek
var timeToRemoveIfNotJudged = noteTravelTime / 2 + hitWindowGood + 500; // Dłuższy czas, jeśli nieoceniona, liczony od targetHitTime
if (n.judged && now > n.targetHitTime + timeToRemoveAfterJudged) {
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
} else if (!n.judged && now > n.targetHitTime + timeToRemoveIfNotJudged) {
if (n.noteType !== 'trap') {}
if (n.parent) {
n.destroy();
}
notes.splice(i, 1);
}
}
}
function findNoteAt(x, y, typeToFind) {
var now = Date.now();
var bestNote = null;
var smallestTimeDiff = hitWindowGood + 1;
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
if (n.judged || n.noteType !== typeToFind) {
continue;
}
var timeDiff = Math.abs(now - n.targetHitTime);
if (timeDiff > hitWindowGood) {
continue;
}
var currentNoteAsset = n.noteAsset;
if (!currentNoteAsset) {
continue;
}
var currentNoteWidth = currentNoteAsset.width * n.scale.x;
var currentNoteHeight = currentNoteAsset.height * n.scale.y;
if (n.noteType === 'swipe') {
currentNoteWidth = SWIPE_NOTE_WIDTH * n.scale.x;
currentNoteHeight = SWIPE_NOTE_WIDTH * n.scale.y;
}
var dx = x - n.x;
var dy = y - n.y;
if (Math.abs(dx) <= currentNoteWidth / 2 && Math.abs(dy) <= currentNoteHeight / 2) {
if (timeDiff < smallestTimeDiff) {
bestNote = n;
smallestTimeDiff = timeDiff;
}
}
}
return bestNote;
}
function addScore(result) {
if (result === 'perfect') {
score += 100;
} else if (result === 'good') {
score += 50;
}
scoreTxt.setText('Score: ' + score);
}
function addCombo() {
combo += 1;
if (combo > maxCombo) {
maxCombo = combo;
}
comboTxt.setText('Combo: ' + combo);
// Animacja dla comboTxt
if (combo > 1) {
// Mała animacja tylko jeśli combo jest większe niż 1
var originalScale = comboTxt.scale.x; // Zakładamy, że skala X i Y jest taka sama
tween(comboTxt.scale, {
x: originalScale * 1.3,
y: originalScale * 1.3
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(comboTxt.scale, {
x: originalScale,
y: originalScale
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
}
function resetCombo() {
combo = 0;
comboTxt.setText('Combo: 0');
}
function checkGameEnd() {
if (gameOverFlag) {
return;
}
if (playerCurrentHP <= 0) {
gameOverFlag = true;
console.log("GAME OVER - Player HP depleted");
if (currentMusic && typeof currentMusic.stop === 'function') {
currentMusic.stop();
}
var gameOverText = new Text2('GAME OVER', {
x: gameScreenWidth / 2,
y: gameScreenHeight / 2,
anchorX: 0.5,
anchorY: 0.5,
// Ensure vertical centering
size: 100,
fill: 0xff0000
});
gameUIContainer.addChild(gameOverText); // Add to gameUIContainer
return;
}
if (bossCurrentHP <= 0) {
gameOverFlag = true;
console.log("YOU WIN - Boss HP depleted");
if (currentMusic && typeof currentMusic.stop === 'function') {
currentMusic.stop();
}
// LK.showYouWin(); // This is an engine specific function, we'll use a text display for now
var winText = new Text2('YOU WIN!', {
x: gameScreenWidth / 2,
y: gameScreenHeight / 2,
anchorX: 0.5,
anchorY: 0.5,
// Ensure vertical centering
size: 100,
fill: 0x00ff00
});
gameUIContainer.addChild(winText); // Add to gameUIContainer
return;
}
if (currentActiveRhythmMap && nextNoteIdx >= currentActiveRhythmMap.length && notes.length === 0) {
if (!gameOverFlag) {
// Check gameOverFlag again to prevent double messages if HP ran out simultaneously
gameOverFlag = true;
console.log("SONG ENDED - Boss might still be alive");
if (currentMusic && typeof currentMusic.stop === 'function') {
currentMusic.stop();
}
var songEndedText = new Text2('SONG ENDED', {
x: gameScreenWidth / 2,
y: gameScreenHeight / 2,
anchorX: 0.5,
anchorY: 0.5,
// Ensure vertical centering
size: 100,
fill: 0xffff00
});
gameUIContainer.addChild(songEndedText); // Add to gameUIContainer
}
}
}
function trySpawnRandomPowerUp() {
var now = Date.now();
if (now > lastPowerUpSpawnAttemptTime + POWERUP_SPAWN_INTERVAL) {
lastPowerUpSpawnAttemptTime = now;
if (Math.random() < POWERUP_SPAWN_CHANCE) {
var powerUpTypes = ['potion', 'shield', 'swipeToTap'];
var randomType = powerUpTypes[Math.floor(Math.random() * powerUpTypes.length)];
var randomColumnIndex = Math.floor(Math.random() * NUM_COLUMNS);
var spawnX = columnCenterXs[randomColumnIndex];
var newPowerUp = new PowerUpItem(randomType, spawnX);
game.addChild(newPowerUp);
activePowerUpItems.push(newPowerUp);
console.log("Spawnowano PowerUp: " + randomType + " w kolumnie " + (randomColumnIndex + 1));
}
}
}
function managePowerUpItems() {
for (var i = activePowerUpItems.length - 1; i >= 0; i--) {
var pItem = activePowerUpItems[i];
// Sprawdzamy, czy obiekt w ogóle istnieje i czy ma rodzica (czy jest na scenie)
// Jeśli został zebrany (collected=true) LUB nie ma rodzica (został zniszczony), to usuwamy z tablicy
if (!pItem || pItem.collected || !pItem.parent) {
activePowerUpItems.splice(i, 1);
} else {
pItem.update(); // Aktualizuj tylko, jeśli jest na scenie i niezebrany
}
}
}
game.onNoteMiss = function (note) {
if (!note) {
return;
}
note.showHitFeedback('miss');
// NOWA ZMIANA: Sprawdzamy, czy tarcza jest aktywna przed zresetowaniem combo
if (!isShieldActive) {
resetCombo();
} else {
console.log("Gracz ominął nutę, ale tarcza jest aktywna! Combo NIE zresetowane.");
}
// Koniec NOWA ZMIANA
if (isShieldActive) {
console.log("Gracz ominął nutę, ale tarcza jest aktywna! Brak utraty HP.");
} else if (!gameOverFlag) {
playerCurrentHP = Math.max(0, playerCurrentHP - 1);
updatePlayerHpDisplay();
console.log("Player HP after miss: " + playerCurrentHP);
}
if (note.parent) {
LK.effects.flashObject(note, 0xff0000, 300);
}
};
game.down = function (x, y, obj) {
// Usunięto logikę dla currentScreenState === 'bossselection' (stare przewijanie)
if (currentScreenState === 'gameplay') {
for (var i_gp_pu = activePowerUpItems.length - 1; i_gp_pu >= 0; i_gp_pu--) {
var pItem_gp = activePowerUpItems[i_gp_pu];
if (pItem_gp && !pItem_gp.collected && pItem_gp.visualAsset && pItem_gp.parent) {
var pWidth_gp = pItem_gp.visualAsset.width * pItem_gp.scale.x;
var pHeight_gp = pItem_gp.visualAsset.height * pItem_gp.scale.y;
if (x >= pItem_gp.x - pWidth_gp / 2 && x <= pItem_gp.x + pWidth_gp / 2 && y >= pItem_gp.y - pHeight_gp / 2 && y <= pItem_gp.y + pHeight_gp / 2) {
if (Math.abs(pItem_gp.y - hitZoneY) < pHeight_gp * 1.5) {
pItem_gp.collect();
return;
}
}
}
}
if (inputLocked) {
return;
}
swipeStart = {
x: x,
y: y,
time: Date.now()
};
var noteUnderCursor_gp = findNoteAt(x, y, 'trap');
if (noteUnderCursor_gp && !noteUnderCursor_gp.judged && noteUnderCursor_gp.isInHitWindow()) {
noteUnderCursor_gp.judged = true;
noteUnderCursor_gp.showHitFeedback('miss');
if (isShieldActive) {
console.log("Gracz trafił w TRAP NOTE, ale tarcza jest aktywna! Brak utraty HP i combo NIE zresetowane.");
} else {
resetCombo();
LK.effects.flashScreen(0xff0000, 400);
if (!gameOverFlag) {
playerCurrentHP = Math.max(0, playerCurrentHP - 1);
updatePlayerHpDisplay();
}
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
}, 200);
return;
}
noteUnderCursor_gp = findNoteAt(x, y, 'tap');
if (noteUnderCursor_gp && !noteUnderCursor_gp.judged && noteUnderCursor_gp.isInHitWindow()) {
var result_gp = noteUnderCursor_gp.getHitAccuracy();
noteUnderCursor_gp.judged = true;
noteUnderCursor_gp.showHitFeedback(result_gp);
if (result_gp !== 'miss') {
addScore(result_gp);
addCombo();
if (!gameOverFlag) {
if (result_gp === 'perfect') {
bossCurrentHP = Math.max(0, bossCurrentHP - 2);
} else if (result_gp === 'good') {
bossCurrentHP = Math.max(0, bossCurrentHP - 1);
}
updateBossHpDisplay();
}
} else {
if (!isShieldActive) {
resetCombo();
} else {
console.log("Tapnięcie nuty ocenione jako 'miss', ale tarcza jest aktywna! Combo NIE zresetowane.");
}
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
}, 120);
return;
}
}
// Tutaj można dodać logikę dla innych stanów, jeśli będzie potrzebna
};
game.move = function (x, y, obj) {};
game.up = function (x, y, obj) {
if (currentScreenState === 'gameplay') {
if (inputLocked || !swipeStart) {
swipeStart = null;
return;
}
var swipeEndX = x;
var swipeEndY = y;
var swipeEndTime = Date.now();
var dx = swipeEndX - swipeStart.x;
var dy = swipeEndY - swipeStart.y;
var dist = Math.sqrt(dx * dx + dy * dy);
var potentialSwipe = dist >= MIN_SWIPE_DISTANCE;
var swipedNoteSuccessfully = false;
if (potentialSwipe) {
var detectedDir = null;
if (Math.abs(dx) > Math.abs(dy)) {
detectedDir = dx > 0 ? 'right' : 'left';
} else {
detectedDir = dy > 0 ? 'down' : 'up';
}
var swipeBoundingBox = {
x: Math.min(swipeStart.x, swipeEndX),
y: Math.min(swipeStart.y, swipeEndY),
width: Math.abs(dx),
height: Math.abs(dy)
};
var notesHitThisSwipe = [];
for (var i_swipe = 0; i_swipe < notes.length; i_swipe++) {
var n_swipe = notes[i_swipe];
if (n_swipe.judged || n_swipe.noteType !== 'swipe') {
continue;
}
var overallSwipeTimeMatchesNote = false;
if (n_swipe.targetHitTime >= swipeStart.time - hitWindowGood && n_swipe.targetHitTime <= swipeEndTime + hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
if (!overallSwipeTimeMatchesNote) {
if (swipeStart.time >= n_swipe.targetHitTime - hitWindowGood && swipeStart.time <= n_swipe.targetHitTime + hitWindowGood || swipeEndTime >= n_swipe.targetHitTime - hitWindowGood && swipeEndTime <= n_swipe.targetHitTime + hitWindowGood) {
overallSwipeTimeMatchesNote = true;
}
}
if (!overallSwipeTimeMatchesNote) {
continue;
}
if (n_swipe.alpha === 0) {
continue;
}
var noteCurrentWidth_swipe = SWIPE_NOTE_WIDTH * n_swipe.scale.x;
var noteCurrentHeight_swipe = SWIPE_NOTE_WIDTH * n_swipe.scale.y;
var noteBoundingBox_swipe = {
x: n_swipe.x - noteCurrentWidth_swipe / 2,
y: n_swipe.y - noteCurrentHeight_swipe / 2,
width: noteCurrentWidth_swipe,
height: noteCurrentHeight_swipe
};
if (rectsIntersect(swipeBoundingBox, noteBoundingBox_swipe)) {
if (detectedDir === n_swipe.swipeDir) {
var verticalProximity = Math.abs(n_swipe.y - n_swipe.centerY);
var verticalTolerance = noteCurrentHeight_swipe / 1.5;
if (verticalProximity < verticalTolerance) {
notesHitThisSwipe.push(n_swipe);
}
}
}
}
if (notesHitThisSwipe.length > 0) {
notesHitThisSwipe.sort(function (a, b) {
var da = Math.abs(swipeEndTime - a.targetHitTime);
var db = Math.abs(swipeEndTime - b.targetHitTime);
return da - db;
});
var maxNotesToHitPerSwipe = 1;
if (notesHitThisSwipe.length > 0 && notesHitThisSwipe[0].isWiderSwipePart) {
maxNotesToHitPerSwipe = 2;
}
var notesActuallyHitCount = 0;
for (var k_swipe = 0; k_swipe < notesHitThisSwipe.length && notesActuallyHitCount < maxNotesToHitPerSwipe; k_swipe++) {
var noteToJudge_swipe = notesHitThisSwipe[k_swipe];
if (noteToJudge_swipe.judged) {
continue;
}
if (notesActuallyHitCount === 1 && notesHitThisSwipe[0].isWiderSwipePart) {
if (!noteToJudge_swipe.isWiderSwipePart || noteToJudge_swipe.mapData.widerSwipePairCenterX !== notesHitThisSwipe[0].mapData.widerSwipePairCenterX || noteToJudge_swipe.mapData.partOfWiderSwipe === notesHitThisSwipe[0].mapData.partOfWiderSwipe) {
continue;
}
}
var result_swipe = noteToJudge_swipe.getHitAccuracy();
noteToJudge_swipe.judged = true;
noteToJudge_swipe.showHitFeedback(result_swipe);
if (result_swipe !== 'miss') {
addScore(result_swipe);
addCombo();
if (!gameOverFlag) {
if (result_swipe === 'perfect') {
bossCurrentHP = Math.max(0, bossCurrentHP - 2);
} else if (result_swipe === 'good') {
bossCurrentHP = Math.max(0, bossCurrentHP - 1);
}
updateBossHpDisplay();
}
} else {
resetCombo();
}
swipedNoteSuccessfully = true;
notesActuallyHitCount++;
}
}
}
inputLocked = true;
LK.setTimeout(function () {
inputLocked = false;
}, 80);
swipeStart = null;
}
};
game.update = function () {
if (typeof notes === 'undefined' || !Array.isArray(notes)) {
notes = [];
}
if (typeof activePowerUpItems === 'undefined' || !Array.isArray(activePowerUpItems)) {
activePowerUpItems = [];
}
if (currentScreenState === 'gameplay') {
if (!hpBarsInitialized) {
setupHpBars();
setupPowerUpDisplay();
lastPowerUpSpawnAttemptTime = Date.now();
hpBarsInitialized = true;
updatePowerUpDisplayCounts();
}
var now = Date.now();
if (isShieldActive) {
if (now > shieldEndTime) {
isShieldActive = false;
if (shieldIcon) {
shieldIcon.alpha = 1.0;
}
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
}
console.log("Tarcza WYGASŁA.");
} else {
if (shieldTimerDisplayContainer && shieldTimerDisplayContainer.visible) {
var remainingSecondsShield = (shieldEndTime - now) / 1000;
if (shieldTimerTextDisplay) {
shieldTimerTextDisplay.setText(remainingSecondsShield.toFixed(1) + "s");
}
}
}
} else {
if (shieldTimerDisplayContainer && shieldTimerDisplayContainer.visible) {
shieldTimerDisplayContainer.visible = false;
}
}
if (isSwipeToTapBuffActive) {
if (now > swipeToTapBuffEndTime) {
isSwipeToTapBuffActive = false;
if (swipeToTapIcon) {
swipeToTapIcon.alpha = 1.0;
}
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
console.log("Buff Swipe-to-Tap WYGASŁ.");
} else {
if (swipeToTapTimerDisplayContainer && swipeToTapTimerDisplayContainer.visible) {
var remainingSecondsBuff = (swipeToTapBuffEndTime - now) / 1000;
if (swipeToTapTimerTextDisplay) {
swipeToTapTimerTextDisplay.setText(remainingSecondsBuff.toFixed(1) + "s");
}
}
}
} else {
if (swipeToTapTimerDisplayContainer && swipeToTapTimerDisplayContainer.visible) {
swipeToTapTimerDisplayContainer.visible = false;
}
}
trySpawnRandomPowerUp();
managePowerUpItems();
spawnNotes();
for (var i_update_notes = 0; i_update_notes < notes.length; i_update_notes++) {
if (notes[i_update_notes] && notes[i_update_notes].update) {
notes[i_update_notes].update();
}
}
removeOldNotes();
checkGameEnd();
} else {
// Jesteśmy w stanie menu lub nowej galerii ('start', 'intro', 'tutorial', 'mainmenu', 'bossGallery_paged', 'credits')
// Usunięto stary blok "MANUAL VISIBILITY CULLING FOR BOSS CARDS",
// ponieważ currentScreenState dla nowego ekranu to 'bossGallery_paged',
// a stary culling był dla 'bossselection' i nie pasuje do nowej logiki.
// Czyszczenie notes i activePowerUpItems w stanach menu (jeśli jakieś zostały z gameplayu)
// Ta logika jest nadal przydatna.
if (notes.length > 0) {
for (var i_notes_clear = notes.length - 1; i_notes_clear >= 0; i_notes_clear--) {
var n_clear = notes[i_notes_clear];
if (n_clear && n_clear.parent) {
n_clear.destroy();
}
}
notes = [];
}
if (activePowerUpItems.length > 0) {
for (var i_pwup_clear = activePowerUpItems.length - 1; i_pwup_clear >= 0; i_pwup_clear--) {
var p_clear = activePowerUpItems[i_pwup_clear];
if (p_clear && p_clear.parent) {
p_clear.destroy();
}
}
activePowerUpItems = [];
}
}
};
// Load the specific song for testing
showStartScreen();
// loadSong("defaultTestTrack"); // Możesz to odkomentować, aby załadować starą mapę testową ===================================================================
--- original.js
+++ change.js
@@ -451,10 +451,147 @@
});
showCreditsScreen();
};
}
+var allBossData = [];
+var currentBossViewStartIndex = 0;
+var visibleBossCards = [null, null, null, null];
+var selectedCardSlotIndex = 0;
+var currentlyPlayingMusic = null;
+var placeholderMusicKey = 'test1';
+var placeholderSongMapKey = 'defaultTestTrack';
+function initializeBossData() {
+ allBossData = [{
+ id: 'boss1',
+ displayName: 'Boss 1',
+ cardAssetKey: 'boss1',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss2',
+ displayName: 'Boss 2',
+ cardAssetKey: 'boss2',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss3',
+ displayName: 'Boss 3',
+ cardAssetKey: 'boss3',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss4',
+ displayName: 'Boss 4',
+ cardAssetKey: 'boss4',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss5',
+ displayName: 'Boss 5',
+ cardAssetKey: 'boss5',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss6',
+ displayName: 'Boss 6',
+ cardAssetKey: 'boss6',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss7',
+ displayName: 'Boss 7',
+ cardAssetKey: 'boss7',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }, {
+ id: 'boss8',
+ displayName: 'Boss 8',
+ cardAssetKey: 'boss8',
+ musicAssetKey: placeholderMusicKey,
+ songMapKey: placeholderSongMapKey
+ }];
+}
+function updateSelectedCardVisual() {
+ for (var i = 0; i < visibleBossCards.length; i++) {
+ var cardContainer = visibleBossCards[i];
+ if (cardContainer && cardContainer.visualAsset) {
+ if (i === selectedCardSlotIndex) {
+ cardContainer.visualAsset.tint = 0xFFFF00;
+ cardContainer.scale.set(1.05);
+ } else {
+ cardContainer.visualAsset.tint = 0xFFFFFF;
+ cardContainer.scale.set(1.0);
+ }
+ }
+ }
+}
+function displayBossCards(newStartIndex, isInitialDisplay) {
+ currentBossViewStartIndex = newStartIndex;
+ var cardSlotsPositions = [{
+ x: gameScreenWidth / 2 - 220,
+ y: gameScreenHeight / 2 - 300
+ }, {
+ x: gameScreenWidth / 2 + 20,
+ y: gameScreenHeight / 2 - 300
+ }, {
+ x: gameScreenWidth / 2 - 220,
+ y: gameScreenHeight / 2 + 20
+ }, {
+ x: gameScreenWidth / 2 + 20,
+ y: gameScreenHeight / 2 + 20
+ }];
+ for (var i = 0; i < visibleBossCards.length; i++) {
+ if (visibleBossCards[i] && visibleBossCards[i].parent) {
+ visibleBossCards[i].destroy();
+ }
+ visibleBossCards[i] = null;
+ }
+ for (var i = 0; i < 4; i++) {
+ var dataIndex = currentBossViewStartIndex + i;
+ if (dataIndex < allBossData.length) {
+ var bossData = allBossData[dataIndex];
+ var cardContainer = new Container();
+ cardContainer.x = cardSlotsPositions[i].x;
+ cardContainer.y = cardSlotsPositions[i].y;
+ cardContainer.bossData = bossData;
+ cardContainer.slotIndex = i;
+ var cardAsset = LK.getAsset(bossData.cardAssetKey, {});
+ cardAsset.anchor.set(0.5, 0.5);
+ cardContainer.visualAsset = cardAsset;
+ cardContainer.addChild(cardAsset);
+ var nameText = new Text2(bossData.displayName, {
+ size: 30,
+ fill: 0xFFFFFF,
+ stroke: 0x000000,
+ strokeThickness: 2
+ });
+ nameText.anchor.set(0.5, 0);
+ nameText.x = 0;
+ nameText.y = cardAsset.height / 2 + 5;
+ cardContainer.addChild(nameText);
+ cardContainer.interactive = true;
+ cardContainer.cursor = "pointer";
+ cardContainer.down = function () {
+ selectedCardSlotIndex = this.slotIndex;
+ updateSelectedCardVisual();
+ console.log("Zaznaczono kartę: " + this.bossData.displayName + " w slocie " + this.slotIndex);
+ };
+ game.addChild(cardContainer);
+ visibleBossCards[i] = cardContainer;
+ }
+ }
+ if (isInitialDisplay) {
+ selectedCardSlotIndex = 0;
+ } else {
+ var maxSlotOnNewPage = Math.min(3, allBossData.length - 1 - currentBossViewStartIndex);
+ if (selectedCardSlotIndex > maxSlotOnNewPage) {
+ selectedCardSlotIndex = maxSlotOnNewPage;
+ }
+ }
+ updateSelectedCardVisual();
+}
function showBossSelectionScreen() {
- currentScreenState = 'bossselection';
+ currentScreenState = 'bossGallery_paged';
if (gameUIContainer) {
gameUIContainer.visible = false;
}
if (hitZoneLine) {
@@ -465,189 +602,197 @@
}
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
- game.setBackgroundColor(0x000000);
+ game.setBackgroundColor(0x101020);
+ initializeBossData();
var screenElements = [];
- // === POCZĄTEK TYMCZASOWYCH ZMIAN TESTOWYCH ===
- var viewportX = (gameScreenWidth - 900) / 2;
- // Zmieniamy viewportY i viewportHeight na wartości testowe:
- var viewportY = gameScreenHeight / 2 - 100; // Ustawia testowy viewport mniej więcej na środku pionowo
- var viewportWidth = 900;
- var viewportHeight = 200; // BARDZO NISKI viewport, żeby łatwo było zauważyć efekt
- console.log("!!! TRYB TESTOWY UKRYWANIA KART !!!");
- console.log("Testowy viewportY:", viewportY, "Testowy viewportHeight:", viewportHeight);
- // === KONIEC TYMCZASOWYCH ZMIAN TESTOWYCH ===
- g_scroll_viewportWidth = viewportWidth;
- g_scroll_viewportHeight = viewportHeight; // WAŻNE: g_scroll_viewportHeight użyje nowej, testowej wartości (200)
- var galleryBg = LK.getAsset('galleryBackground', {
- width: viewportWidth + 100,
- // Użyje testowych wymiarów, ale tło jest pod spodem
- height: viewportHeight + 300 + 100
- });
- galleryBg.x = viewportX - 50;
- galleryBg.y = viewportY - 50; // Tło też się przesunie z testowym viewportY
- game.addChild(galleryBg);
- screenElements.push(galleryBg);
- var cardsViewportObj = new Container();
- cardsViewportObj.name = "MyCardsViewport_TEST"; // Możemy zmienić nazwę dla testu
- cardsViewportObj.x = viewportX;
- cardsViewportObj.y = viewportY; // Użyje testowej wartości viewportY
- cardsViewportObj.interactive = true; // Upewnij się, że to jest odkomentowane dla przewijania
- game.addChild(cardsViewportObj);
- screenElements.push(cardsViewportObj);
- g_scroll_targetViewport = cardsViewportObj;
- var allCardsContainerObj = new Container();
- allCardsContainerObj.name = "MyAllCardsContainer";
- cardsViewportObj.addChild(allCardsContainerObj);
- g_scroll_cardsContainer = allCardsContainerObj;
- var galleryFrameAsset = LK.getAsset('galleryFrame', {
- // Wymiary ramki mogą być oparte na testowych viewportWidth/Height,
- // ale i tak ją ukryjemy, więc nie ma to dużego znaczenia dla testu.
- width: viewportWidth + 100,
- height: viewportHeight + 100
- });
- galleryFrameAsset.x = viewportX - 50;
- galleryFrameAsset.y = viewportY - 50;
- galleryFrameAsset.visible = false; // !!! TYMCZASOWO UKRYJ RAMKĘ DLA TESTU !!!
- game.addChild(galleryFrameAsset);
- screenElements.push(galleryFrameAsset);
- var cardWidth = (viewportWidth - 150) / 2; // Szerokość karty bazuje na testowym viewportWidth
- var cardHeight = 500;
- var spacingX = 50;
- var spacingY = 50;
- var numRegularBosses = 8;
- for (var i = 0; i < numRegularBosses; i++) {
- var card = LK.getAsset('bossCard', {
- width: cardWidth,
- height: cardHeight
- });
- card.name = "BossCard_" + i;
- var col = i % 2;
- var row = Math.floor(i / 2);
- card.x = spacingX + col * (cardWidth + spacingX);
- card.y = spacingY + row * (cardHeight + spacingY);
- var cardText = new Text2("Boss " + (i + 1), {
- size: 70,
- fill: 0x000000
- });
- cardText.name = "TextOnCard_" + i;
- cardText.anchor.set(0.5, 0.5);
- cardText.x = cardWidth / 2;
- cardText.y = cardHeight / 2;
- card.addChild(cardText);
- card.interactive = true;
- card.cursor = "pointer";
- card.bossData = {
- id: "regular_boss_" + (i + 1),
- name: "Boss " + (i + 1)
- };
- card.down = function () {
- if (g_scroll_isDragging) {
- console.log("Card.down wykryte, ale już trwa przeciąganie - ignoruję wybór bossa.");
- return;
+ // --- GŁÓWNA RAMKA WIZUALNA ---
+ var mainFrame = LK.getAsset('galleryFrame', {});
+ mainFrame.width = 920; // PRZYKŁADOWA szerokość ramki (aby objąć karty 200+30+200 = 430, plus margines)
+ mainFrame.height = 970; // PRZYKŁADOWA wysokość ramki (aby objąć karty 280+30+280 = 590, plus margines)
+ mainFrame.x = gameScreenWidth / 2; // Ramka wyśrodkowana
+ mainFrame.y = gameScreenHeight / 2 - 50; // Ramka wyśrodkowana pionowo z tym samym offsetem co karty
+ mainFrame.anchor.set(0.5, 0.5);
+ game.addChild(mainFrame);
+ screenElements.push(mainFrame);
+ // --- Przyciski Nawigacyjne (lewa strona) ---
+ var upButton = LK.getAsset('upbutton', {});
+ upButton.x = 500; // SZTYWNA POZYCJA X
+ upButton.y = gameScreenHeight / 2 - 50; // SZTYWNA POZYCJA Y
+ upButton.anchor.set(0.5, 0.5);
+ upButton.interactive = true;
+ upButton.cursor = "pointer";
+ upButton.down = function () {
+ var newIndex = Math.max(0, currentBossViewStartIndex - 4);
+ if (newIndex !== currentBossViewStartIndex) {
+ displayBossCards(newIndex, false);
+ }
+ };
+ game.addChild(upButton);
+ screenElements.push(upButton);
+ var downButton = LK.getAsset('downbutton', {});
+ downButton.x = 500; // SZTYWNA POZYCJA X
+ downButton.y = gameScreenHeight / 2 + 70; // SZTYWNA POZYCJA Y
+ downButton.anchor.set(0.5, 0.5);
+ downButton.interactive = true;
+ downButton.cursor = "pointer";
+ downButton.down = function () {
+ var newIndex = currentBossViewStartIndex + 4;
+ if (newIndex < allBossData.length) {
+ displayBossCards(newIndex, false);
+ }
+ };
+ game.addChild(downButton);
+ screenElements.push(downButton);
+ // --- Przyciski Akcji (prawa strona) ---
+ var playButton = LK.getAsset('play', {});
+ playButton.x = gameScreenWidth - 600; // SZTYWNA POZYCJA X
+ playButton.y = gameScreenHeight / 2 - 120; // SZTYWNA POZYCJA Y
+ playButton.anchor.set(0.5, 0.5);
+ playButton.interactive = true;
+ playButton.cursor = "pointer";
+ playButton.down = function () {
+ var selectedBossData = allBossData[currentBossViewStartIndex + selectedCardSlotIndex];
+ if (selectedBossData) {
+ if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
+ currentlyPlayingMusic.stop();
}
- console.log("Wybrano: " + this.bossData.name);
- // Tutaj logika wyboru bossa (np. loadSong)
- };
- allCardsContainerObj.addChild(card);
- }
- var numRows = Math.ceil(numRegularBosses / 2);
- var calculatedTotalHeight = numRows * (cardHeight + spacingY) + spacingY;
- // allCardsContainerObj.calculatedHeight = calculatedTotalHeight; // Ta linia nie jest potrzebna dla logiki
- g_scroll_contentHeight = calculatedTotalHeight;
- console.log("[showBossSelectionScreen TEST] Ustawiono g_scroll_contentHeight na:", g_scroll_contentHeight);
- console.log("[showBossSelectionScreen TEST] g_scroll_viewportWidth:", g_scroll_viewportWidth, "g_scroll_viewportHeight:", g_scroll_viewportHeight);
- var specialBossFrameWidth = viewportWidth;
- var specialBossFrameHeight = 200;
- var specialBossAreaAsset = LK.getAsset('specialBossArea', {
- width: specialBossFrameWidth,
- height: specialBossFrameHeight
- });
- specialBossAreaAsset.name = "SpecialBossArea";
- specialBossAreaAsset.x = viewportX;
- // Pozycja specialBossAreaAsset również się przesunie z testowym viewportY
- specialBossAreaAsset.y = viewportY + viewportHeight + 30;
- game.addChild(specialBossAreaAsset);
- screenElements.push(specialBossAreaAsset);
+ currentlyPlayingMusic = LK.getSound(selectedBossData.musicAssetKey);
+ if (currentlyPlayingMusic && typeof currentlyPlayingMusic.play === 'function') {
+ currentlyPlayingMusic.play();
+ }
+ }
+ };
+ game.addChild(playButton);
+ screenElements.push(playButton);
+ var stopButton = LK.getAsset('stop', {});
+ stopButton.x = gameScreenWidth - 600; // SZTYWNA POZYCJA X
+ stopButton.y = gameScreenHeight / 2; // SZTYWNA POZYCJA Y
+ stopButton.anchor.set(0.5, 0.5);
+ stopButton.interactive = true;
+ stopButton.cursor = "pointer";
+ stopButton.down = function () {
+ if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
+ currentlyPlayingMusic.stop();
+ currentlyPlayingMusic = null;
+ }
+ };
+ game.addChild(stopButton);
+ screenElements.push(stopButton);
+ var fightButton = LK.getAsset('fight', {});
+ fightButton.x = gameScreenWidth - 600; // SZTYWNA POZYCJA X
+ fightButton.y = gameScreenHeight / 2 + 120; // SZTYWNA POZYCJA Y
+ fightButton.anchor.set(0.5, 0.5);
+ fightButton.interactive = true;
+ fightButton.cursor = "pointer";
+ fightButton.down = function () {
+ var selectedBossData = allBossData[currentBossViewStartIndex + selectedCardSlotIndex];
+ if (selectedBossData) {
+ if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
+ currentlyPlayingMusic.stop();
+ currentlyPlayingMusic = null;
+ }
+ screenElements.forEach(function (el) {
+ if (el && el.parent) {
+ el.destroy();
+ }
+ });
+ screenElements = [];
+ for (var i = 0; i < visibleBossCards.length; i++) {
+ if (visibleBossCards[i] && visibleBossCards[i].parent) {
+ visibleBossCards[i].destroy();
+ }
+ visibleBossCards[i] = null;
+ }
+ loadSong(selectedBossData.songMapKey);
+ }
+ };
+ game.addChild(fightButton);
+ screenElements.push(fightButton);
+ // --- Przycisk "Special Boss" ---
+ var specialBossButtonAsset = LK.getAsset('specialBossArea', {});
+ specialBossButtonAsset.width = 400; // SZTYWNA SZEROKOŚĆ (szeroki)
+ specialBossButtonAsset.height = 70; // SZTYWNA WYSOKOŚĆ (wąski)
+ specialBossButtonAsset.x = gameScreenWidth / 2; // SZTYWNA POZYCJA X (na środku)
+ specialBossButtonAsset.y = gameScreenHeight * 0.70; // SZTYWNA POZYCJA Y (np. 80% wysokości ekranu)
+ specialBossButtonAsset.anchor.set(0.5, 0.5);
var specialBossText = new Text2("SPECIAL BOSS", {
- size: 60,
+ size: 30,
fill: 0xFFFFFF,
- align: 'center'
+ stroke: 0x000000,
+ strokeThickness: 2
});
- specialBossText.name = "TextOnSpecialBoss";
specialBossText.anchor.set(0.5, 0.5);
- specialBossText.x = specialBossFrameWidth / 2;
- specialBossText.y = specialBossFrameHeight / 2;
- specialBossAreaAsset.addChild(specialBossText);
- specialBossAreaAsset.interactive = true;
- specialBossAreaAsset.cursor = "pointer";
- specialBossAreaAsset.down = function () {
+ if (typeof specialBossButtonAsset.addChild === 'function') {
+ specialBossButtonAsset.addChild(specialBossText);
+ } else {
+ specialBossText.x = specialBossButtonAsset.x;
+ specialBossText.y = specialBossButtonAsset.y;
+ game.addChild(specialBossText);
+ screenElements.push(specialBossText);
+ }
+ specialBossButtonAsset.interactive = true;
+ specialBossButtonAsset.cursor = "pointer";
+ specialBossButtonAsset.down = function () {
var infoPopup = new Text2("Pokonaj wszystkich pozostałych bossów!", {
- size: 50,
- fill: 0xFF0000
+ size: 40,
+ fill: 0xFF0000,
+ stroke: 0x000000,
+ strokeThickness: 2,
+ align: 'center',
+ wordWrap: true,
+ wordWrapWidth: gameScreenWidth * 0.8
});
infoPopup.anchor.set(0.5, 0.5);
infoPopup.x = gameScreenWidth / 2;
infoPopup.y = gameScreenHeight / 2;
game.addChild(infoPopup);
- var popupRef = infoPopup;
LK.setTimeout(function () {
- if (popupRef.parent) {
- popupRef.destroy();
+ if (infoPopup.parent) {
+ infoPopup.destroy();
}
- }, 2500);
+ }, 3500);
};
- var backButton = new Text2("Back to Menu", {
- size: 80,
- fill: 0xCCCCCC
+ game.addChild(specialBossButtonAsset);
+ screenElements.push(specialBossButtonAsset);
+ // --- Przycisk Powrotu ---
+ var backToMainButton = new Text2("Back to Main Menu", {
+ size: 50,
+ fill: 0xDDDDDD
});
- backButton.name = "BackButton_BossSelect";
- backButton.anchor.set(0.5, 1);
- backButton.x = gameScreenWidth / 2;
- backButton.y = gameScreenHeight - 40; // Ten przycisk pozostanie na dole ekranu
- backButton.interactive = true;
- backButton.cursor = "pointer";
- game.addChild(backButton);
- screenElements.push(backButton);
- backButton.down = function () {
- g_scroll_isDragging = false;
- g_scroll_targetViewport = null;
- g_scroll_cardsContainer = null;
- g_scroll_contentHeight = 0;
- g_scroll_viewportWidth = 0;
- g_scroll_viewportHeight = 0; // Resetuj też testową wysokość
- // Usuń dokładnie te elementy, które ta funkcja stworzyła
- // Najpierw dzieci z allCardsContainerObj
- if (allCardsContainerObj && allCardsContainerObj.parent) {
- // Sprawdzenie dodane dla bezpieczeństwa
- while (allCardsContainerObj.children.length > 0) {
- var childCard = allCardsContainerObj.getChildAt(0);
- allCardsContainerObj.removeChild(childCard);
- if (childCard.destroy) {
- // Upewnij się, że metoda istnieje
- childCard.destroy();
- }
- }
+ backToMainButton.anchor.set(0.5, 1);
+ backToMainButton.x = gameScreenWidth / 2;
+ backToMainButton.y = gameScreenHeight - 20;
+ backToMainButton.interactive = true;
+ backToMainButton.cursor = "pointer";
+ backToMainButton.down = function () {
+ if (currentlyPlayingMusic && typeof currentlyPlayingMusic.stop === 'function') {
+ currentlyPlayingMusic.stop();
+ currentlyPlayingMusic = null;
}
- // Potem elementy z screenElements
- screenElements.forEach(function (item) {
- if (item && item.parent) {
- // Sprawdzenie dodane dla bezpieczeństwa
- if (item.destroy) {
- // Upewnij się, że metoda istnieje
- item.destroy();
- } else {
- // Jeśli nie ma destroy(), spróbuj usunąć z rodzica
- item.parent.removeChild(item);
- }
+ screenElements.forEach(function (el) {
+ if (el && el.parent) {
+ el.destroy();
}
});
- screenElements = []; // Wyczyść tablicę
+ screenElements = [];
+ for (var i = 0; i < visibleBossCards.length; i++) {
+ if (visibleBossCards[i] && visibleBossCards[i].parent) {
+ visibleBossCards[i].destroy();
+ }
+ visibleBossCards[i] = null;
+ }
+ currentBossViewStartIndex = 0;
+ selectedCardSlotIndex = 0;
showMainMenu();
};
- allCardsContainerObj.y = 0;
+ game.addChild(backToMainButton);
+ screenElements.push(backToMainButton);
+ displayBossCards(0, true); // Wyświetla karty na środku
}
+// Pamiętaj, aby wywołaċ initializeBossData(); gdzieś na początku, np. po deklaracjach zmiennych globalnych.
+// Aby uruchomiċ ten ekran, wywołaj showBossSelectionScreen();
function showCreditsScreen() {
currentScreenState = 'credits';
if (gameUIContainer) {
gameUIContainer.visible = false;
@@ -763,18 +908,8 @@
showMainMenu();
};
}
var currentScreenState = '';
-var g_scroll_isDragging = false;
-var g_scroll_initialPointerY = 0;
-var g_scroll_initialContainerY = 0;
-var g_scroll_targetViewport = null;
-var g_scroll_cardsContainer = null;
-var g_scroll_minY = 0;
-var g_scroll_maxY = 0;
-var g_scroll_viewportHeight = 0;
-var g_scroll_viewportWidth = 0; // <-- DODANE
-var g_scroll_contentHeight = 0; // <-- DODANE
var gameScreenWidth = 2048;
var gameScreenHeight = Math.round(gameScreenWidth * (2732 / 2048)); // iPad-like proportions
var playfieldWidth = 1408;
var playfieldStartX = (gameScreenWidth - playfieldWidth) / 2;
@@ -1869,61 +2004,9 @@
LK.effects.flashObject(note, 0xff0000, 300);
}
};
game.down = function (x, y, obj) {
- console.log("-----------------------------------");
- console.log("[game.down] Akcja! Stan:", currentScreenState);
- console.log("[game.down] Kliknięty obiekt (obj):", obj);
- if (g_scroll_targetViewport) {
- console.log("[game.down] g_scroll_targetViewport:", g_scroll_targetViewport, "(Nazwa, jeśli jest:.name", (g_scroll_targetViewport.name || "N/A") + ")");
- }
- if (g_scroll_cardsContainer) {
- console.log("[game.down] g_scroll_cardsContainer:", g_scroll_cardsContainer, "(Nazwa, jeśli jest:.name", (g_scroll_cardsContainer.name || "N/A") + ")");
- }
- var actualHitObject = obj;
- if (obj && typeof obj.target !== 'undefined' && typeof obj.global !== 'undefined') {
- actualHitObject = obj.target;
- console.log("[game.down] actualHitObject ustawiony na obj.target:", actualHitObject, "(Nazwa, jeśli jest:.name", (actualHitObject && actualHitObject.name ? actualHitObject.name : "N/A") + ")");
- } else {
- console.log("[game.down] actualHitObject ustawiony bezpośrednio na obj:", actualHitObject, "(Nazwa, jeśli jest:.name", (actualHitObject && actualHitObject.name ? actualHitObject.name : "N/A") + ")");
- }
- var canStartDrag = false;
- if (currentScreenState === 'bossselection' && g_scroll_targetViewport && g_scroll_cardsContainer) {
- var viewportGlobalX = g_scroll_targetViewport.x;
- var viewportGlobalY = g_scroll_targetViewport.y;
- console.log("[DEBUG] Kliknięcie na X:", x, "Y:", y);
- console.log("[DEBUG] Viewport Rect - X:", viewportGlobalX, "Y:", viewportGlobalY, "W:", g_scroll_viewportWidth, "H:", g_scroll_viewportHeight);
- if (x >= viewportGlobalX && x <= viewportGlobalX + g_scroll_viewportWidth && y >= viewportGlobalY && y <= viewportGlobalY + g_scroll_viewportHeight) {
- canStartDrag = true;
- console.log("[game.down] Kliknięcie wewnątrz granic cardsViewport.");
- } else {
- console.log("[game.down] Kliknięcie poza granicami cardsViewport.");
- }
- }
- if (canStartDrag) {
- console.log("[game.down] Warunki do rozpoczęcia przeciągania (na podstawie pozycji) SPEŁNIONE.");
- var contentHeight = g_scroll_contentHeight || 0; // Odczyt tutaj
- var viewportH_calc = g_scroll_viewportHeight || 0; // Odczyt tutaj
- console.log("[game.down] contentHeight:", contentHeight, "viewportHeight:", viewportH_calc);
- if (contentHeight > viewportH_calc && viewportH_calc > 0) {
- console.log("[game.down] Rozpoczynanie faktycznego przeciągania dla listy bossów.");
- g_scroll_isDragging = true;
- g_scroll_initialPointerY = y;
- g_scroll_initialContainerY = g_scroll_cardsContainer.y;
- g_scroll_minY = 0;
- g_scroll_maxY = viewportH_calc - contentHeight;
- if (g_scroll_maxY > 0) {
- g_scroll_maxY = 0;
- }
- console.log("[game.down] Przeciąganie rozpoczęte. initialPointerY:", g_scroll_initialPointerY, "initialContainerY:", g_scroll_initialContainerY, "Granice (min/max Y dla kontenera):", g_scroll_minY, g_scroll_maxY);
- return;
- } else {
- console.log("[game.down] Zawartość nie jest wystarczająco wysoka do przewijania lub g_scroll_viewportHeight nieustawione/zerowe.");
- g_scroll_isDragging = false;
- }
- } else if (currentScreenState === 'bossselection') {
- console.log("[game.down] Warunki do rozpoczęcia przeciągania NIESPEŁNIONE (np. kliknięto poza viewportem lub zły stan).");
- }
+ // Usunięto logikę dla currentScreenState === 'bossselection' (stare przewijanie)
if (currentScreenState === 'gameplay') {
for (var i_gp_pu = activePowerUpItems.length - 1; i_gp_pu >= 0; i_gp_pu--) {
var pItem_gp = activePowerUpItems[i_gp_pu];
if (pItem_gp && !pItem_gp.collected && pItem_gp.visualAsset && pItem_gp.parent) {
@@ -1956,9 +2039,8 @@
LK.effects.flashScreen(0xff0000, 400);
if (!gameOverFlag) {
playerCurrentHP = Math.max(0, playerCurrentHP - 1);
updatePlayerHpDisplay();
- console.log("Player HP after TRAP: " + playerCurrentHP);
}
}
inputLocked = true;
LK.setTimeout(function () {
@@ -1980,9 +2062,8 @@
} else if (result_gp === 'good') {
bossCurrentHP = Math.max(0, bossCurrentHP - 1);
}
updateBossHpDisplay();
- console.log("Boss HP after TAP (" + result_gp + "): " + bossCurrentHP);
}
} else {
if (!isShieldActive) {
resetCombo();
@@ -1996,34 +2077,12 @@
}, 120);
return;
}
}
+ // Tutaj można dodać logikę dla innych stanów, jeśli będzie potrzebna
};
-game.move = function (x, y, obj) {
- // --- LOGIKA PRZESUWANIA DLA GALERII BOSSÓW ---
- if (g_scroll_isDragging && g_scroll_cardsContainer) {
- // Sprawdzaj g_scroll_isDragging jako pierwszy
- var currentPointerY = y; // 'y' z game.move jest globalne
- var deltaY = currentPointerY - g_scroll_initialPointerY;
- var newY = g_scroll_initialContainerY + deltaY;
- // Zastosuj granice
- g_scroll_cardsContainer.y = Math.max(g_scroll_maxY, Math.min(g_scroll_minY, newY));
- }
- // --- KONIEC LOGIKI PRZESUWANIA ---
- // Ewentualna inna globalna logika game.move dla innych stanów
-};
+game.move = function (x, y, obj) {};
game.up = function (x, y, obj) {
- // --- LOGIKA ZAKOŃCZENIA PRZECIĄGANIA DLA GALERII BOSSÓW ---
- if (g_scroll_isDragging) {
- g_scroll_isDragging = false;
- console.log("[game.up] Zakończono przeciąganie listy bossów.");
- // return; // Zastanów się, czy 'up' nie powinno też zakończyć przetwarzania dla tego eventu,
- // aby nie aktywować np. logiki swipe z gameplayu, jeśli jakimś cudem
- // currentScreenState by się zmienił w trakcie, lub jeśli 'up' na karcie ma inną akcję.
- // Na razie zostawmy bez return, aby umożliwić działanie swipe dla notatek.
- }
- // --- KONIEC LOGIKI ZAKOŃCZENIA PRZECIĄGANIA ---
- // --- ISTNIEJĄCA LOGIKA GAME.UP DLA ROZGRYWKI (SWIPE NOTES) ---
if (currentScreenState === 'gameplay') {
if (inputLocked || !swipeStart) {
swipeStart = null;
return;
@@ -2123,9 +2182,9 @@
}
updateBossHpDisplay();
}
} else {
- resetCombo(); // W oryginalnym kodzie tu brakowało warunku na tarczę, ale logika dla swipe może być inna
+ resetCombo();
}
swipedNoteSuccessfully = true;
notesActuallyHitCount++;
}
@@ -2135,39 +2194,32 @@
LK.setTimeout(function () {
inputLocked = false;
}, 80);
swipeStart = null;
- } // Koniec if (currentScreenState === 'gameplay')
+ }
};
game.update = function () {
- // KROK 1: Upewnij się, że krytyczne globalne tablice są zainicjalizowane
if (typeof notes === 'undefined' || !Array.isArray(notes)) {
- console.log("[DIAGNOSTYKA] Globalna tablica 'notes' była: ", _typeof2(notes), ". Ponowna inicjalizacja w game.update.");
notes = [];
}
if (typeof activePowerUpItems === 'undefined' || !Array.isArray(activePowerUpItems)) {
- console.log("[DIAGNOSTYKA] Globalna tablica 'activePowerUpItems' była: ", _typeof2(activePowerUpItems), ". Ponowna inicjalizacja w game.update.");
activePowerUpItems = [];
}
- // KROK 2: Główna logika update w zależności od stanu ekranu
if (currentScreenState === 'gameplay') {
- // ---- POCZĄTEK LOGIKI DLA GAMEPLAY (MUSISZ TU WKLEIĆ SWOJĄ ISTNIEJĄCĄ LOGIKĘ Z GAME.UPDATE) ----
- // Poniżej jest przykład z wersji kodu, którą miałem wcześniej - dostosuj lub wklej swoją.
if (!hpBarsInitialized) {
setupHpBars();
setupPowerUpDisplay();
lastPowerUpSpawnAttemptTime = Date.now();
hpBarsInitialized = true;
updatePowerUpDisplayCounts();
}
var now = Date.now();
- // Logika tarczy
if (isShieldActive) {
if (now > shieldEndTime) {
isShieldActive = false;
if (shieldIcon) {
shieldIcon.alpha = 1.0;
- } // Upewnij się, że shieldIcon istnieje
+ }
if (shieldTimerDisplayContainer) {
shieldTimerDisplayContainer.visible = false;
}
console.log("Tarcza WYGASŁA.");
@@ -2183,15 +2235,14 @@
if (shieldTimerDisplayContainer && shieldTimerDisplayContainer.visible) {
shieldTimerDisplayContainer.visible = false;
}
}
- // Logika Swipe-to-Tap Buff
if (isSwipeToTapBuffActive) {
if (now > swipeToTapBuffEndTime) {
isSwipeToTapBuffActive = false;
if (swipeToTapIcon) {
swipeToTapIcon.alpha = 1.0;
- } // Upewnij się, że swipeToTapIcon istnieje
+ }
if (swipeToTapTimerDisplayContainer) {
swipeToTapTimerDisplayContainer.visible = false;
}
console.log("Buff Swipe-to-Tap WYGASŁ.");
@@ -2217,29 +2268,15 @@
}
}
removeOldNotes();
checkGameEnd();
- // ---- KONIEC LOGIKI DLA GAMEPLAY ----
} else {
- // Jesteśmy w stanie menu ('start', 'intro', 'tutorial', 'mainmenu', 'bossselection', 'credits')
- // --- MANUAL VISIBILITY CULLING FOR BOSS CARDS ---
- if (currentScreenState === 'bossselection' && g_scroll_cardsContainer && g_scroll_targetViewport && typeof g_scroll_viewportHeight === 'number' && g_scroll_viewportHeight > 0) {
- var viewportAbsoluteTopY = g_scroll_targetViewport.y;
- var viewportAbsoluteBottomY = viewportAbsoluteTopY + g_scroll_viewportHeight;
- for (var i_card_update = 0; i_card_update < g_scroll_cardsContainer.children.length; i_card_update++) {
- var card_update = g_scroll_cardsContainer.children[i_card_update];
- if (!card_update || typeof card_update.y === 'undefined' || typeof card_update.height === 'undefined') {
- continue;
- }
- var cardAbsoluteTopY_update = g_scroll_targetViewport.y + g_scroll_cardsContainer.y + card_update.y;
- var cardScaleY_update = card_update.scale && typeof card_update.scale.y === 'number' ? card_update.scale.y : 1;
- var cardScaledHeight_update = card_update.height * cardScaleY_update;
- var cardAbsoluteBottomY_update = cardAbsoluteTopY_update + cardScaledHeight_update;
- var isVisible_update = cardAbsoluteBottomY_update > viewportAbsoluteTopY && cardAbsoluteTopY_update < viewportAbsoluteBottomY;
- card_update.visible = isVisible_update;
- }
- }
+ // Jesteśmy w stanie menu lub nowej galerii ('start', 'intro', 'tutorial', 'mainmenu', 'bossGallery_paged', 'credits')
+ // Usunięto stary blok "MANUAL VISIBILITY CULLING FOR BOSS CARDS",
+ // ponieważ currentScreenState dla nowego ekranu to 'bossGallery_paged',
+ // a stary culling był dla 'bossselection' i nie pasuje do nowej logiki.
// Czyszczenie notes i activePowerUpItems w stanach menu (jeśli jakieś zostały z gameplayu)
+ // Ta logika jest nadal przydatna.
if (notes.length > 0) {
for (var i_notes_clear = notes.length - 1; i_notes_clear >= 0; i_notes_clear--) {
var n_clear = notes[i_notes_clear];
if (n_clear && n_clear.parent) {