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

Posted

技术标签:

【中文标题】如何为 Phaser 3 上的每个矩形设置 pointerDown【英文标题】:How can set pointerDown for each of rectangle on Phaser 3 【发布时间】:2022-01-01 03:12:31 【问题描述】:

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

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

类点:

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

类游戏:

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

【问题讨论】:

【参考方案1】:

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

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

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

然后在“点击事件”中选择矩形/点

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

要获得点击的矩形/点,有很多方法,这里是一种:

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方法中只是清除图形对象。

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

【讨论】:

非常感谢,你告诉我的对我有用。

以上是关于如何为 Phaser 3 上的每个矩形设置 pointerDown的主要内容,如果未能解决你的问题,请参考以下文章

如何为矩形的对角线设置动画?

在 SwiftUI 中,如何为条形图创建动态矩形?

反应导航如何为每个选项卡动态更改标题导航标题?

Tkinter:如何为画布矩形的轮廓着色?

如何为 CALayer 的角半径设置动画

如何为 SVG 多边形设置动画以进行填充?