Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
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  
  Rotating a Rectangle object  (Read 5087 times)
0 Members and 1 Guest are viewing this topic.
Offline Shotgunbunny

Junior Newbie





« Posted 2011-01-26 22:28:23 »

Hi guys,

I wanted to make a simple 2D tank game, just for fun.
I'm having 1 major problem however, and I feel it should be easy to solve, but I just can't find the answer anywhere.

I have a Tank class, which extends Rectangle (java.awt.Rectangle)
It contains an image, which I am easily able to rotate using Graphics2D's rotate method.

I want to use the Rectangle.intersects method, but while the image moves exactly like I want it to, the object itself will not change (it changes location, but not it's shape), meaning the image can easily go through walls before stopping.

The problem however, is that I can't get a Tank -object-to rotate.
Using AffineTransform, I can get a rotated version of the tank Rectangle to appear just as I want it...but I can't get the newshape into my Tank object!

I tried using getBounds, but that doesn't return the actual shape, just a rectangle that encloses the shape.
I believe I need to use Tank.setFrame...but I can't get newshape's frame, or x/y location or dimensions for that matter.
What am I doing wrong here? Please help!

Quote
               Tank t = (Tank) o;                

                AffineTransform at = AffineTransform.getRotateInstance(t.getFacing(), t.getCenterX(), t.getCenterY());
                Shape newshape = at.createTransformedShape(t); //creates a new, rotated version of Tank t
                
                g2d.draw(newshape); //draws the new, rotated version of the Tank. This looks perfect, just like I want it

                /*
                THE PROBLEM: I need to apply newshape to my tank, but HOW?
                */

                g2d.drawRect(t.x, t.y, t.width, t.height); //this draws a rectangle where the Tank object is situated, this one is static, except for it's location, no rotation or such.
                
                g2d.rotate(t.getFacing(), t.getCenterX(), t.getCenterY()); //this rotates and draws the Tank's image, works as it should.
                g2d.drawImage(t.getMainImage(), t.x, t.y, null);

Offline Abuse

JGO Coder


Medals: 11


falling into the abyss of reality


« Reply #1 - Posted 2011-01-26 22:39:35 »

Don't extend Rectangle. is a(inheritance) Vs has a(composition).

A Tank is not a Rectangle. A Tank has bounds; it may be suitable for your needs to simplify these bounds as a Rectangle.

You shouldn't store the transformed geometry, as doing so will compound rounding errors when further transformations are applied.
Instead, store the untransformed geometry & the transformation matrix seperately. (though in this case, the transformation matrix is just a simple angle.)

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline dishmoth
« Reply #2 - Posted 2011-01-27 11:13:18 »

Abuse is right.  Do what Abuse says.

I'll just add that in Java2D a Rectangle is always aligned to the axes, so if you rotate a Rectangle the result is no longer a Rectangle.  It is a general Shape instead.

The quickest way to fix your code would be to add a Shape member to the Tank class (instead of extending Rectangle) and to initially set that member equal to your original Rectangle (or a Rectangle2D since that class is more up-to-date).  Then the Shape member can be transformed the way you expect.

Something like:
1  
2  
3  
4  
5  
class Tank {
  private Shape shape = new Rectangle2D.Double(0, 0, 10, 20);
  public Shape getShape() { return shape; }
  public void transform(AffineTransform at) { shape = at.createTransformedShape(shape); }
}


But, as Abuse says, numerical errors will eventually start to mess things up if you keep applying transformations to a Shape, so this isn't great as a long-term solution.  Better to store position and angle, and transform the shape from scratch each time.

Simon

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

Junior Newbie





« Reply #3 - Posted 2011-01-27 18:32:57 »

Thanks a lot!
I removed the Rectangle inheritance, and simply put a Shape, plus x,y, width and height values in my GameObject class (which Tank now inherits)
And this solved my problem so far. Now my tank will bump into Tiles (which also inherit GameObject).
However, these Tiles always have a Rectangle as Shape, so I can simply do Tank.Shape.intersects(Tile.Shape).

But then how would I go about checking collisions with other GameObjects which have had their Shape rotated?
Is there a way to do this using features in Java2D, or will I have to write something myself?
Offline dishmoth
« Reply #4 - Posted 2011-01-27 19:10:41 »

But then how would I go about checking collisions with other GameObjects which have had their Shape rotated?
Is there a way to do this using features in Java2D, or will I have to write something myself?

For some reason Java2D doesn't have a function for intersecting two Shapes.  But it does have one for intersecting two Areas, and an Area can be built from a Shape.
1  
2  
3  
4  
5  
6  
boolean intersect(Shape s1, Shape s2) {
  Area a1 = new Area(s1);
  Area a2 = new Area(s2);
  a1.intersect(a2);
  return !a1.isEmpty()
}

Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #5 - Posted 2011-01-27 19:45:55 »

But then how would I go about checking collisions with other GameObjects which have had their Shape rotated?
Is there a way to do this using features in Java2D, or will I have to write something myself?

For some reason Java2D doesn't have a function for intersecting two Shapes.  But it does have one for intersecting two Areas, and an Area can be built from a Shape.
1  
2  
3  
4  
5  
6  
boolean intersect(Shape s1, Shape s2) {
  Area a1 = new Area(s1);
  Area a2 = new Area(s2);
  a1.intersect(a2);
  return !a1.isEmpty()
}

Areas are quite slow as I recall. Make sure you keep one in memory for each object or you'll find your overhead getting really noticeable. Since you're only using OOBB's, you might want to just look up the math for rect-to-rect collision and give the math a go yourself. At least go that route if you find your game is running slowly.

See my work:
OTC Software
Offline Gingerious

Junior Member


Medals: 2



« Reply #6 - Posted 2011-11-15 23:37:49 »

I've just run into a situation that's really similar to this one.  It's really bugging me as to how I can't seem to rotate the rectangle to match the image that the rectangle is based on.  The image just uses a transform to rotate.  i've tried messing around with Graphics2D's rotate for the rectangle and holy hell that swirls the entire screen into oblivion. 

Here's a screenshot as an example of my woes:



So I'm supposed to use a shape object instead of a rectangle to work with collision detection?  I'm just wondering how to get the rectangle to match up with the bullet, basically.
Offline ra4king

JGO Kernel


Medals: 336
Projects: 2
Exp: 5 years


I'm the King!


« Reply #7 - Posted 2011-11-16 00:32:19 »

Yes you would have to use Area for this. The easiest way would be to put a Polygon into the Area. Then do a cheap bounding rectangle v. rectangle check before you do an Area check since the intersect(Area) method of Area is slooooow.

Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #8 - Posted 2011-11-16 00:39:44 »

I've just run into a situation that's really similar to this one.  It's really bugging me as to how I can't seem to rotate the rectangle to match the image that the rectangle is based on.  The image just uses a transform to rotate.  i've tried messing around with Graphics2D's rotate for the rectangle and holy hell that swirls the entire screen into oblivion. 

Here's a screenshot as an example of my woes:



So I'm supposed to use a shape object instead of a rectangle to work with collision detection?  I'm just wondering how to get the rectangle to match up with the bullet, basically.
Are you restoring the matrix after applying the transformation? Graphics2D and OpenGL transformations are state-based, so you apply it to everything, draw, then revert to a previous matrix.

Looks like you need translate the matrix to the center of your sprite before rotating it.

See my work:
OTC Software
Offline Gingerious

Junior Member


Medals: 2



« Reply #9 - Posted 2011-11-16 16:43:50 »

Yes you would have to use Area for this. The easiest way would be to put a Polygon into the Area. Then do a cheap bounding rectangle v. rectangle check before you do an Area check since the intersect(Area) method of Area is slooooow.

I'm going to try this solution first.

I've never used an area object, but the docs say that every area object has a getBounds() method that returns a rectangle that completely encases the area.  So if I'm reading you correctly, I'd create an area around each bullet, then use the area object's getBounds() to cheaply test for a collision.  If a collision is found, we test further to see if the actual area is colliding as well?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Gingerious

Junior Member


Medals: 2



« Reply #10 - Posted 2011-11-16 21:47:04 »

My brain hurts.

So here's my progress: I've managed to draw what I want on the screen using a global AffineTransform (i named it identity in the code below) that holds the default transform so that the screen doesn't go all out of whack, but the collisions that occur behind the scenes don't match what I've drawn.  For reference, another screenshot here where the red rectangle surrounding the bullet is what I want to check collisions with, while the blue rectangle is what collisions are actually checked with.



Here's some of the code for drawing what I want:

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  
AffineTransform transform = new AffineTransform();
      Polygon poly;
      for(int i = bullets.size() - 1; i >= 0; i--){
         
         if (bullets.get(i).getX() < 0 || bullets.get(i).getX() > screenWidth ||
            bullets.get(i).getY() < -30 || bullets.get(i).getY() > screenHeight ||
            !bullets.get(i).isAlive())
         {
            bullets.remove(i);
         }else{
            bullets.get(i).update(elapsedTime);
            int[] xpoints = {(int)bullets.get(i).getX(), (int)bullets.get(i).getX() + 30, (int)bullets.get(i).getX() + 30, (int)bullets.get(i).getX()};
            int[] ypoints = {(int)bullets.get(i).getY(), (int)bullets.get(i).getY(), (int)bullets.get(i).getY() + 16, (int)bullets.get(i).getY() + 16};
           
            poly = new Polygon(xpoints, ypoints, 4);
                       
            transform.setToTranslation(bullets.get(i).getX(),
               bullets.get(i).getY());
            transform.rotate(bullets.get(i).theta());
            g2d.setTransform(identity);
            g2d.drawImage(bullets.get(i).getImage(), transform, null);
            g2d.setColor(Color.RED);
            g2d.rotate(bullets.get(i).theta(), bullets.get(i).getX(), bullets.get(i).getY());
            g2d.draw(poly);
                       
         }
      }


And here's the code I'm using for collision detection:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
public void checkCollisions(){
      for(int i = 0; i < zombies.size(); i++){
         //check collision with bullet
        Rectangle zombie = new Rectangle((int)zombies.get(i).getX(), (int)zombies.get(i).getY(),
            zombies.get(i).getWidth(), zombies.get(i).getHeight());
           
           
         for(int j = 0; j < bullets.size(); j++){
            Rectangle bullet = new Rectangle((int)bullets.get(j).getX(), (int)bullets.get(j).getY(),
               bullets.get(j).getWidth(), bullets.get(j).getHeight());
           
            if(bullets.get(j).isAlive() && zombie.intersects(bullet)){
               
               bullets.get(j).setAlive(false);
               zombies.get(i).setAlive(false);
           
            }
         }
         
         if(zombie.intersects(new Rectangle((int)player.getX(), (int)player.getY(), player.getWidth(), player.getHeight()))){
            //do something to the player
        }
      }
   }


I'm not sure how to go forward because i've only transformed the image; i think the polygon needs to have those dimensions itself instead of being transformed.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #11 - Posted 2011-11-16 22:48:57 »

Well yeah, the AffineTransform is only applied to graphics, not to your game logic. There may be some way to put a point into the affine transform and get a transformed point out but that's not what you want.

Why not Google 2D OOB... 1st result

They really are not difficult to code.

See my work:
OTC Software
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.

pw (26 views)
2014-07-24 01:59:36

Riven (25 views)
2014-07-23 21:16:32

Riven (20 views)
2014-07-23 21:07:15

Riven (22 views)
2014-07-23 20:56:16

ctomni231 (51 views)
2014-07-18 06:55:21

Zero Volt (46 views)
2014-07-17 23:47:54

danieldean (37 views)
2014-07-17 23:41:23

MustardPeter (40 views)
2014-07-16 23:30:00

Cero (57 views)
2014-07-16 00:42:17

Riven (55 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!