Java bouncing ball - java

I'm doing this bouncing ball problem and I have was given this formula: (velocity) vx = v0*cos(angle). and (x-position) x = v0*cos(angle)*t. However, I cannot get the ball to bounce properly.
The problem is that after the ball hits the right vertical wall, it starts to bounce inside certain range on the right-hand-side of the window. (y and vy shouldn't matter in this case.)
How can I fix this weird bouncing problem to make it bounce property in the x direction?
public class GamePanel2 extends JPanel implements KeyListener, ActionListener{
Timer tm = new Timer(60, this); //this refers to the ActionListener
public int score = 0;
public GamePanel2(){
addKeyListener(this);
setFocusable(true);
setBackground(Color.BLACK);
}
public int getScore() {
return score;
}
public double v0 = 100;
public double t = 0;
public double angle = Math.PI/2.5;
public double x = 0;
public double y = 0;
public double vx =0;
public double vy = 0;
public int move = 0;
public int paddlex =0;
public void paintComponent(Graphics g){
int h = getHeight();
int w = getWidth();
vx = v0*Math.cos(angle);
vy = v0*Math.sin(angle);
Graphics2D g2d = (Graphics2D)g;
g2d.translate(0.0,h);
g2d.scale(1.0, -1.0);
//ball
g2d.setColor(Color.GREEN);
g2d.fillOval((int)Math.round(x), (int)Math.round(y+6), 20, 20);
//paddle
g2d.setColor(Color.RED);
g2d.fillRect(paddlex + move, 0, 60, 6);
repaint();
}
//KeyListener methods
#Override
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyCode() == KeyEvent.VK_SPACE){
tm.start();
}
else if(arg0.getKeyCode()==KeyEvent.VK_ESCAPE){
tm.stop();
}
if(arg0.getKeyCode() == KeyEvent.VK_RIGHT){
move += 30;
}
//if pressed right key
if(arg0.getKeyCode() == KeyEvent.VK_LEFT){
move -= 30;
}
repaint();
}
#Override
public void keyReleased(KeyEvent arg0) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
#Override
public void actionPerformed(ActionEvent arg0) {
t = 0.2;
vy -= 9.8;
x += vx;
y += (vy)*t-(t*t*9.8)*0.5;
if( x<= 0){
vx = v0*Math.cos(angle);
}
if (x>=getWidth()-20){
vx =-(v0*Math.cos(angle));
}
repaint();
}
}

You're not even close. The differential equations of motion for a ball with gravity supplying the only force are
d^2x/dt^2 = -9.8 and d^2x/dt^2 = 0
You need to integrate these equations. For this purpose, you need to get rid of the second degree differentials by introducing a new variable:
dv_y/dt = -9.8 and dv_x/dt = 0
dy/dt = v_y dx/dt = v_x
With Euler forward differences (the simplest possible integration method), this becomes:
v_y[i+i] = v_y[i] + h * -9.8
y[i+1] = y[i] + h * v_y[i]
v_x[i+1] = v_x[i] + h * 0 // x-velocity is constant!
x[i+1] = x[i] + h * v_x[i]
When the ball encounters a vertical wall with a perfectly elastic collision, the x velocity instantly changes sign. When it hits the floor or ceiling, the y velocity changes sign.
Your formula provides only the initial values of v_x and v_y. All x and y values after are results of the above Euler equations. In pseudocode it will look something like this:
// Initialize the velocity components.
vx = v0 * cos(theta)
vy = v0 * sin(theta)
// Initialize the position of the ball.
x = R // in the corner of the first quadrant
y = R
// Choose a time increment.
h = < a very small number of seconds >
// Start the clock.
t = 0
while (t < END_OF_SIMULATION) {
draw_ball(x,y)
x = x + h * vx;
y = y + h * vy;
vy = vy - h * 9.8;
// Check for bounces
// Assumes box has corners (0,0), (W,H)
if ((vx < 0 and x < r) or (vx > 0 && x > W-r)) x = -x;
if ((vy < 0 and y < r) or (vy > 0 && y > H-r)) y = -y;
t = t + h
}
Note that that 9.8 means that the units are meters and seconds. You need to scale pixels in the Java window and use a timer to get a realistic result.
To roughly simulate lossy collision, you can steal some velocity on every bounce:
x = -<a number a bit less than 1.0> * x and
y = -<a number a bit less than 1.0> * y
With these, the ball will slow down a bit every time it hits a wall.

I can't find where you're changing the angle after detecting a bounce. I also don't see bounds checking for all four sides of the windows the ball is in.
There's a related bug you might run into where there's a double bounce in a corner that leaves the ball outside the window after all the calculations are done. Think about ways to handle that case.

Related

Change color on every 3rd bounce

I'm using Processing;
I have a ball that bounces when it hits the border and changes its color to random. Now I need this ball to change its color on every third bounce. Can't figure out how to do it.
Here is my current code:
float xPos;// x-position
float vx;// speed in x-direction
float yPos;// y-position
float vy;// speed in y-direction
float r;
float g;
float b;
void setup()
{
size(400, 300);
fill(255, 177, 8);
textSize(48);
// Initialise xPos to center of sketch
xPos = width / 2;
// Set speed in x-direction to -2 (moving left)
vx = -2;
yPos = height / 2;
vy = -1;
}
void draw()
{
r = random(255);
b = random(255);
g = random(255);
background(64);
yPos = yPos + vy;
// Change x-position on each redraw
xPos = xPos + vx;
ellipse(xPos, yPos, 50, 50);
if (xPos <= 0)
{
vx = 2;
fill(r, g, b);
} else if (xPos >= 400)
{
vx = -2;
fill(r, g, b);
}
if (yPos <= 0)
{
vy = 1;
fill(r, g, b);
} else if (yPos >= 300)
{
vy = -1;
fill(r, g, b);
}
}
It is quite easy. You maintain a counter which counts the amount of bounces. Therefore you increase the counter by one after every bounce. If it reaches 3 you change the color. After that you reset the counter and repeat.
Therefore add this member variable to your class (like you already did with xPos and others):
private int bounceCounter = 0;
which introduces the variable bounceCounter initially holding 0 as value.
Here is the modified draw method with highlighted changes and comments:
void draw() {
// New color to use if ball bounces
r = random(255);
b = random(255);
g = random(255);
background(64);
yPos = yPos + vy;
// Change x-position on each redraw
xPos = xPos + vx;
ellipse(xPos, yPos, 50, 50);
// Variable indicating whether the ball bounced or not
boolean bounced = false;
// Out of bounds: left
if (xPos <= 0) {
vx = 2;
bounced = true;
// Out of bounds: right
} else if (xPos >= 400) {
vx = -2;
bounced = true;
}
// Out of bounds: bottom
if (yPos <= 0) {
vy = 1;
bounced = true;
// Out of bounds: top
} else if (yPos >= 300) {
vy = -1;
bounced = true;
}
// React to bounce if bounced
if (bounced) {
// Increase bounce-counter by one
bounceCounter++;
// Third bounce occurred
if (bounceCounter == 3) {
// Change the color
fill(r, g, b);
// Reset the counter
bounceCounter = 0;
}
}
}

Trying to do a simple Jump

I'm trying to learn how to make a 2D Game without Game Engines, anyways I already created a background scrolling right now my goal is to make my character jump. But the thing is whenever I start my app the character is spinning up and down and it will just go away to the background.
Here's my character code
public class Deer extends GameCharacter {
private Bitmap spritesheet;
private double dya;
private boolean playing;
private long startTime;
private boolean Jump;
private Animate Animation = new Animate();
public Deer(Bitmap res, int w, int h, int numFrames) {
x = 20;
y = 400;
dy = 0;
height = h;
width = w;
Bitmap[] image = new Bitmap[numFrames];
spritesheet = res;
for (int i = 0; i < image.length; i++)
{
image[i] = Bitmap.createBitmap(spritesheet, i*width, 0, width, height);
}
Animation.setFrames(image);
Animation.setDelay(10);
startTime = System.nanoTime();
}
public void setJump(boolean b){
Jump = b;
}
public void update()
{
long elapsed = (System.nanoTime()-startTime)/1000000;
if(elapsed>100)
{
}
Animation.update();
if(Jump){
dy = (int)(dya+=5.5);
}
else{
dy = (int)(dya+=5.5);
}
if(dy>14)dy = 14;
if(dy>14)dy = -14;
y += dy*2;
dy = 0;
}
public void draw(Canvas canvas)
{
canvas.drawBitmap(Animation.getImage(),x,y,null);
}
public boolean getPlaying(){return playing;}
public void setPlaying(boolean b){playing = b;}
public void resetDYA(){dya = 0;}
}
x - character's horizontal position
y - character's vertical position
dx - character's horizontal acceleration
dy - character's vertical acceleration
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_DOWN) {
if(!deer.getPlaying()) {
deer.setPlaying(true);
}
deer.setJump(true);
return true;
}
return super.onTouchEvent(event);
}
I can't say for sure if this is the only problem because you have other suspicious code but it looks like you jump no matter what.
if(Jump){
dy = (int)(dya+=5.5);
} else {
dy = (int)(dya+=5.5);
}
If Jump is true you set the vertical acceleration. But you also set the vertical acceleration to the same value if Jump is false. You also don't show in your code where Jump is ever set to false.
Another odd bit of code is:
if(dy>14)dy = 14;
if(dy>14)dy = -14;
Here, if dy>14 you set it to 14. Then you check dy>14 immediately after. Of course, this time it's false. But because those two conditions are the same the second one will never pass since the one before it ensures it won't. The only other option is they both fail. IOW, you'll never be able to enter the second if.
All that aside, I'm not sure why you're taking this approach. You can simply rely on physics equations with constant acceleration, give an initial velocity, check for a collision with the ground (or at least the original height), and just let it run. For example:
// These are the variables you need.
int x = 200, y0 = 0, y = 0, velocity = 15;
double t = 0.0, gravity = -9.8;
// This is the statement that should run when you update the GUI.
// It is the fundamental equation for motion with constant acceleration.
// The acceleration is the gravitational constant.
y = (int) (y0 + velocity * t + .5 * gravity * t * t);
if (y < 0) {
y = y0 = 0;
//Stop jumping!
Jump = false;
} else {
// Swap the y values.
y0 = y;
// Increase the time with the frame rate.
t += frameRate;
}
// Draw the character using the y value
The best part about this is you don't need to worry about when you get to the maximum height because the equation will automatically bring you down. It also looks more natural as if the mechanics are real. Try it out.
A simple Swing example that you can play around with. Note that the values are different to deal with the way the components are drawn to the screen. Normally, you would deal with that with transformations but this will do for the task.
public class Main {
static Timer timer;
Main() {
JFrame frame = new JFrame("Hello sample");
frame.setSize(new Dimension(550, 550));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel panel = new MyPanel();
frame.add(panel);
frame.setVisible(true);
timer = new Timer(5, (e) -> panel.repaint());
timer.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(Main::new);
}
class MyPanel extends JPanel {
int x = 200, y0 = 300, y = 0, w = 200, h = 200, v = -8;
double t = 0.0, gravity = 9.8;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.RED);
y = (int) (y0 + v * t + .5 * gravity * t * t);
if (y > 300) {
y = y0 = 300;
// To prevent it from stopping comment the timer.stop() and
// uncomment the t = 0.0 statements.
//t = 0.0;
timer.stop();
} else {
y0 = y;
t += .025;
}
g.drawOval(x, y, w, h);
}
}
}

What is an efficient way to stop a thread indefinitely?

Right now, I am currently making a marbles game where two players try and shoot their marbles into a circle. The player with more marbles in the circle wins.
The player whose turn it is will click and drag in the opposite direction of which they want the ball to move (sort of like a sling shot). In my Marble class, there is a thread which starts when the mouse click is released. The marble will move and bounce off the walls, slowly reaching a X and Y velocity of zero.
When this happens though, my thread continues looping and eating through the computers CPU.
You can tell that the thread is still running because it continues printing out the velocity even when the ball has stopped moving.
I need help trying to figure out a efficient way of stopping the thread without using the Thread class's stop() method.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Ball
{
float x, y, lastX, lastY;
int width, height;
float xVelocity, yVelocity;
float speed;
public Ball()
{
width = (int) (Math.random() * 50 + 10);
height = (int) (Math.random() * 50 + 10);
x = (float) (Math.random() * (Marble.gamePanel.getWidth() - width) + width/2);
y = (float) (Math.random() * (Marble.gamePanel.getHeight() - height) + height/2);
lastX = x;
lastY = y;
xVelocity = (float) Math.random() * speed*2 - speed;
yVelocity = (float) Math.random() * speed*2 - speed;
}
public void update()
{
lastX = x;
lastY = y;
x += xVelocity;
y += yVelocity;
if(x + width/2 >= Marble.gamePanel.getWidth())
{
xVelocity *= -0.75;
x = Marble.gamePanel.getWidth() - width/2;
}
else if (x - width/2 <= 0)
{
xVelocity *= -0.75;
x = width/2;
}
if (y + height/2 >= Marble.gamePanel.getHeight())
{
yVelocity *= -0.75;
y = Marble.gamePanel.getHeight() - height/2;
}
else if (y - height/2 <= 0)
{
yVelocity *= -0.75;
y = height/2;
}
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
/**
* Write a description of class Marble here.
*
* #author (Ryan Lawes)
* #version (5-23-14)
*/
public class Marble extends JFrame implements MouseListener, MouseMotionListener
{
public static GamePanel gamePanel = new GamePanel();
private boolean running = false;
private int fps = 60;
private int frameCount = 0;
private int mouseXC;//X coordinate of where the mouse was clicked
private int mouseYC;//Y coordinate of where the mouse was clicked
private int mouseXR;//X coordinatte of where the mouse was released
private int mouseYR;//Y coordinatte of where the mouse was released
public Marble()
{
super("Fixed Timestep Game Loop Test");
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
JPanel p = new JPanel();
p.setLayout(new GridLayout(1,2));
cp.add(gamePanel, BorderLayout.CENTER);
cp.add(p, BorderLayout.SOUTH);
setSize(500, 500);
addMouseListener(this);
addMouseMotionListener(this);
}
public static void main(String[]args)
{
Marble mrb = new Marble();
mrb.setVisible(true);
}
//Starts a new thread and runs the game loop in it.
public void runGameLoop()
{
Thread loop = new Thread()
{
public void run()
{
gameLoop();
}
};
loop.start();
}
//Only run this in another Thread!
private void gameLoop()
{
//This value would probably be stored elsewhere.
final double GAME_HERTZ = 30.0;
//Calculate how many ns each frame should take for our target game hertz.
final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
//At the very most we will update the game this many times before a new render.
//If you're worried about visual hitches more than perfect timing, set this to 1.
final int MAX_UPDATES_BEFORE_RENDER = 5;
//We will need the last update time.
double lastUpdateTime = System.nanoTime();
//Store the last time we rendered.
double lastRenderTime = System.nanoTime();
//If we are able to get as high as this FPS, don't render again.
final double TARGET_FPS = 60;
final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;
//Simple way of finding FPS.
int lastSecondTime = (int) (lastUpdateTime / 1000000000);
while(running)
{
double now = System.nanoTime();
int updateCount = 0;
//Do as many game updates as we need to, potentially playing catchup.
while(now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER)
{
gamePanel.update();
lastUpdateTime += TIME_BETWEEN_UPDATES;
updateCount++;
}
//If for some reason an update takes forever, we don't want to do an insane number of catchups.
//If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
if(now - lastUpdateTime > TIME_BETWEEN_UPDATES)
{
lastUpdateTime = now - TIME_BETWEEN_UPDATES;
}
//Render. To do so, we need to calculate interpolation for a smooth render.
float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES));
drawGame(interpolation);
lastRenderTime = now;
//Update the frames we got.
int thisSecond = (int) (lastUpdateTime / 1000000000);
}
//////if(gamePanel.ballXVel == 0 && gamePanel.ballYVel == 0)
//////{
////// running = !running;
//////}
}
private void drawGame(float interpolation)
{
gamePanel.setInterpolation(interpolation);
gamePanel.repaint();
}
public void mouseClicked(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
/**
* I want to make it so you have to wait until the marble is done rolling before you can click again
*/
mouseXC = (int) e.getPoint().getX();
mouseYC = (int) e.getPoint().getY();
}
public void mouseReleased(MouseEvent e)
{
mouseXR = (int) e.getPoint().getX();
mouseYR = (int) e.getPoint().getY();
gamePanel.ballXVel = (mouseXC - mouseXR)/2;
gamePanel.ballYVel = (mouseYC - mouseYR)/2;
//////////while(gamePanel.ballXVel != 0 && gamePanel.ballYVel != 0)
//////////{
running = !running;
runGameLoop();
////////}
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
public void mouseDragged(MouseEvent e)
{
}
public void mouseMoved(MouseEvent e)
{
}
}
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class GamePanel extends JPanel
{
float interpolation;
float ballX, ballY, lastBallX, lastBallY;
int ballWidth, ballHeight;
float ballXVel, ballYVel;
int lastDrawX, lastDrawY;
int ballSpeed = 10;
public GamePanel()
{
ballX = lastBallX = 100;
ballY = lastBallY = 100;
ballWidth = 25;
ballHeight = 25;
}
public void setInterpolation(float interp)
{
interpolation = interp;
}
public void update()
{
lastBallX = ballX;
lastBallY = ballY;
ballX += ballXVel;
ballY += ballYVel;
//Slowly decreases the ball's velocity
ballXVel *= 0.975;
ballYVel *= 0.975;
//Prints out the velocity
//////////if(ballXVel > 0.3 && ballYVel > 0.3)
//////////{
System.out.println(ballXVel);
System.out.println(ballYVel);
//////////}
//If the ball is at a slow enough velocity, it will stop moving alltogether
if(ballXVel > 0 && ballYVel > 0)//if x and y velocity are positive
{
if(ballXVel < 0.3 && ballYVel < 0.3)
{
ballXVel = 0;
ballYVel = 0;
}
}
if(ballXVel < 0 && ballYVel < 0)//if x and y velocity are negative
{
ballXVel *=-1;//Changes to a positive number so it is easier to check
ballYVel *=-1;//Changes to a positive number so it is easier to check
if(ballXVel < 0.3 && ballYVel < 0.3)
{
ballXVel = 0;
ballYVel = 0;
}
ballXVel *=-1;//Changes the velocity back if it doesn't get set to 0. Even if it does, 0*-1 is still 0
ballYVel *=-1;//Changes the velocity back if it doesn't get set to 0. Even if it does, 0*-1 is still 0
}
if(ballXVel < 0 && ballYVel > 0)//if x velocity is negative and y velocity is positive
{
ballXVel *=-1;//Changes to a positive number so it is easier to check
if(ballXVel < 0.3 && ballYVel < 0.3)
{
ballXVel = 0;
ballYVel = 0;
}
ballXVel *=-1;//Changes the velocity back if it doesn't get set to 0. Even if it does, 0*-1 is still 0
}
if(ballXVel > 0 && ballYVel < 0)//if x velocity is positive and y velocity is negative
{
ballYVel *=-1;//Changes to a positive number so it is easier to check
if(ballXVel < 0.3 && ballYVel < 0.3)
{
ballXVel = 0;
ballYVel = 0;
}
ballYVel *=-1;//Changes the velocity back if it doesn't get set to 0. Even if it does, 0*-1 is still 0
}
if(ballX + ballWidth/2 >= getWidth())
{
ballXVel *= -0.8;
ballX = getWidth() - ballWidth/2;
}
else if(ballX - ballWidth/2 <= 0)
{
ballXVel *= -0.8;
ballX = ballWidth/2;
}
if(ballY + ballHeight/2 >= getHeight())
{
ballYVel *= -0.8;
ballY = getHeight() - ballHeight/2;
}
else if(ballY - ballHeight/2 <= 0)
{
ballYVel *= -0.8;
ballY = ballHeight/2;
}
}
public void paintComponent(Graphics g)
{
//BS way of clearing out the old rectangle to save CPU.
g.setColor(getBackground());
g.fillRect(lastDrawX-1, lastDrawY-1, ballWidth+2, ballHeight+2);
g.setColor(Color.RED);
int drawX = (int) ((ballX - lastBallX) * interpolation + lastBallX - ballWidth/2);
int drawY = (int) ((ballY - lastBallY) * interpolation + lastBallY - ballHeight/2);
g.fillOval(drawX, drawY, ballWidth, ballHeight);
lastDrawX = drawX;
lastDrawY = drawY;
g.setColor(Color.BLACK);
}
}
The code you have commented:
//////if(gamePanel.ballXVel == 0 && gamePanel.ballYVel == 0)
//////{
////// running = !running;
//////}
Put it inside the while(running) loop like:
float EPSILON = 0.00000001f;
if(Math.abs(gamePanel.ballXVel - 0.0f) < EPSILON && Math.abs(gamePanel.ballYVel - 0.0f) < EPSILON)
{
running = false;
}
You have put it outside the while loop. The interpreter will never reach the code because running=true;
EDIT :
I tested the solution myself, it worked. See:
I suggest you change your gamePanel.update() method to return a boolean value, indicating if the marvel is still moving.
You can then use the result of that method to break out of the loop once the marvel has stopped.
In GamePanel#update() something like that.
final float epsilon = 0.00001f;
return (Math.abs(ballXVel) < epsilon) && (Math.abs(ballXVel) < epsilon);
And in Marble#gameLoop something like that:
running = !gamePanel.update();

Random double Generator for a new position [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a code that replicates a gravitational pull towards my mouse cursor when entered in the parameters. When the mouse is click, it creates a reverse effect pushing objects(Rectangle away from it). I am trying to set it so when you do click and hold, when the objects hit a certain number in the x or y coordinate, it will randomly change x and y of that object. Here is my code. The commented area is where I tried to make x and y go random when it hits 500 parameters.
import java.awt.*;
import java.util.Random;
public class Ball
{
private Color col;
private double x, y; // location
private double vx, vy; // velocity
public Ball(int new_x, int new_y, int new_vx, int new_vy)
{
x = new_x;
y = new_y;
vx = new_vx;
vy = new_vy;
}
public Ball()
{
Random gen = new Random();
x = gen.nextInt(480);
y = gen.nextInt(480);
vx = gen.nextInt(10);
vy = gen.nextInt(10);
col = new Color(gen.nextInt(255),gen.nextInt(255),gen.nextInt(255));
}
void paint( Graphics h)
{
h.setColor(col);
h.fillRect((int)x,(int)y,20,20);
}
void move(int currentX, int currentY, boolean isButtonPressed )
{
double dvx, dvy, rx, ry;
double r_mag;
x = x + vx;
y = y + vy;
//bounce
if (x > 480 || x < 0)
vx = -vx;
if (y > 480 || y < 0)
vy = -vy;
if ( currentX <500 && currentY <500) // mouse is on canvas, apply "gravity"
{
rx = currentX - x;
ry = currentY - y;
r_mag = Math.sqrt((rx*rx) + (ry*ry));
// if ( x = 500 || y = 500)
// Random x = new Random();
// x.nextDouble();
// Random y = new Random();
// y.nextDouble();
if (r_mag < 1)
r_mag = 1;
dvx = (rx / r_mag);
dvy = (ry / r_mag);
if (isButtonPressed)
{
vx = vx - dvx; // + makes balls move to cursor.
vy = vy - dvy; // - makes balls move away from cursor.
}
else
{
vx = vx + dvx; // + makes balls move to cursor.
vy = vy + dvy; // - makes balls move away from cursor.
}
}
// reduce speed slowly
vx = .99*vx;
vy = .99*vy;
}
}
The commented area is where I tried to make x and y go random when it hits 500 parameters.
So when x or y reaches 500, you want to randomly relocate the object?
Instead of
// if ( x = 500 || y = 500)
this is assignment, not comparison
// Random x = new Random();
redeclares x, not what you want
// x.nextDouble();
statement without effect
// Random y = new Random();
// y.nextDouble();
see above
you could use Math.random(), as in
if (x == 500 || y == 500) {
x = Math.random()*480;
y = Math.random()*480;
}
(note: Math.random() returns a double in the half-open interval [0,1), so you have to scale it; the scaling factor of 480 I used is a guess), or (less good, IMO) create a new Random instance each time you enter the if.
But,
x, y, and the velocities vx and vy are doubles, so it is very unlikely that the movements let x or y become exactly 500, so you should probably test for >= rather than == in the condition.
In the code, you flip the velocity when either coordinate passes 480, so getting to 500 or farther is difficult and can only be achieved by judicious acceleration using the mouse, so a smaller threshold may be wanted.

Circular Movement Image in JAVA

I want an circular movement of an image in JAVA, i thought I have the solution but it doesn't work and i'm a bit clueless now.
For calculating the points it needs to go im using pythagoras to calculate the height (point B).
if it does one round im satisfied but more rounds would be cool.
The image size is around 500 x 300 pixels.
Here's my code :
package vogel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
public class Vogel extends Component {
private int x;
private int r;
private int b;
BufferedImage img;
public vogel() {
try {
img = ImageIO.read(new File("F:/JAVA/workspace/School/src/vogel/vogel.png"));
} catch (IOException e) {
}
r = 60;
x = 10;
}
#Override
public void paint(Graphics g) {
for(int i = -x; i <= x; i++) {
b = (int)Math.sqrt(r^2 - i^2);
g.drawImage(img, x, b, this);
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Vogel");
f.setSize(1000,1000);
f.add(new Vogel());
f.setVisible(true);
for (int number = 1; number <= 1500000; number++) {
f.repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {}
}
}
}
Using your loop in the paint(Graphics) method, it draws 21 birds with one repaint.
You should do it with an angle stored in an object variable and use the Math.sin() and Math.cos() function calculate the x and y position. The angle should be increased with every repaint().
To add:
// To control the radius of moving
private final double MAX_X = 200;
private final double MAX_Y = 200;
private double angle = 0;
#Override
public void paint(Graphics g) {
// increase angle (should be a double value)
angle += 0.1;
// rotate around P(0/0), assuming that 0° is vector (1/0)
int x = (int) (Math.cos(angle) * MAX_X);
int y = (int) (Math.sin(angle) * MAX_Y);
// move P to center of JFrame (width and height = 1000)
x += 500;
y += 500;
// image is 500x300, calc upper left corner
x -= 250;
y -= 150;
// draw
g.drawImage(img, x, y, null);
}
To remove:
private double x, b, r;
So this is the code, try it.
Addition to Sibbo's code to convert angle to rads
private double angle = 0.1;
#Override
public void paint(Graphics g) {
// increase angle (should be a double value
double random = angle * 2.0 * Math.PI/360.0; //this will convert it to rads
// rotate around P(0/0)
int x = (int) (Math.cos(random) * MAX_X);
int y = (int) (Math.sin(random) * MAX_Y);
// move P to center of JFrame (width and height = 1000)
x += 500;
y += 500;
// image is 500x300, calc upper left corner
x -= 250;
y -= 150;
angle++
// draw
g.drawImage(img, x, y, null);
}

Categories

Resources