Jump to content

problem with event click in an javascript object


haldur
 Share

Recommended Posts

Hello !

At first : I'm not good in english writing and speeking, sorry for the quality of the language ...

I'm new in javascript, and I wanted to write a little game. After days of searching and reading, I choose pixi.js.

I write an object named Hexagone, witch contains a  PIXI.Graphics named hex that I want to be interactive. in this object I create an hitArea into hex and I had a hex.click function (line 81)

I want that when I click on one figures that the console print the x and y coordonate of the hexagone, but it always print 0, 0, can you explain me why ?

Here is the code, thanks for your attention

function jeu(){
	console.log(PIXI);
	var renderer = PIXI.autoDetectRenderer(600, 600,{antialias: true, transparent: false, resolution: 1});
	document.getElementById("pixi").appendChild(renderer.view);
	var stage = new PIXI.Container(0xFFFFFF);

	//var background= new PIXI.Sprite.fromImage('prairie-verte-1_2997580.jpg');
	
	var param = {
		l : 60,
		calcule : function(){
			this.h= this.l*0.45;
			this.x1 = this.l/4;
			this.y1 = 0;
			this.x2 = this.l*3/4;
			this.y2 = this.y1;
			this.x3 = this.l;
			this.y3 = this.h;
			this.x4 = this.x2;
			this.y4 = this.h*2;
			this.x5 = this.x1;
			this.y5 = this.h*2;
			this.x6 = 0;
			this.y6 = this.h;
		},
	};
	param.calcule()
	function Hexagone(x,y) {
		this.x=x;
		this.y=y;
		if(this.x%2 == 0){
			this.xBase = this.x*3*param.l/4;
			this.yBase = this.y*2*param.h
		} else{
			this.xBase = this.x*3*param.l/4;
			this.yBase = (this.y+1/2)*2*param.h
		}
	}

	Hexagone.prototype.dessiner = function(){
		this.hex = new PIXI.Graphics();	
		this.hex.beginFill(0x00FF00);
		this.hex.lineStyle(1, 0x000000);
		this.hex.moveTo(this.xBase + param.x1, this.yBase + param.y1);
		this.hex.lineTo(this.xBase + param.x2, this.yBase + param.y2);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x2, this.yBase + param.y2);
		this.hex.lineTo(this.xBase + param.x3, this.yBase + param.y3);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x3, this.yBase + param.y3);
		this.hex.lineTo(this.xBase + param.x4, this.yBase + param.y4);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x4, this.yBase + param.y4);
		this.hex.lineTo(this.xBase + param.x5, this.yBase + param.y5);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x5, this.yBase + param.y5);
		this.hex.lineTo(this.xBase + param.x6, this.yBase + param.y6);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x6, this.yBase + param.y6);
		this.hex.lineTo(this.xBase + param.x1, this.yBase + param.y1);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.hitArea = new PIXI.Polygon([
   			new PIXI.Point(this.xBase + param.x1,this.yBase + param.y1),
   			new PIXI.Point(this.xBase + param.x2,this.yBase + param.y2),
   			new PIXI.Point(this.xBase + param.x3,this.yBase + param.y3),
   			new PIXI.Point(this.xBase + param.x4,this.yBase + param.y4),
   			new PIXI.Point(this.xBase + param.x5,this.yBase + param.y5)
		]);
		this.hex.interactive = true;		
		this.hex.click =function(data){console.log("click x :"+this.x+" y : "+this.y)};
		stage.addChild(this.hex);
	}
	
	

	listeHexa=[];
	for(var y=0;y<10;y++){
		for(var x=0;x<10;x++){
			hexa = new Hexagone(x,y)
			hexa.dessiner()
			listeHexa.push(hexa);
		}
	}
	

	renderer.render(stage);
	update();
	function update(){
	    requestAnimationFrame(update);
	    renderer.render(stage);
        };
}

 

Link to comment
Share on other sites

to be more precise i changed the function :

this.hex.click =function(event){
	console.log("click x :"+this.x+" y : "+this.y)
	console.log("event",event)
	console.log("event.data",event.data)
	console.log("event.data.global",event.data.global)
};

and the result is

click x :0 y : 0 hexaboom.js:82:4
14:05:48,307 event Object { stopped: false, target: Object, type: "click", data: Object, stopPropagation: InteractionManager/this.eventData.stopPropagation() } hexaboom.js:83:4
14:05:48,310 event.data Object { global: Object, target: null, originalEvent: mouseup } hexaboom.js:84:4
14:05:48,313 event.data.global Object { x: 346, y: 361.1333312988281 }

But what I want is not just the coordonates in pixels but the column and the row of the Hexagone clicked

Link to comment
Share on other sites

// either this

var self = this;
this.hex.on('click', function(event) {
   console.log(self.x, self.y);
});

// or bind
function click(event) { console.log(this.x, this.y); }
this.hex.on('click', click.bind(this);

// ES6 way

this.hex.on(() => {
   console.log(this.x, this.y);
});

The problem is to pass "this" into the function. Its common javascript problem 

Its the same problem as here: 

 

Link to comment
Share on other sites

Thank you Ivan I've choosen the bind way and it's OK !

Your right it's a problem for newbies in JS (I'm a java programer). And understanding how to handle with function is not easy !

The ECMASCRIPT 6 Way look like scala function, but I didn't manage to implement it.

For peoble who wans to know the solution I post my code here

function jeu(){
	console.log(PIXI);
	var renderer = PIXI.autoDetectRenderer(600, 600,{antialias: true, transparent: false, resolution: 1});
	document.getElementById("pixi").appendChild(renderer.view);
	var stage = new PIXI.Container(0xFFFFFF);

	//var background= new PIXI.Sprite.fromImage('prairie-verte-1_2997580.jpg');

	var param = {
		l : 60,
		calcule : function(){
			this.h= this.l*0.45;
			this.x1 = this.l/4;
			this.y1 = 0;
			this.x2 = this.l*3/4;
			this.y2 = this.y1;
			this.x3 = this.l;
			this.y3 = this.h;
			this.x4 = this.x2;
			this.y4 = this.h*2;
			this.x5 = this.x1;
			this.y5 = this.h*2;
			this.x6 = 0;
			this.y6 = this.h;
		},
	};
	param.calcule()
	function Hexagone(x,y) {
		this.x=x;
		this.y=y;
		if(this.x%2 == 0){
			this.xBase = this.x*3*param.l/4;
			this.yBase = this.y*2*param.h
		} else{
			this.xBase = this.x*3*param.l/4;
			this.yBase = (this.y+1/2)*2*param.h
		}
	}

	Hexagone.prototype.dessiner = function(){
		this.hex = new PIXI.Graphics();	
		this.hex.beginFill(0x00FF00);
		this.hex.lineStyle(1, 0x000000);
		this.hex.moveTo(this.xBase + param.x1, this.yBase + param.y1);
		this.hex.lineTo(this.xBase + param.x2, this.yBase + param.y2);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x2, this.yBase + param.y2);
		this.hex.lineTo(this.xBase + param.x3, this.yBase + param.y3);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x3, this.yBase + param.y3);
		this.hex.lineTo(this.xBase + param.x4, this.yBase + param.y4);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x4, this.yBase + param.y4);
		this.hex.lineTo(this.xBase + param.x5, this.yBase + param.y5);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x5, this.yBase + param.y5);
		this.hex.lineTo(this.xBase + param.x6, this.yBase + param.y6);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.beginFill(0x00FF00);
		this.hex.moveTo(this.xBase + param.x6, this.yBase + param.y6);
		this.hex.lineTo(this.xBase + param.x1, this.yBase + param.y1);
		this.hex.lineTo(this.xBase + param.l/2, this.yBase + param.h);
		this.hex.endFill();
		this.hex.hitArea = new PIXI.Polygon([
   			new PIXI.Point(this.xBase + param.x1,this.yBase + param.y1),
   			new PIXI.Point(this.xBase + param.x2,this.yBase + param.y2),
   			new PIXI.Point(this.xBase + param.x3,this.yBase + param.y3),
   			new PIXI.Point(this.xBase + param.x4,this.yBase + param.y4),
   			new PIXI.Point(this.xBase + param.x5,this.yBase + param.y5)
		]);
		this.hex.interactive = true;		
		this.hex.on('click',this.click.bind(this));
		stage.addChild(this.hex);
	}
	Hexagone.prototype.click = function(event){
			console.log("click x :"+this.x+" y : "+this.y)
			console.log("event",event)
			console.log("event.data",event.data)
			console.log("event.data.global",event.data.global)
	}

	listeHexa=[];
	for(var y=0;y<10;y++){
		for(var x=0;x<10;x++){
			hexa = new Hexagone(x,y)
			hexa.dessiner()
			listeHexa.push(hexa);
		}
	}
	

	renderer.render(stage);
	update();
	function update(){
	    requestAnimationFrame(update);
	    renderer.render(stage);
};
}

 

Link to comment
Share on other sites

WOW! I just wrote a tutorial for you. I didnt test it :)

Ok, there is other stuff I see:

1) if you declare a local variable, that'll remove all "this":

var hex = this.hex = new PIXI.Graphics;
hex.beginFill(...);

2) That will remove xbase and ybase from your code.

hex.position.x = baseX;
hex.position.y = baseY;

hex.moveTo(param.x1, param.y1);

3) Performance of that stuff will be AWFUL. Its better to generate a texture of hexagon, and create multiple sprites based on it. You can look at https://github.com/pixijs/pixi.js/blob/master/src/core/graphics/Graphics.js#L695 if you want to understand it.

//setup a shape for interaction. I assume that (0,0) is your center.
var shape = new PIXI.Polygon([param.x1, param.y1, param.x2, param.y2, ... ]);

// generate texture for hex
var graphics = new PIXI.Graphics();

//set lineWidth and stuff
//...
//now add the shape
//may be this thing will be needed:
//shape.closed = true;
graphics.drawShape(shape);

var hexTex = graphics.generateTexture();

//somewhere in hex
this.hex = new Sprite(hexTex);
//we need the shape for interaction
this.hex.hitArea = shape;
//here i really hope that (0,0) was the center of your shape
this.hex.anchor.x = 0.5;
this.hex.anchor.y = 0.5;
//but if it wasnt, its not the problem. Graphics calculates the shift anyway :)
//var shapeBounds = graphics.getLocalBounds();
//this.hex.anchor.x = -bounds.x / bounds.width;
//this.hex.anchor.y = -bounds.y / bounds.height;

 

Now we have only one texture, and PIXI will draw a bunch of sprite hexes for the same price as it draws one. On mouse click PIXI will check every for hex shape for intersection. We have only one shape, but each sprite has different position, so of course it can be optimized. But mouse clicks are so rare, why bother? :)

If you have multiple types of hex, you can use multiple texture, though that will be a problem in v3 (v4 will have multitexturing), you can switch to using multiple textures per one basetexture, also called "an atlas": http://renderhjs.net/shoebox/ can produce it.

Link to comment
Share on other sites

It was a good id to have juste one shape that could be use everyware.

But I change my code and I work now with a real sprite from a png file.

And I don't manage to make work interactivity with the same shape on all object, I have to create a new one each time.

like that :

	var renderer = PIXI.autoDetectRenderer(600, 600,{antialias: true, transparent: false, resolution: 1});
	document.getElementById("pixi").appendChild(renderer.view);
	var stage = new PIXI.Container(0xFFFFFF,true);

	var textureAssiette= new PIXI.Texture.fromImage('assiette60.png');


...
...
	function Hexagone(x,y) {
		this.x=x;
		this.y=y;
		var hex = new PIXI.Sprite(textureAssiette);
		hex.anchor.x = 0;
		hex.anchor.y = 0;
		hex.position.x=this.xBase;
		hex.position.y=this.yBase;
		hex.interactive=true;
		hex.hitArea = new PIXI.Polygon([
			param.x1,param.y1,
			param.x2,param.y2,
   			param.x3,param.y3,
   			param.x4,param.y4,
   			param.x5,param.y5
		]);
		hex.on('click',this.click.bind(this));
		if(this.x%2 == 0){
			hex.position.x = x*3*param.l/4;
			hex.position.y = y*2*param.h
		} else{
			hex.position.x = x*3*param.l/4;
			hex.position.y = (y+1/2)*2*param.h
		}
		stage.addChild(hex);
		this.hex=hex;
	}

and this doesn't work with no error

	var renderer = PIXI.autoDetectRenderer(600, 600,{antialias: true, transparent: false, resolution: 1});
	document.getElementById("pixi").appendChild(renderer.view);
	var stage = new PIXI.Container(0xFFFFFF,true);



	var textureAssiette= new PIXI.Texture.fromImage('assiette60.png');

...
...
	var zoneCliquable = new PIXI.Polygon([
			param.x1,param.y1,
			param.x2,param.y2,
   			param.x3,param.y3,
   			param.x4,param.y4,
   			param.x5,param.y5
		]);



	param.calcule();
	function Hexagone(x,y) {
		this.x=x;
		this.y=y;
		var hex = new PIXI.Sprite(textureAssiette);
		hex.anchor.x = 0;
		hex.anchor.y = 0;
		hex.position.x=this.xBase;
		hex.position.y=this.yBase;
		hex.interactive=true;
		hex.hitArea = zoneCliquable;
		hex.on('click',this.click.bind(this));
		if(this.x%2 == 0){
			hex.position.x = x*3*param.l/4;
			hex.position.y = y*2*param.h
		} else{
			hex.position.x = x*3*param.l/4;
			hex.position.y = (y+1/2)*2*param.h
		}
		stage.addChild(hex);
		this.hex=hex;
	}

 

Link to comment
Share on other sites

Ok all is workign well now !!!

function jeu(){
	var renderer = PIXI.autoDetectRenderer(600, 600,{antialias: true, transparent: false, resolution: 1});
	document.getElementById("pixi").appendChild(renderer.view);
	var stage = new PIXI.Container(0xFFFFFF,true);

	var textureAssiette= new PIXI.Texture.fromImage('assiette60.png');


	var param = {
		l : 60,
		calcule : function(){
			this.h= this.l*0.45;
			this.x1 = this.l/4;
			this.y1 = 0;
			this.x2 = this.l*3/4;
			this.y2 = this.y1;
			this.x3 = this.l;
			this.y3 = this.h;
			this.x4 = this.x2;
			this.y4 = this.h*2;
			this.x5 = this.x1;
			this.y5 = this.h*2;
			this.x6 = 0;
			this.y6 = this.h;
		},
	};
	textureAssiette.hitArea = new PIXI.Polygon([
			param.x1,param.y1,
			param.x2,param.y2,
   			param.x3,param.y3,
   			param.x4,param.y4,
   			param.x5,param.y5
		]);



	param.calcule();
	function Hexagone(x,y) {
		this.x=x;
		this.y=y;
		var hex = new PIXI.Sprite(textureAssiette);
		hex.anchor.x = 0;
		hex.anchor.y = 0;
		hex.position.x=this.xBase;
		hex.position.y=this.yBase;
		hex.interactive=true;
		
		hex.on('click',this.click.bind(this));
		if(this.x%2 == 0){
			hex.position.x = x*3*param.l/4;
			hex.position.y = y*2*param.h
		} else{
			hex.position.x = x*3*param.l/4;
			hex.position.y = (y+1/2)*2*param.h
		}
		stage.addChild(hex);
		this.hex=hex;
	}
	Hexagone.prototype.click = function(event){
			console.log("click x :"+this.x+" y : "+this.y)
			console.log("event",event)
			console.log("event.data",event.data)
			console.log("event.data.global",event.data.global)
	}
	
	Hexagone.prototype.deplacer = function(){
			this.hex.position.x+=3;
	}
	
	listeHexa=[];
	for(var y=0;y<10;y++){
		for(var x=0;x<10;x++){
			hexa = new Hexagone(x,y)
			listeHexa.push(hexa);
		}
	}
	update();
	function update(){
	    requestAnimationFrame(update);
	    renderer.render(stage);
	};

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...