开发者

Java Swing Applet: How to slow or delay paint() without slowing down the entire program

开发者 https://www.devze.com 2023-03-14 12:05 出处:网络
I\'m creating a whack a mole game on java swing applet but I am having trouble with timing the moles to come up. I can\'t seem to avoid paint () looping on me and thus randomizing the coordinates of t

I'm creating a whack a mole game on java swing applet but I am having trouble with timing the moles to come up. I can't seem to avoid paint () looping on me and thus randomizing the coordinates of the mole too fast. How can I delay the moles to come up and stay for a while and go down if they were not hit? How can I create this delay without delaying the entire program?

please help

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;
import javax.swing.Timer;

public class Game extends JApplet
{

    boolean titleScreen = true;
    boolean gameBegin = false;

    // /////////////////////////////////
    // ///// IMAGE /////////
    // /////////////////////////////////

    Dimension dim;
    Image offscreen;
    static Graphics bufferGraphics;
    static Image h1, h2, bg, gamebg, button1a, button1b, button2a, button2b;
    static Image m1, m1a, m1b, m2a, m2b;
    static Image[] mk = new Image [9];

    // /////////////////////////////////
    // ///// MOUSE /////////
    // /////////////////////////////////

    Cursor c;
    boolean myButtonPressed = false;
    boolean myButtonEntered = false;
    int myMouseX = 0, myMouseY = 0;
    int myRow = -1, myCol = -1;

    // /////////////////////////////////
    // / GAME VARIABLES ///
    // /////////////////////////////////

    private static final int[] mX = {5, 170, 335, 5, 170, 335, 5, 170, 335};
    private static final int[] mY = {5, 5, 5, 170, 170, 170, 335, 335, 335};
    int rand, randm;

    static int[] t = new int [9];

    static boolean mhhit = false;
    static boolean[] mhit = {false, false, false, false, false, false, false, false, false};
    private int[] respawnCounter = {0, 0, 0, 0, 0, 0, 0, 0, 0};
    private int[] removeCounter = {0, 0, 0, 0, 0, 0, 0, 0, 0};

    static int score = 0;

    public JFrame window;
    // /////////////////////////////////
    // ///// BUTTON /////////
    // /////////////////////////////////

    GameScreen g1 = new GameScreen ();
    Timer repaintTimer = null;
    // GameTime m1 = new GameTime (t[]);
    // GameTime m2 = new GameTime (t[]);
    // GameTime m3 = new GameTime (t[]);
    // GameTime m4 = new GameTime (t[]);
    // GameTime m5 = new GameTime (t[]);
    // GameTime m6 = new GameTime (t[]);
    // GameTime m7 = new GameTime (t[]);
    // GameTime m8 = new GameTime (t[]);
    // GameTime m9 = new GameTime (t[]);

    public Game ()
    {
        window = new JFrame ("Monkeying Around");
        window.setResizable (false);
        window.setSize (800, 400);
        window.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

    }


    public void init ()
    {
        // /////////////////////////////////
        // ///// IMAGE /////////
        // /////////////////////////////////
        dim = getSize ();
        setBackground (Color.white);
        offscreen = createImage (dim.width, dim.height);
        bufferGraphics = offscreen.getGraphics ();

        // Getting all the images
        m1a = getImage (getCodeBase (), "m1a.gif");
        m1b = getImage (getCodeBase (), "m1b.gif");
        m1 = getImage (getCodeBase (), "m1.gif");

        h1 = getImage (getCodeBase (), "hammer.gif");
        h2 = getImage (getCodeBase (), "hammer2.gif");
        bg = getImage (getCodeBase (), "mainbg.gif");
        gamebg = getImage (getCodeBase (), "gbg.gif");
        button1a = getImage (getCodeBase (), "button1a.gif");
        button1b = getImage (getCodeBase (), "button1b.gif");
        button2a = getImage (getCodeBase (), "button2a.gif");
        button2b = getImage (getCodeBase (), "button2b.gif");

        for (int mnum = 0 ; mnum < 9 ; mnum++)
        {
            mk [mnum] = m1;
        }
        ///////////////////////
        /////// MOUSE /////////
        ///////////////////////

        Toolkit tk = Toolkit.getDefaultToolki开发者_如何学运维t ();
        c = tk.createCustomCursor (tk.getImage (""), new Point (0, 0), "invisible");
        setCursor (c);

        addMouseListener (new MyMouseListener ());
        addMouseMotionListener (new MyMouseMotionListener ());

        repaintTimer = new Timer (500, new RepaintAction (this));
        // start the timer.

    } // end init method


    public void start ()
    {
    }


    public Image getMouseImage ()
    {
        if (myButtonPressed)
        {
            return h2;
        }
        return h1;
    }


    public void handleMouseEvents ()
    {
        int nCol = myMouseX - 50;
        int nRow = myMouseY - 50;
        if (!myButtonEntered) // assumed to be: if myButtonEntered is
            // not = true i.e. false
            nCol = nRow = -1;
        if (nCol != myCol || nRow != myRow)
        {
            myRow = nRow;
            myCol = nCol;
        }

        repaint ();
    } // end handleMouseEvents method


    /////////////////////////////////////
    /////// MOUSELISTENER CLASS /////////
    /////////////////////////////////////

    public class MyMouseListener implements MouseListener
    {
        public void mousePressed (MouseEvent me)
        {
            myButtonPressed = true;
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        }

        public void mouseReleased (MouseEvent me)
        {
            myButtonPressed = false;
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        }

        public void mouseEntered (MouseEvent me)
        {
            myButtonEntered = true;
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        }

        public void mouseExited (MouseEvent me)
        {
            myButtonEntered = false;
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        }

        public void mouseClicked (MouseEvent me)
        {
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        }
    } // end MyMouseListener class


    public class MyMouseMotionListener implements MouseMotionListener
    {
        public void mouseMoved (MouseEvent me)
        {
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        } // end mouseMoved method

        public void mouseDragged (MouseEvent me)
        {
            myMouseX = me.getX ();
            myMouseY = me.getY ();
            handleMouseEvents ();
        } // end mouseDragged method
    } // end MyMouseListener class


    public void mouse ()
    {
        // logic to render mouse...
        if (myRow != -1 && myCol != -1)
        { // if you do not hit co-ordinates -1
            // (out of bounds) then
            Image mouseImage = getMouseImage ();
            bufferGraphics.drawImage (mouseImage, myCol, myRow, 100, 100, null, this);
        } // end if
    }


    public void paint (Graphics g)
    {
        bufferGraphics.clearRect (0, 0, dim.width, dim.height);
        repaint ();
        if (titleScreen == true)
        {
            // System.out.println("drawing the main screen");
            mainScreen ();
        }
        if (gameBegin == true)
        {
            game (g);
        }
        mouse ();
        g.drawImage (offscreen, 0, 0, this);
    } // end Paint method


    public void update (Graphics g)
    {
        paint (g);
    }


    public void mainScreen ()
    {
        bufferGraphics.drawImage (bg, 0, 0, 600, 500, Color.red, this);
        bufferGraphics.drawImage (button1a, 427, 384, 159, 49, Color.red, this);
        bufferGraphics.drawImage (button2a, 427, 440, 159, 49, Color.red, this);
        mouse ();
        if (myButtonPressed == true)
        {
            if (myRow > (384 - 50) && myRow < (433 - 50) && myCol > (427 - 50)
                    && myCol < (586 - 50))
            {
                titleScreen = false;
                gameBegin = true;
            }
            else if (myRow > (340 - 50) && myRow < (489 - 50)
                    && myCol > (427 - 50) && myCol < (586 - 50))
            {
                titleScreen = false;
            }
        }
    }





    public void game (Graphics g)
    {
        // new ReminderBeep (5);
        bufferGraphics.drawImage (gamebg, 0, 0, 600, 500, Color.red, this);
        for (int i = 0 ; i < 9 ; i++)
        {
            bufferGraphics.drawImage (mk [i], mX [i], mY [i], 160, 160, Color.red, this);
        }

        g.drawString ("har", 520, 140);
    }


    public void monkeyhit ()
    {
        if (myButtonPressed == true)
        {
            for (int hit = 0 ; hit < 9 ; hit++)
                if (mhit [hit] == true && myRow > (mY [hit] - 50) && myRow < (mY [hit] + 160 - 50)
                        && myCol > (mX [hit] - 50) && myCol < (mX [hit] + 160 - 50))
                {
                    mk [hit] = m1b;
                    mhhit = true;
                    mhit [hit] = false;
                    score += 10;
                }
        }
        // reset ();
    }


    public void run ()
    {
        monkey ();
    }


    // public void reset ()
    // {
    //     mhhit = false;
    //     for (int x = 0 ; x < 9 ; x++)
    //     {
    //         mk [x] = m1;
    //         mhit [x] = false;
    //
    //     }
    //
    // }


    public void monkey ()
    {
        rand = ((int) (Math.random () * 100000000)) + 10000000;
        randm = ((int) (Math.random () * 100));


        if (randm <= 8)
        {
            for (int a = 0 ; a < 9 ; a++)
            {
                if (randm == a)
                {
                    mhit [randm] = true;
                    mk [randm] = m1a;
                }
                else if (randm != a)
                {
                    mhit [a] = false;
                    mk [a] = m1;
                }
            }

            for (int i = 0 ; i < rand * 100 ; i++)
            {
                monkeyhit ();
                if (mhit [randm] = false)
                    mk [randm] = m1;
                break;
            }
        }
    }



    // Timer
    class GameTime
    {
        Toolkit toolkit;
        Timer timer;

        public GameTime (int seconds)
        {
            toolkit = Toolkit.getDefaultToolkit ();
            timer = new Timer (seconds, new MTask ());
            timer.start ();
        }


        /*
        public void delay(int seconds) {
                toolkit = Toolkit.getDefaultToolkit();
                timer = new Timer();
                timer.schedule(new Mdelay(), seconds * 1000);
        }
        */

        class MTask implements ActionListener
        {
            public void actionPerformed (ActionEvent ae)
            {
                /*
                for (int tsec = 0; tsec < 9; tsec++) {
                        t[tsec] = ((int) (Math.random() * 11)) * 5;
                }
                */

            }
        }
    }


    class RepaintAction implements ActionListener
    {
        Game game;
        public RepaintAction (Game game)
        {
            this.game = game;
        }


        public void actionPerformed (ActionEvent e)
        {
            game.repaint ();
        }
    }
}


In your painting method (or methods called from there), you should only do painting, nothing else (like checking where the mouse is and such).

Everything else should be done separately. For example, calculating (randomizing) the positions of the moles (or monkeys?) should not be done here, but in the timer method, for example.

Your applet needs to have a model, which will be modified by the user interaction and random events. The paint method then looks at this model, and paints according to this.


How would I create this model?

Here's a very simple game that may guide your design. It illustrates the separation between model and view; it also links to related examples. A model having a List<Mole> with each Mole having a javax.swing.Timer seems apt. The model would notify the view when a mole changes state, and the view could query the model for mouse hit-testing.


Never Don't override update() and paint(). That is old AWT code which is not used in Swing.

In Swing custom painting is done by overriding the paintComponent() method of JPanel or JComponent. Then you add the component to the content pane of the applet (or frame or dialog or window).

Read the section from the Swing tutorial on Custom Painting for more information and examples.

Also, in Swing you would never invoke repaint() from within a painting method as this would cause in infinite loop.


You could create a Mole class with a startTime, upTime, and coordinates and have an ArrayList of moles in your main game class. Then, in your paint loop, check if any of the moles have been up for their allocated up time, and if so, remove them. To keep a fairly uniform number of moles at all times, you could create a new mole to replace each mole that is destroyed with a random start time (based on current time), up time, and coordinates.

for(Mole mole : this.moles) {
    if(System.currentTimeMillis() - mole.getStartTime() >= mole.getUpTime()) {
        this.moles.remove(mole); 
    }
}

Threading could also be a suitable, but much more complex alternative.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号