So far I am just making a new Shape to "move" it. But is there a better way to change the position of a Shape in Java?
// Collision Shape
protected RectangularShape col;
public GameObject() {
col = new Ellipse2D.Double(x, y, ObjectSpriteManager.SIZE, ObjectSpriteManager.SIZE);
}
public void tick() {
x += velX;
y += velY;
col = new Ellipse2D.Double(x, y, ObjectSpriteManager.SIZE, ObjectSpriteManager.SIZE);
}
See the setFrame() methods of RectangulerShape. For example:
col.setFrame(x, y, width, height);
Related
My partner and I are trying to remake Tetris for our final project of the year in my Computer Science class we currently have a for loop that draws individual rectangles in an overwritten paint method.
private final int spacer = 30;
public int getSpacer()
{
return spacer;
}
public void paint(Graphics g) {
setBackground(Color.GRAY);
for(int i = getHeight()/2 - (spacer * 10); i < getHeight()/2 + (spacer * 10); i += spacer) {
for(int x = getWidth()/2 - (spacer * 5); x < getWidth()/2 + (spacer * 5); x += (spacer)) {
g.drawRect(x, i, (spacer), (spacer));
}
}
setForeground(Color.black);
}
The method basically takes the width and height of the window and makes a 10 x 20 grid of boxes that are 30 units, pixels I think, wide.
We'd like to make a Grid.java class that takes in color, the spacer int, and an x and y int. The constructor for Grid.java should draw the exact same thing as the code above using the for loop, but when we tried it gave us a white screen that would not resize with the window.
private final int spacer = 30;
private static Grid[][] arr = new Grid[10][20];
public int getSpacer()
{
return spacer;
}
public void paint(Graphics g) {
setBackground(Color.GRAY);
int countY = 0;
int countX = 0;
for(int y = getHeight()/2 - (spacer * 10); y < getHeight()/2 + (spacer * 10); y += spacer) {
for(int x = getWidth()/2 - (spacer * 5); x < getWidth()/2 + (spacer * 5); x += spacer) {
arr[countX][countY] = new Grid(x, y, spacer, g);
countX++;
}
countY++;
}
setForeground(Color.black);
}
*Grid.java Class*
package Tetris_Shapes;
import javax.swing.*;
import java.awt.*;
public class Grid {
private int x;
private int y;
private int side;
private Graphics g;
public Grid(int x, int y, int side, Graphics g) {
// g.drawRect(x, y, spacer, spacer);
this.x = x;
this.y = y;
this.side = side;
this.g = g;
paint(this.g);
}
private void paint(Graphics g) {
g.drawRect(x, y, side, side);
}
}
When we try and run this we get the white box that doesn't resize. My question is does anyone know of a way to get a constructor to draw shapes. Thank you in advance, this is pretty niche so I'm also going to apologize in advance.
this is a really weird bug and I can't seem to figure it out. To simplify this, I have three classes: A Canvas class (which draws the object with Graphics2D.draw()) then lots ob furniture classes, which can be viewed as one because all they do is return different shapes. Last I have a CustomShape class, which lets me create a new Shape based on my existing other shapes. But the shapes are being drawn at weird places. The x any y coordinates do not match where the shape is being drawn.
Closet.java:
public class Closet {
double x, y, width, height, rotation;
Color color;
Closet() {
this.x = X;
this.y = Y;
this.width = 40;
this.height = 40;
this.rotation = 0;
this.color = Color.blue;
}
public Shape getShape() {
GeneralPath closetShape = new GeneralPath();
closetShape.append(new Rectangle2D.Double(0, 0, width, height), false);
closetShape.moveTo(0 , 0);
closetShape.lineTo(width, height);
closetShape.moveTo(0, height);
closetShape.lineTo(width, 0);
// transform:
AffineTransform t = new AffineTransform();
t.translate(x, y);
Rectangle2D umriss = closetShape.getBounds2D();
t.rotate(Math.toRadians(rotation),umriss.getX()+umriss.getWidth()/2,umriss.getY()+umriss.getHeight()/2);
return t.createTransformedShape(closetShape);
}
}
CustomShape.java
public class CustomShape {
double x, y, width, height, rotation;
Color color;
private Closet[] c;
CustomShape(Closet... elements) {
this.m = elements;
GeneralPath path = new GeneralPath();
Closet[] newC = elements.clone();
Arrays.stream(newC).forEach(e -> path.append(e.getShape(), false));
this.x = path.getBounds2D().getX();
this.y = path.getBounds2D().getY();
this.width = path.getBounds2D().getWidth();
this.height = path.getBounds2D().getHeight();
this.rotation = 0;
this.color = Color.blue;
}
public Shape getShape() {
GeneralPath path = new GeneralPath();
Arrays.stream(c).forEach(e -> path.append(e.getShape(), false));
AffineTransform t = new AffineTransform();
t.translate(x, y);
Rectangle2D umriss = path.getBounds2D();
t.rotate(Math.toRadians(rotation),umriss.getX()+umriss.getWidth()/2,umriss.getY()+umriss.getHeight()/2);
return t.createTransformedShape(path);
}
}
I found the solution: I had transformed these Shapes before adding them to the CustomShape. That is why the x and y coordinates were wrong.
I'm trying to learn how collision detection works in android and I am doing so using Android rectangles.
I need to be able to detect a collision of the second rectangles top, left and bottom walls but the issue is that the first rectangle is able to go straight in to the second rectangle through the top left corner.
Below is a snippet of the code that I am using:
Snippet from GameView2 class:
private Shape s1 = new Shape(this, Color.BLACK, 0, 100, 50, 50);
private Shape s2 = new Shape(this, Color.BLUE, 200, 100, 50, 50);
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
this.drawBackground(canvas);
s1.onDraw(canvas);
s2.onDraw(canvas);
s1.x+=s1.vx;
s1.y+=s1.vy;
//left wall collision
if(s1.x+s1.width==s2.x && s1.y+s1.height > s2.y && s1.y < s2.y + s2.height){
s1.vx = 0;
}
//top wall
else if(s1.y+s1.height==s2.y && s1.x+s1.width > s2.x && s1.x < s2.x+s2.width){
s1.vy = 0;
}
else{
s1.vx = 2;
}
}
Shape class:
public class Shape{
protected GameView2 game_view;
protected int x;
protected int y;
protected int vx;
protected int vy;
protected int width;
protected int height;
protected int color;
public Shape(GameView2 game_view, int color, int x, int y, int width, int height) {
this.game_view = game_view;
this.x = x;
this.y = y;
this.vx = 2;
this.vy = 0;
this.width = width;
this.height = height;
this.color = color;
}
public Rect getRect(){
return new Rect(x, y, x + width, y + height);
}
public void onDraw(Canvas canvas){
Paint paint = new Paint();
Rect rec = new Rect(x, y, x + width, y + height);
paint.setColor(color);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(rec, paint);
}
}
Here is a really simple algorithm for collision between two rectangles.
x1+width1 < x2 || x2+width2 < x1 || y1+height1 < y2 || y2+height2
If the statement above is true, no collision occurs. Else, the two rectangles are colliding.
I have this java program that is made up of different classes. But it basically displays a circle and rectangle moving in a frame a Brownian motion.
I am trying to make a triangle class to add an equilateral triangle to the mix and to this I have to modify my nervous shape class and create a equilateral triangle class. I made a triangle class but I am not sure how to modify my nervous shape program to make it work. The nervous shape program work fine on it own without the triage class
I created my triangle class a subclass of shape but I am not sure how to modify nervous shape to make it work. I need to create the triangle class with one instance variable.
Any help will be appreciated.
// Program name: NervousShapes
//
// Displays a frame containing a random mixture of circles
// and rectangles with random colors, sizes, and positions.
// The shapes periodically change position, with the
// direction of motion chosen randomly for each shape. The
// new x coordinate for each shape will either be the same
// as the old x coordinate, one pixel smaller, or one pixel
// larger; the new y coordinate will be computed in a
// similar manner. Shapes will be constrained so that they
// do not move outside the drawing area.
public static void main(String[] args) {
createWindow();
createShapes();
animateShapes();
}
///////////////////////////////////////////////////////////
// NAME: createWindow
// BEHAVIOR: Creates a frame labeled "Nervous Shapes",
// displays the frame, and sets the size of
// the frame (using the WINDOW_SIZE class
// variable). Assigns the frame to the df
// class variable, and assigns the frame's
// graphics context to the g class variable.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void createWindow() {
// Create a frame labeled "Nervous Shapes" and set its
// size
df = new DrawableFrame("Nervous Shapes");
df.show();
df.setSize(WINDOW_SIZE, WINDOW_SIZE);
// Get the frame's graphics context
g = df.getGraphicsContext();
}
///////////////////////////////////////////////////////////
// NAME: createShapes
/ / BEHAVIOR: Creates enough Circle and Rectangle objects
// to fill the shapes array. Each shape has a
// random color, size, and position. The height
// and width of each shape must lie between
// MIN_SIZE and MAX_SIZE (inclusive). The
// position is chosen so that the shape is
// completely within the drawing area.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void createShapes() {
for (int i = 0; i < shapes.length; i++) {
// Select a random color
int red = generateRandomInt(0, 255);
int green = generateRandomInt(0, 255);
int blue = generateRandomInt(0, 255);
Color color = new Color(red, green, blue);
// Decide whether to create a circle or a rectangle
if (Math.random() < 0.5) {
// Generate a circle with a random size and position
int diameter = generateRandomInt(MIN_SIZE, MAX_SIZE);
int x = generateRandomInt(0, WINDOW_SIZE - diameter);
int y = generateRandomInt(0, WINDOW_SIZE - diameter);
shapes[i] = new Circle(x, y, color, diameter);
} else {
// Generate a rectangle with a random size and
// position
int width = generateRandomInt(MIN_SIZE, MAX_SIZE);
int height = generateRandomInt(MIN_SIZE, MAX_SIZE);
int x = generateRandomInt(0, WINDOW_SIZE - width);
int y = generateRandomInt(0, WINDOW_SIZE - height);
shapes[i] = new Rectangle(x, y, color, width, height);
}
}
}
///////////////////////////////////////////////////////////
// NAME: animateShapes
// BEHAVIOR: Establishes an infinite loop in which the
// shapes are animated. During each loop
// iteration, the drawing area is cleared and
// the shapes are then drawn at new positions.
// The new x and y coordinates for each shape
// will either be the same as the old ones,
// one pixel smaller, or one pixel larger. A
// shape is not moved if doing so would cause
// any portion of the shape to go outside the
// drawing area. At the end of each animation
// cycle, there is a brief pause, which is
// controlled by the delay constant.
// PARAMETERS: None
// RETURNS: Nothing
///////////////////////////////////////////////////////////
private static void animateShapes() {
while (true) {
// Clear drawing area
g.setColor(Color.white);
g.fillRect(0, 0, WINDOW_SIZE - 1, WINDOW_SIZE - 1);
for (int i = 0; i < shapes.length; i++) {
// Change the x coordinate for shape i
int dx = generateRandomInt(-1, +1);
int newX = shapes[i].getX() + dx;
if (newX >= 0 &&
newX + shapes[i].getWidth() < WINDOW_SIZE)
shapes[i].move(dx, 0);
// Change the y coordinate for shape i
int dy = generateRandomInt(-1, +1);
int newY = shapes[i].getY() + dy;
if (newY >= 0 &&
newY + shapes[i].getHeight() < WINDOW_SIZE)
shapes[i].move(0, dy);
// Draw shape i at its new position
shapes[i].draw(g);
}
// Call repaint to update the screen
df.repaint();
// Pause briefly
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {}
}
}
///////////////////////////////////////////////////////////
// NAME: generateRandomInt
// BEHAVIOR: Generates a random integer within a
// specified range.
// PARAMETERS: min - the lower bound of the range
// max - the upper bound of the range
// RETURNS: A random integer that is greater than or
// equal to min and less than or equal to max
///////////////////////////////////////////////////////////
private static int generateRandomInt(int min, int max) {
return (int) ((max - min + 1) * Math.random()) + min;
}
}
Here is my shape superclass that I use to make my triangle.
// Represents a geometric shape that can be displayed in a
// graphics context
import java.awt.*;
public abstract class Shape {
// Instance variables
private int x;
private int y;
private Color color;
// Constructor
protected Shape(int x, int y, Color color) {
this.x = x;
this.y = y;
this.color = color;
}
// Abstract methods
public abstract void draw(Graphics g);
public abstract int getHeight();
public abstract int getWidth();
// Other instance methods
public Color getColor() {
return color;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void move(int dx, int dy) {
x += dx;
y += dy;
}
public void setColor(Color color) {
this.color = color;
}
}
Here is the rectangle subclass needed to make program work
// Represents a rectangle that can be displayed in a graphics
/ / context
import java.awt.*;
public class Rectangle extends Shape {
// Instance variables
private int width;
private int height;
// Constructor
public Rectangle(int x, int y, Color color,
int width, int height) {
super(x, y, color);
this.width = width;
this.height = height;
}
// Instance methods
public void draw(Graphics g) {
g.setColor(getColor());
g.fillRect(getX(), getY(), width, height);
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
}
Here is the circle graphic in the nervous shape.
// Represents a circle that can be displayed in a graphics
// context
import java.awt.*;
public class Circle extends Shape {
// Instance variables
private int diameter;
// Constructor
public Circle(int x, int y, Color color, int diameter) {
super(x, y, color);
this.diameter = diameter;
}
// Instance methods
public void draw(Graphics g) {
g.setColor(getColor());
g.fillOval(getX(), getY(), diameter, diameter);
}
public int getHeight() {
return diameter;
}
public int getWidth() {
return diameter;
}
}
And here is the new triangle class I created and I am trying to make nervous shape program run I have to modify create shape part of my nervous shape.
import java.awt.*;
public class Triangle extends Shape {
// Instance variables
private int leng;
// Constructor
public Triangle(int x, int y, Color color,
int leng) {
super(x, y, color);
this.leng=leng;
}
// Instance methods
public void draw(Graphics g) {
int[]Xcoord={getX(),getX()+leng,getX()+leng/2};
int[]Ycoord={getY(),getY(),getY()+math.sqrt(3)/2};
g.drawPolygon(Xcoord,Ycoord,3);
}
public int getleng() {
return leng;
}
So far I have a java app where I draw a circle(player) and then draw a green rectangle on top(gun barrel). I have it so when the player moves, the barrel follows with it. I want it to find where the mouse is pointing and then rotate the barrel accordingly. For an example of what I mean look at this video I found http://www.youtube.com/watch?v=8W7WSkQq5SU See how the player image reacts when he moves the mouse around?
Here's an image of what the game looks like so far:
So how do I rotate it like this? Btw I don't like using affinetransform or Graphics2D rotation. I was hoping for a better way. Thanks
Using the Graphics2D rotation method is indeed the easiest way. Here's a simple implementation:
int centerX = width / 2;
int centerY = height / 2;
double angle = Math.atan2(centerY - mouseY, centerX - mouseX) - Math.PI / 2;
((Graphics2D)g).rotate(angle, centerX, centerY);
g.fillRect(...); // draw your rectangle
If you want to remove the rotation when you're done so you can continue drawing normally, use:
Graphics2D g2d = (Graphics2D)g;
AffineTransform transform = g2d.getTransform();
g2d.rotate(angle, centerX, centerY);
g2d.fillRect(...); // draw your rectangle
g2d.setTransform(transform);
It's a good idea to just use Graphics2D anyway for anti-aliasing, etc.
Using AffineTransform, sorry, only way I know how :P
public class RotatePane extends javax.swing.JPanel {
private BufferedImage img;
private Point mousePoint;
/**
* Creates new form RotatePane
*/
public RotatePane() {
try {
img = ImageIO.read(getClass().getResource("/MT02.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mousePoint = e.getPoint();
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(img.getWidth(), img.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
double rotation = 0f;
int width = getWidth() - 1;
int height = getHeight() - 1;
if (mousePoint != null) {
int x = width / 2;
int y = height / 2;
int deltaX = mousePoint.x - x;
int deltaY = mousePoint.y - y;
rotation = -Math.atan2(deltaX, deltaY);
rotation = Math.toDegrees(rotation) + 180;
}
int x = (width - img.getWidth()) / 2;
int y = (height - img.getHeight()) / 2;
g2d.rotate(Math.toRadians(rotation), width / 2, height / 2);
g2d.drawImage(img, x, y, this);
x = width / 2;
y = height / 2;
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.RED);
g2d.drawLine(x, y, x, y - height / 4);
g2d.dispose();
}
}
Will produce this effect
The red line (point out from the center) will want to follow the cursor.