Using Dr.Java, want to know how to make an item bounce - java

So I have a program that I'm trying to create for a class, and I need to create a country scene with a farm and a sun. The sun has to bounce up and down. The current problem I'm facing is that the sun keeps going down, and won't bounce up. Here is my code:
import javax.swing.*;
import java.awt.*;
/**
* Date: Oct 14, 2016
* Author:
* Description: Shows a country side with a farm and a sun bouncing up and down.
*/
public class WeAreInThePictures extends JFrame
{
ImageIcon sun, farm, bG; //assigns sun, farm and background to an image variable
static int x = 0, y = -50; //starting position of the sun
static int ySpeed = 10; //speed in y direction
static double delay = 1.0;
public WeAreInThePictures() {
super ("We Are In The Pictures!");
setSize (852, 480);
bG = new ImageIcon ("1.jpg");
sun = new ImageIcon ("sun.png");
farm = new ImageIcon ("farm.png");
setVisible (true);
}
public static void main(String[] args) {
new WeAreInThePictures ();
}
public void paint (Graphics g)
{
for (int i = 0; i < 1000; i++)
{
bG.paintIcon (this, g, 0, 0);
farm.paintIcon (this, g, 500, 50);
y = y + ySpeed;
if (ySpeed > 0)
{
sun.paintIcon (this, g, x, y);
for (int j = 0; j < 550000; j++)
{
delay = Math.pow (delay, 1);
}
}
else if (y > 50)
{
ySpeed = ySpeed - 1;
}
else if (y <= 0)
{
ySpeed = ySpeed - 1;
}
}
}
}
Can someone explain to me what is wrong, how i should fix it and why the problem is occurring?

Your problem is that you appear to have written this code without looking at any Swing Graphics tutorial or similar question on this site regarding Swing animation (why?). You're drawing directly in the JFrame, something that you shouldn't be doing, you've got object mutation code within a paint method, again something that you shouldn't be doing.
Instead do as you recommended in the tutorials, and most any other similar question on this site, in fact, search the problem before asking:
Draw in the paintComponent method of a JPanel that is displayed in a JFrame.
Use a Swing Timer for your animation loop
Change the speed's direction in the timer's ActionListener, not in a paintComponent method.

Related

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;
}

Random circles applet java

I am new to programming and trying to write a graphics program in java that displays ovals of different sizes and colors, however, I am not able to get the program to display the ovals in applet window. Does anyone have any suggestions/input on where I went wrong here? Please see an example of my paint method below:
public void paint(Graphics g)
{
for(int i=0; i<n; i++)
{
x[i] = (int)(600* Math.random() +1);
y[i] = (int)(600* Math.random() +1);
}
int c= (int)(255*Math.random()); //random foreground color
int a= (int)(255*Math.random());
int t= (int)(255*Math.random());
Color f = new Color(c,a,t);//variables have been declared in init
g.setColor(f);
g.fillOval(rand(0, 600), rand(0, 600), r = rand(5, 100), r);
sleep(100);
cnt += 1;
if(cnt >= 500) clearScreen();
else update(g);
}
I modified a recent school project (we were supposed to make a hot air balloon) so excuse the naming of some of the stuff:
import java.awt.*;
import javax.swing.*;
public class Balloon extends JComponent {
public static void main(String args[]){
JFrame frame = new JFrame("balloons");
frame.setSize(200,200);
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
Balloon balloon = new Balloon();
frame.setContentPane(balloon);
}
public void paint(Graphics g){
super.paint(g);
for(int i = 0; i<20; i++){
int c= (int)(255*random()); //random foreground color
int a= (int)(255*random());
int t= (int)(255*random());
g.setColor(new Color(c,a,t));
g.fillOval((int)(200*random()),(int)(200*random()),(int)(30*random()),(int)(30*random()));
}
}
public double random(){
return Math.random();
}
}
Its rather small at the moment so you may want to change around some of the variables... however it does what you asked.
In terms of where you went wrong... it appears you have a loop that put values into two arrays... however I don't see a second array that goes through and draws all the ovals... In my code, I generate all the coordinates, colours, and print it out all at once.

Issue with drawRect/fillRect from Swing Library (Images included)

Just started messing around with Swing for a class project GUI in Java. I'm trying to draw a game board, however, not a conventional one. I'm trying to draw one more like a parchessi board, so each board tile needs to have a specific location rather than a grid.
So far, I've run into this issue. In paint(), I'm trying to paint 5 rectangles, odd ones blue and empty, even ones red and filled in. However, instead of a nice checkered pattern, I get this:
Can anyone help me figure out why it's doing this?
Code:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Rectangles extends JPanel {
public static void main(String[] a) {
JFrame f = new JFrame();
f.setSize(800, 800);
f.add(new Rectangles());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public void paint(Graphics g) {
int x = 15;
int y = 15;
int w = 15;
int h = 15;
for(int i = 0; i < 5; i++){
if(i%2==0){
g.setColor(Color.RED);
g.fillRect (x, y, x+w, y+h);
}
else{
g.setColor(Color.BLUE);
g.drawRect (x, y, x+w, y+h);
}
x+=15;
System.out.println(Integer.toString(x) + ' ' + Integer.toString(y) + '|' + Integer.toString(w) + ' ' + Integer.toString(h));
}
}
}
Output from the Println statement(x,y,width,height):
30 15|15 15
45 15|15 15
60 15|15 15
75 15|15 15
90 15|15 15
It looked like there was overlap in the first image, so I modified the code and tried this:
for(int i = 0; i < 5; i++){
g.setColor(Color.BLUE);
g.drawRect (x, y, x+w, y+h);
x+=15;
}
Here's what happens with this code:
Why is there overlap? What causes this?
Also, does anyone know a good way to make an easily modifiable array of Rectangles? Or any good advice or tools for drawing that type of board?
Welcome to the reasons you should not break the paint chain...
Start by calling super.paint(g) as the first line of your paint method, before you do any custom painting.
A better solution would be to override paintComponent instead of paint, but still making sure you call super.paintComponent before you perform any custom painting...
Take a look at Performing Custom Painting and Painting in AWT and Swing for more details
Next, start reading the JavaDocs on Graphics#fillRect, you will see that the last two parameters represent the width and height, not the x/y position of the bottom corner
public class Rectangles extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = 15;
int y = 15;
int w = 15;
int h = 15;
for (int i = 0; i < 5; i++) {
if (i % 2 == 0) {
g.setColor(Color.RED);
g.fillRect(x, y, w, h);
} else {
g.setColor(Color.BLUE);
g.drawRect(x, y, w, h);
}
x += 15;
System.out.println(Integer.toString(x) + ' ' + Integer.toString(y) + '|' + Integer.toString(w) + ' ' + Integer.toString(h));
}
}
}

Bouncing Cube Program from The Office

I'm writing a program taken from the TV show, THE OFFICE, when they're sitting in the conference room and watching the bouncing DVD logo on the screen try to hit the corner. The square is supposed to change color when it hits an edge.
However, I'm running into a few issues.
Issue one: The Square sometimes bounces off an edge. Other times it sinks, and I can't figure out why.
Issue two: I'm not sure how to change the color of the square when it hits the edge.
Issue three: I'm trying to learn how to make a JFRAME fullscreen. And not just fullscreen on my screen but on anyone's.
THE CODE HAS BEEN POSTED TO AN ONLINE IDE FOR EASIER READING. That can be found HERE
Otherwise if you're too busy for that link. Here it is posted below.
import java.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BouncingMischievousSquare extends JPanel implements ActionListener {
private static final int SQUARE_SIZE = 40;
private static final int SPEED_OF_SQUARE = 6;
private int xPosit, yPosit;
private int xSpeed, ySpeed;
BouncingMischievousSquare(){
//speed direction
xSpeed = SPEED_OF_SQUARE;
ySpeed = -SPEED_OF_SQUARE;
//a timer for repaint
//http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
Timer timer = new Timer(100, this);
timer.start();
}
public void actionPerformed(ActionEvent e){
//Screensize
int width = getWidth();
int height = getHeight();
xPosit += xSpeed;
yPosit += ySpeed;
//test xAxis
if(xPosit < 0){
xPosit = 0;
xSpeed = SPEED_OF_SQUARE;
}
else if(xPosit > width - SQUARE_SIZE){
xPosit = width - SQUARE_SIZE;
xSpeed = -SPEED_OF_SQUARE;
}
if(yPosit < 0){
yPosit = 0;
ySpeed = SPEED_OF_SQUARE;
}
else if(yPosit > height - SQUARE_SIZE){
xPosit = height - SQUARE_SIZE;
xSpeed = -SPEED_OF_SQUARE;
}
//ask the computer gods to redraw the square
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(xPosit, yPosit, SQUARE_SIZE, SQUARE_SIZE );
}
}
MAIN CLASS
import javax.swing.*;
public class MischievousMain {
public static void main(String[] args) {
JFrame frame = new JFrame("Bouncing Cube");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// mischievous square input
frame.add(new BouncingMischievousSquare());
frame.setVisible(true);
}
}
Anyways, Thanks for taking the time to read through my code. It's appreciated. I'm really interested in different ways to go about this.
Issue one: The Square sometimes bounces off an edge. Other times it
sinks, and I can't figure out why.
You'll hate yourself for this, but
} else if (yPosit > height - SQUARE_SIZE) {
xPosit = height - SQUARE_SIZE;
xSpeed = -SPEED_OF_SQUARE;
}
Should be...
} else if (yPosit > height - SQUARE_SIZE) {
yPosit = height - SQUARE_SIZE;
ySpeed = -SPEED_OF_SQUARE;
}
You were using xPosyit and xSpeed instead of yPosyit and ySpeed...
Issue two: I'm not sure how to change the color of the square when it
hits the edge.
Basically, whenever you detect a edge collision and change direction, simple change the panel's foreground color to something else...
This might require you to have a list of colors from which you can randomly pick or simply randomly generate the color
Then in your paintComponent method, simple use g.setColor(getForeground()) before you fill the rect...
...ps...
To make life easier, you could just write a method that either generates a random color or sets the foreground to a random color, for example...
protected void randomiseColor() {
int red = (int) (Math.round(Math.random() * 255));
int green = (int) (Math.round(Math.random() * 255));
int blue = (int) (Math.round(Math.random() * 255));
setForeground(new Color(red, green, blue));
}
Issue three: I'm trying to learn how to make a JFRAME fullscreen. And
not just fullscreen on my screen but on anyone's.
Take a look at Full-Screen Exclusive Mode API

double casting not producing expected value [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I'm trying to use a double that has a very small value to produce one of a more regular size. For example, dividing 1/(double) would produce something like 14.12848572.... I then cast this double into an int to produce a number which I can use to draw an image in a JPanel.
The issue I've been having is that the image does not draw how I expect it to draw. I think this is because there's something I don't understand about how casting doubles works. Anyone who can tell me a bit about how this process actually goes down would be very helpful.
EDIT:
The purpose of this code is translating a monetary value into the size of a bar on a graph. The size of these bars should change as the value changes so that they utilize space in the most efficient manner.
Therefore...
Due to the nature of the monetary values, max will never be less than 430.
I want the image to be bigger the smaller xscale is. If there are fewer values to graph, xscale is smaller, and then the bars are drawn bigger.
EDIT:
The following image shows what my program is currently drawing. What I would like to draw is a series of bars on a bar graph. The xscale and associated variables are what I am primarily concerned with right now.
EDIT:
The SSCCE is completed (I think)! If you run this code, you will see the drawing I don't want. If you change barwidth to equal 7 or some normal int, you will see something that is more along the lines of what I want drawn. Please let me know if there is anything more I should do to make things easier!
EDIT: Copy/pasted wrong code, has been corrected (derp)
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class castingexample extends JPanel
{
private static int ypoint;
private static int barheight;
private static Color color;
private static int bars = 10;
private static int xpoint = 0;
private static int barwidth = 7;
private static double xscale = 7;
private static int yscaleplus = 10000;
private static int yscaleneg = 0;
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.add(new castingexample());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
}
public castingexample()
{
new Timer(100, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
resize();
repaint();
}
}).start();
}
public void resize()
{
xscale = bars/(800 - bars*5);
xscale = 1/xscale;
}
public void paintComponent (Graphics g)
{
super.paintComponent(g);
for (int i = 0; i < bars; i++)
{
barheight = 200;
barwidth = (int) (xscale);
ypoint = 450 - barheight;
xpoint = 105+(barwidth + 5)*i;
if(ypoint < 450)
color = Color.green;
else
color = Color.red;
g.setColor(color);
g.fillRect(xpoint, ypoint, barwidth, barheight);
}
}
}
Here's some relevant code:
public void resize()
{
int max = 0;
int min = 0;
for (int i = 0; i < bars; i++)
{
if (getTime(i) > max)
max = (int)getTime(i);
}
yscaleplus = max/430;
/*
for (int i = (int)(getLife() - getRetire() + 1); i < bars; i++)
{
if (getTime(i) < min)
min = (int)getTime(i);
}
yscaleneg = Math.abs(min/200);
*/
xscale = bars/(800 - bars*5);
xscale = 1/xscale;
}
public void paintComponent (Graphics g)
{
super.paintComponent(g);
g.drawLine(100, 20, 100, 630);
g.drawLine(100, 450, 900, 450);
for (int i = 0; i < bars; i++)
{
barheight = (int) (getTime(i)/yscaleplus);
barwidth = (int) (xscale);
ypoint = 450 - barheight;
xpoint = 105+(barwidth + 5)*i;
if(ypoint < 450)
color = Color.green;
else
color = Color.red;
g.setColor(color);
g.fillRect(xpoint, ypoint, barwidth, barheight);
}
}
doubles do not store information as you seem to think, they store information as a value followed by an exponential value of 2^x, this removes the capability you are trying to use
take a look at Math.round(x) instead.

Categories

Resources