Hello everyone and Happy New Year.
I have a question regarding Phaser3 that I can not resolve.
You see, I’m trying to set up the conway life game using phaser as I learn new things. My question is this: how can I make a Rectangular of the Phaser.geom class contain a click event? I have tried in different ways and I can not find the right way to do it, could you help me? 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);
I hope you can help me because I’m too blocked
CodePudding user response:
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();
// ...
}