You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

529 lines
11 KiB

import Phaser from "phaser";
import bg from "./bg.jpg";
import tiles from "./tiles.png";
import sprites from "./tiles.json";
import title from "./title.png";
import instruction from "./instruction.png";
class PlayScene extends Phaser.Scene {
constructor() {
super({
key: "PlayScene",
});
this.allowClick = true;
this.gridBG;
this.instructions;
this.text1;
this.text2;
this.text3;
this.currentColor = "";
this.emitters = {};
this.grid = [];
this.matched = [];
this.moves = 25;
this.frames = [
"red.png",
"bu.png",
"grey.png",
"ye.png",
"pr.png",
"gr.png",
];
}
preload() {
this.load.image("bg", bg);
this.load.image("title", title);
this.load.atlas("tiles", tiles, sprites);
this.load.image("instruction", instruction);
}
create() {
const bg = this.add.image(0, 0, "bg");
bg.setOrigin(0);
bg.displayWidth = 1080;
bg.displayHeight = 1080;
this.createIcon(0, 0, 272);
this.createIcon(1, 0, 272 + 252);
this.createIcon(2, 0, 272 + 252 * 2);
this.createIcon(3, 1080 - 184, 272);
this.createIcon(4, 1080 - 184, 272 + 252);
this.createIcon(5, 1080 - 184, 272 + 252 * 2);
// The game is played in a 14x14 grid with 6 different colors
this.grid = [];
for (var x = 0; x < 14; x++) {
this.grid[x] = [];
for (var y = 0; y < 14; y++) {
var sx = 204 + x * 48;
var sy = 309 + y * 48;
var color = Phaser.Math.Between(0, 5);
var block = this.add.image(sx, -1032 + sy, "tiles", this.frames[color]);
block.setOrigin(0);
block.displayWidth = 48;
block.displayHeight = 48;
block.setData("oldColor", color);
block.setData("color", color);
block.setData("x", sx);
block.setData("y", sy);
this.grid[x][y] = block;
}
}
// Do a few floods just to make it a little easier starting off
this.helpFlood();
for (var i = 0; i < this.matched.length; i++) {
var blockk = this.matched[i];
blockk.setFrame(this.frames[blockk.getData("color")]);
}
this.currentColor = this.grid[0][0].getData("color");
this.particles = this.add.particles("tiles");
for (var i = 0; i < this.frames.length; i++) {
this.createEmitter(this.frames[i]);
}
const title = this.add.image(1080 / 2, 228, "title");
title.displayWidth = 222;
title.displayHeight = 50;
this.text1 = this.add
.text(440, 160, "MOVES:", {
fontSize: 40,
color: "#fff",
})
.setAlpha(0);
this.text2 = this.add
.text(590, 160, "00", { fontSize: 40, color: "#fff" })
.setAlpha(0);
this.text3 = this.add.text(180, 200, "", 48).setAlpha(0);
this.instructions = this.add.image(500, 600, "instruction").setAlpha(0);
//初始化位置
this.revealGrid();
}
update() {}
helpFlood() {
for (var i = 0; i < 8; i++) {
var x = Phaser.Math.Between(0, 13);
var y = Phaser.Math.Between(0, 13);
var oldColor = this.grid[x][y].getData("color");
var newColor = oldColor + 1;
if (newColor === 6) {
newColor = 0;
}
this.floodFill(oldColor, newColor, x, y);
}
}
createIcon(color, x, y) {
const area = this.add.rectangle(x, y, 184, 758 / 3);
area.setOrigin(0);
area.setData("color", color);
area.setInteractive();
}
revealGrid() {
this.tweens.add({
targets: this.gridBG,
y: 300,
ease: "Power3",
});
var i = 500;
for (var y = 13; y >= 0; y--) {
for (var x = 0; x < 14; x++) {
var block = this.grid[x][y];
this.tweens.add({
targets: block,
y: block.getData("y"),
ease: "Power3",
duration: 500,
delay: i,
});
i += 20;
}
}
i -= 1000;
// Text
this.tweens.add({
targets: [this.text1, this.text2],
alpha: 1,
ease: "Power3",
delay: i,
});
i += 500;
var movesTween = this.tweens.addCounter({
from: 0,
to: 25,
ease: "Power1",
onUpdate: function (tween, targets, text) {
text.setText(
Phaser.Utils.String.Pad(tween.getValue().toFixed(), 2, "0", 1)
);
},
onUpdateParams: [this.text2],
delay: i,
});
i += 500;
// this.tweens.add({
// targets: [this.instructions],
// alpha: 1,
// ease: "Power3",
// delay: i,
// });
this.time.delayedCall(i, this.startInputEvents, [], this);
}
startInputEvents() {
this.input.on("gameobjectdown", this.onIconDown, this);
// Cheat mode :)
this.input.keyboard.on(
"keydown_M",
function () {
this.moves++;
this.text2.setText(Phaser.Utils.String.Pad(this.moves, 2, "0", 1));
},
this
);
this.input.keyboard.on(
"keydown_X",
function () {
this.moves--;
this.text2.setText(Phaser.Utils.String.Pad(this.moves, 2, "0", 1));
},
this
);
}
stopInputEvents() {
this.input.off("gameobjectdown", this.onIconDown);
}
onIconDown(pointer, gameObject) {
if (!this.allowClick) {
return;
}
var icon = gameObject;
var newColor = icon.getData("color");
// Valid color?
if (newColor === this.currentColor) {
return;
}
var oldColor = this.grid[0][0].getData("color");
// console.log('starting flood from', oldColor, this.frames[oldColor], 'to', newColor, this.frames[newColor]);
if (oldColor !== newColor) {
this.currentColor = newColor;
this.matched = [];
this.instructions.setVisible(false);
this.moves--;
this.text2.setText(Phaser.Utils.String.Pad(this.moves, 2, "0", 1));
this.floodFill(oldColor, newColor, 0, 0);
if (this.matched.length > 0) {
this.startFlow();
}
}
}
createEmitter(color) {
this.emitters[color] = this.particles.createEmitter({
frame: color,
lifespan: 1000,
speed: { min: 300, max: 400 },
alpha: { start: 1, end: 0 },
scale: { start: 0.5, end: 0 },
rotate: { start: 0, end: 360, ease: "Power2" },
blendMode: "ADD",
on: false,
});
}
startFlow() {
this.matched.sort(function (a, b) {
var aDistance = Phaser.Math.Distance.Between(a.x, a.y, 166, 66);
var bDistance = Phaser.Math.Distance.Between(b.x, b.y, 166, 66);
return aDistance - bDistance;
});
// Swap the sprites
var t = 0;
var inc = this.matched.length > 98 ? 6 : 12;
this.allowClick = false;
for (var i = 0; i < this.matched.length; i++) {
var block = this.matched[i];
var blockColor = this.frames[block.getData("color")];
var oldBlockColor = this.frames[block.getData("oldColor")];
var emitter = this.emitters[oldBlockColor];
this.time.delayedCall(
t,
function (block, blockColor) {
block.setFrame(blockColor);
emitter.explode(6, block.x, block.y);
},
[block, blockColor, emitter]
);
t += inc;
}
this.time.delayedCall(
t,
function () {
this.allowClick = true;
if (this.checkWon()) {
this.gameWon();
} else if (this.moves === 0) {
this.gameLost();
}
},
[],
this
);
}
checkWon() {
var topLeft = this.grid[0][0].getData("color");
for (var x = 0; x < 14; x++) {
for (var y = 0; y < 14; y++) {
if (this.grid[x][y].getData("color") !== topLeft) {
return false;
}
}
}
return true;
}
clearGrid() {
// Hide everything :)
var i = 500;
for (var y = 13; y >= 0; y--) {
for (var x = 0; x < 14; x++) {
var block = this.grid[x][y];
this.tweens.add({
targets: block,
scaleX: 0,
scaleY: 0,
ease: "Power3",
duration: 800,
delay: i,
});
i += 10;
}
}
return i;
}
gameLost() {
this.stopInputEvents();
this.text1.setText("Lost!");
this.text2.setText(":(");
var i = this.clearGrid();
this.text3.setAlpha(0);
this.text3.setVisible(true);
this.tweens.add({
targets: this.text3,
alpha: 1,
duration: 1000,
delay: i,
});
this.game.onLose && this.game.onLose();
this.input.once("pointerdown", this.resetGame, this);
}
resetGame() {
this.text1.setText("Moves");
this.text2.setText("00");
this.text3.setVisible(false);
// Show everything :)
var i = 500;
for (var y = 13; y >= 0; y--) {
for (var x = 0; x < 14; x++) {
var block = this.grid[x][y];
// Set a new color
var color = Phaser.Math.Between(0, 5);
block.setFrame(this.frames[color]);
block.setData("oldColor", color);
block.setData("color", color);
this.tweens.add({
targets: block,
scaleX: 64 / 128,
scaleY: 64 / 128,
ease: "Power3",
duration: 800,
delay: i,
});
i += 10;
}
}
// Do a few floods just to make it a little easier starting off
this.helpFlood();
for (var i = 0; i < this.matched.length; i++) {
var block = this.matched[i];
block.setFrame(this.frames[block.getData("color")]);
}
this.currentColor = this.grid[0][0].getData("color");
this.tweens.addCounter({
from: 0,
to: 25,
ease: "Power1",
onUpdate: function (tween, targets, text) {
text.setText(
Phaser.Utils.String.Pad(tween.getValue().toFixed(), 2, "0", 1)
);
},
onUpdateParams: [this.text2],
delay: i,
});
this.moves = 25;
this.time.delayedCall(i, this.startInputEvents, [], this);
}
gameWon() {
this.game.onWon && this.game.onWon();
this.stopInputEvents();
this.text1.setText("Won!!");
this.text2.setText(":)");
var i = this.clearGrid();
this.time.delayedCall(2000, this.boom, [], this);
}
boom() {
var color = Phaser.Math.RND.pick(this.frames);
this.emitters[color].explode(
8,
Phaser.Math.Between(128, 672),
Phaser.Math.Between(28, 572)
);
color = Phaser.Math.RND.pick(this.frames);
this.emitters[color].explode(
8,
Phaser.Math.Between(128, 672),
Phaser.Math.Between(28, 572)
);
this.time.delayedCall(100, this.boom, [], this);
}
//调低难度中间放一些相同颜色的
floodFill(oldColor, newColor, x, y) {
if (
oldColor === newColor ||
this.grid[x][y].getData("color") !== oldColor
) {
return;
}
this.grid[x][y].setData("oldColor", oldColor);
this.grid[x][y].setData("color", newColor);
if (this.matched.indexOf(this.grid[x][y]) === -1) {
this.matched.push(this.grid[x][y]);
}
if (x > 0) {
this.floodFill(oldColor, newColor, x - 1, y);
}
if (x < 13) {
this.floodFill(oldColor, newColor, x + 1, y);
}
if (y > 0) {
this.floodFill(oldColor, newColor, x, y - 1);
}
if (y < 13) {
this.floodFill(oldColor, newColor, x, y + 1);
}
}
}
export default PlayScene;