Search code examples
javaappletawtevent-dispatch-threadthread-sleep

This demo works 4 out of 5 times, why is it giving me an error sometimes?


I am practicing rendering and drawing graphics, I can't seem to find out why eclipse gives me an error around 1/5 of the time.

Exception in thread "Thread-3" java.lang.NullPointerException
  at game.StartingPoint.run(StartingPoint.java:74)
  at java.lang.Thread.run(Unknown Source)

Is it a problem with my thread? How can I fix this?

Here is my source code.

StartingPoint.java:

package game;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;

public class StartingPoint extends Applet implements Runnable {

    Image i;
    Graphics doubleG;
    Ball b1;
    Ball b2;

    public StartingPoint() {

    }

    @Override
    public void init() {

    }

    @Override
    public void start() {

        setSize(480, 360);

        Thread thread = new Thread(this);
        thread.start();

        b1 = new Ball(40, 40);
        b2 = new Ball(70, 200);

    }

    @Override
    public void stop() {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void update(Graphics g) {

        if (i == null) {
            i = createImage(this.getWidth(), this.getHeight());
            doubleG = i.getGraphics();
        }
        doubleG.setColor(getBackground());
        doubleG.fillRect(0, 0, this.getWidth(), this.getHeight());

        doubleG.setColor(getForeground());
        paint(doubleG);

        g.drawImage(i, 0, 0, this);
    }

    @Override
    public void paint(Graphics g) {
        b1.paint(g);
        b2.paint(g);

    }

    @Override
    public void run() {
        while (true) {

            b1.update(this);
            b2.update(this);

            repaint();
            try {
                Thread.sleep(30);
                } catch (Exception e) {

                System.out.print("Error");

            }
        }

    }
}

Ball.java:

package game;

import java.awt.Color;
import java.awt.Graphics;

public class Ball {
    double gravity = 15.0;
    double energyLoss = .65;
    double outsideEnergy = .95;
    double dt = .25;
    double xFriction = .9;
    int x = 40;
    int y = 40;
    double dx = 7.0;
    double dy = 0.0;
    int radius = 20;

    public Ball() {

    }

    public Ball(int x, int y) {

        this.x = x;
        this.y = y;

    }

    public void update(StartingPoint sp) {
        if (x <= 0 | x >= sp.getWidth()) {
            dx = -dx;
        }

        if (y > sp.getHeight() - radius - 1) {
            y = sp.getHeight() - radius - 1;
            dy *= energyLoss;
            dy = -dy;
            dx *= outsideEnergy;
            } else {
            // velocity
            dy = dy + gravity * dt;
            // d=viT + 1/2(a)t^2
            y += dy * dt + .5 * gravity * dt * dt;

        }

        x += dx;
    }

    public void paint(Graphics g) {
        g.setColor(Color.green);
        g.fillOval(x - radius, y - radius, radius * 2, radius * 2);

    }
}

Solution

  • Look at

    Thread thread = new Thread(this);
    thread.start();
    
    b1 = new Ball(40, 40);
    b2 = new Ball(70, 200);
    

    You are initializing your variables after your thread starts. Sometimes the thread uses them before they are actually initialized, sometimes they get initialized first. Move them before the start() call:

    b1 = new Ball(40, 40);
    b2 = new Ball(70, 200);
    
    Thread thread = new Thread(this);
    thread.start();