3

我正在创建一个视频游戏,当我调用 repaint() 方法时,整个屏幕会更新并不规则地闪烁。通过在这行代码中指定重绘的内容(charRect,它是一个 Rectangle 对象),我稍微解决了这个问题: repaint(charRect.x, charRect.y, 20, 32); 整个屏幕停止闪烁,但这个角色却出奇地小故障。我只需要帮助让动画从移动(a 和 d)和跳跃(w)顺利运行。

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.io.*;
import java.net.*;
import java.lang.*;
import static java.lang.Math.*;
import static java.lang.System.out;
import java.util.Random.*;
import javax.swing.JApplet;
import java.awt.Graphics;

public class UltimaBlade extends JApplet implements KeyListener
{
public final int        WIDTH = 900;
public final int        HEIGHT = 650;

public  int             score = 0;
private boolean         jumping = false;
private boolean         moveRight = false;
private boolean         moveLeft = false;
private boolean         jumpRight = false;
private boolean         jumpLeft = false;
private boolean         moveRightWhileJumping = false;
private boolean         moveLeftWhileJumping = false;

public  JFrame          JTitle = new JFrame("UltimaBlade"); 
        Image           characterImg = null;
        Image           blockImg1 = null;
        Image           floorImg1 = null;
        Image           wallImg1 = null;
             JLabel          scoreLabel = new JLabel("Score: " + score);

        Rectangle       charRect = new Rectangle(25, 450, 20, 32);
        Rectangle       blockRect1 = new Rectangle(25, 482, 30, 30);
        Rectangle       floorRect1 = new Rectangle(25, 482, 200, 1);CHANGE BACK TO 30
        Rectangle       wallRect1 = new Rectangle(55, 490, 1, 30);
        //Rectangle       tempGhost = new Rectangle(charRect.x, charRect.y, 20, 32);

public  JMenuBar        mb = new JMenuBar();
public  JMenu           menuFile = new JMenu("File");
public  JMenuItem       menuItemSave = new JMenuItem("Save");
public  JMenuItem       menuItemLoad = new JMenuItem("Load");
        Container       cont;
        Runner          runner;

public void init()
{
    setSize(WIDTH, HEIGHT);

    JTitle.setJMenuBar(mb);
    menuFile.add(menuItemSave);
    menuFile.add(menuItemLoad);
    mb.add(menuFile);
    JTitle.getContentPane().setLayout(new BorderLayout());
    menuItemSave.addActionListener(new ListenMenuSave());
    setJMenuBar(mb);
    new UltimaBlade();
}

public UltimaBlade()
{
    setLayout(null);
    setSize(WIDTH, HEIGHT);
    setVisible(true);

    cont = getContentPane();
    cont.setLayout(null);
    addKeyListener(this);
    cont.setBackground(Color.WHITE);

    cont.add(scoreLabel);
    scoreLabel.setBounds(50, 50, 100, 30);
    scoreLabel.setForeground(Color.BLACK);
    cont.setLayout(null);

    repaint();
    cont.validate();

    runner = new Runner();
    runner.start();
    setContentPane(cont);
}

public class ListenMenuSave implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        new Save();
    }
}

public void paint(Graphics g)
{
    super.paint(g);

    try
    {
        URL     url1 = this.getClass().getResource("character.gif");       //Character
                characterImg = Toolkit.getDefaultToolkit().getImage(url1);
        URL     url2 = this.getClass().getResource("block.gif");           //Block
                blockImg1 = Toolkit.getDefaultToolkit().getImage(url2);
        URL     url3 = this.getClass().getResource("floor_line.gif");      //Floor Line
                floorImg1 = Toolkit.getDefaultToolkit().getImage(url3);
        URL     url4 = this.getClass().getResource("wall_line.gif");      //Wall Line
                wallImg1 = Toolkit.getDefaultToolkit().getImage(url4);
    }
    catch(Exception e)
    {

    }

    g.drawImage(characterImg, charRect.x, charRect.y, this);
    g.drawImage(floorImg1, floorRect1.x, floorRect1.y, this);
    g.drawImage(blockImg1, blockRect1.x, blockRect1.y, this);
    g.drawImage(wallImg1, wallRect1.x, wallRect1.y, this);
}

public void keyPressed(KeyEvent e)
{
    if(e.getKeyChar() == 'd' || e.getKeyChar() == 'D')
    {
        moveRight = true;
        if(jumping)
            moveRightWhileJumping = true;
    }
    if(e.getKeyChar() == 'a' || e.getKeyChar() == 'A')
    {
        moveLeft = true;
        if(jumping)
            moveLeftWhileJumping = true;
    }
}

public void keyReleased(KeyEvent e)
{
    if(e.getKeyChar() == 'd' || e.getKeyChar() == 'D')
    {
        moveRight = false;
        if(!jumping)
            moveRightWhileJumping = false;
    }
    if(e.getKeyChar() == 'a' || e.getKeyChar() == 'A')
    {
        moveLeft = false;
        if(!jumping)
            moveLeftWhileJumping = false;
    }
}

public void keyTyped(KeyEvent e)
{
    if(e.getKeyChar() == 'w' || e.getKeyChar() == 'W')
    {
        jumping = true;
    }
}

public class Runner extends Thread// implements Runnable
{
    public void run()
    {
        while(true)
        {
            try
            {
                int     j = 5;     //Beginning velocity
                double  t = 0;
                double  sum = j/5;
                while(jumping)
                {
                    repaint(charRect.x, charRect.y, 20, 32);
                    cont.validate();
                    int jump = (int)((-4.9 * ((t * t)/10)) + (j * t));
                    if(moveRightWhileJumping)
                    {
                        charRect.x = charRect.x + j; // Move Right while jumping.
                        if(charRect.intersects(wallRect1))
                        {
                            charRect.x = wallRect1.x - 21;
                            moveRightWhileJumping = false;
                        }
                    }
                    if(moveLeftWhileJumping)
                    {
                        charRect.x = charRect.x - j;  //Move Left while jumping.
                        if(charRect.intersects(wallRect1))
                        {
                            charRect.x = wallRect1.x + 1;
                            moveLeftWhileJumping = false;
                        }
                    }
                    if(jump > 0)
                    {
                        charRect.y = charRect.y - Math.abs(jump);
                        if(charRect.intersects(floorRect1))
                        {
                            charRect.y = floorRect1.y - 32;
                            jumping = false;
                            moveRightWhileJumping = false;
                            moveLeftWhileJumping = false;
                            break;
                        }
                    }
                    else if(jump < 0)
                    {
                        charRect.y = charRect.y + Math.abs(jump);
                        if(charRect.intersects(floorRect1))
                        {
                            charRect.y = floorRect1.y - 32;
                            jumping = false;
                            moveRightWhileJumping = false;
                            moveLeftWhileJumping = false;
                            break;
                        }
                    }
                    else
                    {
                        if(charRect.intersects(floorRect1))
                        {
                            charRect.y = floorRect1.y - 32;
                            jumping = false;
                            moveRightWhileJumping = false;
                            moveLeftWhileJumping = false;
                            break;
                        }
                    }

                    t++;
                    Thread.sleep(30);
                }


                while(moveLeft)
                {
                    repaint(charRect.x, charRect.y, 20, 32);
                    cont.validate();
                    charRect.x = charRect.x - j;  //Move Left speed.
                    if(charRect.intersects(wallRect1))
                    {
                        charRect.x = wallRect1.x + 1;
                    }
                    if(charRect.intersects(floorRect1))
                    {
                        charRect.y = floorRect1.y - 32;
                        jumping = false;
                        moveRightWhileJumping = false;
                        moveLeftWhileJumping = false;
                        break;
                    }
                    t++;
                    Thread.sleep(30);
                }


                while(moveRight)
                {
                    repaint(charRect.x, charRect.y, 20, 32);
                    cont.validate();
                    charRect.x = charRect.x + j;  //Move Left speed.
                    if(charRect.intersects(wallRect1))
                    {
                        charRect.x = wallRect1.x + 1;
                    }
                    if(charRect.intersects(floorRect1))
                    {
                        charRect.y = floorRect1.y - 32;
                        jumping = false;
                        moveRightWhileJumping = false;
                        moveLeftWhileJumping = false;
                        break;
                    }
                    t++;
                    Thread.sleep(30);
                }
            }
            catch(Exception e)
            {
                break;
            }
        }
    }
}

}

4

1 回答 1

3

您的主要问题之一是您直接在paint(...)JApplet 方法本身中进行绘制,而不是在paintComponent(...)applet 所持有的 JPanel 或 JCompnent 方法中进行绘制。如果您使用后者,您将受益于 Swing 的默认双缓冲,而这会带来很大的不同。此外,您可以使用其中一个repaint(...)重载重绘 GUI 的较小矩形,但这是次要的。首先你应该解决你缺乏双缓冲的问题。

请从本教程开始学习基础知识:课程:执行自定义绘画

然后继续阅读本文,了解有关在 Swing 中绘图的更多高级信息:在 AWT 和 Swing 中绘图

Edit
Also, you should never read in files from within the paint(...) or paintComponent(...) methods as this will slow painting down and thereby reduce perceived responsiveness of your GUI several fold. Why not simply read in the files once and on applet startup, and then store their contents into a variable?

于 2012-07-10T00:42:39.447 回答