Búsqueda de sitios web

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();
    // ...
}

Artículos relacionados