ghostsoldier23
|
 |
«
Posted
2012-04-27 05:10:28 » |
|
I'm trying to figure out how to read pixel data from a BufferedImage (sprite sheet for example) and render it on screen. The main issue is how to associate the color data with coordinates so that I can do collision detection and what not. What is the standard method of reading pixel data and displaying it on screen?
EDIT: Let's start with just reading the pixel data from a BufferedImage (for all intents and purposes we will say everything not transparent for now) and then rendering it onto another BufferedImage at a specified x,y coordinate. Can anyone show me how to do that through manipulation of the Raster and/or setRGB() methods?
|
|
|
|
|
ra4king
|
 |
«
Reply #1 - Posted
2012-04-27 05:51:03 » |
|
You don't need to access the pixel data to draw a BufferedImage to the screen. Just pass the BufferedImage to Graphics.drawImage, and it will draw it. If you want to access the pixel data for collision detection, use the BufferedImage.getRGB method 
|
|
|
|
ghostsoldier23
|
 |
«
Reply #2 - Posted
2012-04-27 20:12:24 » |
|
I know about Graphics.drawImage. The issue with that is using rectangles as collision bounds is clunky and unappealing. I want to set the ARGB values for one BufferedImage to the canvas BufferedImage at their respective coordinates on screen.
|
|
|
|
|
Games published by our own members! Check 'em out!
|
|
ra4king
|
 |
«
Reply #3 - Posted
2012-04-27 22:22:16 » |
|
Collision != rendering.
Use whatever data type you want for collision, but as everything, the entity has an X, Y, width, and a height.
Use Graphics.drawImage for drawing, use whatever data type you want for collision.
However, I fail to see how rectangle collision is clunky and unappealing. If your images are nowhere close to rectangularly-shaped, rectangle intersect check would be innacurate...not clunky.
Maybe use a Circle v. Circle check?
|
|
|
|
jonjava
|
 |
«
Reply #4 - Posted
2012-04-27 22:35:12 » |
|
Can't you just pick the non transparent pixels and do a bitwise & when the rectangle intersect to get precise collision?
|
|
|
|
ra4king
|
 |
«
Reply #5 - Posted
2012-04-27 22:47:40 » |
|
Pixel perfect collision is very a very expensive calculation. However, how would you use bitwise operations in this circumstance?
|
|
|
|
jonjava
|
 |
«
Reply #6 - Posted
2012-04-27 22:52:00 » |
|
When you load a sprite, grab pixels into boolean "collision mask" array ( transparent = 0, non-transparent = 1 ).
Check collisions based on rectangles. When rectangles intersect, copy intersected area of collision mask from object A and check it with object B's mask.
Should work, no?
Perhaps not the optimal solution, especially with larger sprites. :p
|
|
|
|
ra4king
|
 |
«
Reply #7 - Posted
2012-04-27 22:55:48 » |
|
It'd be much quicker to traverse the pixel arrays in the intersected area and check their alpha values instead of copying into a boolean array then checking for mask.
|
|
|
|
jonjava
|
 |
«
Reply #8 - Posted
2012-04-27 22:57:45 » |
|
Indeed.
[EDIT]: Actually, is this really as expensive as you make it sound?
I think I'm going to try it out :>
|
|
|
|
ra4king
|
 |
«
Reply #9 - Posted
2012-04-27 23:01:00 » |
|
@OP if you want to use pixel perfect collision, I could post my code if you want.
|
|
|
|
Games published by our own members! Check 'em out!
|
|
Nyhm
|
 |
«
Reply #10 - Posted
2012-04-28 17:42:40 » |
|
I think this code demonstrates what you're asking for. I'm not saying this is the best way to do collision detection. I'm just trying to help answer your question. Explanation: Notice that the red, green, blue values are not used here (just for demonstration). The alphaThreshold is arbitrary [0..255]. If using bitmask transparency, then just set this to zero. If using translucent transparency (for example, if your graphics have anti-aliased edges), setting this higher will avoid collision detection on very transparent parts. The meaning of add to collision matrix is whatever data structure you want to keep for the collision detection. (My original method actually constructs a rectangular bounding box for every non-transparent pixel in the image, but I edited that out for demonstration, and because you're asking about per-pixel transparency detection.) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| int R_BAND = 0; int G_BAND = 1; int B_BAND = 2; int A_BAND = 3; int alphaThreshold = 64; int w = image.getWidth(); int h = image.getHeight(); Raster raster = bufferedImage.getRaster(); for (int x = 0; x < w; x++) { for (int y = 0; y < h; y++) { int r = raster.getSample(x,y,R_BAND); int g = raster.getSample(x,y,G_BAND); int b = raster.getSample(x,y,B_BAND); int a = raster.getSample(x,y,A_BAND); if (a > alphaThreshold) { } } } |
|
|
|
|
ghostsoldier23
|
 |
«
Reply #11 - Posted
2012-04-28 23:19:26 » |
|
Yes but the collision has to be done using the image bounds. Circle v. Circle isn't supported in default Java, and would require some heavy math calculations to find intersection points, possibly damaging performance.
Based off of reading your discussion so far, I'm going to ask this question: does Java have a built in convenience method for returning the rectangle formed by two rectangles intersecting? If not, I'm sure we can figure out a way to do so fairly easily...
|
|
|
|
|
ghostsoldier23
|
 |
«
Reply #12 - Posted
2012-04-28 23:22:02 » |
|
Read OP for some clarifications I made.
|
|
|
|
|
ra4king
|
 |
«
Reply #13 - Posted
2012-04-28 23:56:50 » |
|
Circle v. Circle is the cheapest collision check there is.... Returning intersection is also super easy  I would post code but I'm on my phone.
|
|
|
|
Nyhm
|
 |
«
Reply #14 - Posted
2012-04-29 00:21:43 » |
|
...I'm going to ask this question: does Java have a built in convenience method for returning the rectangle formed by two rectangles intersecting? If not, I'm sure we can figure out a way to do so fairly easily...
Refer to the Javadocs for java.awt.Rectangle. Have a look at Rectangle.add(..) and Rectangle.intersects(..)
|
|
|
|
ghostsoldier23
|
 |
«
Reply #15 - Posted
2012-04-29 19:35:43 » |
|
Circle v. Circle is the cheapest collision check there is.... Returning intersection is also super easy  I would post code but I'm on my phone. Hmm... I stand corrected then. Post your code when you are able. @OP if you want to use pixel perfect collision, I could post my code if you want.
Please do. Refer to the Javadocs for java.awt.Rectangle. Have a look at Rectangle.add(..) and Rectangle.intersects(..)
Wouldn't Rectangle2D.createIntersection(Rectangle2D) also work?
|
|
|
|
|
ra4king
|
 |
«
Reply #16 - Posted
2012-05-01 03:42:17 » |
|
My working collision detection code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public static boolean intersect(Entity e1, Entity e2) { if(e1.getBounds().intersects(e2.getBounds())) { Entity leftMost = e1.getX() < e2.getX() ? e1 : e2; Entity rightMost = e2.getX() < e1.getX() ? e1 : e2; Entity topMost = e1.getY() < e2.getY() ? e1 : e2; Entity bottomMost = e2.getY() < e1.getY() ? e1 : e2; int left = rightMost.getX() - leftMost.getX(); int top = bottomMost.getY() - topMost.getY(); int width = leftMost.getWidth() - left; int height = topMost.getHeight() - top; byte[] leftData = leftMost.getImageData(); byte[] rightData = rightMost.getImageData(); int leftTop = leftMost == topMost ? top : 0; int rightTop = rightMost == topMost ? top : 0; for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { int leftIdx = 3 + 4 * (x + left + (y + leftTop) * leftMost.getWidth()); int rightIdx = 3 + 4 * (x + (y + rightTop) * rightMost.getWidth()); if(!((leftData[leftIdx] & 0xff) < 100 || (rightData[rightIdx] & 0xff) < 100)) return true; } } return false; } return false; } |
|
|
|
|
|