I am using Java Slick StateBaeedGame and want to rotate my rectangles for my collisions, I know this is possible to do for visual purposes using the Graphics or Graphics2D object but that does not modify the rectangle itself, the rectangle that is originally listed with the variables and called for in the graphics method does not rotate, to make things more clear here is some code:
java.awt.geom.Rectangle2D.Float rectTwo = new Rectangle2D.Float(460 + buckyPositionX, 50 + buckyPositionY, 100, 100);
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
worldMap.draw(buckyPositionX,buckyPositionY); //draw the map at 0,0 to start
bucky.draw(shiftX,shiftY); //draw bucky at 320, 160 (center of the screen)
g.rotate(460 + buckyPositionX, 50 + buckyPositionY, 40);
g.fillRect((float)rectTwo.getX(), (float)rectTwo.getY(), (float)rectTwo.getWidth(), (float)rectTwo.getHeight());
}
The rectangle rectTwo will be shown as rotation when I load my GUI but it is not actually rotated, if I test for a collision the rectangle is still at 0 degrees.
So, how do I get my rectangle variable to change its angle?
Generally, you can't.
What you can do, is transform the path of the shape...
PathIterator pathIterator = shape.getPathIterator(AffineTransform.getRotateInstance(Math.toRadians(33.5)));
This isn't much use to you right now, but you can then use a Path2D#append to append the path back into a Shape object...
GeneralPath path = new GeneralPath();
path.append(pathIterator, true);
Which would allow you to paint it...
((Graphics2D)g).fill(path);
This, of course, assumes that your Graphics context is a Graphics2D instance.
This also means, that you can't maintain a direct reference to a Rectange2D, but would need to use Shape instead.
Related
So I have this program to test the possibility of an object to slide down in a ramp given its friction, object mass and ramp angle. However I need to animate the box if the force is positive. Just a simple animation moving the box from that point to the end of the ramp. But I can't. Please help
private void drawTransform(Graphics g, double modifier) {
// redtowhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE);
Rectangle rect = new Rectangle(130,350, 350, 15);
Rectangle box = new Rectangle((int) (rect.getX()+300), 300, 50, 50);
AffineTransform at = new AffineTransform();
at.rotate(-Math.toRadians(modifier), rect.getX(), rect.getY() + rect.height);
// Transform the shape and draw it to screen
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.DARK_GRAY);
// g2d.fillRect(0, 0, 350, 600);
g2d.fill(at.createTransformedShape(rect));
g2d.draw(at.createTransformedShape(box));
}
Screenshot:
If all you want to do is move the box, this can be done by simply updating it's X position. You should be able to manipulate the rectangle's X position directly using something like "box.x++". Alternatively you could create a variable and reference that to provide the initial X co-ordinate, then updating that variable will "move" the box. One issue is this will only move the box along the X axis, hence you will also need some kind of constant downward force acting as gravity. This is easy to achieve, just minus the box's Y position value when it is not colliding with the ground, or your ramp.
Another approach is velocity based movement using vectors, however you mentioned that the animation should be simple. If you do want a smoother animation velocity based movement will provide this but you will need to perform a little research first.
Is it possible to rotate the Rectangle object to a certain degree around it's axis? Is it as easy as Rectangle rect = new Rectangle(x,y,w,h,r)?
If it is not possible to rotate the object, what would be a way I could get similar results?
Edit: for clarity here is my dilemma, I have images that rotate but when they colide with other images the collisions only work at 90 and 180 degree rotations because their hit box Rectangle objects don't rotate.
Edit: for clarity here is my dilemma, I have images that rotate but when they colide with other images the collisions only work at 90 and 180 degree rotations because their hit box Rectangle objects don't rotate.
You can rotate a Shape-derived object, such as a Rectangle2D by using the AffineTransform method, createTransformedShape(...).
Rectangle2D myRect = new Rectangle2D.Double(100, 100, 200, 200);
AffineTransform at = AffineTransform.getRotateInstance(Math.PI / 4, 150, 150);
Shape rotatedRect = at.createTransformedShape(myRect);
Note: code not compiled nor tested.
To rotate the rectangle, you give the graphics context an AffineTransform for rotation. Here's an example:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
AffineTransform oldTransform = g2d.getTransform();
g2d.setTransform(AffineTransform.getRotateInstance(radians);
g2d.draw(rectangle);
g2d.setTransform(oldTransform);
}
You can also use g2d.rotate(radians) for rotation.
Note that the angle must be in radians. To convert degrees into radians, use degrees * (Math.PI/180) for the angle.
There's also another way to do this (besides createTransformedShape) which creates fewer temporary objects, if that's desirable.
Instead of keeping a Rectangle2D for the bounding box, you can keep a Path2D and then do the transform in place, using Path2D.transform(AffineTransform):
import java.awt.geom.*;
public class Example {
private final Path2D hitBox;
public Example(Rectangle2D initialHitBox) {
this.hitBox = new Path2D.Double(initialHitBox);
}
public void transform(AffineTransform tx) {
path.transform(tx); // In-place transformation.
}
// ...
}
This is very similar to what AffineTransform actually does under the hood.
I have coded a simple Java game where there are two rectangles on the screen, one of the rectangles moves and the other stays still, the moving Rectangle moves with keyboard arrow input and can move either up, down, left or right. The problem I am having is drawing my rectangles on the screen, I mean I have the 2 rectangles set up with my variables as shown:
Rectangle rectOne = new Rectangle(shiftX, shiftY,90,90);
Rectangle rectTwo = new Rectangle(500 + buckyPositionX, 330 + buckyPositionY, 210, 150);
I have made a render method to draw the things on the screen which I want shown:
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
}
The problem I am having is showing my rectangles on the screen by writing the code in the render method, I could do the following:
g.fillRect(x, y,90,90);
g.fillRect(500 + buckyPositionX, 330 + buckyPositionY, 210, 150);
Which makes 2 rectangles on the screen but I need the rectangles to be drawn using the Rectangle code written with the variables, I have been told this can be done using Graphics2D but I am wondering if there is a simpler way of just using the graphics function, if not could you please help me set this up?
Thank you in advance.
You can access attributes of the Rectangle instances easily:
g.fillRect(rectOne.getX(), rectOne.getY(), rectOne.getWidth(), rectOne.getHeight());
In any case mind that usually the Graphics object is a Graphics2D instance at runtime so this could work easily too:
Graphics2D g2d = (Graphics2D)g;
g2d.fill(rectOne);
Just use:
g.fillRect(myRect.getX(), myRect.getY(), myRect.getWidth(), myRect.getHeight());
where myRect is the rectangle you want to draw. You could even make a custom method drawRect(Graphics g, Rectangle myRect); if you have lots of rectangles to draw.
Using Graphics2D is not that difficult as well, as the provide Graphics object normally is a Graphics2D object:
Graphics2D g2d = (Graphics2D) g;
g2d.fill(myRect);
I am trying to rotate a player to follow the mouse. To do this I use a Graphics obj casted to a Graphics2D object and use the rotate method. Here is my Panel draw:
public void paint(Graphics g){
g.setColor(Color.white);
g.clearRect(0, 0, this.getWidth(), this.getHeight());
player.draw(g);
enemy.draw(g);
mouseSelection.draw(g);
wallBoard.draw(g);
//draw the existing walls
for(Wall w : walls)
w.draw(g);
//draw the potential wall
potentialWall.draw(g);
//draw the lineWalls
for(Wall w : lineWalls)
w.draw(g);
}
All my rotation stuff is happening in player.draw(g), but I figured it would be better to have more information than less. Here is my player.draw(g)
public void draw(Graphics g){
//draw the player as a circle for now
g.setColor(Color.black);
Graphics2D g2d = (Graphics2D)g;
g2d.drawOval(getX(), getY(), 20, 20);
sword.draw(g2d);
g2d.rotate(rotation);
g2d.rotate(0);
}
I have tried many combinations of the g2d.rotate and drawing the shapes. Any advice as how i can rotate the player and the sword, but not the entire world itself?
I would try drawing your player to its own image (with its own graphics object), rotating THAT image, and then drawing that image on your main graphics.
You'll run into some potentially annoying hurdles to get across, like transparency on the temporary image, but they aren't anything that can't be gotten around with a little blood sweat and tears.
I would like to draw some shapes on a JPanel by overriding paintComponent. I would like to be able to pan and zoom. Panning and zooming is easy to do with AffineTransform and the setTransform method on the Graphics2D object. After doing that I can easyli draw the shapes with g2.draw(myShape) The shapes are defined with the "world coordinates" so it works fine when panning and I have to translate them to the canvas/JPanel coordinates before drawing.
Now I would like to change the quadrant of the coordinates. From the 4th quadrant that JPanel and computer often uses to the 1st quadrant that the users are most familiar with. The X is the same but the Y-axe should increase upwards instead of downwards. It is easy to redefine origo by new Point(origo.x, -origo.y);
But How can I draw the shapes in this quadrant? I would like to keep the coordinates of the shapes (defined in the world coordinates) rather than have them in the canvas coordinates. So I need to transform them in some way, or transform the Graphics2D object, and I would like to do it efficiently. Can I do this with AffineTransform too?
My code for drawing:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.blue);
AffineTransform at = g2.getTransform();
at.translate(-origo.x, -origo.y);
at.translate(0, getHeight());
at.scale(1, -1);
g2.setTransform(at);
g2.drawLine(30, 30, 140, 20);
g2.draw(new CubicCurve2D.Double(30, 65, 23, 45, 23, 34, 67, 58));
}
This is an off the cuff answer, so it's untested, but I think it will work.
Translate by (0, height). That should reposition the origin to the lower left.
Scale by (1, -1). That should flip it about the x axis.
I don't think the order of operations matters in this case.