i have to do an exercise of java swing.
draw a simple circle/ball (done)
move a circle (done)
from a starting point (half of jpanel(x),0(y)) move this circle/ball that follow an arch direction and bounce when the circle touch the end of screen side (in my case the window it's only x: 0-300 y: 0-300, it's a very little windows)
when the screen end (see picture that i have linked below) continue to bounce in arch movement following the sides of screen until ball return in initial position,no need to be exactly initial position but bounce must is infinite and continuosly(sorry for my english)
https://imgur.com/jNtxeld
what's the function that i need for doing an arch movement? i can't use graphic2d or existent class in java, i need function to apply for x,y for move this ball
i know arch formula from mathematic but i don't know how apply in java in this case, i think i need a function for get all points of a arch position and then i can apply to x and y for move the ball.
help
i have this code
public class Ani2 extends JPanel implements Runnable{
private final int DELAY =105;
public Ani2(){
JFrame jf = new JFrame();
jf.setSize(300,300);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.add(this);
jf.setVisible(true);
}
private Thread animator;
int x=150, y=150;
#Override
public void addNotify() {
super.addNotify();
animator = new Thread(this);
animator.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(red);
Graphics2D g2d = (Graphics2D)g;
g2d.fillOval(x,y, 20, 20);
g.dispose();
}
public static void main(String[] args) {
new Ani2();
}
#Override
public void run() {
long beforeTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
while (true) {
x += 1;
y -= 1;
repaint();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = DELAY - timeDiff;
if (sleep < 0)
sleep = 2;
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
beforeTime = System.currentTimeMillis();
}
}
}
I'm guessing that "arch function" means physics.
Imagine your ball sitting at rest on a ledge at height h above a surface. The ball has mass m; gravity exerts a force on the ball equal to m*g in the down direction.
The equations of motion for the ball are:
F = m*a
This is a vector equation, because force, acceleration, velocity, and displacement are all vector quantities.
I can use calculus to solve for the distance the ball falls from the height after giving it a push in the positive x-direction (initial x-velocity).
The result will be a quadratic equation.
Related
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;
}
I had glitching in speech marks because I am farily sure it is not a glitch.
I have just recently started to code using JFrames, in fact I started Java at school couple months ago, but recently I have tried to push my understanding using these handy frames.
I made a program which would bounce a ball around the frame, and I wanted to make it so there would be 2 (for now they would not collide) however whenever I try to add another it simply shows one.
Here is the code:
public static void main(String[] args) throws InterruptedException{
JFrame frame = new JFrame("Hello There");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setLayout(new FlowLayout());
Main ball = new Main();
Main ball2 = new Main();
ball2.SetValues(200, 200, Color.BLUE);
frame.add(ball2);
frame.add(ball);
while (true) {
ball.move();
ball.repaint();
ball2.move();
ball2.repaint();
Thread.sleep(5);
}
}
public void move() {
x = x + xDirection;
y = y + yDirection;
if (x < 0) { //If Ball has gone off the screen on x direction
xDirection = 1; //Start moving to the right
} else if (x > getWidth() - 50) { //If x has gone off the screen to the right
xDirection = -1;//Start moving to the left
}
if (y < 0) { //If Ball has gone off the screen on x direction
yDirection = 1; //Start moving to the right
} else if (y > getHeight() - 50) { //If x has gone off the screen to the right
yDirection = -1;//Start moving to the left
}
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(color);
g.fillOval(x, y, 50, 50);
}
I recently added the line "frame.setLayout(new FlowLayout()" and it appears to show the 2 balls but they are in a glitched state.
Could anyone help me out?
You should not sleep or do any long process on Swing thread, nor should you update the gui from other threads. See Concurrency in Swing
One alternative is to use javax.swing.Timer :
Timer timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ball.move();
ball.repaint();
ball2.move();
ball2.repaint();
}
});
timer.start();
Another alternative is to use a separate thread
It is also recommended to read Performing Custom Painting
I am trying to change the y position of the rectangle, however, whenever I try to, it expands/gets bigger vertically.
public class PlayerPaddle implements Paddle {
double yVelocity;
final double GRAVITY = 0.94;
//move up/down faster (if not accelerating = slow down)
boolean upAccel, downAccel;
//determines if player 1 or player 2 (on left or on right)
int player;
//position of actual paddle
int x;
double y;
Rectangle panel;
public PlayerPaddle(int player) {
upAccel = false;
downAccel = false;
y = 210; //not moving initially
yVelocity = 0;
if (player == 1) {
//left side
x = 20;
} else {
//right side
x = 660;
}
}
#Override
public void draw(Graphics g) {
//draw paddle
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
}
#Override
public void move() {
if (upAccel) {
yVelocity -= 2;
} else if (downAccel) {
yVelocity += 2;
} else if ((!upAccel) && (!downAccel)) {
yVelocity *= GRAVITY;
}
y += yVelocity; //changes y position of paddle
}
public void setUpAccel(boolean input) {
upAccel = input;
}
public void setDownAccel(boolean input) {
downAccel = input;
}
#Override
public int getY() {
return (int) y;
}
}
I want to know how to make the rectangle move up and down vertically. A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding. But even when I say g.clearRect(...) it still expands and does not move.
I am new to Swing and Awt but I am really committed to learning. Thanks for the help.
A similar question had only one answer which said that the previously painted rectangle was not being cleared and as a result is expanding
And that is still probably the problem here.
Somewhere, not in the code presented here, you need to invoke the draw(...) method of this class.
So in that code you need to make sure the background of the component is cleared before you draw the paddle. Since you should be overriding the paintComponent(...) method of a panel to do custom painting your code should look something like:
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw the paddle
}
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
I am new to Swing and Awt but I am really committed to learning.
Then keep a link to the tutorial handy for all Swing basics.
My program is to create a bouncing ball that goes up and down and up minus 30% each time and down... in tell the ball has stopped in a resting position.
also I would like to make the ball progressively slow down as it reaches the top of the bonce, and progressively speed up as it descends back to its original position.
So I got the first part set up, I'm just having trouble with not making an infinity loop, and decreasing the up wards y stopping position to decrease by 30% after each bounce.
As I was writing this question I realized, I need to make the y value in the first while loop increase by 30% lintel it reaches 400 correct?
How do I make a loop around the two while loops to repeat over and over, without an infinity loop?
I appreciate any input or comments or ideas!
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JApplet;
public class MY_Proj04 extends JApplet
{
int x, y;
Color Background;
public void init()
{
x = 100;
y = 400;
Background = getBackground();
}
public void paint(Graphics g)
{
// I tryed putting a while loop around the two following while loops and
// doing y = y * 30/100, I did this because the fill oval can't take a double
// as one of its parameters.
// 1st while loop
while(y >= 0) // Ball goes up to (0,100)
{
g.setColor(Background);
// fill the 500 by 500 square with it background color
// any old draw will be covered
g.fillRect(0, 0, 500, 500);
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
for(long i = 1; i < 5000000; i++); //speed of ball
y -=1;
}
// 2nd while loop
while(y <= 400) // ball goes down to 400,100
{
g.setColor(Background);
// fill the 500 by 500 square with it background color
// any old draw will be covered
g.fillRect(0, 0, 500, 500);
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
for(long i = 1; i < 5000000; i++); //speed of ball
y += 1;
}
}
}
I tried this program in a different way. Its working. For the speed of ball, i used Thread.sleep() instead of the loop that you used.
Also, a correction is that the first while loop in your code is moving ball back to the starting position. To make it bounce less than its previous height, you need to increase the RHS value (which is fixed in your code i.e. 0). One more thing, to give the ball look like its bouncing, I've done a few changes.
Here's the code:
import java.applet.*;
import java.awt.*;
/**<applet code="ball" height = "768" width = "1366" ></applet>*/
public class ball extends Applet implements Runnable
{
int x,y,height,width,a;
float z;
public void start()
{
x=100; y=400; h=50; w=50; a=0;
z = y;
Thread th=new Thread(this);
th.start();
}
public void run()
{
while(Math.round(z)!=0)
{
while(y>=a) //Ball bounces till it reaches point a. Which in turn is increasing with each bounce till it is equal to 400.
{
y--;
repaint();
try{Thread.sleep(3);} // Speed of the ball.
catch(Exception e){}
}
while(y<=400) // This loop gives ball a bouncing look each time it hits the floor (i.e. 400).
{
y++;
repaint();
if(y==400)
{
while(h!=40)
{
y++;
height--;
x--;
width+=2;
repaint();
try{Thread.sleep(3);}
catch(Exception e){}
}
while(h!=50)
{
y--;
height++;
x++;
widt--=2;
repaint();
try{Thread.sleep(3);}
catch(Exception e){}
}
}
try{Thread.sleep(3);}
catch(Exception e){}
}
z=z*(0.7f); //This line and the next line calculates the value of a for the next bounce.
a=Math.round(y-z); //round() function rounds the floating value to nearest whole number and converts it into an integer.
}
}
public void paint(Graphics g)
{
g.fillOval(x,y,width,height);
}
}
I'm making simple 2D games. I have a game loop, and in the game loop i have an update
method. I make things move by adding 1 to xPos whenever it loops. This means that if you have a slow fps then everything goes in slow motion and if you have a high fps everything moves
really quick.
This is my code:
long fpsTimer;
int frames;
public void run(){
running = true;
fpsTimer = System.nanoTime();
while(running){
render();
update();
try{
Thread.sleep(6);
}catch(InterruptedException e){}
frames++;
if(System.nanoTime() >= fpsTimer+1000000000){
System.out.println(frames+" fps");
frames = 0;
fpsTimer = System.nanoTime();
}
}
}
All Code
import java.awt.*;
import java.awt.image.*;
import javax.swing.JFrame;
import java.awt.event.*;
public class Game extends Canvas implements Runnable{
public static final int WIDTH = 800;
public static final int HEIGHT = 300;
public JFrame f;
private String title = "Untitled Test";
private Image image;
private Sprite player;
public Game(){
player = new Sprite(100, 100);
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setMaximumSize(new Dimension(WIDTH, HEIGHT));
setMinimumSize(new Dimension(WIDTH, HEIGHT));
addKeyListener(new KeyAdapter(){
public void keyPressed(KeyEvent e){
player.keyPressed(e.getKeyCode());
}
public void keyReleased(KeyEvent e){
player.keyReleased(e.getKeyCode());
}
});
}
public static void main(String[] args){
Game g = new Game();
g.f = new JFrame(g.title);
g.f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g.f.add(g);
g.f.setResizable(false);
g.f.pack();
g.f.setLocationRelativeTo(null);
Thread gameLoop = new Thread(g);
gameLoop.start();
g.f.setVisible(true);
}
private void render(){
BufferStrategy bs = getBufferStrategy();
if(bs==null){
createBufferStrategy(3);
return;
}
image = createImage(WIDTH, HEIGHT);
Graphics g = image.getGraphics();
player.draw(g);
g.dispose();
Graphics bsg = bs.getDrawGraphics();
bsg.drawImage(image, 0, 0, WIDTH, HEIGHT, null);
bsg.dispose();
bs.show();
}
private void update(){
player.move();
}
long fpsTime;
int frames;
public void run(){
fpsTime = System.nanoTime();
while(true){
render();
update();
try{
Thread.sleep(6);
}catch(InterruptedException e){}
frames++;
if(System.nanoTime() >= fpsTime+1000000000){
System.out.println(frames+" fps");
frames = 0;
fpsTime = System.nanoTime();
}
}
}
}
First of all you should not have a constant sleep time. Instead, the value should be dynamically computed. Maybe its easier to use Timer#scheduleAtFixedRate(...) cause this already takes care of that for you.
Then, 6 ms per iteration seems much too less. 60 frames per second is ideal (if you just have 30, its ok too i think), so 16 ms is enough (or about 32 for 30 fps). (Note that the refresh rate of your screen is the upper limit - it should be about 60 Hz - more doesn't make sense).
Thirdly think about dynamically computing the moves of your objects. Instead of having a constant delta that you add to the coordinates you should better have some kind of 'move function' that calculates the coordinates based on the current time.
Let's say you want to move an object along the x-axis with a constant speed of pps pixels per second. The function for the x coordinate of that object would then be:
x(t) := x0 + (t - t0) * pps / 1000
(t is the time that has passed since start in ms, x0 is the initial x coordinate of the object when it appeared first, t0 is the time at which the object appeared, pps is the number of pixels the object should move per second).
This makes your objects move with the same speed - no matter what framerate you've got.
Note that this approach gets more complex if your objects should react to user input or other events (like collisions etc.).