如何在 Phaser 3 上为每个矩形设置 pointerDown

How can set pointerDown for each of rectangle on Phaser 3

我正在尝试使用 Phaser 设置 Conway 的生命游戏。

我的问题是:如何使 Phaser.geom class 的 Rectangular 包含点击事件?

Class 点数:

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);
   }
}

Class 游戏:

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);

您在 graphics 几次设置交互,它是 forEach 循环。我认为这只能完成一次,所以你覆盖了它,但我不是专家。

我会为 整个 区域设置一次交互性:

    this.graphics.setInteractive({ useHandCursor: true, 
            hitArea: new Phaser.Geom.Rectangle(0, 0, pixel_width, pixel_height),
            hitAreaCallback: Phaser.Geom.Rectangle.Contains,
    })

并且比在“点击事件”selectRectangle/Dot

    this.graphics.on( 'pointerdown', function(){
       // ...    
    });

点击Rectangle/Dot有很多种方法,这里是一个:

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);

顺便说一句:
我会在 create 方法中添加一次 graphics

create () {
    // ...
    this.graphics = this.add.graphics();
    this.graphics.setInteractive({
        // ...
    });

    this.graphics.on('pointerdown', () => { 
        // ...
    });

    this.draw();
}

并且在绘图方法中只需清除图形对象。

draw () {
    this.graphics.clear();
    // ...
}