I’m trying to set up the Conway’s Game of Life using Phaser.
My question is this: how can I make a Rectangular
of the Phaser.geom
class contain a click event?
Class Dots:
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 Game:
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);
Advertisement
Answer
You are setting interactive on the graphics
serveral time, it the forEach-loop. I think this can be done only once, so you are overriding it, but I’m no expert.
I would set the interactivity once, for the whole region:
this.graphics.setInteractive({ useHandCursor: true, hitArea: new Phaser.Geom.Rectangle(0, 0, pixel_width, pixel_height), hitAreaCallback: Phaser.Geom.Rectangle.Contains, })
And than in the “click event” select the Rectangle/Dot
this.graphics.on( 'pointerdown', function(){ // ... });
To get the Rectangle/Dot clicked, there are many ways, here is one:
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);
btw.:
I would add the graphics
once in the create
method:
create () { // ... this.graphics = this.add.graphics(); this.graphics.setInteractive({ // ... }); this.graphics.on('pointerdown', () => { // ... }); this.draw(); }
and in the draw method just clear the graphics-object.
draw () { this.graphics.clear(); // ... }