Hi, I'm new to this site, and I thought this place might help me with some of the problems I am hitting.

I am currently in grade 12 Computer Science, and I am coding a third-dimensional snake game (isometric view, so can all be drawn in 2D)

I have taken a simple JFrame code from the internet for a base start, and rehauled the program to work both in Applet and in 3D.

My current issue is that nothing repaints, and I am not exactly sure why. This is meant to be run in another class, but seems to work by itself. I am not sure if that is how it is supposed to work though.

My current progress:

package snake;

//The "Board" class.
import java.applet.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;

public class Board extends Applet
{
    // Place instance variables here

    private final int total_dots = 1000;

    private boolean left = false;
    private boolean right = true;
    private boolean up = false;
    private boolean down = false;
    private boolean in = false;
    private boolean out = false;
    private boolean inGame = false;

    private int x[] = new int [total_dots];
    private int y[] = new int [total_dots];
    private int z[] = new int [total_dots];

    private int dots;
    private int delay = 2000;
    private int applex;
    private int appley;
    private int applez;
    private int score;

    private Graphics g;
    private Image offscreen;

    public int highscore = 0;

    public Board ()
    {
        addKeyListener (new TAdapter ());

        setBackground (Color.cyan);
        init ();
    }


    public void init ()
    {
        inGame = true;
        dots = 3;

        x [0] = 2;
        x [1] = 1;
        x [2] = 0;
        y [0] = 0;
        y [1] = 0;
        y [2] = 0;
        z [0] = 0;
        z [1] = 0;
        z [2] = 0;

        score = 0;

        locateApple ();

        offscreen = createImage (800, 600);

        try
        {
            Thread.sleep (delay); // do nothing for delay time
            repaint ();
        }
        catch (InterruptedException e)
        {
            e.printStackTrace ();
        }
    } // init method


    public void paint (Graphics g1)
    {
        g = offscreen.getGraphics ();
        if (inGame)
        {
            int j[] = {40 + 40 * applex + 25 * applez, 65 + 40 * applex + 25 * applez, 105 + 40 * applex + 25 * applez, 105 + 40 * applex + 25 * applez, 80 + 40 * applex + 25 * applez, 40 + 40 * applex + 25 * applez};
            int k[] = {190 + 40 * appley - 15 * applez, 175 + 40 * appley - 15 * applez, 175 + 40 * appley - 15 * applez, 215 + 40 * appley - 15 * applez, 230 + 40 * appley - 15 * applez, 230 + 40 * appley - 15 * applez};

            g.setColor (Color.red);
            g.fillPolygon (j, k, 6);

            for (int i = 0 ; i < dots ; i++)
            {
                if (i == 0)
                    g.setColor (Color.red);
                else
                    g.setColor (Color.orange);
                int m[] = {40 + 40 * x [i] + 25 * z [i], 65 + 40 * x [i] + 25 * z [i], 105 + 40 * x [i] + 25 * z [i], 105 + 40 * x [i] + 25 * z [i], 80 + 40 * x [i] + 25 * z [i], 40 + 40 * x [i] + 25 * z [i] };
                int n[] = {190 + 40 * y [i] - 15 * z [i], 175 + 40 * y [i] - 15 * z [i], 175 + 40 * y [i] - 15 * z [i], 215 + 40 * y [i] - 15 * z [i], 230 + 40 * y [i] - 15 * z [i], 230 + 40 * y [i] - 15 * z [i] };
                g.fillPolygon (m, n, 6);
            }
        }
        else
        {
            gameOver (g);
        }
        g1.drawImage (offscreen, 0, 0, this);
    } // paint method


    public void gameOver (Graphics g)
    {
        if (score > highscore)
        {
            highscore = score;
        }
    }

    public void checkApple ()
    {
        if ((x [0] == applex) && (y [0] == appley) && (z [0] == applez))
        {
            dots++;
            score += 1;
            locateApple ();
        }
    }


    public void move ()
    {
        for (int i = dots ; i > 0 ; i--)
        {
            x [i] = x [i - 1];
            y [i] = z [i - 1];
            z [i] = z [i - 1];
        }
        //left
        if (left && x [0] == 0)
            x [0] = 9;
        else if (left && x [0] != 0)
            x [0] -= 1;
        //right
        if (right && x [0] == 9)
            x [0] = 0;
        else if (right && x [0] != 9)
            x [0] += 1;
        //up
        if (up && y [0] == 9)
            y [0] = 0;
        else if (up && y [0] != 9)
            y [0] += 1;
        //down
        if (down && y [0] == 0)
            y [0] = 9;
        else if (down && x [0] != 0)
            y [0] -= 1;
        //forward
        if (in && z [0] == 9)
            z [0] = 0;
        else if (in && z [0] != 9)
            z [0] += 1;
        //backward
        if (out && z [0] == 0)
            z [0] = 9;
        else if (out && z [0] != 0)
            z [0] -= 1;
    }


    public void checkCollision ()
    {
        for (int i = dots ; i > 0 ; i--)
        {
            if ((i > 0) && (x [0] == x [i]) && (y [0] == y [i]) && (z [0] == z [i]))
                inGame = false;
        }
    }


    public void locateApple ()
    {
        int r = (int) (Math.random () * 10);
        applex = r;
        r = (int) (Math.random () * 10);
        appley = r;
        r = (int) (Math.random () * 10);
        applez = r;
    }


    public void actionPerformed (ActionEvent e)
    {

        if (inGame)
        {
            checkApple ();
            checkCollision ();
            move ();
        }

        paint (g);
    }


    private class TAdapter extends KeyAdapter
    {

        public void keyPressed (KeyEvent e)
        {

            int key = e.getKeyCode ();

            if ((key == KeyEvent.VK_LEFT) && (!right))
            {
                left = true;
                up = false;
                down = false;
                in = false;
                out = false;
            }

            if ((key == KeyEvent.VK_RIGHT) && (!left))
            {
                right = true;
                up = false;
                down = false;
                in = false;
                out = false;
            }

            if ((key == KeyEvent.VK_UP) && (!down))
            {
                up = true;
                right = false;
                left = false;
                in = false;
                out = false;
            }

            if ((key == KeyEvent.VK_DOWN) && (!up))
            {
                down = true;
                right = false;
                left = false;
                in = false;
                out = false;
            }

            if ((key == KeyEvent.VK_A) && (!out))
            {
                in = true;
                down = false;
                left = false;
                right = false;
                up = false;
            }

            if ((key == KeyEvent.VK_Z) && (!in))
            {
                out = true;
                down = false;
                left = false;
                right = false;
                up = false;
            }
        }
    }
} // Board class

Original code I used as frame of reference: http://zetcode.com/tutorials/javagamestutorial/snake/

If anyone can help, it would be largely appreciated.

Edited 4 Years Ago by yuyuttiu: new title

please do not accuse me of copying this code from anywhere else, I spent roughly 15 hours worth of work.

The output does not repaint itself, just need to know where to insert that. Do not need much more help than that, but anything is appreciated. This was written is Ready to Program Java (I know, it's horrible, not going into details).

Why is the sleep() call? After commenting that out I get a window with the cyan color and two shapes, one all red on right and one with red and yellow on the left.

What is the code supposed to do?

Edited 4 Years Ago by NormR1

I just had a quick look, so maybe I missed something , but anyway...
The original correctly uses a Timer to call its actionPerformed method at regular intervals. That's how the animation is updated and finally repaint() is called to tell Java that the screen needs to be updated. (Java will then call the overridden paint(Graphics g) method.) I don't see the Timer in your code - a single sleep isn't remotely equivalent.
It's a classic beginner's mistake to code hundreds of lines before running any tests to check if the basic ideas are right. I recommend that you set this aside and write a minimally short program that uses a Timer to move a simple rectangle once across the screen. That will give you an understanding of the Timer, the actionPerformed method, and the paint method, and the relationship between them. Then you can go back to your more complex code and you will know what you are doing.

thank you so much!

looking back, i may just use the keylistener i used last year to animate a scene. I had a double-buffer with threading working on that. Should've stuck with what I knew.

sry bout the trouble, thanks for the help!

With Java Swing you can use your own buffering and timing threads, but it's better to use the highly optimised and integrated Swing timimg/buffering that are made available to you. Here's a trivial but fully runnable program that shows how these fit together to animate a box moving across the window, it's the basis of the "standard" approach to Swing animation

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class MiniAnimation extends JFrame implements ActionListener {

   public static void main(String[] args) {
      new MiniAnimation();
   }

   private int xPos = 0;

   MiniAnimation() {
      super("Minimal Animation Demo");
      setMinimumSize(new Dimension(300, 200));
      setLocationRelativeTo(null);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setVisible(true);
      new javax.swing.Timer(50, this).start();
   }

   @Override
   public void actionPerformed(ActionEvent arg0) {
      xPos += 1;
      repaint();
   }

   @Override
   public void paint(Graphics g) {
      super.paint(g);
      g.fillRect(xPos, 50, 100, 100);
   }

}

Edited 4 Years Ago by JamesCherrill

Thanks for the example, I think I know where the program went wrong. Forgot about timers and threading. Now as soon as I find that solved button, I'll be golden. thx for all the help!

This question has already been answered. Start a new discussion instead.