Jump to content

Return the color of a sprite?


forleafe
 Share

Recommended Posts

Is there a way for PixiJS (or any plugin/script) to return the color value of a sprite if given a point value to check? 

What I'd like to do is create a collision map, which would be a large sprite with nothing but black and white shapes. This sprite would be on it's own layer underneath a painted background image. a character sprite would move around on a layer above, and any time the edges of it collides with a black part of the collision map, it would hit a wall.

Link to comment
Share on other sites

9 minutes ago, icp said:

Hi!

I think that you are looking for the .tint property:

https://pixijs.download/dev/docs/PIXI.Sprite.html#tint

I'm not sure that's quite right. It says the tint value "applied" to the sprite. But we're not applying any tint here I don't think. The map is just a black and white colored png that gets loaded in. I need to be able know, given a position, whether a part of that sprite is black or white.

Link to comment
Share on other sites

Take original source, use getImageData() on canvas to get everything and convert it to your monochrome image.

Unfortunately, nobody who did that posted a plugin, so you have to learn the same thing from scratch. Fortunately, you'll need to know whats getImageData and 2d context anyway :)

As for extract, that'll be very slow.

let img = texture.baseTexture.resource.source
let canvas = null
if (img instanceof Canvas) {
    canvas = img;
} else {
   //create canvas, use drawImage
}
let context = canvas.getContext('2d');
let imageData = context .getImageDate(0, 0, w, h);

If you want to be a hero - please make a plugin after you implement it for your game.

Link to comment
Share on other sites

On 7/14/2019 at 6:00 AM, ivan.popelyshev said:

Take original source, use getImageData() on canvas to get everything and convert it to your monochrome image.

Unfortunately, nobody who did that posted a plugin, so you have to learn the same thing from scratch. Fortunately, you'll need to know whats getImageData and 2d context anyway :)

As for extract, that'll be very slow.


let img = texture.baseTexture.resource.source
let canvas = null
if (img instanceof Canvas) {
    canvas = img;
} else {
   //create canvas, use drawImage
}
let context = canvas.getContext('2d');
let imageData = context .getImageDate(0, 0, w, h);

If you want to be a hero - please make a plugin after you implement it for your game.

Thanks so much for your reply, but I have a few additional questions if you don't mind, hun?

You say use getimagedata to fetch all of the image data from the entire canvas, but I just need the data from one black and white png Sprite, which may not even be visible on the screen. It would be covered up by other sprites.

Also, why do I need to convert it to a monochrome image if the image I'm providing is already black and white?

Lastly, what do you mean by "take original source?"

Thanks so much for your help! ?

 

Link to comment
Share on other sites

You say use getimagedata to fetch all of the image data from the entire canvas

For every image that you download, you have to run through temp canvas to get all pixels - that way you'll get monochrome bitmaps for those images. You even can pack it 1 bit per pixel if you know bitwise operations.

It has to be done independent of pixi, you dont need renderer for that, only loader. 

You also have to pass it to Sprites somehow, maybe make a link from baseTexture to corresponding black*white image.  

If you want perfect interaction, override Sprite containsPoint() method and check which pixel was hit, look at your mono-bitmap. 

I wrote that stuff several times but so far no one made a plugin from it. I already have like 10 plugins in pixi that are actively used by people, and it looks like i have to write 10 more :)

Link to comment
Share on other sites

Usually people use different approach to collisions - they wrap objects with PhysicsEditor and download their shapes as separate JSON files.

How does that shape connect to pixijs object, its for you to decide.

That's shame that we dont provide examples for all those approaches, but our team is very small and focused on rendering nightmares, and, again, if somebody else makes a good article (GOOD and not just hello-world in medium.com), we can add a link in pixijs wiki.

Link to comment
Share on other sites

On 7/15/2019 at 4:58 PM, ivan.popelyshev said:

Sorry for complaining.

If you happen to actually solve that problem the way I wrote, I can spend time to polish it to a real plugin or at least article, and you'll be our hero :)

I'll absolutely work on this, and come up with a solution. But before I can begin I need to do a good bit of additional research/learning, and be 100% sure of this approach you're suggesting. I'm still a little unsure that I fully understand the approach.

So let me get this straight:
My objective here is to have a function that, when given a coordinate point value and a sprite, it will return the pixel color in either RGB or Hex.

In order to do this, I need to grab the image from the Pixi loader, and then run a standard Javascript method called getImageData() to break the image down and retrieve all of the data from it. I then need to sort through that data and build an array which will contain every pixel's position and color. From there, A function can easily be made which can retrieve the necessary information from the array.

Is my understanding correct? If I'm misunderstanding anything at all please feel free to correct me.

To my knowledge, I'll need to do a little extra research on the getImageData() method, and learn what the heck 2D context is. Anything else you recommend I research here?

Once again, I deeply appreciate all of the help! I do hope to create something that is useful to many people.
 

Link to comment
Share on other sites

Yep, its correct!

Now that i think about it, we can make it lazy, something like 
 

function getSpriteAlpha(sprite, point) {
   localPoint = sprite.toLocal(point);
   localPoint.x += sprite.anchor.x * sprite.texture.width;
   localPoint.y += sprite.anchor.y * sprite.texture.height;
   localPoint.x = Math.round(localPoint.x);
   if (localPoint.x < 0 || localPoint.x >= sprite.texture.width) {return false; }
   baseTex = sprite.texture.baseTexture;
   if (!baseTex.bitmapStuff) {
       const img = baseTex.resource.source;
       //generate bitmapStuff based on img, use temporary canvas + getImageData here
       
   } 
   return baseTex.bitmapStuff[localPoint.y * baseTex.height + localPoint.x];
}

OH, I almost implemented that. Guess its not that difficult.

I actually need like 10 minutes more to implement that and debug, but I'll leave it to you :) Tell me if you'll have problems with implementing the rest.

Link to comment
Share on other sites

16 hours ago, ivan.popelyshev said:

OK, I apologize, its not 10 minutes, its 20.

https://www.pixiplayground.com/#/edit/EOxtz6zy7rsr2ryzzPNBC

A shame. Now we dont need a hero. One more interesting problem was murdered by serial task-maniac.

I hope that you can convert containsPoint to whatever you need for collisions :)

Oh darn!! I was going to work on this over the weekend, but thank you very much for writing this. I very much so appreciate it!

I'm looking over what you wrote, and had a couple of questions about it.

Your containsPoint function looks like it contains all of the necessary logic for converting the bunny sprite to a bitmap image that we can determine the pixel color with if we're given a point. But as is, does this function actually return the pixel color of a given point yet? I'm having trouble understanding what this function will actually end up doing and what further work I'll need to do from here.

Second, I'm not sure I'm quite following why on mouse over, the bunny sprite has a tint filter added to it. Is there a reason you added this?

Thanks!
 

Link to comment
Share on other sites

it asks to generate "hitmap" if its not ready.

hitmap stores only 1 bit per pixel, whether alpha is more than threshold=127, or less.

tint is here for a test, if you move mouse over the bunny you'll see tint :)

if you need more than 1 bit per pixel, you can adjust the way hitmap is generated - either save every 4th byte (alpha), or just store everything (hitmap = imageData.data) 

dont forget to change address function, right now im using "hitmap[NUM / 32  ] = 32 bits, NUM%32-th bit is pixel value" , but with 1 byte per data it'll be just "hitmap[num] = alpha" , hitmap is Uint8Array.

If you fail to do your stuff in hour or two, ask me again, i'll help.

Link to comment
Share on other sites

On 7/19/2019 at 11:57 AM, ivan.popelyshev said:

it asks to generate "hitmap" if its not ready.

hitmap stores only 1 bit per pixel, whether alpha is more than threshold=127, or less.

tint is here for a test, if you move mouse over the bunny you'll see tint :)

if you need more than 1 bit per pixel, you can adjust the way hitmap is generated - either save every 4th byte (alpha), or just store everything (hitmap = imageData.data) 

dont forget to change address function, right now im using "hitmap[NUM / 32  ] = 32 bits, NUM%32-th bit is pixel value" , but with 1 byte per data it'll be just "hitmap[num] = alpha" , hitmap is Uint8Array.

If you fail to do your stuff in hour or two, ask me again, i'll help.

omigosh!! Oh no!! The link that you posted with the code doesn't have hardly anything in it anymore?! Did the code get deleted? ;; If so, is there anywhere you kept it where I can find it? I only just got around to trying to implement it.

https://www.pixiplayground.com/#/edit/EOxtz6zy7rsr2ryzzPNBC

Edit: Okay PHEW, found a cached version of the page on my laptop and put the code here:
https://pastebin.com/pJN65ZS6

Link to comment
Share on other sites

On 7/19/2019 at 11:57 AM, ivan.popelyshev said:

If you fail to do your stuff in hour or two, ask me again, i'll help.

Okay I give. I really just need a function where I give it a point, and I get back a sprite color, and I'm just not understanding what steps I need to take to turn the code you've written into that.

Part of the problem is I'm just not understanding what you've written well enough to know how to utilize it properly. I really just don't get it.

Like, how do I kick this thing off and get it to generate a hitmap, then where is the hitmap being stored? Then how do I get a color value out of that?

The Code: https://pastebin.com/pJN65ZS6

What I've tried:
running in the console:

PIXI.Sprite.prototype.containsPoint(app.stage.children[0].position);

PIXI.Sprite.prototype.containsPoint(tempPoint);

PIXI.Sprite.prototype.containsPoint(500);

var p1 = new PIXI.Point(960,472);
PIXI.Sprite.prototype.containsPoint(p1);

//Basically all of these return: TypeError: this.transform is undefined 
//I'm so confused, How does this thing work?


Any help would be wonderful, as I think I just don't have a clue what I'm doing at this point.

Link to comment
Share on other sites

4 hours ago, ivan.popelyshev said:

OK, today or in weekend.

Judging by your mistake with ".prototype", you are not js coder originally, right? Java or C#? 

You need full color, right? not just alpha? 

I feel a little ashamed. This was a pretty basic mistake. But yes, while I originally learned to code in JS, my job has forced me to do a lot of work in a proprietary language called "APEX" which is basically Java with some extra primitives. So I spend all day in Java and forgot what prototypes even were. I had to review them just now, and I feel a little dumb. I forgot that the Prototype property is how we ADD a new method/property to a constructor. so knowing this...
 

var bunbun = new PIXI.Sprite(app.loader.resources.bunny.texture);

bunbun.containsPoint(pixiPointGoesHere);

In your code, you were ADDING new data to the "containsPoint" method to the PIXI.Sprite constructor, correct?

Question: Once the Hitmap is generated, I see we have an array of what I believe are all the pixels in the sprite. How can we use this data to retrieve the color of any given pixel? Is there a method/property that can help us with this?
 

Link to comment
Share on other sites

yeah, and containsPoint() is a method that returns boolean that is used by pixijs interaction, that's how i tested it. You can create another method, it doesnt matter whether you add it in prototype , in sprite , or just make a function that accepts sprite as a param.

The thing is, inside you have to calculate hitmap, in your case if you want all data its obvious : "hitmap = imageData.data", then you have to look inside. Give me 10 minutes, i'll make it :)

Link to comment
Share on other sites

Here you go: https://www.pixiplayground.com/#/edit/E0zWdinWc3u0ay~Qgg3iF

getColorByPoint gets color by global point, and I made a testing 'mouseMove' that  uses it :) Try move mouse over a rabbit.

This example will be available for everyone, im adding it to new wiki page on our github: https://github.com/pixijs/pixi.js/wiki/v5-Hacks

We have hundreds issues like that, we need to cover everything with a cookbook recipes. 

I just leave the link here: https://opencollective.com/pixijs

Java is cool, I'm originally Java coder and I used many domain specific languages with it.

Link to comment
Share on other sites

5 minutes ago, ivan.popelyshev said:

Here you go: https://www.pixiplayground.com/#/edit/E0zWdinWc3u0ay~Qgg3iF

getColorByPoint gets color by global point, and I made a testing 'mouseMove' that  uses it :)

I can't thank you enough for your help, it seriously means a lot to me and has helped tremendously! I can't wait to show off what I make with this~

xoxo

-Clover

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...