Rotation of collision bounds - java

I'm working on my 2D java game and I have a problem with rotation of collision bounds.
I have an Attack Class:
public void render(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AffineTransform old = g2d.getTransform();
g2d.rotate(Math.toRadians(player.getDir()), (double) player.getX() + 16, (double) player.getY() + 16);
g2d.setComposite(makeTransparent(alpha));
g.setColor(Color.gray);
g.fillRect((int) x, (int) y, 32, 32);
g2d.setComposite(makeTransparent(1));
g.setColor(Color.red); // drawing the results
g2d.draw(getBounds()); // drawing the getBounds();
g2d.setTransform(old);
}
private AlphaComposite makeTransparent(float alpha) {
int type = AlphaComposite.SRC_OVER;
return (AlphaComposite.getInstance(type, alpha));
}
public Rectangle getBounds() {
return new Rectangle((int) x, (int) y, (int) width + 32, (int) height + 32);
}
But in practice it only "deals damage" to the right of the character - like no rotation happens. I was trying to use:
https://stackoverflow.com/a/5925715/5502471
solution, but I kinda failed and not sure what I'm doing wrong.
Few hints:
Attack is a seperate class,
Attack is caused from a Player Class by Keyboard input,
Collision happens in enemy class,
if (tempObject.getId() == ID.Attack){
if (getBounds().intersects(tempObject.getBounds())){
health-=3;
}
}
I was looking for some "easy" way to do it, since I was hoping to use this in many many things ;) If there is no easy way, then the hard way will do too - challenge accepted!

I found a pretty simple solution (somewhere at stackoverlow.com ;P). It's not perfect but, well, at least it works ;). Just useing a method to move around the starting point of drawing the rectangle bounds.
public Rectangle getBounds() {
double newX = 0;
double newY = 0;
Rectangle attack = new Rectangle((int) newX, (int) newY, 32, 32);
double[] pt = { x, y };
AffineTransform
.getRotateInstance(Math.toRadians(player.getDir()), (double) player.getX(), (double) player.getY())
.transform(pt, 0, pt, 0, 1);
//playeer.getDir() - method to return the rotation angle in degress
newX = pt[0];
newY = pt[1];
attack = new Rectangle((int) newX, (int) newY, 32, 32);
return attack;
}
Results
I hope you find out it usefull. Cheers!

Related

How to make a shape that follows the cursor, without setting the background to the draw function in Java?

I'm working on a basic Java project in Processing for school. It's a simple doodling program that makes random shapes when you click and drag. I am happy with how it has turned out so far, but I want the shape to appear and follow the cursor before the user clicks, so they can see what shape it is before it gets drawn onto the background. Most of the pertinent advice I could find elsewhere involved having the background in the draw function, but since the point is for the user to create a persistent picture (until they choose to reset it), that does not really work with my current setup as far as I can tell. Is there some other way to create a shape that follows the cursor? Or would I have to rework some or all of the code?
The code is set to determine the value of shape at random when the program is first ran and when the mouse is released, and then print whichever shape when the mouse is clicked and dragged, so I pretty much need to find a way to make that shape appear and follow the cursor before it is clicked and changed. I'm basically new to Java so I am not familiar with possible options to explore for achieving this. Any advice is greatly appreciated!
The whole program is only 70 lines, so here it is in its entirety minus the .wav files for the sound effects:
`
import processing.sound.*;
SoundFile file;
SoundFile fileb;
float x;
float y;
float w;
float h;
float r;
float b;
float g;
float re;
float gr;
float bl;
float shape = random(0, 30);
float c;
void setup() {
size(640, 360);
re = random(0, 256);
gr = random(0, 256);
bl = random(0, 256);
background(re, gr, bl);
rectMode (CENTER);
noStroke();
file = new SoundFile(this,"whoosh.wav");
fileb = new SoundFile(this,"pen.wav");
file.amp(.2);
fileb.amp(.15);
}
void draw() {
if (mousePressed) {
if (shape < 10) {
rect (mouseX, mouseY, w, h);
}
if (shape >= 20) {
ellipse(mouseX, mouseY, w, h);
}
if (shape >= 10 && shape < 20) {
triangle(mouseX - (w / 2), mouseY + (h / 2), mouseX + (w / 2), mouseY + (h / 2), mouseX, mouseY - (h / 2));
}
}
}
void mousePressed() {
c = random(0, 17);
fileb.cue(c);
fileb.play();
w = random(5, 125);
h = random(5, 125);
r = random(0, 256);
g = random(0, 256);
b = random(0, 256);
fill(r, g, b);
}
void mouseReleased() {
fileb.stop();
shape = random(0, 30);
}
void keyPressed() {
re = random(0, 256);
gr = random(0, 256);
bl = random(0, 256);
background(re, gr, bl);
file.play();
}
`

Java Canvas - Rectangle2D Scales when Moving

I am drawing a series of rectangles on a Canvas. The rectangles are supposed to move on an angle. For some reason, when they move, they scale up:
xPos += xSpeed;
yPos += ySpeed;
updateBounds(xPos, yPos, width, height);
My UpdateBounds method:
public void updateBounds(double x, double y, double w, double h) {
bounds.setRect(x, y, w, h);
}
Bounds is a Rectangle2D object.
And my Drawing method:
g.fillRect((int) bounds.getX(), (int) bounds.getY(),
(int) bounds.getMaxX(), (int) bounds.getMaxY());
Why am I getting this behaviour?
Graphics.fillRect() accepts a width and height parameter, not the largest x and y position of the rectangle to draw.
The third and fourth parameters to fillRect should be Rectangle2D's getWidth() and getHeight().
As a reference, a link to what getMaxX() would give you.

Draw curved lines,any suggestions

Hello guys I need to draw the curved lines in bold mainly those starting N - S and if possible the ones getting 350-10 340-20 and so on. I have tried QuadCurve2D and drawArc, but none of those worked. Is there any way possible to avoid the use of drawPolyline(xPoints, yPoints, WIDTH) because it will take hundreds of pairs to draw just one line.
This is part of the code in order to avoid your loss of time testing yourself :
public class PaintMyQuad extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
QuadCurve2D.Double curve = new QuadCurve2D.Double(200,0,200,100,200,200);
QuadCurve2D.Double curve1 = new QuadCurve2D.Double(200,0,180,100,200,200);
QuadCurve2D.Double curve2 = new QuadCurve2D.Double(200,0,160,100,200,200);
//etc
g2d.setColor(Color.RED);
g2d.draw(curve);
g2d.draw(curve1);
g2d.draw(curve2);
g2d.drawOval(100,100,200,200);
g2d.drawArc(100,100, 100, 200, 90, 180);
g2d.drawArc(100, 100, 100, 200, 180, 360);
g2d.drawArc(100, 100, 0, 200, 90, 180);
g2d.drawRect(100, 100, 200, 200);
If you need bold lines, try so:
....
Graphics2D g2d = (Graphics2D)g;
BasicStroke pen1 = new BasicStroke(5); // this is stroke with 5px width,
g2d.setStroke(pen1);
g2d.drawArc(100,100, 100, 200, 90, 180);
g2d.drawArc(100, 100, 100, 200, 180, 360);
...
Make 2 strokes for two types of lines, and use it.
Im not sure if this is an really an answer - but have I have run into a resolution problem. I have tried anti-aliasing but it looked worse.
One way you could do it is in the for loop put an if statement for odd and even numbers.Happy for some advice on this, I was thinking there maybe a better library to get nicer circles.
Maybe I'm doing it the old school way?
import java.awt.*;
import javax.swing.*;
public class Stereonet{
private static int centreX, centreY, radius;
private Color colour;
/**Stereonet template contructor takes 3 int parameters
* x, y for centre position and radius for stereonet radius*/
public Stereonet(int x , int y, int radius, Color colour){
centreX = x;
centreY = y;
this.radius = radius;
this.colour = colour;
}
public void draw(Graphics g){
Graphics2D g2D = (Graphics2D) g;
g2D.setStroke(new BasicStroke(2F));
g.setColor(colour);
g.drawOval(centreX - radius , centreY - radius, radius * 2 , radius * 2);
g2D.setStroke(new BasicStroke(1F));
g.drawLine(centreX, centreY - radius, centreX, centreX + radius);
g.drawLine(centreX - radius, centreY, centreX + radius, centreY);
g2D.setStroke(new BasicStroke(1F));
for(int degrees = 10; degrees <= 80; degrees += 10){
double greatRadius = radius / (Math.cos(Math.toRadians(degrees))); // radius of great circle
int greatX1 = (int)Math.round(centreX + radius * (Math.tan(Math.toRadians(degrees)))
- greatRadius); // x coord of great circle left hemisphere
int greatX2 = (int)Math.round(centreX - (radius * (Math.tan(Math.toRadians(degrees))))
- greatRadius); // x coord of great circle right hemisphere
int greatY = (int)Math.round(centreY - greatRadius); // y coord of great circle
double smallRadius = (radius / (Math.tan(Math.toRadians(degrees))));
int smallY1 = (int)Math.round((centreY - (radius / (Math.sin(Math.toRadians(degrees)))) - smallRadius));
int smallY2 = (int)Math.round((centreY + (radius / (Math.sin(Math.toRadians(degrees)))) - smallRadius));
int smallX = (int)Math.round(centreX - smallRadius);
g.drawArc(greatX1, greatY, 2 * (int)Math.round(greatRadius), 2 * (int)Math.round(greatRadius),
90 + degrees, 180 - ( 2 * degrees));
g.drawArc(greatX2, greatY, 2 * (int)Math.round(greatRadius), 2 * (int)Math.round(greatRadius),
270 + degrees, 180 - ( 2 * degrees));
g.drawArc(smallX, smallY1, 2 * (int)Math.round(smallRadius), 2 * (int)Math.round(smallRadius),
270 - degrees, 180 - ( 2 * (90 - degrees)));
g.drawArc(smallX, smallY2, 2 * (int)Math.round(smallRadius), 2 * (int)Math.round(smallRadius),
90 - degrees, 180 - ( 2 * (90 - degrees)));
}
}
public static int getRadius(){
return radius;
}
public static int getX(){
return centreX;
}
public static int getY(){
return centreY;
}

Java GUI Rotation and Translation of Rectangle

I am trying to draw a rectangle in JPanel that would translate and then rotate itself to mimic the movement of a car. I have been able to make the rectangle translate and rotate, however it rotates around the origin of (0,0). I'm very pleased that I was able to have the rectangle move and rotate as I am very new to Java GUI, but I can not seem to get how to have the rectangle rotate around itself, because I experimented more with it, and when I initialized the rectangle and rotate it 45 degrees it's position was changed, which I would assume is the transform matrix that is appended from the rotate method.
I checked through the site on how would I solve this, however I only found how to rotate a rectangle and not on how to rotate and move like the movement of a simulated car. I would presume it is concerning about its transform matrix, but I'm only speculating. So my question is how would I be able to have the rectangle be able to rotate and move around itself and not against a point in JPanel.
Here's the code that I have come up so far:
public class Draw extends JPanel implements ActionListener {
private int x = 100;
private int y = 100;
private double theta = Math.PI;
Rectangle rec = new Rectangle(x,y,25,25);
Timer timer = new Timer(25,this);
Draw(){
setBackground(Color.black);
timer.start();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.white);
rec.x = 100;
rec.y = 100;
g2d.rotate(theta);
g2d.draw(rec);
g2d.fill(rec);
}
public void actionPerformed(ActionEvent e) {
x = (int) (x + (Math.cos(theta))*1);
y = (int) (y + (Math.sin(theta))*1);
theta = theta - (5*Math.PI/180);
repaint();
}
One of two approaches are commonly used:
Rotate the graphics context around the center (x, y) of the Shape, as shown here.
rotate(double theta, double x, double y)
Translate to the origin, rotate and translate back, as shown here.
g2d.translate(this.getWidth() / 2, this.getHeight() / 2);
g2d.rotate(theta);
g2d.translate(-image.getWidth(null) / 2, -image.getHeight(null) / 2);
Note the apparent reverse order of concatenation in the second example.
Addendum: Looking more closely at your example, the following change rotates the Rectangle around the panel's center.
g2d.rotate(theta, getWidth() / 2, getHeight() / 2);
Also, use the #Override annotation, and give your panel a reasonable preferred size:
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
Use affine transform to rotate the rectangle and convert it into the rotated polynomial. Check the code below:
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.white);
/* rotate rectnagle around rec.x and rec.y */
AffineTransform at = AffineTransform.getRotateInstance(theta,
rec.x, rec.y);
/* create the plunomial */
Polygon p = new Polygon();
/* path interator of the affine transformed polynomial */
PathIterator i = rec.getPathIterator(at);
while (!i.isDone()) {
double[] points = new double[2];
i.currentSegment(points);
p.addPoint((int) points[0], (int) points[1]);
i.next();
}
g2d.fill(p);
}

Rotating BufferedImage instances

I am having trouble getting a rotated BufferedImage to display. I think the rotation is working just fine, but I can't actually draw it to the screen. My code:
Class extends JPanel {
BufferedImage img;
int rotation = 0;
public void paintComponent(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
img2d = img.createGraphics();
img2d.rotate(Math.toRadians(rotation), img.getWidth() / 2, img.getHeight() / 2);
g.drawImage(img, imgx, imgy, null);
this.repaint();
}
}
This is not working for me. I could not find any way to draw the rotated img2d onto g.
EDIT: I have multiple objects that are being drawn onto g, so I can't rotate that. I need to be able to rotate things individually.
Maybe you should try using AffineTransform like this:
AffineTransform transform = new AffineTransform();
transform.rotate(radians, bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2);
AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
bufferedImage = op.filter(bufferedImage, null);
Hope this helps.
I would use Graphics2D.drawImage(image, affinetranform, imageobserver).
The code example below rotates and translates an image to the center of the component. This is a screenshot of the result:
public static void main(String[] args) throws IOException {
JFrame frame = new JFrame("Test");
frame.add(new JComponent() {
BufferedImage image = ImageIO.read(
new URL("http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png"));
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// create the transform, note that the transformations happen
// in reversed order (so check them backwards)
AffineTransform at = new AffineTransform();
// 4. translate it to the center of the component
at.translate(getWidth() / 2, getHeight() / 2);
// 3. do the actual rotation
at.rotate(Math.PI / 4);
// 2. just a scale because this image is big
at.scale(0.5, 0.5);
// 1. translate the object so that you rotate it around the
// center (easier :))
at.translate(-image.getWidth() / 2, -image.getHeight() / 2);
// draw the image
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, at, null);
// continue drawing other stuff (non-transformed)
//...
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
}
You are rotating the graphics for drawing into your image, not the image. Thats why you see no effect. Apply the rotation to the graphics you are painting on and it will draw the image rotated:
public void paintComponent(Graphics g) {
g.clearRect(0, 0, getWidth(), getHeight());
g.rotate(Math.toRadians(rotation), img.getWidth() / 2, img.getHeight() / 2);
g.drawImage(img, imgx, imgy, null);
this.repaint();
}
This will probably not draw entirely what you expect, the rotation will revolve around the coordinate origin. For the image to be rotate around its center you need to apply a coordinate translation before the rotation, for example:
g.translate(imgx >> 1, imgy >> 1);
The Graphics2D Tutorial has some more examples.
I know this question is old but I came up with a solution that has some advantages:
creates image of correct size.
correct offset.
does not unnecessarily rotate by 0° or 360°.
works for negative angles (e.g. -90°).
works when input is BufferedImage.TYPE_CUSTOM.
As it is, it is assumed that the angle is a multiple of 90°. The only improvement that one might need is to use an Enum for angle instead of just int.
Here's my code:
public static BufferedImage rotateBufferedImage(BufferedImage img, int angle) {
if (angle < 0) {
angle = 360 + (angle % 360);
}
angle %= 360;
if (angle == 0) {
return img;
}
final boolean r180 = angle == 180;
if (angle != 90 && !r180 && angle != 270)
throw new IllegalArgumentException("Invalid angle.");
final int w = r180 ? img.getWidth() : img.getHeight();
final int h = r180 ? img.getHeight() : img.getWidth();
final int type = img.getType() == BufferedImage.TYPE_CUSTOM ? BufferedImage.TYPE_INT_ARGB : img.getType();
final BufferedImage rotated = new BufferedImage(w, h, type);
final Graphics2D graphic = rotated.createGraphics();
graphic.rotate(Math.toRadians(angle), w / 2d, h / 2d);
final int offset = r180 ? 0 : (w - h) / 2;
graphic.drawImage(img, null, offset, -offset);
graphic.dispose();
return rotated;
}
public static BufferedImage rotateBufferedImage(String img, int angle) throws IOException {
return rotateBufferedImage(Paths.get(img), angle);
}
public static BufferedImage rotateBufferedImage(Path img, int angle) throws IOException {
return rotateBufferedImage(ImageIO.read(img.toFile()), angle);
}

Categories