How to draw an image based on polygon coordinates Java - java

I'm making my first game(asteroids) and until now I have been using a polygon as the space ship however I'd like to use an image I drew instead. How do I take what I have and draw the image so it behaves like the polygon did?
My draw method:
public void draw(Graphics2D g){
AffineTransform at = g.getTransform();
g.translate(position.x, position.y);
double rot = direction.angle() + Math.PI / 2;
g.rotate(rot);
g.scale(DRAWING_SCALE, DRAWING_SCALE);
g.setColor(COLOR);
g.fillPolygon(XP, YP, XP.length);
if (thrusting) {
g.setColor(Color.orange);
g.fillPolygon(XPTHRUST, YPTHRUST, XPTHRUST.length);
}
g.setTransform(at);
}
My coordinate arrays:
public int[] XP = {0,1,0,-1}; //sets the position of the ship
public int[] YP = {1,-1,0,-1};
public int[] XPTHRUST = {0,1,0,-1}; //sets position of thrust
public int[] YPTHRUST = {-3,-1,0,-1};

Related

Change the origin of Graphics2D coords

I have a simple elevator simulator. The painting class of that simulator, paints a wall on the left side and a wall on the right - both are Line2D Objects. In the center is a rectangle that represents the cabin.
My Member Variables are:
private PaintableElevator paintableObject;
private Line2D wallLeftSide = new Line2D.Double();
private Line2D wallRightSide = new Line2D.Double();
private Rectangle2D elevator = new Rectangle2D.Double();
paintableObject gives the information where to paint as proportions. For example, if it says that the cabin has a height of 0.1, than its height on the panel is: this.getHeight * 0.1
I also have a component Listener that just reacts on rezize Events as follows:
#Override
public void componentResized (ComponentEvent e)
{
wallLeftSide.setLine(new Point2D.Double(0, changeYCoordsOrigin(getHeight() * paintableObject.getTotalHeight())), new Point2D.Double(0, getWidth()));
wallRightSide.setLine(new Point2D.Double(getWidth(), changeYCoordsOrigin(getHeight() * paintableObject.getTotalHeight())), new Point2D.Double(getWidth(), getHeight()));
elevator.setRect(0, changeYCoordsOrigin(getHeight() * paintableObject.getHeightInShaft()), getWidth(), paintableObject.getCabinHeight() * getHeight() *-1);
}
My Problem is that Graphics 2D sets the origin of their coords to the top left hand side. I would like it to have on the button left side. thats why i use my method changeYCoordOrigin()
public double changeYCoordsOrigin (double coord)
{
return getHeight() - coord;
}
My hope was that I could convert my coords by calculating them minus the current height. That worked. But when I want to set a negative height for the rectangle, my component dont show anything.
But this is very important, because I want to drive my little cabin by the following code:
#Override
public void setHeigth (double height)
{
elevator.setRect(0, getHeight() * height, getWidth(), paintableObject.getCabinHeight());
repaint();
}
When just dont use changeYCoordOrigin and use a positive height, my elevator drives down, when i want to drive up. Because of that it is important to change the origin of the coordinates, or simulate that.
My paint Method just paints that objects:
#Override
public void paint (Graphics g)
{
if (g instanceof Graphics2D)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(wallLeftSide);
g2.draw(wallRightSide);
g2.setBackground(Color.gray);
g2.draw(elevator);
}
}

Rotate Rectangle 2D For Hit Detection

I was looking to rotate a rectangle by a specific angle, as I have a game using java fx which has comets move at an angle. If the rocket intersects with that comet, the game is over. However, a diagonal comet possesses a rectangle at 0 degrees, which covers unnecessary space. I tried using following code, but the rectangles are still 0 degrees:
public void isRocketHit(){
Rectangle2D rocketrec = new Rectangle2D(rocket.getX(), rocket.getY(), rocket.getImage().getWidth(), rocket.getImage().getHeight());
for(Streak i : rstreaks){
double width = i.getImage().getWidth();
double height = i.getImage().getHeight();
Rectangle2D cometrec = new Rectangle2D(i.gmarkX(), i.gmarkY(), width, height);
double rotationCenterX = (i.gmarkX() + width)/2;
double rotationCenterY = (i.gmarkY() + height)/2;
gc.save();
gc.translate(rotationCenterX, rotationCenterY);
gc.rotate(i.getAngle());
gc.translate(-rotationCenterX, -rotationCenterY);
gc.fillRect(i.gmarkX(), i.gmarkY(), width, height);
gc.setFill(Color.AZURE);
if(rocketrec.intersects(cometrec)){
play = false;
System.out.println("HIT");
}
gc.restore();
}
}

Draw multiple elements to canvas

I successfully added an oval shape to the canvas, however now i'd like to add two more rectangles but for some reason they do not get added to the canvas. The oval shape is a ball which moves and rectangle shapes are static elements which are for "background". One rectangle should be as a floor and another one as an obstacle for the moving object, ball.
I tried to visualize it in the image:
This is the code, mBack and mObs are the rectangles i'm trying to add.
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
ShapeDrawable mBack = new ShapeDrawable();
ShapeDrawable mJump = new ShapeDrawable();
public static int x;
public static int y;
public class AnimatedView extends ImageView {
static final int width = 50;
static final int height = 50;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mBack = new ShapeDrawable(new RectShape());
mObs = new ShapeDrawable(new RectShape());
mDrawable.getPaint().setColor(0xffffAC23);
//mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.setBounds(y, x, y + width, x + height);
mBack.setBounds(100, 100, 100, 100);
mObs.setBounds(120,120,120,120);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(y, x, y + width, x + height);
mBack.draw(canvas);
mDrawable.draw(canvas);
invalidate();
}
}
mDrawable will be added however mBack or mObs not. Adding setBounds to onDraw won't change a thing also.
The way you are setting Bounds is wrong. The definition of the setBounds method is here:
setBounds(int left, int top, int right, int bottom)
for the two rectangles you are setting it as
mBack.setBounds(100, 100, 100, 100);
mObs.setBounds(120,120,120,120);
This means you are left and right corners are same and top and bottom are same so you are not seeing your rectangle.
Set it something like this then you will see your rectangles
mBack.setBounds(100, 100, 300, 400);
And call draw method on both rectangle shapes in onDraw method.
It seems the problem is that for mBack you defined the bounds to zero pixel (start end ends in (100,100)), same for mObs, but for that you didn't call draw either.

Converting an Ellipse2D to Polygon

I have a Java swing application where I can draw hot spots. I am allowing user to draw Rectangle , Polygon and Circle.
For Circle I am using Ellipse2D
Ellipse2D.Double ellipseDouble = new Ellipse2D.Double(x,y,width,height);
g.draw(ellipseDouble);
Above works fine and it does draw an ellipse/circle.
Now the problems when I want the region to be used in HTML Image map.
Html Image map doesn't support Ellipse so I was thinking to use polygon for Ellipse2D but really don't know how would I convert it.
Does anyone know how would I go about it converting an Ellipse2D to Polygon ponits?
Use FlatteningPathIterator.
See e.g. http://java-sl.com/tip_flatteningpathiterator_moving_shape.html where point moves following custom Shape.
You can get list of Points and create Polygon.
Maybe someone will find this one useful: this is pdfbox ellipse or circle (width=height) draw function inside rectangle, it make ellipse as polygon initially to draw.
Code based on math function of ellipse at poin [0 , 0]: x^2/a^2 + y^2/b^2 = 1
private PdfBoxPoligon draw_Ellipse_or_Circle_as_poligon_with_PDFBOX (
PDPageContentStream content, float bottomLeftX, float bottomLeftY,
float width, float height, boolean draw) throws IOException {
PdfBoxPoligon result = new PdfBoxPoligon();
float a = width/2;
float b = height/2;
int points = (int) (a*b/20);
if (DEBUG) {
System.out.println("points=" + points);
}
//top arc
for (float x = -a; x < a; x = x + a / points) {
result.x.add(bottomLeftX + a + x);
float y = (float) Math.sqrt((1-(x*x)/(a*a))*(b*b));
result.y.add(bottomLeftY+b+y);
}
//bottom arc
for (float x = a; x >= -a; x = x - a / points) {
result.x.add(bottomLeftX + a + x);
float y = -(float) Math.sqrt((1-(x*x)/(a*a))*(b*b));
result.y.add(bottomLeftY+b+y);
}
result.x.add(result.x.get(0));
result.y.add(result.y.get(0));
if (draw) {
for (int i=1; i < result.x.size(); i++) {
content.addLine(result.x.get(i-1), result.y.get(i-1), result.x.get(i), result.y.get(i));
}
}
return result;
}

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);
}

Categories