Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (522)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (589)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Could someone explain this line of code?  (Read 2651 times)
0 Members and 1 Guest are viewing this topic.
Offline evilfrenchguy

Junior Devvie


Medals: 3



« Posted 2012-03-13 16:35:16 »

Hi guys!

I found this code for pixel-perfect collision, but there's 1 line I can't grasp...

Here's the 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  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
// returns a HashSet of strings that list all the pixels in an image that aren't transparent
   // the pixels contained in the HashSet follow the guideline of:
   // x,y where x is the absolute x position of the pixel and y is the absolute y position of the pixel
   public HashSet<String> getMask(GameObject go){
     
      HashSet<String> mask = new HashSet<String>();
      BufferedImage image = null;
      try {
         image = ImageIO.read(new File (go.getDefaultImageLocation()));
      } catch (IOException e) {
         System.out.println("error");
      }
      int pixel, a;
      for(int i = 0; i < image.getWidth(); i++){ // for every (x,y) component in the given box,
         for( int j = 0; j < image.getHeight(); j++){
     
      pixel = image.getRGB(i, j); // get the RGB value of the pixel
      a= (pixel >> 24) & 0xff;
     
      if(a != 0){  // if the alpha is not 0, it must be something other than transparent
         mask.add((go.xPos+i)+","+(go.yPos- j)); // add the absolute x and absolute y coordinates to our set
      }
         }
      }
     
      return mask;  //return our set
     
   }

// Returns true if there is a collision between object a and object b  
   public boolean checkCollision(GameObject a, GameObject b){
     
      // This method detects to see if the images overlap at all. If they do, collision is possible
      int ax1 = a.getxPos();
      int ay1 = a.getyPos();
      int ax2 = ax1 + a.getWidth();
      int ay2 = ay1 + a.getHeight();
      int bx1 = b.getxPos();
      int by1 = b.getyPos();
      int bx2 = bx1 + b.getWidth();
      int by2 = by1 + b.getHeight();
     
      if(by2 < ay1 || ay2 < by1 || bx2 < ax1 || ax2 < bx1)
      {
         return false; // Collision is impossible.
      }
      else // Collision is possible.
      {
         // get the masks for both images
         HashSet<String> maskPlayer1 = getMask(player1);
         HashSet<String> maskPlayer2 = getMask(player2);
     
         maskPlayer1.retainAll(maskPlayer2);  // Check to see if any pixels in maskPlayer2 are the same as those in maskPlayer1
         
         if(maskPlayer1.size() > 0){  // if so, than there exists at least one pixel that is the same in both images, thus
            System.out.println("Collision" + count);//  collision has occurred.
            count++;
            return true;
           
            }
         }
         return false;  
      }


This is the line I don't get:
1  
a= (pixel >> 24) & 0xff;


I have no experience with bitwise operators, but Google revealed that the 0xff notation is alpha-hex shorthand for fully transluscent. And the pixel >> 24 apparently moves the color data to the right 24 bits, but I don't know what that means. No clue what & means either and what it does to the operands.

Could someone please explain what this line does?
Offline sproingie

JGO Kernel


Medals: 202



« Reply #1 - Posted 2012-03-13 16:54:05 »

0xff is hex for 255, that's all, there's nothing about it that inherently means "alpha".  This particular code is simple bitwise arithmetic for reading the fourth byte from the least significant, i.e. the leftmost byte in a 32-bit word.  

If it's treating it as an alpha, that implies ARGB encoding, or any other encoding that puts the alpha first.

Offline evilfrenchguy

Junior Devvie


Medals: 3



« Reply #2 - Posted 2012-03-13 17:14:34 »

Yeah, that's what I figured out. It's a shorthand for alpha as 0xAARRGGBB with the base 16 0-F I am assuming.

What exactly is it setting a equal to? I guess I'm asking what does & do with operands, why is the pixel being moved 24 bits, and why is it and 0xff operands to '&'?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline SimonH
« Reply #3 - Posted 2012-03-13 17:24:20 »

'&' is the bitwise AND operator.
0xAARRGGBB & 0xff = 0xBB
( 0xAARRGGBB >> 8 ) & 0xff = 0xGG
( 0xAARRGGBB >> 16 ) & 0xff = 0xRR
( 0xAARRGGBB >> 24 ) & 0xff = 0xAA

It's a way of getting the R, G, B and alpha values for a pixel.

People make games and games make people
Offline evilfrenchguy

Junior Devvie


Medals: 3



« Reply #4 - Posted 2012-03-13 17:30:30 »

Ah! That's a little more clear.

How does 8 bits get you to green and 16 get you to red? I'll guess that it's no coincidence that there 8 bits in a byte.
Offline gbeebe

Senior Devvie


Medals: 5
Projects: 1



« Reply #5 - Posted 2012-03-13 17:59:32 »

>> 8 gives you green, because green starts at the 8th bit (it's address, if you will).  >> shifts in bits,  so to get red it's >> 16 (3rd byte) and so on.
Offline evilfrenchguy

Junior Devvie


Medals: 3



« Reply #6 - Posted 2012-03-13 18:10:53 »

Interesting...

So, getRGB() must return an 0xAARRGGBB notation which you'd have to parse (for lack of a better word) to get the exact color data you want.

What is the 0xff for then? Is that to say I only want 2 bytes out of my 0xAARRGGBB? If I didn't specify, would I get everything up to >> 24 as well?
Offline evilfrenchguy

Junior Devvie


Medals: 3



« Reply #7 - Posted 2012-03-13 18:55:36 »

Maybe you guys could help me with this.

I'm just screwing around with this code trying to work it, and at most angles it is to-the-pixel collision. At some angles though it is closer than bounding box, but there's still a gap when it registers a collision. I'll post my 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  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashSet;


public class PixelPerfect extends JFrame implements KeyListener, Runnable {

   int x = 0, y = 0, xVel = 0, yVel = 0;
   HashSet<String> maskPlayer1, maskPlayer2;
   JPanel panel = new JPanel();
   BufferedImage b1, b2;
   
   @Override
   public void keyPressed(KeyEvent arg0) {
     
      if(arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
         xVel = 3;
      }
      if(arg0.getKeyCode() == KeyEvent.VK_LEFT) {
         xVel = -3;
      }
      if(arg0.getKeyCode() == KeyEvent.VK_DOWN) {
         yVel = 3;
      }
      if(arg0.getKeyCode() == KeyEvent.VK_UP) {
         yVel = -3;
      }
   }

   @Override
   public void keyReleased(KeyEvent arg0) {
     
      xVel = 0;
      yVel = 0;
   }

   @Override
   public void keyTyped(KeyEvent arg0) {
     
     
   }
   
   public void paint(Graphics g) {
     
      Graphics2D g2d = (Graphics2D)g;
      g2d.setColor(Color.white);
      g2d.fillRect(0,0,300,300);
     
      g2d.drawImage(b1.getSubimage(0, 0, 79, 77), x, y, 79, 77, null);
      g2d.drawImage(b2.getSubimage(0, 0, 67, 60), 200, 200, 67, 60, null);
   }


   public static void main(String[] args) {
     
      new Thread(new PixelPerfect()).start();
   }
   
   public PixelPerfect() {
     
            b1 = new BufferedImage(79, 77, BufferedImage.TYPE_INT_ARGB);
      b2 = new BufferedImage(67, 60, BufferedImage.TYPE_INT_ARGB);
         try {
            b1.createGraphics().drawImage(ImageIO.read(this.getClass().getResource("groudon.gif")),
                  0,0,79,77,null);
            b2.createGraphics().drawImage(ImageIO.read(this.getClass().getResource("squirrel.png")),
               0,0,67,60,null);
         } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
         
         
         setSize(300, 300);
      add(panel);
      setVisible(true);
     
      addKeyListener(this);
      setFocusable(true);
   }

   @Override
   public void run() {
     
      try {
         while(true) {
           
            update();
            repaint();
           
            Thread.sleep(17);
           
         }
      } catch(Exception ex) {
         
      }
   }

   private void update() {
     
      x += xVel;
      y += yVel;
     
      if(checkCollision()) {

         x -= xVel;
         y -= yVel;
      }
   }

   private boolean checkCollision() {
     
      // This method detects to see if the images overlap at all. If they do, collision is possible
            int ax1 = x;
            int ay1 = y;
            int ax2 = x + 79;
            int ay2 = y + 77;
            int bx1 = 200;
            int by1 = 200;
            int bx2 = 267;
            int by2 = 260;
           
            /*if(by2 < ay1 || ay2 < by1 || bx2 < ax1 || ax2 < bx1)
            {
               return false; // Collision is impossible.
            }
            else // Collision is possible.
            {*/

               // get the masks for both images
               maskPlayer1 = getMask(b1);
               maskPlayer2 = getMask(b2);
           
               maskPlayer1.retainAll(maskPlayer2);  // Check to see if any pixels in maskPlayer2 are the same as those in maskPlayer1
               
               if(maskPlayer1.size() > 0){  // if so, than there exists at least one pixel that is the same in both images, thus
                  return true;
               }
               return false;  
            //}
   }

//returns a HashSet of strings that list all the pixels in an image that aren't transparent
   // the pixels contained in the HashSet follow the guideline of:
   // x,y where x is the absolute x position of the pixel and y is the absolute y position of the pixel
   public HashSet<String> getMask(BufferedImage img){
     
      String s = "";
      HashSet<String> mask = new HashSet<String>();
      BufferedImage image = img;

      int pixel, a;
      for(int i = 0; i < image.getWidth(); i++){ // for every (x,y) component in the given box,
         for( int j = 0; j < image.getHeight(); j++){
     
            pixel = image.getRGB(i, j); // get the RGB value of the pixel
            a = (pixel >> 24) & 0xff;
     
            if(a != 0){  // if the alpha is not 0, it must be something other than transparent
               if(img == b1) {
                  s = (x + i) + "," + (y + j);
                  mask.add(s); // add the absolute x and absolute y coordinates
               }
               else {
                  s = (200 + i) + "," + (200 + j);
                  mask.add(s);
               }
            }
         }
      }
     
      return mask;  //return our set
   }

}


It's sloppy, but I don't care as I'm just messin' around.

Here's a screen of the near-collision.



These are fully-transparent pics.

Any ideas?
Offline sproingie

JGO Kernel


Medals: 202



« Reply #8 - Posted 2012-03-13 19:04:06 »

What is the 0xff for then? Is that to say I only want 2 bytes out of my 0xAARRGGBB? If I didn't specify, would I get everything up to >> 24 as well?

0xff is the mask used with the & operator to strip off all bits but the last 8 (0xff is binary 11111111).  If you don't mask, any bits to the left of the byte you're looking for will be added in.  For an int, shifting it by 24 then masking it is kind of redundant, but people write it that way anyway for clarity.  Any shift smaller than that does need the mask.

http://en.wikipedia.org/wiki/Bitwise_operation has some okay examples for how bitwise arithmetic works.
Offline ra4king

JGO Kernel


Medals: 355
Projects: 3
Exp: 5 years


I'm the King!


« Reply #9 - Posted 2012-03-13 20:52:25 »

This post explains how RGB works and this post explains everything that deals with bitwise operations Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline evilfrenchguy

Junior Devvie


Medals: 3



« Reply #10 - Posted 2012-03-13 21:10:06 »

Thanks ra4king, that was really helpful.

Still fiddling with the collision. Maybe it's just how my move code works is why it seems like it isn't colliding.
Offline DrZoidberg

Senior Devvie


Medals: 17



« Reply #11 - Posted 2012-03-14 05:53:12 »

To extract the alpha value from an int that represents a pixel as 0xAARRGGBB there are two options.
(pixel >> 24) & 0xFF
or
pixel >>> 24

The >> operator is a signed shift, that means it "fills" the left side of the int with 1s if the number is negative i.e. if the leftmost bit is 1.
>>> is the unsigned shift operator
e.g.
0xAARRGGBB >> 24 = 0xFFFFFFAA - if AA is bigger then 127, because then it starts with a 1
0xAARRGGBB >>> 24 = 0x000000AA
& 0xFF sets everything to 0 exept the rightmost 8 bits so (0xAARRGGBB >> 24) & 0xFF gives also 0x000000AA
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xFryIx (62 views)
2014-11-13 12:34:49

digdugdiggy (41 views)
2014-11-12 21:11:50

digdugdiggy (34 views)
2014-11-12 21:10:15

digdugdiggy (30 views)
2014-11-12 21:09:33

kovacsa (52 views)
2014-11-07 19:57:14

TehJavaDev (56 views)
2014-11-03 22:04:50

BurntPizza (55 views)
2014-11-03 18:54:52

moogie (70 views)
2014-11-03 06:22:04

CopyableCougar4 (70 views)
2014-11-01 23:36:41

DarkCart (156 views)
2014-11-01 14:51:03
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!