/
aksjon
/
RNCB_Game
Обзор
Документация
Войти
/
aksjon
/
RNCB_Game
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/scenes/Level.js
374 строки
13 KB
aksjon
first_commit
18 май 2025, 19:19
18 май 2025, 19:19
f0429ce
Код
Авторство
О чём код?
export default class Level extends Phaser.Scene { constructor() { super({ key: 'Level' }); } create() { //this.scene.launch('UIscene'); const background = this.add.image(1280 / 2, 720 / 2, 'background'); background.setDisplaySize(1280, 720); //созд. массив. с уник. карт. this.cards = ['card_1', 'card_2', 'card_3', 'card_4', 'card_5', 'card_6']; this.cards = this.cards.concat(this.cards); //дубль карт для пар this.cards = Phaser.Utils.Array.Shuffle(this.cards); //перемеш. // Парам. сетки карт this.gridSize = 4; //кол-во карт в строке this.cardSpacing = 20; //расст. меж. картами this.cardWidth = 150; //высота карты this.cardHeight = 150; //ширина карты //рассчит. общ. шир. и выс. сетки const gridWidth = this.gridSize * this.cardWidth + (this.gridSize - 1) * this.cardSpacing; const gridHeight = Math.ceil(this.cards.length / this.gridSize) * this.cardHeight + (Math.ceil(this.cards.length / this.gridSize) - 1) * this.cardSpacing; //рассчит. нач. коорд. для центр. сетки this.startX = (1280 - gridWidth) / 2; this.startY = (720 - gridHeight) / 2; //созд карты на сцене this.cardObjects = []; //массив для хран. карт this.cards.forEach((card, index) => { const row = Math.floor(index / this.gridSize); //строка const col = index % this.gridSize; //столбец //рассчит. конеч. коорд. для кажд. карты const targetX = this.startX + col * (this.cardWidth + this.cardSpacing) + this.cardWidth / 2; const targetY = this.startY + row * (this.cardHeight + this.cardSpacing) + this.cardHeight / 2; //созд. карту в нач. поз. сверху за пред. экрана const cardObject = this.add.image( targetX, //нач. поз. Х -this.cardHeight, //нач. поз. Y 'card_back' ).setInteractive(); cardObject.setData('id', card); //сохр. id карты cardObject.setData('flipped', false); //сост. карты (перев. или нет) cardObject.setData('targetX', targetX); //конеч. поз. Х cardObject.setData('targetY', targetY); //конеч. поз. Н // Обработчик клика по карте cardObject.on('pointerdown', () => { this.flipCard(cardObject); }); this.cardObjects.push(cardObject); //добав. карту. в массив }); this.selectedCards = []; //массив для хран. выбран. карт this.isInputEnabled = false; //блок. ввод. до заверш. аним. расклада //запуск. аним. расклада карт this.dealCards(); } dealCards() { //аним. перемещ. карт в конеч. поз. this.cardObjects.forEach((card, index) => { //нач. аним. масштаб., карты появ. из точки card.setScale(0); //нач. масштаб this.tweens.add({ targets: card, scale: 1, //конеч. масштаб duration: 600, //длит. аним. delay: index * 100, //задерж. для каждой карты ease: 'Power2', //плав. функция }); //аним. перемещ. карт в их конеч. поз. this.tweens.add({ targets: card, y: card.getData('targetY'), //перемещ. карты в конеч. поз. Y duration: 1000, delay: index * 100, ease: 'Power2', onComplete: () => { if (index === this.cardObjects.length - 1) { //после заверш. аним. послед. карты разблок. ввод this.isInputEnabled = true; //this.removeCards(); // УБИРАЕТ КАРТЫ СРАЗУ//Убрать при чист. } } }); }); } flipCard(card) { //если ввод заблок. или карта перев., от ничего не делаем if (!this.isInputEnabled || card.getData('flipped')) return; //блок. ввод this.isInputEnabled = false; this.cardFlip = this.sound.add('cardFlip', {loop: false}); this.cardFlip.play(); this.cardFlip.setVolume(0.7); //аним. перевор. карты this.tweens.add({ targets: card, scaleX: 0, duration: 200, onComplete: () => { card.setTexture(card.getData('id')); //меняем текст. на лиц. стор. this.tweens.add({ targets: card, scaleX: 1, duration: 200, onComplete: () => { card.setData('flipped', true); this.selectedCards.push(card); if (this.selectedCards.length === 2) { this.checkMatch(); } else { //разблок ввод, если выбр. только одна карта this.isInputEnabled = true; } } }); } }); } checkMatch() { const [card1, card2] = this.selectedCards; if (card1.getData('id') === card2.getData('id')) { this.matchSound = this.sound.add('matchSound', {loop: false}); this.matchSound.play(); this.matchSound.setVolume(0.3); //карты совп. card1.setData('matched', true); //помеч. совп. карты card2.setData('matched', true); this.jumpCards(card1, card2); this.selectedCards = []; this.isInputEnabled = true; //разблок. ввод //пров. все ли карты совп. this.checkWin(); } else { this.dismatchSound = this.sound.add('dismatchSound', {loop: false}); this.dismatchSound.play(); this.dismatchSound.setVolume(0.3); //карты не сов., добав. аним. дрож. this.shakeCards(card1, card2); //перевор. карты обратно через 1 сек. this.time.delayedCall(1000, () => { this.flipCardBack(card1); this.flipCardBack(card2); this.selectedCards = []; this.isInputEnabled = true; //разблок. воод после заверш. аним. }); } } jumpCards(card1, card2) { this.tweens.add({ targets: card1, scaleX: 1.1, scaleY: 1.1, duration: 250, yoyo: true, repeat: 0, ease: 'Power2.out', }); this.tweens.add({ targets: card2, scaleX: 1.1, scaleY: 1.1, duration: 250, yoyo: true, repeat: 0, ease: 'Power2.out', }); } shakeCards(card1, card2) { this.tweens.add({ targets: card1, x: card1.x + 5, duration: 65, yoyo: true, repeat: 4, ease: 'Sine.inOut', }); this.tweens.add({ targets: card2, x: card2.x - 5, duration: 65, yoyo: true, repeat: 4, ease: 'Sine.inOut', }); } //пров. все ли карты откр. checkWin() { const allMatched = this.cardObjects.every(card => card.getData('matched')); if (allMatched) { this.isInputEnabled = false; this.time.delayedCall(800, () => { this.removeCards(); this.victorySound = this.sound.add('victorySound', {loop: false}); this.time.delayedCall(150, () =>{ this.victorySound.play(); this.victorySound.setVolume(0.6); }); }); } } //убир. карты. после. всех совп. removeCards() { this.cardObjects.forEach((card, index) => { //аним. перемещ. вверх this.tweens.add({ targets: card, y: -this.cardHeight, duration: 1000, delay: index * 100, ease: 'Sine.in', }); //аним. уменьш. масш. this.tweens.add( { targets: card, scale: 0, duration: 600, delay: index * 100, ease: 'Power2.in', //после заверш. запуск. функ. побед. сообщ. onComplete: () => { if (index === this.cardObjects.length - 1) { this.showWinMessage(); } } }); }); } //побед. сообщ. showWinMessage() { const winText = this.add.image( 1280 / 2, 720 / 2 - 200, 'winText' ).setOrigin(0.5).setDepth(20).setScale(0.5); //аним. текста winText.setAlpha(0); this.tweens.add({ targets: winText, alpha: 1, duration: 1000, ease: 'Power2.out', }); const restartButton = this.add.image( 1280 / 2, 720 / 2, 'restartButton' ).setOrigin(0.5).setDepth(20).setScale(0.6).setInteractive(); restartButton.setAlpha(0); this.tweens.add({ targets: restartButton, alpha: 1, duration: 1000, ease: 'Power2.out', }); //аним. при навед. restartButton.on('pointerover', () => { this.tweens.add({ targets: restartButton, scale: 0.65, duration: 200, ease: 'Power2.out' }); }); //свеч. при навед. restartButton.on('pointerout', () => { this.tweens.add({ targets: restartButton, scale: 0.6, duration: 200, ease: 'Power2.out', }); }); restartButton.on('pointerdown', () => { this.scene.start('Level'); }); const infoButton = this.add.image( 1280 / 2, 720 / 2 + 120, 'infoButton' ).setOrigin(0.5).setDepth(20).setScale(0.6).setInteractive(); infoButton.setAlpha(0); this.tweens.add({ targets: infoButton, alpha: 1, duration: 1000, ease: 'Power2.out', }); infoButton.on('pointerover', () => { this.tweens.add({ targets: infoButton, scale: 0.65, duration: 200, ease: 'Power2.out' }); }); infoButton.on('pointerout', () => { this.tweens.add({ targets: infoButton, scale: 0.6, duration: 200, ease: 'Power2.out' }); }); infoButton.on('pointerdown', () => { window.open('https:/www.rncb.ru/', '_blank'); }); } flipCardBack(card) { this.tweens.add({ targets: card, scaleX: 0, duration: 200, onComplete: () => { card.setTexture('card_back'); // Возвращаем обложку this.tweens.add({ targets: card, scaleX: 1, duration: 200, onComplete: () => { card.setData('flipped', false); } }); } }); } }