Our restart button is only appearing by itself. Our two tanks disappear when we run the game. We haven't coded the function of the button, we're just trying to figure out how to make the button appear in the lower left corner
We moved the code into the game object class, but it does not change anything
This is our game object class. The button is at the bottom.
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameObject {
// Every moving object in our game is a separate GameObject. However, since there are different types of moving objects (eg. players and
// projectiles), each with their own variables and functions, we don't want to instantiate GameObjects (otherwise, we wouldn't be able
// to distinguish between a player and a projectile). Instead, we want to create derived (also known as child) classes to implement the
// separate functionality, and instantiate the derived/child classes instead. The purpose of this GameObject "parent" class is to
// provide the derived/child classes with a set of useful functions for handling physics interactions (eg. collisions with the terrain
// or the walls of the arena) between different GameObjects (eg. player/player, player/projectile, or even projectile/projectile). Note:
// depending on the features you implement, you may not end up using all of the functions provided in this class.
// Every GameObject contains its own velocity, position, size, and mass information (necessary for moving and handling physics
// interactions). We store this information in the GameObject class instead of the derived/child classes because every type of
// GameObject has the same set of velocity, position, size, and mass variables.
public double vX; // Velocity in the x direction. Positive if moving right. Negative if moving left.
public double vY; // Velocity in the y direction. Positive if moving down. Negative if moving up. Notice how it's flipped from the usual
// coordinate system in math!
public double posX; // Position along the x direction. Ranges from 0 (left edge) to maximumX (see below).
public double posY; // Position along the y direction. Ranges from 0 (top edge) to maximumY (see below).
public int width; // Width of the bounding box of the GameObject.
public int height; // Height of the bounding box of the GameObject.
public int mass; // Used in realistic physics collision calculations. Ignore it if you don't want to implement that feature.
public double radius; // Used for circular GameObjects only.
public int maximumX; // Maximum x position for a GameObject, equal to the arena width subtracted by the game object's width.
public int maximumY; // Maximum y position for a GameObject, equal to the arena height subtracted by the game object's height.
// Constructor. All derived (ie. child) classes call this constructor in their own constructors. The resulting derived/child class
// object can then call the other functions in this class.
public GameObject(int arenaWidth, int arenaHeight, double vX, double vY, double posX, double posY, int width, int height, int mass) {
this.vX = vX;
this.vY = vY;
this.posX = posX;
this.posY = posY;
this.width = width;
this.height = height;
this.mass = mass;
this.maximumX = arenaWidth - width;
this.maximumY = arenaHeight - height;
radius = Math.min(width, height) / 2.0;
}
// Note: No need to change this function since we're going to override it in the the child classes.
public boolean move(Map map, double translateX, double translateY) {
return false;
}
// Check if the calling GameObject currently intersects with the obj GameObject.
public boolean currentlyIntersects(GameObject obj) {
return (posX + width >= obj.posX && posY + height >= obj.posY && obj.posX + obj.width >= posX && obj.posY + obj.height >= posY);
}
// Check if the calling GameObject will intersect with the obj GameObject, after both have moved according to their velocities. A note
// of caution: what might go wrong if either player moves too fast?
public boolean willIntersect(GameObject obj) {
double nextX = posX + vX;
double nextY = posY + vY;
double nextObjX = obj.posX + obj.vX;
double nextObjY = obj.posY + obj.vY;
return (nextX + width >= nextObjX && nextY + height >= nextObjY && nextObjX + obj.width >= nextX && nextObjY + obj.height >= nextY);
}
// Clip the calling GameObject to within the arena's x bounds, if it has moved outside the arena along the x direction.
public boolean xClip() {
if (posX < 0) {
posX = 0;
return true;
} else if (posX > maximumX) {
posX = maximumX;
return true;
}
return false;
}
// Clip the calling GameObject to within the arena's y bounds, if it has moved outside the arena along the y direction.
public boolean yClip() {
if (posY < 0) {
posY = 0;
return true;
} else if (posY > maximumY) {
posY = maximumY;
return true;
}
return false;
}
// If the calling GameObject will move outside the arena along either direction (after moving according to its velocity), this function
// tells you which of the four edges of the arena it hit. If the calling GameObject will stay within the bounds of the arena, this
// function returns null.
public Direction hitEdgeDirection() {
if (posX + vX < 0) {
return Direction.LEFT;
} else if (posX + vX > maximumX) {
return Direction.RIGHT;
}
if (posY + vY < 0) {
return Direction.UP;
} else if (posY + vY > maximumY) {
return Direction.DOWN;
} else {
return null;
}
}
// If the calling GameObject will intersect with the "other" GameObject (after both move according to their velocities), this function
// tells you which of the four sides of the calling GameObject that the "other" GameObject hit. If the calling GameObject will not
// intersect with the "other" GameObject, this function returns null. Note: this function is great for figuring out when and where two
// rectangles intersect, but is it a good choice for handling circle/rectangle or circle/circle intersections?
public Direction hitObjectDirection(GameObject other) {
if (this.willIntersect(other)) {
double dx = other.posX + other.width / 2.0 + other.vX - (posX + width / 2.0 + vX);
double dy = other.posY + other.height / 2.0 + other.vY - (posY + height / 2.0 + vY);
double theta = Math.acos(dx / (Math.sqrt(dx * dx + dy * dy)));
double diagTheta = Math.atan2(height / 2.0, width / 2.0);
if (theta <= diagTheta) {
return Direction.RIGHT;
} else if (theta <= Math.PI - diagTheta) {
if (dy > 0) {
return Direction.DOWN;
} else {
return Direction.UP;
}
} else {
return Direction.LEFT;
}
} else {
return null;
}
}
// Change the calling GameObject's velocity (to simulate a "bouncing" effect) based on which direction it intersected another GameObject
// or the edge of the arena. If the passed in direction is null, this function does nothing (why is this a good idea?). This function is
// best used with the hitEdgeDirection and hitObjectDirection functions above.
public void bounce(Direction d) {
if (d == null) {
return;
}
// Note: We probably should use a "switch" statement here instead. But for pedagogical purposes it's left as a simple if/else
// conditional.
if (d == Direction.UP) {
vY = Math.abs(vY);
} else if (d == Direction.DOWN) {
vY = -Math.abs(vY);
} else if (d == Direction.LEFT) {
vX = Math.abs(vX);
} else if (d == Direction.RIGHT) {
vX = -Math.abs(vX);
}
}
// TODO: (Challenge!) If you want to implement realistic sphere-sphere collisions that take into account the laws of physics, do so in
// the function below.
public boolean bounceWith(GameObject otherObj, Map map, long frames, double[] actualVelocities) {
return false;
}
// Calculate the distance from (pointX, pointY)---perhaps representing the center of a circle---to the closest point on a rectangle
// bounded by minX (left), maxX (right), minY (top), and maxY (bottom). If the point is inside the rectangle, this function returns 0.
public double pointToRectSqrDist(double minX, double maxX, double minY, double maxY, double pointX, double pointY) {
double dx = Math.max(Math.max(minX - pointX, 0), pointX - maxX);
double dy = Math.max(Math.max(minY - pointY, 0), pointY - maxY);
return dx * dx + dy * dy;
}
// Rotate the point (x, y) "degrees" degrees around (centerX, centerY) in counterclockwise fashion, and return the resulting point in an
// array of length 2. If the returned array is "result", then (result[0], result[1]) is the final point.
public double[] rotatePoint(double centerX, double centerY, double degrees, double x, double y) {
double s = Math.sin(Math.toRadians(degrees));
double c = Math.cos(Math.toRadians(degrees));
x -= centerX;
y -= centerY;
double xNew = x * c - y * s;
double yNew = x * s + y * c;
double[] result = new double[2];
result[0] = xNew + centerX;
result[1] = yNew + centerY;
return result;
}
// Note: No need to change this function since we're going to override it in the the child classes.
public void draw(Graphics g) {
}
public static void main(String []args){
JButton b= new JButton("Reset");
JFrame f = new JFrame();
f.setSize(1200,800);
f.setVisible(true);
f.getDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
f.add(p);
p.add(b);
b.setSize(50,50);
b.setVisible(true);
b.setLocation(50, 50);
}
}
This is our arena class:
// TODO: Feel free to import any other libraries that you need.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
#SuppressWarnings("serial")
public class Arena extends JPanel {
public int arenaWidth;
public int arenaHeight;
public Player player1;
public Player player2;
Timer timer;
public static int INTERVAL = 35;
public long lastTick;
// TODO: Add other variables to keep track of the game state or other game objects (eg. the map) that will be in your game. Don't forget
// to instantiate them in reset()!
// Constructor. Called inside Game.java for setting up the Arena on game start.
public Arena() {
// Create a timer that calls the tick() function every INTERVAL milliseconds. Every call of the tick() function is a "frame".
timer = new Timer(INTERVAL, new ActionListener() {
public void actionPerformed(ActionEvent e) {
tick();
}
});
lastTick = System.currentTimeMillis();
timer.start();
setFocusable(true);
// TODO: To recognize key presses, you need to fill in the following.
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent butthole) {
if (butthole.getKeyCode() == KeyEvent.VK_W) {
player1.isWPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_S) {
player1.isSPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_A) {
player1.isAPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_D) {
player1.isDPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_SPACE) {
player1.isSpacePressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_UP) {
player2.isUpPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_DOWN) {
player2.isDownPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_LEFT) {
player2.isLeftPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_RIGHT) {
player2.isRightPressed = true;
}
if (butthole.getKeyCode() == KeyEvent.VK_ENTER) {
player2.isEnterPressed = true;
}
}
public void keyReleased(KeyEvent butthole) {
if (butthole.getKeyCode() == KeyEvent.VK_W) {
player1.isWPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_S) {
player1.isSPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_A) {
player1.isAPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_D) {
player1.isDPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_SPACE) {
player1.isSpacePressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_UP) {
player2.isUpPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_DOWN) {
player2.isDownPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_LEFT) {
player2.isLeftPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_RIGHT) {
player2.isRightPressed = false;
}
if (butthole.getKeyCode() == KeyEvent.VK_ENTER) {
player2.isEnterPressed = false;
}
}
});
}
// Resets the game to its initial state.
public void reset() {
this.removeAll();
this.setBackground(Color.WHITE);
this.setOpaque(true);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
arenaWidth = (int) screenSize.getWidth();
arenaHeight = (int) screenSize.getHeight();
player1 = new Player(arenaWidth, arenaHeight, 100, 100, 1);
player2 = new Player(arenaWidth, arenaHeight, arenaWidth - Player.INIT_SIZE - 100, arenaHeight - Player.INIT_SIZE - 100, 2);
requestFocusInWindow();
}
// Function called once per "frame".
void tick() {
// While tick() should be called once every INTERVAL amount of time, there's no guarantee of that, particularly if you have a lot
// of background apps running. Thus, we need to calculate the time difference (timeDelta) between every two calls of the tick()
// function. Note: 1 divided by this difference is commonly known as the "frames per second", or fps.
long currentTime = System.currentTimeMillis();
long timeDelta = (currentTime - lastTick)/35;
lastTick = currentTime;
if ((player1.isWPressed && player1.isSPressed) ||
(!player1.isWPressed && !player1.isSPressed)) {
player1.vX = 0;
player1.vY = 0;
} else if (player1.isWPressed) {
//System.out.println("Up");
player1.vX = Math.cos(player1.RotationDegree*Math.PI/180)*player1.speed * timeDelta;
player1.vY = Math.sin(player1.RotationDegree*Math.PI/180)*player1.speed * timeDelta;
//player1.posY -= player1.speed*timeDelta;
// MOVE FORWARD
} else if (player1.isSPressed) {
//System.out.println("Down");
player1.vX = -Math.cos(player1.RotationDegree*Math.PI/180)*player1.speed * timeDelta;
player1.vY = -Math.sin(player1.RotationDegree*Math.PI/180)*player1.speed * timeDelta;
//player1.posY += player1.speed*timeDelta;
// MOVE BACKWARD;
}
if (player1.isAPressed) {
//System.out.println("Left");
player1.RotationDegree -= player1.rotateSpeed* timeDelta;
// MOVE BACKWARD;
}
if (player1.isDPressed) {
//System.out.parintln("Right");
player1.RotationDegree += player1.rotateSpeed* timeDelta;
// MOVE BACKWARD;
}
if(player1.RotationDegree > 360) {
player1.RotationDegree -= 360;
}
else if(player1.RotationDegree < 0) {
player1.RotationDegree += 360;
}
player1.move(null, player1.vX, player1.vY);
if ((player2.isUpPressed && player2.isDownPressed) ||
(!player2.isUpPressed && !player2.isDownPressed)) {
player2.vX = 0;
player2.vY = 0; }
else if (player2.isUpPressed) {
//System.out.println("Up");
player2.vX = Math.cos(player2.RotationDegree*Math.PI/180)*player2.speed* timeDelta;
player2.vY = Math.sin(player2.RotationDegree*Math.PI/180)*player2.speed* timeDelta;
//player2.posY -= player2.speed*timeDelta;
// MOVE FORWARD
}
else if (player2.isDownPressed) {
//System.out.println("Down");
player2.vX = -Math.cos(player2.RotationDegree*Math.PI/180)*player2.speed * timeDelta;
player2.vY = -Math.sin(player2.RotationDegree*Math.PI/180)*player2.speed * timeDelta;
//player2.posY += player2.speed*timeDelta;
// MOVE BACKWARD;
}
if (player2.isLeftPressed) {
//System.out.println("Left");
player2.RotationDegree -= player2.rotateSpeed*timeDelta;
// MOVE BACKWARD;
}
if (player2.isRightPressed) {
//System.out.println("Right");
player2.RotationDegree += player2.rotateSpeed*timeDelta;
// MOVE BACKWARD;
}
if(player2.RotationDegree > 360) {
player2.RotationDegree -= 360;
}
else if(player2.RotationDegree < 0) {
player2.RotationDegree += 360;
}
player2.move(null, player2.vX, player2.vY);
player1.currentReload -= timeDelta;
if (player1.currentReload <= 0)
;
{
if (player1.isSpacePressed) {
// create bullet and fire
BasicWeapon newBullet = new BasicWeapon(arenaWidth, arenaHeight, player1.posX + player1.radius, player1.posY + player1.radius, player1);
player1.bullets.add(newBullet);
player1.currentReload = player1.MaxReload;
}
}
ArrayList<PlayerProjectile> bulletsToDelete1 = new ArrayList<PlayerProjectile>();
for (int i = 0; i < player1.bullets.size(); i++) {
PlayerProjectile bulletToChange = player1.bullets.get(i);
bulletsToDelete1.add(bulletToChange);
}
player1.bullets.removeAll(bulletsToDelete1);
// TODO: Update the game state each frame. This can be broken into the following steps:
// Step 1: Handle the keys pressed during the last frame by both players and calculate their resulting velocities/orientations.
// Step 2: Move the players and detect/handle player/player collisions and player/terrain collisions.
// Step 3: Decide whether a bullet should be fired for each player and create new bullet(s) if so. Also, handle reload mechanics.
// Step 4: Move all bullets via their calculated velocities (up to bullet range). Handle bullet/player & bullet/terrain collisions.
// Step 5: Decide whether the game has ended. If so, stop the timer and print a message to the screen indicating who's the winner.
// Note: If you implement other features (eg. weapon swapping, damage counters...etc.), you might also need to add more steps above.
// Update the display: this function calls paintComponent as part of its execution.
repaint(); }
// TODO: Draw all of the objects in your game.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//AffineTransform at = AffineTransoform.getTranslateInstance();
player1.draw(g);
player2.draw(g);
}
// Returns the dimensions of the Arena (for properly resizing the JPanel on the screen).
#Override
public Dimension getPreferredSize() {
return new Dimension(arenaWidth, arenaHeight);
}
}
THIS IS OUR PLAYER CLASS
// TODO: Feel free to import any other libraries that you need.
//import java.*;
import java.awt.*;
import java.util.ArrayList;
//import javax.swing.*;
//import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Player extends GameObject {
public static void main(String []args){
}
// TODO: Set these values as you see fit. However, which variables should you not set as negative numbers? Which variables should you
// not set as zero? Which v'ariables should you not set as a very large positive number? Why?
public static final int INIT_SIZE = 30;
public static final int INIT_MASS = 0;
public static final int INIT_DAMAGE = 0;
public static final double INIT_SPEED = 10;
public static final double INIT_ROTATE_SPEED = 10;
public static final int INIT_HEALTH = 100;
// Member variables of the player that you can change over the course of the game.
public int damage = INIT_DAMAGE;
public double speed = INIT_SPEED;
public double rotateSpeed = INIT_ROTATE_SPEED;
public int health = INIT_HEALTH;
public double orientation = 0;
public int id;
// TODO: You may need to set up extra variables to store the projectiles fired by this player, the reload status/time of this player,
// the key press/release status of this player, and any other player-related features you decide to implement. Make sure to update the
// constructor appropriately as well!
long currentReload = 0;
long MaxReload = BasicWeapon.INIT_RELOAD;
ArrayList<PlayerProjectile> bullets = new ArrayList<PlayerProjectile>();
double RotationDegree = 0;
boolean isWPressed = false;
boolean isSPressed = false;
boolean isAPressed = false;
boolean isDPressed = false;
boolean isSpacePressed = false;
boolean isEnterPressed = false;
boolean isUpPressed = false;
boolean isDownPressed = false;
boolean isLeftPressed = false;
boolean isRightPressed = false;
boolean isLeftCLickPressed = false;
// Constructor that calls the super (ie. parent) class's constructor and instantiates any other player-specific variables.
public Player(int arenaWidth, int arenaHeight, double startPosX, double startPosY, int id) {
super(arenaWidth, arenaHeight, 0, 0, startPosX, startPosY, INIT_SIZE, INIT_SIZE, INIT_MASS);
this.id = id;
}
// TODO: This function should move the player and handle any player-terrain interactions.
#Override
public boolean move(Map map, double translateX, double translateY) {
posX += translateX;
posY += translateY;
xClip();
yClip();
return false;
}
//UPDATE PLAYER POSTION HERE
//}
public void draw(Graphics g) {
// TODO: Draw the barrel(s) for the player here
double xChords[] = new double[4];
double YChords[] = new double[4];
xChords[0] = posX + 0.6 * width;
xChords[1] = posX + 0.6 * width;
xChords[2] = posX + 1.5 * width;
xChords[3] = posX + 1.5 * width;
YChords[0] = posY + 0.4 * height;
YChords[1] = posY + 0.5 * height;
YChords[2] = posY + 0.5 * height;
YChords[3] = posY + 0.4 * height;
double[] point0 = rotatePoint(posX + 0.5 * width, posY + 0.5 * height, RotationDegree, xChords[0], YChords[0]);
double[] point1 = rotatePoint(posX + 0.5 * width, posY + 0.5 * height, RotationDegree, xChords[1], YChords[1]);
double[] point2 = rotatePoint(posX + 0.5 * width, posY + 0.5 * height, RotationDegree, xChords[2], YChords[2]);
double[] point3 = rotatePoint(posX + 0.5 * width, posY + 0.5 * height, RotationDegree, xChords[3], YChords[3]);
int rotatedPointsX[] = new int[4];
int rotatedPointsY[] = new int[4];
rotatedPointsX[0] = (int)Math.round(point0[0]);
rotatedPointsX[1] = (int)Math.round(point1[0]);
rotatedPointsX[2] = (int)Math.round(point2[0]);
rotatedPointsX[3] = (int)Math.round(point3[0]);
rotatedPointsY[0] = (int)Math.round(point0[1]);
rotatedPointsY[1] = (int)Math.round(point1[1]);
rotatedPointsY[2] = (int)Math.round(point2[1]);
rotatedPointsY[3] = (int)Math.round(point3[1]);
g.drawPolygon(rotatedPointsX, rotatedPointsY, 4);
g.setColor(Color.BLACK);
g.fillPolygon(rotatedPointsX, rotatedPointsY, 4);
if (id == 1) {
g.setColor(new Color(255, 215, 0));
} else if (id == 2) {
g.setColor(Color.RED);
}
// Body
g.fillOval((int) posX, (int) posY, width, height);
g.setColor(Color.BLACK);
g.drawOval((int) posX, (int) posY, width, height);
// TODO: Draw the health bar for the player here.
}
}
Only the button appears, and player1 and player2 don't.
I think what you are trying to achieve is something like :
public static void main(String []args){
JButton button= new JButton("Reset");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.add(button);
frame.add(panel, BorderLayout.NORTH);
frame.add(new Arena(), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
For future question please do not post so much code. See: don't just copy in your entire program!
I'm making a rudimentary particle simulator in Java. For now, all I've done is make the particles atract each other with an equivalent to the electrical force. This part works fine (or at least as well as you would expect for such a basic model).
However, when I add a few particles, the program loses their values for position, velocity and acceleration, but does not lose other data (like, for example, their ID number). This does not always happens with the same amount of particles. Sometimes it happens when I add the fourth, fifth, second or third particle, but never with the first one. It always happens when I click to add a particle, and after it fails, I can no longer add anything (which is odd), and the particles don't move anymore (as you would expect, being their velocities and accelerations 0).
I am storing the particles in an ArrayList. The array does not lose the data (I've checked, the objects are in there, and I can even call their toString() method and retrieve their ID). The problem seems to be related to synchronization (given that it doesn't always happen at the same moment, it seems to be a bit random), but I can't figure out what it is.
I leave all the relevant code below.
public class Scene implements KeyListener, MouseListener, MouseMotionListener{
public static ArrayList<Particle> particleArray = new ArrayList<Particle>();
public static Object particleLock = new Object();
public void update() {
synchronized(particleLock) {
for(Particle particle: particleArray) {
double resultX = 0;
double resultY = 0;
for(int i = 0; i<particleArray.size(); i++) {
if(i != particleArray.indexOf(particle)) {
double[] result = PhysicsEngine.applyElectircalForce(particle, particleArray.get(i));
resultX += result[0];
resultY += result[1];
}
}
particle.netForceX = resultX;
particle.netForceY = resultY;
particle.update();
}
}
}
public void mousePressed(MouseEvent e) {
int mouseX = e.getX();
int mouseY = e.getY();
boolean positive = true;
if(e.getButton() == MouseEvent.BUTTON1) {
positive = true;
} else if(e.getButton() == MouseEvent.BUTTON3) {
positive = false;
}
synchronized(particleLock){
particleArray.add(new Particle(mouseX, mouseY, positive));
System.out.println("New particle added at " + mouseX + ", " + mouseY);
}
}
}
public class Particle{
public double x;
public double y;
public Point2D position;
public double velX;
public double velY;
public double acX;
public double acY;
private Color particleColor;
private int radius = 10;
// PHYSICS
public double mass;
public double charge;
public double netForceX;
public double netForceY;
private boolean positive;
public Particle(double x, double y, boolean positive) {
this.x = x - radius;
this.y = y - radius;
this.velX = 3;
this.velY = 2;
this.acX = 0;
this.acY = 0;
this.mass = 100;
this.positive = positive;
if(positive) {
this.charge = defaultCharge;
} else {
this.charge = defaultCharge*(-1);
}
this.position = new Point2D.Double(x, y);
particleColor = Color.WHITE;
}
public void update() {
acX = netForceX / mass;
acY = netForceY / mass;
velX += acX;
velY += acY;
if(x<=0 || x>=Simulation.WIDTH - 23){
velX = velX * -1;
x+= velX;
}
if(y<=0 || y>=Simulation.HEIGHT - 35){
velY = velY * -1;
y+= velY;
}
synchronized(Scene.particleLock) {
for(Particle otherPart: Scene.particleArray) {
if(otherPart.equals(this)) {
continue;
}
double distance = otherPart.position.distance(position);
if(distance <= radius + otherPart.radius) {
//aplicar lo que sé de choques de alguna manera
}
}
}
x+= velX;
y+= velY;
position.setLocation(x, y);
}
}
public class PhysicsEngine {
static double electricalConstant = 100000;
public static double[] applyElectircalForce(Particle thisPart, Particle otherPart) {
double distance = otherPart.position.distance(thisPart.position);
double angle = Math.asin(Math.abs(thisPart.y - otherPart.y)/distance);
double force = (electricalConstant * thisPart.charge * otherPart.charge)/Math.pow(distance, 2);
double forceX = force * Math.cos(angle);
double forceY = force * Math.sin(angle);
if(otherPart.x < thisPart.x) {
forceX = forceX*(-1);
}
if(otherPart.y < thisPart.y) {
forceY = forceY*(-1);
}
double[] result = {forceX, forceY};
return result;
}
}
I once had a similar problem with synchronization when I was working on an android project, try declaring particleArray volatile so that the compiler knows that particleArray will be changed on other or multiple threads. If that does not work I would suggest using a queue to push changes to the particle array from different threads and then pulling the intended changes to the array list in the update method to update your particle array list. In my experience changing values directly between different threads almost always causes problems.
I'm new to programming and I need to make ten or more bouncing objects that will bounce off of each other. Can someone give me an example of a program that will create this?
Edit:Here is the code that I'm currently working on.
//main program
float hue;
float alpha;
float scale = 50;
AnArray HmWd;
void setup(){
size(1000,1000);
colorMode(HSB, 360, 100, 100);
HmWd = new AnArray(scale,3);
}
void display(){
background(0,0,100);
HmWd.display();
}
AnArray class:
class AnArray{
Agent Gems1[];
Agent Gems2[];
Agent Gems3[];
Agent Gems4[];
Agent Gems5[];
float size;
int quant;
int ol = 1;
AnArray(float _size,int _quant){
size = _size;
quant = _quant;
for(int i=0; i<quant;i++){
Gems1[i]=new Agent(size,ol); //I'm getting a "NullPointerException" Error here
ol++;
Gems2[i]=new Agent(size,ol);
ol++;
Gems3[i]=new Agent(size,ol);
ol++;
Gems4[i]=new Agent(size,ol);
ol++;
Gems5[i]=new Agent(size,ol);
ol=1;
}
}
void display(){
for(int i=0; i<quant;i++){
Gems1[i].display();
Gems2[i].display();
Gems3[i].display();
Gems4[i].display();
Gems5[i].display();
}
}
}
Agent class:
class Agent{
PVector position, speed;
float r;
float highlightHue, basicHue;
Agent(float _r,int c){
position = new PVector((random(100,900)),(random(100,900)));
r = _r; ///radius is for test intersection
speed = new PVector(2,2);
highlightHue = 72+(5*c);
basicHue = 190+(5*c);
hue = basicHue;
}
PVector getCenter(){
PVector center = new PVector();
center.x = position.x ;
center.y = position.y ;
return center;
}
void highlight(){
hue = highlightHue;
}
void reverseSpeed(){
speed.x *= -1;
}
void display(){
colorMode(HSB);
fill(hue, 200,200,alpha);
stroke(50, alpha);
ellipse(position.x,position.y, 2*r,2*r);
hue= basicHue;
}
void move(){
if( position.x >width || position.x < 0){
speed.x *= -1;
}
if( position.y > height || position.y < 0){
speed.y *= -1;
}
position.add(speed);
}
void grow(){
if( r < 150){
r++;
alpha = alpha > 50? alpha -= 2: 50; //ternary assignment operator
}
}
void shrink(){
if( r>10){
r--;
alpha = alpha< 200? alpha +=2: 200;
}
}
boolean intersect( Agent a){
boolean isIntersect = false;
float d = PVector.dist(position,a.position);
if(d < this.r + a.r){
isIntersect= true;
}
return isIntersect;
}
}
Okay, so I'm in the progress of making a game, and I need the collisions to work. I have an if() { } else if() {} -statement, but BOTH of them are being called. Here is my code:
Inside my Player Class:
public Rectangle[] tileRect;
public void update() {
tileRect = new Rectangle[Level1.tiles.size()];
for (int w = 0; w < Level1.tiles.size(); w++) {
Tile m = (Tile) Level1.tiles.get(w);
tileRect[w] = m.getBounds();
if(tileRect[w].intersects(getRect())) {
System.out.println("intersecting");
dy = 0;
} else if (!tileRect[w].intersects(getRect())){
dy = 4;
}
}
x += dx;
y += dy;
}
public Rectangle getRect() {
return new Rectangle(x, y, 32, 32);
}
Here is my Tile class (the Level1.tiles is an arrayList of tiles):
package level;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Tile extends Rectangle {
// Defines the id of the tile, used for setting textures.
private static final long serialVersionUID = 1L;
public int id;
// Location
public int x;
public int y;
// Variables for the terrain sprite sheet.
public BufferedImage image;
public String imageLocation;
public BufferedImage[] sprite;
public int rows = 16;
public int collumns = 16;
public int width = 16;
public int height = 16;
public Tile(int idVal, int xPos, int yPos) {
x = xPos * 32;
y = yPos * 32;
id = idVal;
setBounds(x, y, 32, 32);
createImages();
}
public BufferedImage getImage() {
return sprite[id];
}
public void createImages() {
imageLocation = "res/tile/terrain.png";
try {
image = ImageIO.read(new File(imageLocation));
} catch (IOException e) {
System.out.println("Unable to find file " + imageLocation
+ ", printing stack trace!");
e.printStackTrace();
}
sprite = new BufferedImage[rows * collumns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < collumns; j++) {
sprite[(i * collumns) + j] = image.getSubimage(j * width, i
* height, width, height);
}
}
}
public int getXLoc() {
return x;
}
public int getYLoc() {
return y;
}
public void setX(int xPos) {
x = xPos;
}
public void setY(int yPos) {
y = yPos;
}
}
I'm getting the "intersecting" message in the console, but the player is still falling down (because dy = 4). Please help! I've been trying to solve this all morning...
If and Else cannot both be caught at the same time.
Looks like you are looping through, seeing an intersection, then continuing to loop through regardless.
Try adding a break command to your for loop.
if(tileRect[w].intersects(getRect())) {
System.out.println("intersecting");
dy = 0;
break;
} else if (!tileRect[w].intersects(getRect())){
dy = 4;
}
The break will stop your for loop from continuing and you will exit the loop with dy = 0; rather than going onto the next tile and changing it back to dy = 4;
if and else if cannot be called in the same run. If if condition is true, then any else is never run (not even checked). It's probably different runs. Debug or put a log to see the flow.
Also
if(tileRect[w].intersects(getRect())) {
System.out.println("intersecting");
dy = 0;
} else if (!tileRect[w].intersects(getRect())){
dy = 4;
}
is much simpler written as
if(tileRect[w].intersects(getRect())) {
System.out.println("intersecting");
dy = 0;
} else {
dy = 4;
}
I have a chicken image that only moves whenever I press my arrow keys, the image always appear at the lower left corner when I start to run the program. My problem is that how can I make the image appear at the top or anywhere on the screen(except on the lower left) and the image still moves when I press the arrow keys . I'm not really sure but I think this problem is coming from my translate(). Is there something wrong with my calculation? Thanks for sharing your ideas...
Here's the code...
public class Chicken extends Sprite implements ImageObserver
{
private java.awt.Image fishImage;
private final Board board;
private double x;
private double y;
private final double chickenHeight = 1.6;
private final double chickenWidth = 1.8;
private double speed;
private boolean visible;
private double angle;
private double dx_m;
private double dy_m;
private boolean collision = false;
public Chicken(Board board, String name, double x, double y, double speed)
{
super(name);
this.board = board;
this.x = x;
this.y = y;
this.speed = convertToMeterPerSecond(speed);
visible = true;
URL iU = this.getClass().getResource("chicken.jpg");
ImageIcon icon = new ImageIcon(iU);
chickenImage = icon.getImage();
}
public Image getImage()
{
return chickenImage;
}
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
{
dx_m = -0.5;
}
if (key == KeyEvent.VK_RIGHT)
{
dx_m = 0.5;
}
if (key == KeyEvent.VK_UP)
{
dy_m = 0.5;
}
if (key == KeyEvent.VK_DOWN)
{
dy_m = -0.5;
}
}
public void keyReleased(KeyEvent e)
{
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
{
dx_m = 0;
}
if (key == KeyEvent.VK_RIGHT)
{
dx_m = 0;
}
if (key == KeyEvent.VK_UP)
{
dy_m = 0;
}
if (key == KeyEvent.VK_DOWN)
{
dy_m = 0;
}
}
#Override
public void move(long dt)
{
double right_wall = board.x1_world;
double up_wall = board.y1_world;
double down_wall = 0.0;
double left_wall = 0.0;
x += dx_m;
y += dy_m;
if (x >= right_wall)
{
x = right_wall;
}
if (y > up_wall)
{
y = up_wall;
}
if (x <= left_wall)
{
x = left_wall;
}
if (y < down_wall)
{
y = down_wall;
}
}
#Override
public void render(Graphics2D g2d)
{
AffineTransform t = g2d.getTransform();
final double foot_position_y = chickenHeight;
final double foot_position_x = chickenWidth / 2;
double xx = board.convertToPixelX(x - foot_position_x);
double yy = board.convertToPixelY(y + foot_position_y);
g2d.translate(xx, yy);
// ratio for the actual size of the Image
double x_expected_pixels = chickenHeight * board.meter;
double y_expected_pixels = chickenWidth * board.meter;
double w = ((ToolkitImage) chickenImage).getWidth();
double h = ((ToolkitImage) chickenImage).getHeight();
double x_s = x_expected_pixels / w;
double y_s = y_expected_pixels / h;
g2d.scale(x_s, y_s);
g2d.drawImage(getImage(), (int) x, (int) y, this);
g2d.setTransform(t);
}
#Override
public void moveAt(double distance_x, double distance_y)
{
this.x = (int) distance_x;
this.y = (int) distance_y;
}
public void setAngle(double angle)
{
this.angle = angle;
}
#Override
public RectangleX getBounds()
{
return new RectangleX(x, y, chickenWidth, chickenHeight);
}
#Override
public double getWidth()
{
return WIDTH;
}
#Override
public double getHeight()
{
return HEIGHT;
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
return true;
}
}
this is my chicken class
public double meter;
int y1_pixel;
y1_pixel = getHeight();
public int convertToPixelX(double distance)
{
return (int) (distance * meter);
}
public int convertToPixelY(double y_world)
{
return (int) (y1_pixel - (y_world * meter));
}
this is coming from my board class.
Your render method is using the x and y coordinates of the class to determine where to draw the Chicken each time. A simple solution to your problem is to use random values for x and y when you create a Chicken instance.
An alternate solution would be to create another constructor that do not take values for x or y and instead sets them to be default values anywhere between 0 and board.x1_world or board.y1_world, depending on the variable.
public Chicken(Board board, String name, double speed)
{
this( board, name,
(int)( Math.random() * ( board.x1_world - chickenWidth ) ),
(int)( Math.random() * ( board.y1_world - chickenHeight ) ),
speed );
}