-2

First of all, I would like to say that I am pretty new to applets (I don't plan on developing any, but I have a school project to complete on them). I have a couple of questions before posting my code:

Why is the coordinate system of the applet window so messed up? I suppose it should show the first quadrant of a coordinate system by default, which should mean that (0, 0) is in the lower left corner and (500, 500) (if that's the size of the window) should be in the upper right corner. However, (0, 0) is in the upper left corner and (500, 500) in in the lower right. Why is that so and is there a simple fix for it?

In my code (some of it provided by the teacher) there is a try-catch block containing this:

Thread.currentThread().sleep(40)

It runs smoothly on any other computer I've tried but mine. Unless I set the number to 100 the ball keeps flickering and flashing on the screen, instead of running smoothly and when I do set it to 100, it starts moving really slowly.

Now, I have to make an applet that animates a ball moving on an inverted parabolic trajectory, whose radius increases when going up and decreases when going down. It should change its colour during its run.

Here's my code:

import java.awt.*;
import java.applet.*;

public class Ball extends Applet implements Runnable 
{
    private static final long serialVersionUID = 1L;
    //double x, y, xInit, wide = 100, high = 400;
    //int dx, dy, diam, sizex, sizey;
    int wide = 100, high = 400;
    int xIncrement = 1;
    int xInit = (int)(-parabolaX (0, wide, high));
    int x = xInit;
    int y = (int)(parabolaY (x, wide, high));
    int diam, sizex, sizey;
    Thread ballPlay = new Thread(this);

    public void init() 
    {
        setBackground(Color.black);
        diam = 12;
        setSize(500, 500);
        sizex = 500;
        sizey = 500;
        ballPlay.start();
    }

public void run() 
{
    while (true) 
    {
        try  { Thread.currentThread().sleep(100); }
        catch (InterruptedException e) {};
        if ((x <= -xInit) && (y >= 0)) {
            x += xIncrement;
        } else {
            xInit = (int)(-parabolaX (0, wide, high));
            x = xInit;
        }
        repaint();
    }
}

//returns y-value of parabola
int parabolaY (int x, int wideness, int highness) {
  //equation of parabola
  int y = wideness*(x*x) + highness;

  return y;
}

//returns x-value of parabola
int parabolaX (int y, int wideness, int highness) {
  //equation of parabola
  int x = (int)Math.sqrt((y - highness)/wideness);

  return x;
}

 public void paint(Graphics g) 
   {    
        g.setColor(Color.red);
        System.out.println("PAINTING... X = " + x + " Y = " + y);
        g.fillArc(x, y, diam, diam, 0, 360);
        g.drawString(String.valueOf(x), 20, sizey-40);
        g.drawString(String.valueOf(y), 20, sizey-20);
   }
}

Currently, it doesn't work at all. By tweaking it in numerous ways, I have succeeded in putting the ball in its initial position (100, 400) but no movement whatsoever happened. Browsing the net the other day I found this - http://www.openprocessing.org/sketch/25434 And it is exactly what I need (without the radius and color changing part) and still I can't figure it out. Obviously, there's something (or most probably many things) I'm doing completely wrong but having almost no clue how applets work, I can't seem to find the problem. The code is a mashup of some of the code provided by my teacher and the one from the webpage.

What I want to do is make an animation of the ball moving on an inverted parabolic trajectory with a starting position (100, 400). After completing the parabola it should return to its initial position and continue looping te animation. However, with the current code it isn't even close to working as I need it to.

Abvgz
  • 11
  • 4
  • What exactly are you trying to do with the Thread.sleep()? – EpicPandaForce Jun 04 '14 at 14:10
  • The flickering indicates you probably need to check out double buffering. that's a technique to smooth out the screen flickering. – LhasaDad Jun 04 '14 at 14:13
  • @Zhuinden This block was part of the code provided by the teacher. As far as I can tell, it's included in this try-catch block in order to catch any exceptions regarding any halts of movement of the object (ball). Ihasadad, I have read about this and tried some examples but my point is that this code works perfectly on other machines as is with minimal to no flickering and on mine it just skips 3/4 of the frames resulting in constant flickering. I don't know why this is but it's certainly not a performance issue, as the other machines are way slower than mine. – Abvgz Jun 04 '14 at 16:05
  • 1) Why code an applet? If it is due to spec. by teacher, please refer them to [Why CS teachers should stop teaching Java applets](http://programmers.blogoverflow.com/2013/05/why-cs-teachers-should-stop-teaching-java-applets/). 2) Why AWT rather than Swing? See my answer on [Swing extras over AWT](http://stackoverflow.com/a/6255978/418556) for many good reasons to abandon using AWT components. – Andrew Thompson Jun 05 '14 at 08:30
  • @AndrewThompson It's a java course and applets are just one lesson of it but I have a project to complete on them, so it's really just like a little detour from the main subject - no need to try convincing her that they're obsolete or something. As for Swing over AWT, as I said, I don't plan on developing any applets in the future so due to AWT being able to fulfil the task, I don't see any need to learn about Swing. All I ask for is some help with the logic of the program as I can't make it work. – Abvgz Jun 05 '14 at 09:20

1 Answers1

0

However, (0, 0) is in the upper left corner and (500, 500) in in the lower right. Why is that so and is there a simple fix for it?

Well it does make sense to have 0,0 at the top, if you think about it, all modern GUI windows when you resize them, shrink towards the top and to the left. But if you had point 0,0 on the bottom right, it would be awfully more difficult to code up the math to see how much space is left towards the left and towards the top and how much you should pad the components to center them and that sort of thing.

Unless I set the number to 100 the ball keeps flickering and flashing on the screen, instead of running smoothly and when I do set it to 100, it starts moving really slowly.

That's because your machine is probably not as powerful as other machines, as your machine is not rendering the graphics fast enough before the next render wants to come in, or something like that. If Applet's paint method was double buffered, then you wouldn't have this issue.

About the speed, that sleep is sleeping for 40 milliseconds every time it's executed, so you could think of your application running at 1000 milliseconds divided by however many milliseconds there per sleep, so with 100, you are running at about updates per second. Now unlike most animation in games, your application's movement is tick based, meaning your graphics move over a set number of pixels per update, so the less updates in a second, the less your graphics move (the better way is to update the positions of your graphics based on how much time has elapsed since the last update).

So to get rid of the flickering, you have to have your drawing buffered. Upgrading your class to extend from JApplet instead of Applet would be a good start. After that, create another class that extends JPanel, and move all of your logic there, and override paintComponent(Graphics) instead of paint(Graphics) in your applet class. You should still use the applet class (a JApplet now), but the only thing you should have there is the addition of a child component of your custom JPanel class. This new paint method you'll use is double buffered, which will get rid of the flickering.

// This code may not be exactly what you need but here's the general idea
public class Ball extends JApplet
{
    public void init() 
    {
        this.add(new MyCustomGraphicsPanel());
    }
}

public class MyCustomGraphicsPanel extends JPanel implements Runnable {
    private static final long serialVersionUID = 1L;
    //double x, y, xInit, wide = 100, high = 400;
    //int dx, dy, diam, sizex, sizey;
    double wide = 100, high = 400;
    int xIncrement = 1;
    double xInit = -parabolaX (0, wide, high);
    double x = xInit;
    double y;
    int diam, sizex, sizey;
    Thread ballPlay = new Thread(this);

    // Move init code into the constructor
    public MyCustomGraphicsComponent()
    {
        setBackground(Color.black);
        y = parabolaY (x, wide, high);
        diam = 12;
        setSize(500, 500);
        sizex = 500;
        sizey = 500;
        ballPlay.start();
    }

    public void run() 
    {
        while (true) 
        {
            try  { Thread.currentThread().sleep(100); }
            catch (InterruptedException e) {};
            if ((x <= -xInit) && (y >= 0)) {
                x += xIncrement;
            } else {
                xInit = -parabolaX (0, wide, high);
                x = xInit;
            }
            repaint();
        }
    }
}
NESPowerGlove
  • 5,496
  • 17
  • 28
  • Thank you for your thorough reply. However, the flickering isn't a really big deal because the applet is going to be shown on a lab computer (where it doesn't flicker with the same code). Also, it has nothing to do with my machine's performance, because it's way more powerful than any other I've tried the code on (might be a java bug or something but as I said that isn't the problem at all). What I most need help with is creating a code that successfully moves the ball on an inverted parabolic trajectory, as shown in the website from the first post (I need help with the logic of the program). – Abvgz Jun 05 '14 at 06:20
  • Your code is suppose to flicker using non buffered drawing techniques. Just set the ball's y position equal to the output of the function per update and the x position to the input to that function. Increment x every update or so. – NESPowerGlove Jun 05 '14 at 19:38
  • Okay, I get it now. However, isn't this exactly what the code is doing right now? The output from my code currently is the ball constantly switching from (0, 400) to (1, 400). What do I need to change in order to put it on (100, 400) and make it move on an inverted parabolic trajectory from there (just like in the code from the website in the first post)? – Abvgz Jun 05 '14 at 19:51
  • So you're saying according to your drawing code x and y is not being updated? Try making x and y volatile. So declare it volatile int x/y, this will let both threads (the thread you create which updates it, and the EDT, the Swing thread) see the same value for this primitive type whenever it's updated. If that doesn't help, keep the change in, and check your Runnable code, that's some odd logic there with that if statement, your logic looks wrong because it seems like only x is updated and y never is. I'd imagine you would do a call like y = someFunction(x) – NESPowerGlove Jun 05 '14 at 20:04
  • where in the method someFunction you increment x after calculating the return value, or increment it yourself after you call the function. When you go too far (like when x is now a value that's off the screen, you could reset x back to 0 or whatever (which when the next update rolls around, resets y). – NESPowerGlove Jun 05 '14 at 20:05