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;
}
}
}
Related
I made a bouncing ball code, and so far as the bouncing itself the code works perfectly. I then created a second ball, and it also does what it's supposed to do. However, when I try to use an if condition to make the two balls bounce off one another as well as the edges, it doesn't work. Either they don't move or they just don't collide, and go through each other. This code was made in processing. Can anyone help me make ball1 and ball2 collide?
Moving ball1;
Moving ball2;
void setup(){
size(600,600);
ball1 = new Moving();
ball2 = new Moving();
}
void draw(){
background(255);
ball1.move();
ball1.display();
ball1.bounce();
ball2.move();
ball2.display();
ball2.bounce();
ball1.clash();
ball2.clash();
}
class Moving {
float speed = 7;
float x = random(0, width);
float y= random(0, height);
float xdirection = 1;
float ydirection = 1;
float ball_size = 50;
float radius = ball_size/2;
Moving() {
}
void move() {
x = x + (xdirection * speed);
y = y + (ydirection* speed);
}
void display() {
noStroke();
fill(50, 0, 50);
circle(x, y, ball_size);
}
void bounce() {
if ((x >= width - radius) || (x <= radius)) {
xdirection = xdirection * -1;
}
if ((y >= height - radius)|| (y<=radius)) {
ydirection = ydirection * -1;
}
}
void clash() {
if ((ball1.y+radius == ball2.y+radius) && (ball1.x+radius == ball2.x+radius)) {
ball1.ydirection = ball1.ydirection * -1;
ball2.ydirection = ball2.ydirection * -1;
ball1.xdirection = ball1.xdirection * -1;
ball2.xdirection = ball2.xdirection * -1;
x = x + (xdirection * speed);
y = y + (ydirection* speed);
if (ball1.x+radius == ball2.x+radius) {
xdirection = xdirection * -1;
}
}
}
}
When I run the code it generates 16 rectangles with a random size, random position, and a random color. It is then supposed to turn white if it is colliding with another rectangle. Most of the time it works fine but every so often rectangles turn white when they are not colliding with anything.
Main
int boxCount = 16;
Box[] boxes = new Box[boxCount];
void setup(){
size(500, 500);
for(int i = 0; i < boxCount; i++){
boxes[i] = new Box(random(50, width - 50), random(50, height - 50), random(20, 50), random(20, 50), color(random(0, 255), random(0, 255), random(0, 255)));
}
}
void draw(){
for(int i = 0; i < boxCount; i++){
boxes[i].create();
for(int x = 0; x < boxCount; x++){
if(boxes[i] != boxes[x]){
boxes[i].collide(boxes[x]);
}
}
}
}
Class
class Box{
float x;
float y;
float w;
float h;
color c;
Box(float _x, float _y, float _w, float _h, color _c){
x = _x;
y = _y;
w = _w;
h = _h;
c = _c;
}
void create(){
fill(c);
rect(x, y, w, h);
}
void collide(Box o){
float right = x + (w / 2);
float left = x - (w / 2);
float top = y - (h / 2);
float bottom = y + (h / 2);
float oRight = o.x + (o.w / 2);
float oLeft = o.x - (o.w / 2);
float oTop = o.y - (o.h / 2);
float oBottom = o.y + (o.h / 2);
if(right > oLeft && left < oRight && bottom > oTop && top < oBottom){
c = color(255, 255, 255);
}
}
}
rect doesn't draw a rectangle around center point, by default the rectangle is drawn at a top left position (x, y) with a size (with, height).
You've 2 possibilities to solve the issue:
Either change the collision detection method:
class Box{
// [...]
void collide(Box o){
if(x < o.x+o.w && o.x < x+w && y < o.y+o.h && o.y < y+h){
c = color(255, 255, 255);
}
}
}
Or set the CENTER rectMode(), which will cause the rectangle to be drawn as you expect it:
class Box{
// [...]
void create(){
fill(c);
rectMode(CENTER);
rect(x, y, w, h);
}
// [...]
}
I just made a code with a bouncing ball. It works fine but, it doesn't slow down. What I want is to put a fricition (20%) and every time when the ball bounces on the edge, it should slow down (0.2%) till it stops and turn black.
My Code:
float posX = 300;
float posY = 200;
float speedY= 2;
float speedX = 5;
float ballsize = 25;
float damping = 0.2;
color red = color(255,0,0);
color green = color(0,255,0);
color black = color(0);
color ballcolor;
void setup() {
size(600, 400);
background(191);
surface.setTitle("ball");
surface.setLocation((displayWidth-width)>>1, (displayHeight-height)>>1);
}
void draw() {
background(191);
posX = posX + speedX;
posY = posY + speedY;
if (posX > width) {
speedX = speedX* -1;
ballcolor = (ballcolor == red ? green : red);
}
if (posX < 0) {
speedX = speedX* -1;
ballcolor = (ballcolor == red ? green : red);
}
if (posY > height) {
speedY= speedY* -1;
ballcolor = (ballcolor == red ? green : red);
}
if (posY < 0) {
speedY= speedY* -1;
ballcolor = (ballcolor == red ? green : red);
}
if (abs(speedY) < 0.1 && abs(speedX) < 0.1) {
speedX = 0;
speedY = 0;
}
fill(ballcolor);
ellipse(posX, posY, ballsize, ballsize);
}
I've created a bouncing balls animation, that's drawn on a surface (library from my university) that has 2 frames in it, and 2 arrays of balls that half goes to the first frame and the second to the second frame.
For some reason - the balls pass through to y and x axis of their frame.
I've already tried doing some of the solutions that were suggested (like here) and it didn't help..
my code:
public static void updateBalVelocity(Ball ball, int width, int height,
int minWidth, int minHeight) {
// get default value of the dx and dy
double dx = ball.getVelocity().getDx();
double dy = ball.getVelocity().getDy();
// check if the ball is touching the border (x/y axis) and if so -
// change it's directions
if ((ball.getX() + ball.getSize() + dx) >= width) {
dx = (dx > 0) ? -dx : dx;
} else if ((ball.getX() - ball.getSize()) <= minWidth) {
dx = Math.abs(dx);
}
if ((ball.getY() + ball.getSize() + dy) >= height) {
dy = (dy > 0) ? -dy : dy;
} else if ((ball.getY() - ball.getSize()) <= minHeight) {
dy = Math.abs(dy);
}
// apply the velocity to the ball
ball.setVelocity(dx, dy);
}
public static void moveBalls(Ball[] balls, DrawSurface d, int height,
int width, int minHeight, int minWidth) {
for (Ball ball : balls) {
updateBalVelocity(ball, width, height, minWidth, minHeight);
ball.moveOneStep();
d.setColor(ball.getColor());
d.fillCircle(ball.getX(), ball.getY(), ball.getSize());
ball.drawOn(d);
}
}
and in the run method:
while (true) {
...
// move balls
BouncingBallHelper.moveBalls(ballsD1, d, 500, 500, 50, 50);
BouncingBallHelper.moveBalls(ballsD2, d, 600, 600, 450, 450);
gui.show(d);
// wait for 50 milliseconds.
sleeper.sleepFor(50);
}
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.