javascript - ¿Cómo puedo establecer pointerDown para cada rectángulo en Phaser 3?
Estoy tratando de configurar el Juego de la Vida de Conway usando Phaser.
Mi pregunta es esta: ¿cómo puedo hacer que un Rectangular de la clase Phaser.geom contenga un evento de clic?
Puntos de Clase:
import 'phaser';
const COLOUR_ALIVE = 0xffffff;
const COLOUR_DEAD = 0x00000;
export class Dots extends Phaser.Geom.Rectangle {
public alive: number;
public fillColor: number;
public id: string;
constructor(scene, x, y, width, height, alive, id?) {
super(x, y, width, height);
this.alive = alive;
if(this.alive == 1){
this.fillColor = COLOUR_ALIVE;
} else {
this.fillColor = COLOUR_DEAD;
}
this.id = id;
console.log(id);
}
public isAlive():boolean{
return (this.alive == 1);
}
public returnAliveValue():number{
return this.alive;
}
public getFillColor(): number{
return this.fillColor;
}
public dead(){
this.alive = 0;
this.fillColor = COLOUR_DEAD;
}
public setAlive(){
this.alive = 1;
this.fillColor = COLOUR_ALIVE;
}
public click(pointer, gameobject){
console.log(pointer, gameobject);
}
}
Clase Juego:
import 'phaser';
import {Dots} from './classes/Dots'
const square_size = 10;
const pixel_height = 600;
const pixel_width = 800;
const DOTS = 100;
export default class Demo extends Phaser.Scene
{
private alives: Dots[] = [];
private graphics:Phaser.GameObjects.Graphics = null;
public timeElapsed: number;
public maxTime: number;
public cont = 0;
constructor ()
{
super('demo');
this.timeElapsed = 0;
this.maxTime = 1;
}
preload ()
{
}
draw () {
this.graphics = this.add.graphics();
//Afegim les fitxes vives
let pointer = this.input.activePointer;
this.alives.forEach((rectangle:Dots) => {
this.graphics.fillStyle(rectangle.getFillColor(), 1);
this.graphics.fillRectShape(rectangle);
this.graphics.setInteractive({
hitArea: new Phaser.Geom.Rectangle(0, 22, 27, 29),
hitAreaCallback: Phaser.Geom.Rectangle.Contains,
useHandCursor: true
}, (evt, geom) => {
if(pointer.isDown){
console.log(evt, geom);
}
});
});
}
destroy(obj:Phaser.GameObjects.Graphics) {
obj.destroy();
}
intersects(object1:Dots, object2:Dots){
let x = object1.x;
let y = object1.y;
let intersects = false;
if(object2.x == x - square_size && y == object2.y){
//Bloque izquierda
intersects = true;
} else if( object2.x == x + square_size && y == object2.y){
//Bloque derecha
intersects = true;
}
if(object2.y == y - square_size && x == object2.x){
//Bloque superior
intersects = true;
} else if(object2.y == y + square_size && x == object2.x){
//Bloque inferior
intersects = true;
}
if(object2.x == x - square_size && object2.y == y - square_size){
// Bloque izquierda superior
intersects = true;
} else if (object2.x == x - square_size && object2.y == y + square_size){
// Bloque izquierda inferior
intersects = true;
}
if(object2.x == x + square_size && object2.y == y - square_size){
// Bloque derecha superior
intersects = true;
} else if (object2.x == x + square_size && object2.y == y + square_size){
// Bloque derecha inferior
intersects = true;
}
return intersects;
}
searchArrIntersect(){
this.alives.forEach((x) => {
if(x.alive == 1){
let intersections = 0;
this.alives.forEach((y) => {
if(x != y){
let intersects = this.intersects(x, y);
if(intersects){
intersections ++;
}
}
});
if(intersections == 2 || intersections == 3){
x.isAlive();
}
if(intersections >= 3){
x.dead();
}
} else{
//fichas muertas
let intersections = 0;
this.alives.forEach((y) => {
if(x != y){
let intersects = this.intersects(x, y);
if(intersects){
intersections ++;
}
}
});
if(intersections == 3){
x.isAlive();
}
}
});
}
castObjectIntersects(object_search:Dots):Dots{
let dot_intersect = null;
this.alives.forEach((x, index) => {
if(x.x == object_search.x && x.y == object_search.y){
dot_intersect = x;
}
});
return dot_intersect;
}
create ()
{
let positions = [
//cross
// {x: pixel_width/2 - square_size, y: pixel_height/2, alive:1, id:'left'},
// {x: pixel_width/2 + square_size, y: pixel_height/2, alive:1, id:'right'},
// {x: pixel_width/2, y: pixel_height/2, alive:1, id:'center'},
// {x: pixel_width/2, y: pixel_height/2 - square_size, alive:1, id:'up'},
// {x: pixel_width/2, y: pixel_height/2 + square_size, alive:1, id:'down'},
// //borders
// //left
// {x: pixel_width/2 - square_size, y: pixel_height/2 - square_size, alive: 1, id:'left_up'},
// {x: pixel_width/2 - square_size, y: pixel_height/2 + square_size, alive: 1, id:'left_down'},
// //right
// {x: pixel_width/2 + square_size, y: pixel_height/2 - square_size, alive:0, id:'right_up'},
// {x: pixel_width/2 + square_size, y: pixel_height/2 + square_size, alive:0, id:'right_down'},
];
for(let i = 0; i < pixel_width; i+=10){
for(let j = 0; j < pixel_height; j+=10){
positions.push({x: i, y: j, alive:0, id:`${i}-${j}`});
}
}
positions.forEach((obj) => {
this.alives.push(new Dots(this, obj.x, obj.y, square_size, square_size, obj.alive, obj.id));
});
for(let i = 0; i <= DOTS; i++){
let random_length = Math.floor(Math.random() * (this.alives.length - 1 + 1) + 1);
let dot = this.alives[random_length];
dot.setAlive();
}
this.draw();
}
update(time: number, delta: number): void {
let deltaInSecond = delta/1000; // convert it to second
this.timeElapsed = this.timeElapsed + deltaInSecond;
if(this.timeElapsed >= this.maxTime) // if the time elapsed already more than 1 second
{
this.searchArrIntersect();
this.destroy(this.graphics);
this.draw();
// this.maxTime = 1200;
this.timeElapsed = 0;
}
}
}
const config = {
type: Phaser.AUTO,
backgroundColor: '#000000',
width: pixel_width,
height: pixel_height,
render: {
pixelArt: true
},
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH
},
scene: Demo
};
const game = new Phaser.Game(config);
Respuesta #1
Estás configurando interactivo en el graphics varias veces, está en el bucle forEach. Creo que esto solo se puede hacer una vez, por lo que lo estás sobrescribiendo, pero no soy un experto.
Configurarías la interactividad una vez, para toda la región:
this.graphics.setInteractive({ useHandCursor: true,
hitArea: new Phaser.Geom.Rectangle(0, 0, pixel_width, pixel_height),
hitAreaCallback: Phaser.Geom.Rectangle.Contains,
})
Y luego en el "evento de clic" selecciona el Rectángulo/Punto
this.graphics.on( 'pointerdown', function(){
// ...
});
Para hacer clic en el Rectángulo/Punto, hay muchas formas, aquí hay una:
this.graphics.on( 'pointerdown', function(pointer){
let selected = this.alives.find( point => Phaser.Geom.Rectangle.Contains( new
Phaser.Geom.Rectangle(point.x, point.y, point.width, point.height), pointer.worldX, pointer.worldY
));
console.log('pointerover', pointer, selected);
}, this);
por cierto:
Agregaría el graphics una vez en el método create:
create () {
// ...
this.graphics = this.add.graphics();
this.graphics.setInteractive({
// ...
});
this.graphics.on('pointerdown', () => {
// ...
});
this.draw();
}
y en el método draw simplemente limpia el objeto gráfico.
draw () {
this.graphics.clear();
// ...
}
