Java application freezing - java

I am very new to java. Very. Like I basically started today. I have previous programming knowledge in other languages, like c, c++, PHP, javascript, etc, but I can't figure this one out. I started watching tutorials on Youtube about how to make a video game in Java(videos from theChernoProject), but about 7 episodes in, I came across a problem, where we have our window, and we paint a black rectangle across the whole thing, and the application freezes my whole computer. Here is my code:
package com.darksun.theonetruemike.rain;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Game extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
public static int width = 300;
public static int height = width / 16 * 9;
public static int scale = 3;
private Thread thread;
private JFrame frame;
private boolean running = false;
public Game(){
Dimension size = new Dimension(width * scale, height * scale);
setPreferredSize(size);
frame = new JFrame();
}
public synchronized void start(){
running = true;
thread = new Thread(this, "Display");
thread.start();
}
public synchronized void stop(){
running = false;
try{
thread.join();
} catch(InterruptedException e){
e.printStackTrace();
}
}
public void run(){
while(running){
update();
render();
}
}
public void update(){
}
public void render(){
BufferStrategy bs = getBufferStrategy();
if(bs == null){
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.dispose();
bs.show();
}
public static void main(String args[]){
Game game = new Game();
game.frame.setResizable(false);
game.frame.setTitle("Rain");
game.frame.add(game);
game.frame.pack();
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setLocationRelativeTo(null);
game.frame.setVisible(true);
game.start();
}
}
I'm using eclipse to make this project(highly against my will), and when I press the Debug button, the window appears, and my computer freezes, resulting in having to force quit the entire computer. Please help if you can, and thanks for help ahead of time!

since i have low reputation, i will post my comment as answer, try not to -rep
i copied your code to netbeans, a black console like window appears, nothing happens, but it doesnt freeze, but the JVM is using about 50% of cpu

Related

Getting graphics object to draw with buffer strategy

I've made a JFrame with a canvas on it and I want to draw on that canvas. At a later date the canvas will be updating many times a second so I am using a buffer strategy for this. Here is the code:
package mainPackage;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class TickPainter {
//just some presets for a window.
public static JFrame makeWindow(String title, int width, int height) {
JFrame mainWindow = new JFrame();
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainWindow.setSize(width, height);
mainWindow.setVisible(true);
mainWindow.setLocationRelativeTo(null);
mainWindow.setTitle(title);
return mainWindow;
}
public static void main(String[] args) {
JFrame mainWindow = makeWindow("Practice", 800, 600);
Canvas mainCanvas = new Canvas();
mainWindow.add(mainCanvas);
mainCanvas.setSize(mainWindow.getWidth(), mainWindow.getHeight());
mainCanvas.setBackground(Color.white);
mainCanvas.createBufferStrategy(3);
BufferStrategy bufferStrat = mainCanvas.getBufferStrategy();
Graphics g = bufferStrat.getDrawGraphics();
g.setColor(Color.black);
g.fillRect(250, 250, 250, 250);
g.dispose();
bufferStrat.show();
}
}
The program does not draw the black rectangle as intended, I feel like I've missed something really obvious here and I just can't see it. At the moment the program just makes a blank white canvas. I feel like part of the issue is that the buffer is just passing the frame with the rectangle faster than I can see, but there is no frame to load after that so I don't know why it's doing this.
A BufferStrategy has a number of initial requirements which must be meet before it can be rendered to. Also, because of the nature of how it works, you might need to repeat a paint phases a number of times before it's actually accepted by the hardware layer.
I recommend going through the JavaDocs and tutorial, they provide invaluable examples into how you're suppose to use a BufferStrategy
The following example uses a Canvas as the base component and sets up a rendering loop within a custom Thread. It's very basic, but shows the basic concepts you'd need to implement...
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
TestCanvas canvas = new TestCanvas();
JFrame frame = new JFrame();
frame.add(canvas);
frame.setTitle("Test");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
canvas.start();
}
});
}
public class TestCanvas extends Canvas {
private Thread thread;
private AtomicBoolean keepRendering = new AtomicBoolean(true);
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public void stop() {
if (thread != null) {
keepRendering.set(false);
try {
thread.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public void start() {
if (thread != null) {
stop();
}
keepRendering.set(true);
thread = new Thread(new Runnable() {
#Override
public void run() {
createBufferStrategy(3);
do {
BufferStrategy bs = getBufferStrategy();
while (bs == null) {
System.out.println("get buffer");
bs = getBufferStrategy();
}
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
System.out.println("draw");
Graphics graphics = bs.getDrawGraphics();
// Render to graphics
// ...
graphics.setColor(Color.RED);
graphics.fillRect(0, 0, 100, 100);
// Dispose the graphics
graphics.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (bs.contentsRestored());
System.out.println("show");
// Display the buffer
bs.show();
// Repeat the rendering if the drawing buffer was lost
} while (bs.contentsLost());
System.out.println("done");
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} while (keepRendering.get());
}
});
thread.start();
}
}
}
Remember, the point of BufferStrategy is to give you full control over the painting process, so it works outside the normal painting process generally implemented by AWT and Swing
"At a later date the canvas will be updating many times a second so I am using a buffer strategy for this" - Before going down the "direct to hardware" solution, I'd consider using a Swing Timer and the normal painting process to see how well it works

Major confusion about Graphics in Java

I'm new to Java and OOP programming in general so if you guys could give me dumbed down explanation I would appreciate it. I don't really understand how the Graphics object and paintComponent work in general.
The basic idea of the Simulation class is that it will do the following.
1) Create a JFrame for my animation to take place in.
2) Create a Panel (I tried using a Canvas but people told me not to do that) which fits inside my JFrame, the animation will we painted to this panel.
3) Depending on the value of 'type' (and maybe some other conditions which I have not yet coded) it will set up and paint (to the Panel) the background picture (the graphics) for the corresponding Animation.
4) After painting the background image I wan't to be able to return it to Simulation class and modify it (the background Image) in a Loop with my Simulation running on a thread (therefore creating an animation).
5) After the animation is finished I want the Simulation JFrame to close (I'm not even close to getting to this part though).
Everything I see on here just tells me to create the class InitSimGraphics and have paintComponent method within it. I want to be able to paint my lines/rectangles ect.. onto the Panel and then go on to use it again where I can modify parts of it (aka make a particle move through the screen).
What I am doing right now is clearly not working and I am really really new to this so please try to go easy on me. A different approach is probably best I think since this isn't working.
Thanks!
package comp4Pack;
import javax.swing.*;
import java.awt.*;
public class Simulation implements Runnable {
private final int pwidth = 768, pheight = 432;
private int type;
private JFrame frame;
private JPanel panel;
private boolean running = false;
private Thread thread;
/* Type means the following
*
* 0 - Kinematics
* 1 - Dynamics (Momentum)
* 2 - Vectors
* 3 - ...
*
*/
public Simulation(int type){
this.type = type;
initSimulation();
InitSimGraphics i = new InitSimGraphics();
panel.add(i);
}
private void initSimulation(){
if(type == 0){
frame = new JFrame("Kinematics Simulation");
} else if(type == 1){
frame = new JFrame("Dynamics Simulation");
} else {
frame = new JFrame("Vectors Simulation");
}
frame.setSize(pwidth, pheight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
panel = new JPanel(new BorderLayout());
panel.setPreferredSize(new Dimension(pwidth, pheight));
panel.setMaximumSize(new Dimension(pwidth, pheight));
panel.setMinimumSize(new Dimension(pwidth, pheight));
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
private void initGraphics(){
}
public void run() {
while(running){
tick();
render();
}
stop();
}
private void tick(){
}
private void render(){
}
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
..
package comp4Pack;
import javax.swing.*;
import java.awt.*;
public class InitSimGraphics extends JPanel {
Graphics g;
private final int pwidth = 768, pheight = 432;
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawLine(0, 0, pwidth, pheight);
this.g = g;
}
public Graphics getGraphics(){
return g;
}
}

How do I correctly set up canvas capable on running a simulation

I'm brand new to Java and have only recently learnt about object oriented programming. I'm trying to create a program which can run a simulation, the general idea is that I want a part of the screen dedicated to buttons/sliders and another part to be dedicated the the Canvas running the simulation. For now I'm not worried about the simulation itself, I'm just trying to get some graphics on the canvas (which is smaller than the JFrame).
Here is my code (I'll try to leave some explanation below it)
public class Launcher {
public static void main(String[] args){
Display display = new Display();
}
}
.
import java.awt.*;
import javax.swing.*;
public class Display {
public final int width = 1280, height = 720;
public final int cwidth = 894, cheight = 504;
public final String title = "Mechancis Simulator";
private JFrame frame;
//private JPanel panel;
private Canvas canvas;
private Simulation simulation;
public Display(){
initDisplay();
simulation = new Simulation();
}
private void initDisplay(){
frame = new JFrame(title);
frame.setSize(width, height);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
/*panel = new JPanel();
panel.setSize(width, height);
panel.setLocation(0,0); */
canvas = new Canvas();
canvas.setPreferredSize(new Dimension(cwidth, cheight));
canvas.setMaximumSize(new Dimension(cwidth, cheight));
canvas.setMinimumSize(new Dimension(cwidth, cheight));
canvas.setLocation(width - (cwidth +15), 15);
//panel.add(canvas);
frame.add(canvas);
/* Add code for buttons/sliders/boxes here */
/* Add these to panel */
}
public JFrame getFrame(){
return frame;
}
public Canvas getCanvas(){
return canvas;
}
}
.
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.*;
import javax.swing.*;
public class Simulation extends Display implements Runnable {
private boolean running = false;
private Thread thread;
private BufferStrategy bs;
private Graphics g;
public Simulation(){
}
private void init(){
}
private void tick(){
}
private void render(){
bs = getCanvas().getBufferStrategy();
if(bs == null){
getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
//Draw Here!
//End Drawing!
bs.show();
g.dispose();
}
public void run(){
init();
while(running){
tick();
render();
}
stop();
}
public synchronized void start(){
if(running)
return;
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop(){
if(!running)
return;
running = false;
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
When I run the program the window starts going crazy. I'm quite new to classes and threading so maybe that is the problem. I just want to be able to run the simulation after setting up Frame and Canvas in the Display object.
Thanks.
What you're doing basically is this:
class Display {
private final Simulation sim;
public Display() { sim = new Simulation(); }
}
class Simulation extends Display {
public Simulation() { }
}
when you create a new Display the constructor creates a new Simulation which is a Display which creates a new Simulation which is a Display which creates a new Simulation which is a Display which creates a new Simulation...*
So don't. There's no reason for your Simulation to be a display and to own another Simulation. If you want all the control in Display define a constructor that takes as an argument the Simulation it's displaying and give it a simulation when you create it:
class Display {
private final Simulation sim;
public Display(Simulation sim) { this.sim = sim; }
}
class Simulation {
}
...
Display display = new Display(new Simulation());
*I suggest you google for a tutorial on inheritance, if you wish to know more. Here's the tutorial from oracle to get you started: "You can write a subclass constructor that invokes the constructor of the superclass, either implicitly or by using the keyword super." In your code example the constructor super() is invoked implicitly.

Creating a java method that can continuously update variables

I've been taking AP Computer Science this year as a sophomore in high school and we mainly cover material like loops, classes, methods, general CS logic, and some math stuff. I am missing what I really loved about coding in the first place, making games. Now every game I have made had some sort of way to manage it whether it was using timers in visual basic or a XNA plugin for c# that setup a update method for me. The problem is I have not learned how to do this for java in my course. I've read up a little on threads and implements runnable but i'm not really sure where I'm going with it.
Class 1
import java.awt.FlowLayout;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class GFXScreen extends JFrame
{
/**
* #param screenHeigth
* #param screenHeigth
* #param The file name of the image. Make sure to include the extension type also
* #param The title at the top of the running screen
* #param The height of the screen
* #param The width of the screen
*/
public GFXScreen(String fileName, String screenTitle, int screenHeight, int screenWidth)
{
setLayout(new FlowLayout());
image1 = new ImageIcon(getClass().getResource(fileName));
label1 = new JLabel(image1);
this.add(label1);
//Set up JFrame
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setTitle(screenTitle);
this.setSize(screenWidth, screenHeight);
}
/**
* #param desired amount to move picture
*/
public void updatePic(int increment)
{
//update pos
label1.setBounds(label1.bounds().x, label1.bounds().y - increment,
label1.bounds().width, label1.bounds().height);
}
private ImageIcon image1;
private JLabel label1;
}
Class 2
public class MainClass implements Runnable {
public static void main(String[] args)
{
(new Thread(new MainClass())).start();
GFXScreen gfx = new GFXScreen("pixel_man.png", "pixel_Man", 1000, 1000);
}
public void run()
{
gfx.updatePic(1);
}
}
In this instance what I want to happen is, I want a picture that starts in the top to slowly move down smoothly to the bottom. How would i do this?
Suggestions:
Again, a Swing Timer works well for simple Swing animations or simple game loops. It may not be the greatest choice for complex or rigorous tame loops as its timing is not precise.
Most game loops will not be absolutely precise with time slices
And so your game model should take this into consideration and should note absolute time slices and use that information in its physics engine or animation.
If you must use background threading, do take care that most all Swing calls are made on the Swing event thread. To do otherwise will invite pernicious infrequent and difficult to debug program-ending exceptions. For more details on this, please read Concurrency in Swing.
I avoid using null layouts, except when animating components, as this will allow my animation engine to place the component absolutely.
When posting code here for us to test, it's best to avoid code that uses local images. Either have the code use an image easily available to all as a URL or create your own image in your code (see below for a simple example).
Your compiler should be complaining to you about your using deprecated methods, such as bounds(...), and more importantly, you should heed those complaints as they're there for a reason and suggest increased risk and danger if you use them. So don't use those methods, but instead check the Java API for better substitutes.
Just my own personal pet peeve -- please indicate that you've at least read our comments. No one likes putting effort and consideration into trying to help, only to be ignored. I almost didn't post this answer because of this.
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
#SuppressWarnings("serial")
public class GfxPanel extends JPanel {
private static final int BI_WIDTH = 26;
private static final int BI_HEIGHT = BI_WIDTH;
private static final int GAP = 6;
private static final Point INITIAL_LOCATION = new Point(0, 0);
private static final int TIMER_DELAY = 40;
public static final int STEP = 1;
private ImageIcon image1;
private JLabel label1;
private Point labelLocation = INITIAL_LOCATION;
private int prefW;
private int prefH;
private Timer timer;
public GfxPanel(int width, int height) {
// the only time I use null layouts is for component animation.
setLayout(null);
this.prefW = width;
this.prefH = height;
// My program creates its image so you can run it without an image file
image1 = new ImageIcon(createMyImage());
label1 = new JLabel(image1);
label1.setSize(label1.getPreferredSize());
label1.setLocation(labelLocation);
this.add(label1);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
public void startAnimation() {
if (timer != null && timer.isRunning()) {
timer.stop();
}
labelLocation = INITIAL_LOCATION;
timer = new Timer(TIMER_DELAY, new TimerListener());
timer.start();
}
// My program creates its image so you can run it without an image file
private Image createMyImage() {
BufferedImage bi = new BufferedImage(BI_WIDTH, BI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = bi.createGraphics();
g2.setColor(Color.red);
g2.fillRect(0, 0, BI_WIDTH, BI_HEIGHT);
g2.setColor(Color.blue);
int x = GAP;
int y = x;
int width = BI_WIDTH - 2 * GAP;
int height = BI_HEIGHT - 2 * GAP;
g2.fillRect(x, y, width, height);
g2.dispose();
return bi;
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
int x = labelLocation.x + STEP;
int y = labelLocation.y + STEP;
labelLocation = new Point(x, y);
label1.setLocation(labelLocation);
repaint();
if (x + BI_WIDTH > getWidth() || y + BI_HEIGHT > getHeight()) {
System.out.println("Stopping Timer");
((Timer) e.getSource()).stop();
}
}
}
private static void createAndShowGui() {
final GfxPanel gfxPanel = new GfxPanel(900, 750);
JButton button = new JButton(new AbstractAction("Animate") {
#Override
public void actionPerformed(ActionEvent arg0) {
gfxPanel.startAnimation();
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
JFrame frame = new JFrame("GFXScreen");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(gfxPanel);
frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
What I always use is an infinite loop that calls an update method each iteration, in that method, you would do whatever was required to update the state of the game or render a GUI.
Example
public static void main(String[] args){
// Initialise game
while(true){
updateGame();
}
}
public static void updateGame(){
// Update things here.
}
What I also do ,which is a little more complex, is create and interface called IUpdateListener and have certain classes that are specialised for a certain element of the game. I would example have an InputListener, an AIListener, each handling a certain element of game updating.
public interface IUpdateListener{
public void update();
}
public class Main{
public static ArrayList<IUpdateListener> listeners = new ArrayList<IUpdateListener>();
public static void main(String[] args){
listeners.add(new InputListener());
while(true){
for(IUpdateListener listener : listeners){
listener.update();
}
}
}
}
public class InputListener implements IUpdateListener{
public void update(){
// Handle user input here etc
}
}

Java making a ball bounce, its left a trail behind?

Im newish to java, and im writing a pong game.
Ive got the ball to move (Thats my first priority) and make it apear on screen.
But for some Reason its leaving a black line behind it, I dont know if im supposed to errase this or something, but heres the code of my 2 classes (The Ball Class is just a class to save the info of the ball)
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Main extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
public static int Width=650;
public static int Height=600;
public boolean Running=false;
public Thread thread;
public Ball ball = new Ball();
public static void main(String[] args){
Main game = new Main();
JFrame frame = new JFrame();
frame.setSize(Width+25, Height+49);
frame.setTitle("Pong By Poo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.add(game);
game.start();
}
public void start(){
if(Running==true){
return;
} else {
Running=true;
thread = new Thread(this);
thread.start();
}
}
public void run(){
while(Running==true){
try{
Thread.sleep(5);
Draw();
Update();
ball.YVelocity();
ball.XVelocity();
} catch(Exception e){}
}
}
public void Draw(){
BufferStrategy bs = this.getBufferStrategy();
if(bs==null){
createBufferStrategy(2);
} else {
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillOval(ball.BallLocationX, ball.BallLocationY, 20, 20);
g.dispose();
bs.show();
}
}
public void Update(){
if(ball.BallLocationX==0) {
ball.BallMovementX=true;
System.out.println("Ball has hit the Left");
}
if(ball.BallLocationX==Width) {
ball.BallMovementX=false;
System.out.println("Ball has hit the Right");
}
if(ball.BallLocationY==0){
ball.BallMovementY=true;
System.out.println("Ball has hit the Top");
}
if(ball.BallLocationY==Height){
ball.BallMovementY=false;
System.out.println("Ball has hit the bottom");
}
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Ball extends JPanel{
public int BallLocationX;
public int BallLocationY;
public boolean BallMovementY; //true makes the ball go up, false makes it go down
public boolean BallMovementX; //True makes the ball go right, false makes it go left.
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillOval(BallLocationX, BallLocationY, 10, 10);
}
//moves the ball left to right
public int YVelocity(){
if(BallMovementY==true){
BallLocationY++;
} else {
BallLocationY--;
}
return BallLocationY;
}
//Moves the ball up and down
public int XVelocity(){
if(BallMovementX==true){
BallLocationX+=2;
} else {
BallLocationX-=2;
}
return BallLocationX;
}
}
Please help!
Essentially, everywhere your ball moves stays permanently Color.BLACK on your Canvas. If you want to get rid of that, you need to refresh every time the ball moves and repaint the Canvas to Color.WHITE (or whatever) before painting the ball's position again.
Specifically, look at your code here:
public void Draw(){
BufferStrategy bs = this.getBufferStrategy();
if(bs==null){
createBufferStrategy(2);
} else {
Graphics g = bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillOval(ball.BallLocationX, ball.BallLocationY, 20, 20);
g.dispose();
bs.show();
}
}
There is no logic here that overwrites your previous changes to the Canvas indicating the ball's location.
Also, as a side nitpick, Java standards are to have method names in camelCase.
And to answer the question in the comments: there is nothing in the Canvas API which automatically understands what you want the default background of the Canvas to be and can reset all other graphics attributes to that. To get this functionality, however, all you'll need to do is repaint your default layout (whether it's all one color, or a basic background image, or anything else) before painting the ball's position on top of it.

Categories