Unable to get the conditions right - java

I am trying to make a program of a bouncing ball. I have tried some conditions in it.But i have not got what i wanted.The ball keeps on moving back and forth in the diagonal direction of the frame.Where is the problem ? I have highlighted the main logic of this program.
Here is the program :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class MovingBall2D extends JPanel{
int x_Pos=0;
int y_Pos=0;
int speedX=1;
int speedY=1;
int diameter=30;
int height=30;
int frameX=500;
int frameY=500;
MovingBall2D() {
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if( x_Pos > ( frameX - diameter ) ) { // <------ logic starts from here
x_Pos = frameX - diameter;
speedX = -1;
}
else if(x_Pos < 0) {
x_Pos = 0;
speedX = 1;
}
else if( y_Pos > ( frameY - diameter ) ) {
y_Pos = frameY - height;
speedY = -1;
}
else if(y_Pos < 0) {
y_Pos = 0;
speedY = 1;
}
x_Pos = x_Pos + speedX;
y_Pos = y_Pos + speedY;
repaint();
}
};
new Timer(10,taskPerformer).start(); // <------- logic ends here
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(x_Pos,y_Pos,diameter,height);
}
}
class Main2D {
Main2D() {
JFrame fr=new JFrame();
MovingBall2D o = new MovingBall2D();
fr.add(o);
fr.setSize(500,500);
fr.setVisible(true);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
new Main2D();
}
}
EDIT - Ball moves back and forth. Why this happens? I expect the output shown here.
If the question is unclear to any one please compile and then run to see the output .

The ball starts at position 0, 0. At each time step from then until it hits a wall, its x position and y position each increase by 1. So at time 471, its position is (471, 471). At this point both the x and y conditions for turning around are true, so both get switched and the ball turns completely around.
If you change the starting position to something like (0, 30) or change one of the speeds to something other than 1 or -1 you will see that your code works. The ball will always be following some loop, but because of the frame size and ball placement yours happens to be very small.
However, I would suggest that you remove the else conditions. It is possible in a single frame for the ball to be too far left and too far down, so in that frame both conditions should be fixed, not just one. Also, you may notice the ball continuing off the screen in the y direction. This is because your main frame is set to the same height as the panel. The frame height includes the portion used for the top window bar, so it needs to be slightly larger than the panel it is holding.

In all four of your cases, you set the corresponding speed to -1:
speedX = -1;
//...
speedY = -1;
But you only want it to be negative when X is greater than the width or Y is greater than the height. In the other two cases, you want the speed to be positive.
Or, maybe what you were going for was
speedX *= -1;
Which would toggle the speed to the opposite direction.

Seems to me that speedX and speedY are not properly updated. I think it should be like this instead:
if( x_Pos > ( frameX - diameter ) ) { // <------ logic starts from here
x_Pos = frameX - diameter;
speedX = -1;
}
else if(x_Pos < 0) {
x_Pos = 0;
speedX = 1;
}
else if( y_Pos > ( frameY - diameter ) ) {
y_Pos = frameY - height;
speedY = -1;
}
else if(y_Pos < 0) {
y_Pos = 0;
speedY = 1;
}
x_Pos = x_Pos + speedX;
y_Pos = y_Pos + speedY;

I think you have all the logic right, but your initialization makes it sure to bounce diagonally (from bottom left to top right)
Change them up, use random values OR hardcode them like so
int x_Pos=100; // These are changed so the ball no longer starts at bottom left
int y_Pos=20;
int speedX=1; //This should be fine as long as your initial position is different
int speedY=1;
int diameter=30;
int height=30;
int frameX=500;
int frameY=500;
I also think this would work
int x_Pos = 100* Math.Rand(1);
etc.

Related

How do i save a variable in a loop to use it again later?

I want to make a program which sets ellipses next to each other until one touches a border of my canvas and then proceeds in the other direction. Unfortunately it only works in one direction and stops when it hits the right border.Is there a way to save the sx variable at some point to use it again in the second if statement?
void setup() {
size(700, 500);
frameRate(20); // frame rate = 20 Hz
}
int sx=50;
int sy=50;
int dx=15;
void draw() {
if(sx<width){
ellipse(sx,sy,20,20);
sx=sx+dx;
if(sx>width){
sx=sx-dx;
}
}
}
sx is in global scope, so there is no need to "store" it, because the value is persistent.
What you want to do is quite simple. The key is dx rather than sx. If the the ellipse reaches the border of the window, the direction has to be changed. This can be achieved by inverting dx.
Invert dx (dx *= -1) when sx is at the right border (sx >= width) or left border (sx <= 0). e.g.:
void setup() {
size(700, 500);
frameRate(20); // frame rate = 20 Hz
}
int sx=50;
int sy=50;
int dx=15;
void draw() {
background(196);
ellipse(sx,sy,20,20);
sx=sx+dx;
if (sx >= width || sx <= 0 ){
dx *= -1;
}
}

I cannot figure out a way to move the balls

I am currently working on a 3 cushion billiards game project. I have added two balls on the table so far. I am trying to move one of the balls but I am having a hard time doing that. Should I use a timer? If so then could you tell me an effective way to use the timer on my code so I can move my balls?
Your help would be much appreciated.
Thanks in advance.
Farhan Hasan
I have tried to create a move function for the class balls. But I am not sure what I should put inside the function, I have added the xSpeed and ySpeed. The xLocation and the yLocation changes depending on the xSpeed and ySpeed.
public class Balls
{
private Color ballFillColor;
private Color ballBorderColor;
private int ballX = 0;
private int ballY = 0;
private int xSpeed = 5;
private int ySpeed = 0;
private int ballWidth = 0;
private int ballHeight = 0;
Timer t;
public boolean fillBall = false;
private static Balls ballArray[]; //Required for drawMultipleBalls
Balls(){ //Constructor
ballBorderColor = Color.black;
}
Balls(int ballX, int ballY, int ballWidth, int ballHeight, Color ballBorderColor, JFrame window){ //Constructor
// X , Y , Width, Height, Border Colour, container
this.setBallBorderColor(ballBorderColor);
this.setBallWidth(ballWidth);
this.setBallHeight(ballHeight);
this.setBallX(ballX);
this.setBallY(ballY);
this.drawBall(window);
}
//Here is the move function. I am not really sure what to do here.
public void move()
{
if(this.ballX < 1000 - this.ballWidth)
{
this.ballX += this.xSpeed;
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
//GET AND SET FUNCTIONS HERE
//HERE ARE THE FUNCTIONS WHICH ARE RESPONSIBLE FOR DRAWING MY BALLS IN JFRAME
public void drawBall(JFrame frame)
{
frame.getContentPane().add(new MyComponent());
}
public void drawMultipleBalls(JFrame frame, Balls[] balls)
{
ballArray = balls;
frame.getContentPane().add(new MyComponent2());
}
private class MyComponent extends JComponent{
public void paintComponent(Graphics g){
if (fillBall) //Fill first, and then draw outline.
{
g.setColor(ballFillColor);
g.fillOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
g.setColor(getBallBorderColor());
g.drawOval(getBallX(),getBallY(), getBallHeight(),getBallWidth());
}
}
private class MyComponent2 extends JComponent{
public void paintComponent(Graphics g){
for (int i = 0; i < ballArray.length; i++)
{
if (ballArray[i].fillBall) //Fill first, and then draw outline.
{
g.setColor(ballArray[i].ballFillColor);
g.fillOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
g.setColor(ballArray[i].getBallBorderColor());
g.drawOval(ballArray[i].getBallX(),ballArray[i].getBallY(), ballArray[i].getBallHeight(),ballArray[i].getBallWidth());
}
}
}
Hopefully, I can have two movable balls for the game, the should bounce back as the hit the edge of the screen and they should be able to slow down over time. For that, I am thinking to use a damper (I will multiply the xSpeed and ySpeed with a number less than 1, eventually it will slow down the ball)
Here is a simple example I came up with to show a ball moving and bouncing off the edges.
The direction changes based on the boundary. Left and top edges just check for 0. Bottom and right edges need to include the diameter of the ball.
The x and y increments are independent. And these amounts in conjunction with the timer can change the movement. Notice however, that to have objects bounce off of each other (as in a pool game) is more complicated due to angle of trajectories, etc. And the distances bounced will vary and slow with time based on frictional values. Everything else is documented in the Java API.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MovementDemo extends JPanel implements ActionListener {
JFrame frame = new JFrame("Movement Demo");
int size = 500;
int x = 50;
int y = 200;
int diameter = 50;
int yinc = 2;
int xinc = 2;
int xdirection = 1;
int ydirection = 1;
public MovementDemo() {
setPreferredSize(new Dimension(size, size));
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MovementDemo().start());
}
public void start() {
Timer timer = new Timer(100, this);
timer.setDelay(5);
timer.start();
}
public void actionPerformed(ActionEvent ae) {
if (x < 0) {
xdirection = 1;
}
else if (x > size - diameter) {
xdirection = -1;
}
if (y < 0) {
ydirection = 1;
}
else if (y > size - diameter) {
ydirection = -1;
}
x = x + xdirection * xinc;
y = y + ydirection * yinc;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fillOval(x, y, diameter, diameter);
}
}
It seems in general there are a few things you need to figure out:
has the ball collided with another ball
has the ball collided with a wall
otherwise just figure out what is the ball's new position based on its velocity
Below is some sample code that stubs some of this out. You can first compare the current ball's position to all others (not including the current ball of course). If there are any equal positions, process a collision with a ball. If the ball is at the window border i.e it hit a wall, process a collision with a wall. Otherwise just calculate its new position based on its current velocity.
The process collision part is just to apply physics mechanics to whatever degree of complexity you require. One general suggested change would be to update the velocity of the balls then apply it to the position after. The specific calculations for velocity changes you could apply as needed and as you can imagine it can get pretty involved which is why I suggest using a separate method and possibly a sub class for velocity instead of managing each part of the velocity vector in the ball itself. I used the wall as an object because of this. The composition, weights, velocities etc of the object's colliding can affect the resulting collision, but how complex you want that processing to be is up to you.
Sorry I'm no physics expert but I hope this sends you in the right direction in terms of code! Also this might help with the specific calculations you might want to use:
https://www.khanacademy.org/science/physics/one-dimensional-motion/displacement-velocity-time/v/calculating-average-velocity-or-speed
public void move()
{
// check if balls are on same position not including this ball
for(Ball b: ballArray){
if (this.position == b.position && this != b){
processCollision(this, b, null);
} else{
// if the ball hasn't collided with anything process its movement based on speed
// this assumes a 1000 x 1000 window for keeping objects inside it
if(this.ballX < 1000 - this.ballWidth && this.ballY < 1000 - this.ballHeight){
this.ballX += this.xSpeed;
this.ballY += this.ySpeed;
}else {
processCollision(this, null, new Wall());
}
}
}
try
{
Thread.sleep(1);
}
catch(Exception e)
{
}
}
public void processCollision(Ball b1, Ball b2, Wall w){
// if ball hasn't collided with a wall, process a ball - ball collision
if(w == null){
// apply physics mechanics according the complexity desired for ball collisions
b1.xSpeed -= b2.xSpeed;
b1.ySpeed -= b2.ySpeed;
// ball 2 would end up slowing down
b2.xSpeed -= b1.xSpeed;
b2.ySpeed -= b1.ySpeed;
}
// if ball hasn't collided with a ball, process a ball - wall collision
if(b2 == null){
// apply physics mechanics for hitting a wall
// e.g as below: just send ball in opposite direction
b1.xSpeed = b1.xSpeed * -1;
b1.ySpeed = b1.ySpeed * -1;
}
// either way, process ball's new position based on its new speed
b1.ballX += b1.xSpeed;
b1.ballY += b1.ySpeed;
b2.ballX += b2.xSpeed;
b2.ballY += b2.ySpeed;
}

Matrixes and for loops becoming inconsistent?

This is a follow-up post to my previous question, here. I got a remarkable response to instead of using array data tracking, to use matrixes. Now, the code here works just as planned (as in, the rectangles somewhat most of the time get filled in properly with white), but it's very inconsistent. When holding the left or right mouse button the colors phase over each other in a battle of randomness, and I don't know nearly that much about why this is happening. Just for reference, I'm using Java in Processing 3.
This is a result that I made with the project. As you can see, it looks fine.
Except for that jitter when hovering over a rect, and that more than not the rectangles are not being filled in half the time. And plus, the hover color is cycling almost randomly.
int cols, rows;
int scl = 20;
boolean[][] matrix = new boolean[scl+1][scl+1];
void setup() {
size(400, 400);
int w = 400;
int h = 400;
cols = w / scl;
rows = h / scl;
}
void draw() {
background(255);
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
int xpos = x*scl;
int ypos = y*scl;
stroke(55);
if ((mouseX >= xpos && mouseX <= xpos+scl) &&
(mouseY >= ypos && mouseY <= ypos+scl)) {
fill(75);
if (mousePressed == true) {
println("Clicked at: " + xpos + " and " + ypos);
if (!matrix[xpos/scl][ypos/scl]) {
matrix[xpos/scl][ypos/scl] = true;
} else {
matrix[xpos/scl][ypos/scl] = false;
}
fill(100);
//here is the desired location for the fill to remain constant even
//after unclicking and leaving hover
}
println("Mouse at: " + xpos + " and " + ypos);
} else {
fill(50);
}
if (matrix[x][y]) {
//fill(204, 102, 0);
fill(240);
rect(xpos, ypos, scl, scl);
}
rect(xpos, ypos, scl, scl);
}
}
}
Remeber that Processing fires the draw() function 60 times per second.
So your check for whether the mouse is pressed is happening 60 times per second. That means you're toggling the state of whatever cell the mouse is in 60 times per second.
To fix that problem, you might switch to using the event functions like mousePressed() instead of constantly polling every frame.
From the reference:
int value = 0;
void draw() {
fill(value);
rect(25, 25, 50, 50);
}
void mousePressed() {
if (value == 0) {
value = 255;
} else {
value = 0;
}
}
As for certain cells being skipped over, that's because when you move the mouse, it doesn't actually go through every pixel. It "jumps" from frame to frame. Those jumps are usually small enough that humans don't notice it, but they're large enough that it's skipping over cells.
One solution to this is to use the pmouseX and pmouseY variables to calculate a line from the previous mouse position to the current mouse position, and fill in any cells that would have been hit along the way.

Ball stops moving after a few bounces

Ok so I have been try to get this ball to bounce naturally for a few weeks now and can't seem to get it right. The program should allow the user to input a set amount of gravity and then have the ball bounce according to that amount. It works for the first few bounces but stopping the ball is the problem. I have to deliberately set its movement to 0 or else it will endlessly bounce in place but not move on the x-axis. This issue only happens when the gravity is set to 15, other amount and things really go bad. The ball will bounce naturally but then keep rolling on x-axis forever. I've never taken a physics class so the issue is probably in the physics code. Anyone know where the issue is?
Here is the code my code-
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.util.Random;
import javax.swing.JOptionPane;
//key stuff
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
public class StartingPoint extends Applet implements Runnable{
//key press
private static boolean wPressed = false;
public static boolean isWPressed() {
synchronized (StartingPoint.class) {
return wPressed;
}
}
//for position of circle
int x = 0;
int y= 0;
//for position change
double dx = 2;
double dy = 2;
//for circle size
int rad = 11;
//image for update()
private Image i;
private Graphics gTwo;
//Physics
double grav = 15;
double engloss= .65;
double tc = .2;
double friction = .9;
#Override
public void init() {
// sets window size
setSize(800,600);
}
#Override
public void start() {
//"this" refers to the implemented run method
Thread threadOne = new Thread(this);
//this goes to run()
threadOne.start();
}
#Override
public void run() {
String input = JOptionPane.showInputDialog( "How much gravity?" );
grav= Double.parseDouble(input);
// sets frame rate
while (true){
//makes sure it doesn't go off screen x wise
//right side
if (x + dx > this.getWidth() - rad -1){
x= this.getWidth() -rad -1; //blocks it from moving past boundary
dx = -dx; //Reveres it
}
//left side
else if (x + dx < 1 + rad){
x= 1+rad; //ball bounces from the center so it adjusts for this by adding one and rad to pad out the radius of the ball plus one pixel.
dx = -dx; //Inverters its movement so it will bounce
}
//makes the ball move
else{
x += dx; // if its not hitting anything it keeps adding dx to x so it will move.
}
//friction
if(y == this.getHeight()-rad -1){
dx *= friction; //every time the ball hits the bottom dx is decreased by 10% by multiplying by .9
//Keeps it from micro bouncing for ever
if (Math.abs(dy) < 4){ // if the speed of y (dy) is less than .4 it is set to 0
dy= 0;
}
/**if (Math.abs(dx) < .00000000000000000001){ // if the speed of x (dx) is less than .00000000000000000001 it is set to 0, this value doesn't seem to matter
dx = 0;
}**/
}
//makes sure it doesn't go off screen y wise
//down
if (y > this.getHeight() - rad -0){ // TODO Check how getHieght is measured.
y= this.getHeight() -rad -0;
//makes ball loose speed.
dy *= engloss;
dy = -dy;
}
else {
//velocity
// tc makes grav smaller. Total of which is added to dy. To increase velocity as the ball goes down.
dy += grav *tc;
//gravity
//new dy is decreased by tc + .5 multiplied by gravity and tc squared. This makes the ball bounce lower every time based on its speed
y += dy*tc + .5*grav*tc*tc;
}
//frame rate
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//end frame rate
}
#Override
public void stop() {
}
#Override
public void destroy() {
}
#Override
public void update(Graphics g) {
//keeps it from flickering... don't know how though
if(i == null){
i = createImage(this.getSize().width, this.getSize().height);
gTwo = i.getGraphics();
}
gTwo.setColor(getBackground());
gTwo.fillRect(0, 0, this.getSize().width, this.getSize().height);
gTwo.setColor(getForeground());
paint(gTwo);
g.drawImage(i, 0, 0, this);
//do some thing with setDoubleBuffered
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLUE);
g.fillOval(x-rad, y-rad, rad*2, rad*2);
}
}

Collision Detection between two images in Java

I have two characters displayed in a game I am writing, the player and the enemy. defined as such:
public void player(Graphics g) {
g.drawImage(plimg, x, y, this);
}
public void enemy(Graphics g) {
g.drawImage(enemy, 200, 200, this);
}
Then called with:
player(g);
enemy(g);
I am able to move player() around with the keyboard, but I am at a loss when trying to detect a collision between the two. A lot of people have said to use Rectangles, but being a beginner I cannot see how I would link this into my existing code. Can anyone offer some advice for me?
I think your problem is that you are not using good OO design for your player and enemies. Create two classes:
public class Player
{
int X;
int Y;
int Width;
int Height;
// Getters and Setters
}
public class Enemy
{
int X;
int Y;
int Width;
int Height;
// Getters and Setters
}
Your Player should have X,Y,Width,and Height variables.
Your enemies should as well.
In your game loop, do something like this (C#):
foreach (Enemy e in EnemyCollection)
{
Rectangle r = new Rectangle(e.X,e.Y,e.Width,e.Height);
Rectangle p = new Rectangle(player.X,player.Y,player.Width,player.Height);
// Assuming there is an intersect method, otherwise just handcompare the values
if (r.Intersects(p))
{
// A Collision!
// we know which enemy (e), so we can call e.DoCollision();
e.DoCollision();
}
}
To speed things up, don't bother checking if the enemies coords are offscreen.
First, use the bounding boxes as described by Jonathan Holland to find if you may have a collision.
From the (multi-color) sprites, create black and white versions. You probably already have these if your sprites are transparent (i.e. there are places which are inside the bounding box but you can still see the background). These are "masks".
Use Image.getRGB() on the mask to get at the pixels. For each pixel which isn't transparent, set a bit in an integer array (playerArray and enemyArray below). The size of the array is height if width <= 32 pixels, (width+31)/32*height otherwise. The code below is for width <= 32.
If you have a collision of the bounding boxes, do this:
// Find the first line where the two sprites might overlap
int linePlayer, lineEnemy;
if (player.y <= enemy.y) {
linePlayer = enemy.y - player.y;
lineEnemy = 0;
} else {
linePlayer = 0;
lineEnemy = player.y - enemy.y;
}
int line = Math.max(linePlayer, lineEnemy);
// Get the shift between the two
x = player.x - enemy.x;
int maxLines = Math.max(player.height, enemy.height);
for ( line < maxLines; line ++) {
// if width > 32, then you need a second loop here
long playerMask = playerArray[linePlayer];
long enemyMask = enemyArray[lineEnemy];
// Reproduce the shift between the two sprites
if (x < 0) playerMask << (-x);
else enemyMask << x;
// If the two masks have common bits, binary AND will return != 0
if ((playerMask & enemyMask) != 0) {
// Contact!
}
}
Links: JGame, Framework for Small Java Games
You don't want to have the collision check code inside the painting code. The painting needs to be fast. Collision can go in the game loop. Therefore you need an internal representation of the objects independent of their sprites.
Here's the main class from my collision detection program.
You can see it run at: http://www.youtube.com/watch?v=JIXhCvXgjsQ
/**
*
* #author Tyler Griffin
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.GraphicsDevice.*;
import java.util.ArrayList;
import java.awt.Graphics;
import java.awt.geom.Line2D;
public class collision extends JFrame implements KeyListener, MouseMotionListener, MouseListener
{
ArrayList everything=new ArrayList<tile>();
int time=0, x, y, width, height, up=0, down=0, left=0, right=0, mouse1=0, mouse2=0;
int mouseX, mouseY;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice screen = environment.getDefaultScreenDevice();
DisplayMode displayMode = screen.getDisplayMode();
//private BufferStrategy strategy;
JLayeredPane pane = new JLayeredPane();
tile Tile;
circle Circle;
rectangle Rectangle;
textPane text;
public collision()
{
setUndecorated(screen.isFullScreenSupported());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(null);
setResizable(false);
screen.setFullScreenWindow(this);
width=displayMode.getWidth();
height=displayMode.getHeight();
Circle=new circle(-(int)Math.round((double)height/7*2),-(int)Math.round((double)height/7*2),(int)Math.round((double)height/7*.85),this);
Rectangle=new rectangle(-(int)Math.round((double)height/7*1.5),-(int)Math.round((double)height/7*1.5),(int)Math.round((double)height/7*1.5),(int)Math.round((double)height/7*1.5),this);
Tile=Circle;
Tile.move(mouseX-Tile.width/2, mouseY-Tile.height/2);
text=new textPane(0,0,width,height,this);
everything.add(new circle((int)Math.round((double)width/100*75),(int)Math.round((double)height/100*15),(int)Math.round((double)width/100*10),this));
everything.add(new rectangle((int)Math.round((double)width/100*70),(int)Math.round((double)height/100*60),(int)Math.round((double)width/100*20),(int)Math.round((double)height/100*20),this));
//everything.add(new line(750,250,750,750,this));
/*everything.add(new line(width/700*419,height/700*68,width/700*495,height/700*345,this));
everything.add(new line(width/700*495,height/700*345,width/700*749,height/700*350,this));
everything.add(new line(width/700*749,height/700*350,width/700*549,height/700*519,this));
everything.add(new line(width/700*549,height/700*519,width/700*624,height/700*800,this));
everything.add(new line(width/700*624,height/700*800,width/700*419,height/700*638,this));
everything.add(new line(width/700*419,height/700*638,width/700*203,height/700*800,this));
everything.add(new line(width/700*203,height/700*800,width/700*279,height/700*519,this));
everything.add(new line(width/700*279,height/700*519,width/700*76,height/700*350,this));
everything.add(new line(width/700*76,height/700*350,width/700*333,height/700*345,this));
everything.add(new line(width/700*333,height/700*345,width/700*419,height/700*68,this));
everything.add(new line(width/950*419,height/700*68,width/950*624,height/700*800,this));
everything.add(new line(width/950*419,height/700*68,width/950*203,height/700*800,this));
everything.add(new line(width/950*76,height/700*350,width/950*624,height/700*800,this));
everything.add(new line(width/950*203,height/700*800,width/950*749,height/700*350,this));
everything.add(new rectangle(width/950*76,height/700*350,width/950*673,1,this));*/
everything.add(new line((int)Math.round((double)width/1350*419),(int)Math.round((double)height/1000*68),(int)Math.round((double)width/1350*624),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*419),(int)Math.round((double)height/1000*68),(int)Math.round((double)width/1350*203),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*76),(int)Math.round((double)height/1000*350),(int)Math.round((double)width/1350*624),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*203),(int)Math.round((double)height/1000*800),(int)Math.round((double)width/1350*749),(int)Math.round((double)height/1000*350),this));
everything.add(new rectangle((int)Math.round((double)width/1350*76),(int)Math.round((double)height/1000*350),(int)Math.round((double)width/1350*673),1,this));
addKeyListener(this);
addMouseMotionListener(this);
addMouseListener(this);
}
public void keyReleased(KeyEvent e)
{
Object source=e.getSource();
int released=e.getKeyCode();
if (released==KeyEvent.VK_A){left=0;}
if (released==KeyEvent.VK_W){up=0;}
if (released==KeyEvent.VK_D){right=0;}
if (released==KeyEvent.VK_S){down=0;}
}//end keyReleased
public void keyPressed(KeyEvent e)
{
Object source=e.getSource();
int pressed=e.getKeyCode();
if (pressed==KeyEvent.VK_A){left=1;}
if (pressed==KeyEvent.VK_W){up=1;}
if (pressed==KeyEvent.VK_D){right=1;}
if (pressed==KeyEvent.VK_S){down=1;}
if (pressed==KeyEvent.VK_PAUSE&&pressed==KeyEvent.VK_P)
{
//if (paused==0){paused=1;}
//else paused=0;
}
}//end keyPressed
public void keyTyped(KeyEvent e){}
//***********************************************************************************************
public void mouseDragged(MouseEvent e)
{
mouseX=(e.getX());
mouseY=(e.getY());
//run();
}
public void mouseMoved(MouseEvent e)
{
mouseX=(e.getX());
mouseY=(e.getY());
//run();
}
//***********************************************************************************************
public void mousePressed(MouseEvent e)
{
if(e.getX()==0 && e.getY()==0){System.exit(0);}
mouseX=(e.getX()+x);
mouseY=(e.getY()+y);
if(Tile instanceof circle)
{
Circle.move(0-Circle.width, 0-Circle.height);
Circle.setBounds(Circle.x, Circle.y, Circle.width, Circle.height);
Tile=Rectangle;
}
else
{
Rectangle.move(0-Rectangle.width, 0-Rectangle.height);
Rectangle.setBounds(Rectangle.x, Rectangle.y, Rectangle.width, Rectangle.height);
Tile=Circle;
}
Tile.move(mouseX-Tile.width/2, mouseY-Tile.height/2);
}
public void mouseReleased(MouseEvent e)
{
//run();
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
//***********************************************************************************************
public void run()//run collision detection
{
while (this == this)
{
Tile.move(Tile.x + ((mouseX - (Tile.x + (Tile.width / 2))) / 10), Tile.y + ((mouseY - (Tile.y + (Tile.height / 2))) / 10));
//Tile.move((mouseX - Tile.width / 2), mouseY - (Tile.height / 2));
for (int i = 0; i < everything.size(); i++)
{
tile Temp = (tile) everything.get(i);
if (Temp.x < (Tile.x + Tile.width) && (Temp.x + Temp.width) > Tile.x && Temp.y < (Tile.y + Tile.height) && (Temp.y + Temp.height) > Tile.y)//rectangles collided
{
if (Temp instanceof rectangle)
{
if (Tile instanceof rectangle){rectangleRectangle(Temp);}
else {circleRectangle(Temp);}//Tile instanceof circle
}
else
{
if (Temp instanceof circle)
{
if (Tile instanceof rectangle) {rectangleCircle(Temp);}
else {circleCircle(Temp);}
}
else//line
{
if (Tile instanceof rectangle){rectangleLine(Temp);}
else{circleLine(Temp);}
}
}
}//end if
}//end for
try {Thread.sleep(16L);}
catch (Exception e) {}
Tile.setBounds(Tile.x, Tile.y, Tile.width, Tile.height);
//Rectangle.setBounds(x, y, width, height);
//Circle.setBounds(x, y, width, height);
repaint();
text.out=" ";
}//end while loop
}//end run
//***************************************special collision detection/handling functions************************************************
void rectangleRectangle(tile Temp)
{
int lapTop, lapBot, lapLeft, lapRight, small, scootX=0, scootY=0;
lapTop=(Temp.y+Temp.height)-Tile.y;
lapBot=(Tile.y+Tile.height)-Temp.y;
lapLeft=(Temp.x+Temp.width)-Tile.x;
lapRight=(Tile.x+Tile.width)-Temp.x;
small=999999999;
if (lapTop<small){small=lapTop; scootX=0; scootY=lapTop;}
if (lapBot<small){small=lapBot; scootX=0; scootY=lapBot*-1;}
if (lapLeft<small){small=lapLeft; scootX=lapLeft; scootY=0;}
if (lapRight<small){small=lapRight; scootX=lapRight*-1; scootY=0;}
Tile.move(Tile.x+scootX, Tile.y+scootY);text.out="collision detected!";
}
void circleRectangle(tile Temp)
{
if((Tile.x+Tile.width/2<=Temp.x+Temp.width && Tile.x+Tile.width/2>=Temp.x)||(Tile.y+Tile.height/2>=Temp.y && Tile.y+Tile.height/2<=Temp.y+Temp.height))
{
rectangleRectangle(Temp);
}
else//push from nearest corner
{
int x,y;
if(Tile.x+Tile.width/2>Temp.x+Temp.width && Tile.y+Tile.height/2<Temp.y){x=Temp.x+Temp.width; y=Temp.y;}
else if(Tile.x+Tile.width/2<Temp.x && Tile.y+Tile.height/2<Temp.y){x=Temp.x; y=Temp.y;}
else if(Tile.x+Tile.width/2>Temp.x+Temp.width && Tile.y+Tile.height/2>Temp.y+Temp.height){x=Temp.x+Temp.width; y=Temp.y+Temp.height;}
else {x=Temp.x; y=Temp.y+Temp.height;}
double distance = Math.sqrt(Math.pow(Tile.x+(Tile.width/2) - x, 2) + Math.pow(Tile.y+(Tile.height/2) - y, 2));
if((int)Math.round(distance)<Tile.height/2)
{
double normY = ((Tile.y+(Tile.height/2) - y) / distance);
double normX = ((Tile.x+(Tile.width/2) - x) / distance);
Tile.move(x-Tile.width/2+(int)Math.round(normX*((Tile.width/2))) , y-Tile.height/2+(int)Math.round(normY*((Tile.height/2))));text.out="collision detected!";
}
}
}
void rectangleCircle(tile Temp)
{
if((Temp.x+Temp.width/2<=Tile.x+Tile.width && Temp.x+Temp.width/2>=Tile.x)||(Temp.y+Temp.height/2>=Tile.y && Temp.y+Temp.height/2<=Tile.y+Tile.height))
{
rectangleRectangle(Temp);
}
else//push from nearest corner
{
int x,y;
if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2<Tile.y){x=Tile.x+Tile.width; y=Tile.y;}
else if(Temp.x+Temp.width/2<Tile.x && Temp.y+Temp.height/2<Tile.y){x=Tile.x; y=Tile.y;}
else if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2>Tile.y+Tile.height){x=Tile.x+Tile.width; y=Tile.y+Tile.height;}
else {x=Tile.x; y=Tile.y+Tile.height;}
double distance = Math.sqrt(Math.pow(Temp.x+(Temp.width/2) - x, 2) + Math.pow(Temp.y+(Temp.height/2) - y, 2));
if((int)Math.round(distance)<Temp.height/2)
{
double normY = ((Temp.y+(Temp.height/2) - y) / distance);
double normX = ((Temp.x+(Temp.width/2) - x) / distance);
if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2<Tile.y){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2)))-Tile.width,(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2))));text.out="collision detected!";}
else if(Temp.x+Temp.width/2<Tile.x && Temp.y+Temp.height/2<Tile.y){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2))),(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2))));text.out="collision detected!";}
else if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2>Tile.y+Tile.height){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2)))-Tile.width,(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2)))-Tile.height);text.out="collision detected!";}
else {Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2))),(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2)))-Tile.height);text.out="collision detected!";}
}
}
}
void circleCircle(tile Temp)
{
double distance = Math.sqrt(Math.pow((Tile.x+(Tile.width/2)) - (Temp.x+(Temp.width/2)),2) + Math.pow((Tile.y+(Tile.height/2)) - (Temp.y+(Temp.height/2)), 2));
if((int)distance<(Tile.width/2+Temp.width/2))
{
double normX = ((Tile.x+(Tile.width/2)) - (Temp.x+(Temp.width/2))) / distance;
double normY = ((Tile.y+(Tile.height/2)) - (Temp.y+(Temp.height/2))) / distance;
Tile.move((Temp.x+(Temp.width/2))+(int)Math.round(normX*(Tile.width/2+Temp.width/2))-(Tile.width/2) , (Temp.y+(Temp.height/2))+(int)Math.round(normY*(Tile.height/2+Temp.height/2))-(Tile.height/2));text.out="collision detected!";
}
}
void circleLine(tile Temp)
{
line Line=(line)Temp;
if (Line.x1 < (Tile.x + Tile.width) && (Line.x1) > Tile.x && Line.y1 < (Tile.y + Tile.height) && Line.y1 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x1, Line.y1, 1, 1, this);
circleRectangle(rec);
remove(rec);
}
if (Line.x2 < (Tile.x + Tile.width) && (Line.x2) > Tile.x && Line.y2 < (Tile.y + Tile.height) && Line.y2 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x2, Line.y2, 1, 1, this);
circleRectangle(rec);
remove(rec);
}
int x1=0, y1=0, x2=Tile.x+(Tile.width/2), y2=Tile.y+(Tile.height/2);
x1=Tile.x+(Tile.width/2)-Line.height;//(int)Math.round(Line.xNorm*1000);
x2=Tile.x+(Tile.width/2)+Line.height;
if(Line.posSlope)
{
y1=Tile.y+(Tile.height/2)-Line.width;
y2=Tile.y+(Tile.height/2)+Line.width;
}
else
{
y1=Tile.y+(Tile.height/2)+Line.width;
y2=Tile.y+(Tile.height/2)-Line.width;
}
Point point=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
if (point.x < (Line.x + Line.width) && point.x > Line.x && point.y < (Line.y + Line.height) && point.y > Line.y)//line intersects within line segment
{
//if(point!=null){System.out.println(point.x+","+point.y);}
double distance = Math.sqrt(Math.pow((Tile.x+(Tile.width/2)) - point.x,2) + Math.pow((Tile.y+(Tile.width/2)) - point.y, 2));
if((int)distance<Tile.width/2)
{
//System.out.println("hit");
double normX = ((Tile.x+(Tile.width/2)) - point.x) / distance;
double normY = ((Tile.y+(Tile.height/2)) - point.y) / distance;
Tile.move((point.x)+(int)Math.round(normX*(Tile.width/2))-(Tile.width/2) , (point.y)+(int)Math.round(normY*(Tile.height/2))-(Tile.height/2));text.out="collision detected!";
//System.out.println(point.x+","+point.y);
}
}
//new bullet(this, (int)Math.round(tryX), (int)Math.round(tryY));
}
void rectangleLine(tile Temp)
{
line Line=(line)Temp;
if(new Line2D.Double(Line.x1,Line.y1,Line.x2,Line.y2).intersects(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height)))
{
if (Line.x1 < (Tile.x + Tile.width) && (Line.x1) > Tile.x && Line.y1 < (Tile.y + Tile.height) && Line.y1 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x1, Line.y1, 1, 1, this);
rectangleRectangle(rec);
remove(rec);
}
if (Line.x2 < (Tile.x + Tile.width) && (Line.x2) > Tile.x && Line.y2 < (Tile.y + Tile.height) && Line.y2 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x2, Line.y2, 1, 1, this);
rectangleRectangle(rec);
remove(rec);
}
if(Line.posSlope)//positive sloped line
{
//first we'll do the top left corner
int x1=Tile.x-Line.height;
int x2=Tile.x+Line.height;
int y1=Tile.y-Line.width;
int y2=Tile.y+Line.width;
Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
double topDistance=0, botDistance=0;
topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
topDistance = Math.sqrt(Math.pow(Tile.x - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//new let's do the bottom right corner
x1=Tile.x+Tile.width-Line.height;
x2=Tile.x+Tile.width+Line.height;
y1=Tile.y+Tile.height-Line.width;
y2=Tile.y+Tile.height+Line.width;
botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
botDistance = Math.sqrt(Math.pow((Tile.x+Tile.width) - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
if(topDistance<botDistance)
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
{
Tile.move(topPoint.x,topPoint.y);text.out="collision detected!";
}
}
else
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
{
Tile.move(botPoint.x-Tile.width,botPoint.y-Tile.height);text.out="collision detected!";
}
}
}
else//negative sloped lne
{
//first we'll do the top right corner
int x1=Tile.x+Tile.width-Line.height;
int x2=Tile.x+Tile.width+Line.height;
int y1=Tile.y+Line.width;
int y2=Tile.y-Line.width;
Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
double topDistance=0, botDistance=0;
topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
topDistance = Math.sqrt(Math.pow(Tile.x + Tile.width - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//new let's do the bottom left corner
x1=Tile.x-Line.height;
x2=Tile.x+Line.height;
y1=Tile.y+Tile.height+Line.width;
y2=Tile.y+Tile.height-Line.width;
botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
botDistance = Math.sqrt(Math.pow(Tile.x - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
if(topDistance<botDistance)
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
{
Tile.move(topPoint.x-Tile.width,topPoint.y);text.out="collision detected!";
}
}
else
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
{
Tile.move(botPoint.x,botPoint.y-Tile.height);text.out="collision detected!";
}
}
}
}
}
public Point intersection(double x1, double y1, double x2, double y2,double x3, double y3, double x4, double y4)//I didn't write this. got it from http://www.ahristov.com/tutorial/geometry-games/intersection-lines.html (I altered it)
{
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
int x=(int)Math.round(xi);
int y=(int)Math.round(yi);
return new Point(x, y);
}
//***************************************************************************************
public static void main(String[] args)
{
final collision Collision=new collision();
Collision.run();
}//end main
}//end class
Since Java doesn't have an intersect function (really!?) you can do collision detection by simply comparying the X and Y, Width and Height values of the bounding boxes (rectangle) for each of the objects that could potentially collide.
So... in the base object of each colliding object... i.e. if your player and enemy have a common base you can put a simple Rectangle object called something like BoundingBox. If the common base is a built in Java class then you'll need to create a class that extends the build in class and have the player and enemy objects extend your new class or are instances of that class.
At creation (and each tick or update) you'll need to set the BoundingBox paremeters for both your player and enemy. I don't have the Rectangle class infront of me but its most likely something like X, Y, Width and finally Height. X and Y are that objects location in your game world. The width and height are self explanatory I think. They'll most likely come out from the right of the players location though so, if the X and Y were bothe at 0 and your Width and Height were both at 256 you wouldn't see anything because the character would be at the top left outside of the screen.
Anyways... to detect a collision, you'll want to compare the attributes of the player and enemy BoundingBoxes. So something like this...
if( Player.BoundingBox.X = Enemy.BoundingBox.X && If( Player.BoundingBox.Y = Enemy.BoundingBox.Y )
{
//Oh noes! The enemy and player are on top of eachother.
}
The logic can get sort of complicated but you'll need to compare the distances between each BoundingBox and compare locations.
Here's a useful of an open source game that uses a lot of collisions: http://robocode.sourceforge.net/
You may take a look at the code and complement with the answers written here.
is there a problem with:
Rectangle box1 = new Rectangle(100,100,100,100);
Rectangle box2 = new Rectangle(200,200,100,100);
// what this means is if any pixel in box2 enters (hits) box1
if (box1.contains(box2))
{
// collision occurred
}
// your code for moving the boxes
this can also be applied to circles:
Ellipse2D.Double ball1 = new Ellipse2D.Double(100,100,200,200);
Ellipse2D.Double ball2 = new Ellipse2D.Double(400,100,200,200);
// what this means is if any pixel on the circumference in ball2 touches (hits)
// ball1
if (ball1.contains(ball2))
{
// collision occurred
}
// your code for moving the balls
to check whether youve hit the edge of a screen you could use the following:
Rectangle screenBounds = jpanel.getBounds();
Ellipse2D.Double ball = new Ellipse2D.Double(100,100,200,200); // diameter 200
Rectangle ballBounds = ball.getBounds();
if (!screenBounds.contains(ballBounds))
{
// the ball touched the edge of the screen
}
Use a rectangle to surround each player and enemy, the height and width of the rectangles should correspond to the object you're surrounding, imagine it being in a box only big enough to fit it.
Now, you move these rectangles the same as you do the objects, so they have a 'bounding box'
I'm not sure if Java has this, but it might have a method on the rectangle object called .intersects() so you'd do if(rectangle1.intersectS(rectangle2) to check to see if an object has collided with another.
Otherwise you can get the x and y co-ordinates of the boxes and using the height/width of them detect whether they've intersected yourself.
Anyway, you can use that to either do an event on intersection (make one explode, or whatever) or prevent the movement from being drawn. (revert to previous co-ordinates)
edit: here we go
boolean
intersects(Rectangle r)
Determines whether or not this Rectangle and the specified
Rectangle intersect.
So I would do (and don't paste this code, it most likely won't work, not done java for a long time and I didn't do graphics when I did use it.)
Rectangle rect1 = new Rectangle(player.x, player.y, player.width, player.height);
Rectangle rect2 = new Rectangle(enemy.x, enemy.y, enemy.width, enemy.height);
//detects when the two rectangles hit
if(rect1.intersects(rect2))
{
System.out.println("game over, g");
}
obviously you'd need to fit that in somewhere.
No need to use rectangles ... compare the coordinates of 2 players constantly.
like
if(x1===x&&y1==y)
remember to increase the range of x when ur comparing.
if ur rectangle width is 30 take as if (x1>x&&x2>x+30)..likewise y
It's Java code for collision of two or more ImageViews not rectangles or other,use ImageViews Instead.
1.This code of Collision works every where in any views or layouts.
2.Add a timer to repeat it and to detect collision repeatedly.
3.It only works with views and layout.
if ((getLocationX(_v1) > (getLocationX(_v2) - ((_w2*3) + 40))) && (getLocationX(_v1) < (getLocationX(_v2) + ((_w2*3) +40)))){
if ((getLocationY(_v1) > (getLocationY(_v2) - ((_h2*3) + 40))) && (getLocationY(_v1) < (getLocationY(_v2) + ((_h2*3) +40)))){
showMessage("Collided");
}
}

Categories

Resources