【问题标题】:How do I make a java action perform smoother?如何使 java 动作执行更流畅?
【发布时间】:2014-02-26 16:06:06
【问题描述】:

我创建了一个简单的程序,该程序根据您按下按钮的次数填充仪表,最终形成“按下按钮获胜”风格的游戏。我将它设置为每次按下空格键时,仪表会填充 10/440,如果达到最大值,440,你就赢了。我遇到的问题是如何使添加的增量更平滑且不那么突然;就好像你在给自行车轮胎打气一样:连续的,较少的增量。 这是有问题的代码:

import javax.swing.JOptionPane;
import javax.swing.*;               
import java.util.*;                             
import static java.lang.System.*;
import static java.lang.Math.*;
import java.awt.*;                              
import java.awt.event.*;                                
import java.io.*;   //for files                     
public class MyClicker
{
    public static void main(String args[])
    {
        new Clicker();  //Make a window
    }

}
class Clicker extends Frame   implements KeyListener, MouseListener
{
    // global variables
    private final static int SCHEIGHT=768,SCWIDTH=1024;
    // direction constants

    final static int N = 0,NE = 1,E = 2,SE = 3, S = 4, SW = 5, W = 6, NW =7,STILL = 8;
    // movement change constants
    final  int X = 0,Y = 1,Z = 2;
    final int TITLE = 30, STATUS = 40;
    final static int size = 2;
    Image myPic;

    private boolean gameNotOver = true;
    private boolean keyPressed = false;
    private Image myScreen;
    private int whichScreen;
    private int timePassed;
    private int numScreen;
    private int maxAmt=450;
    private int timer;
    private int amt;

    public Clicker()
    {       
        setSize(SCWIDTH,SCHEIGHT);
        addWindowListener(new WindowAdapter()
              {
                  public void windowClosing(WindowEvent e)
                    {
                      System.exit(0);
                    }
               });
       timer = -1;
       this.setVisible(true);
       out.println(amt);
       this.addKeyListener(this);
       gameLoop();
    }
public void gameLoop()
{   
    do   
     {
        if (keyPressed)
           {
             amt = amt + 50;
             out.println(keyPressed + " " +gameNotOver+" "+ "Time "+timer);
             this.repaint();
             keyPressed = false;
           }
        if(amt >= 400)
            gameNotOver = false;
        pause(1000);
        timer++;
        this.setVisible(true);
        //this.repaint();
        pause(0);
        if(amt > maxAmt - 10)   
            amt = maxAmt - 10;
     }
   while (gameNotOver);

   if(!gameNotOver)
    {
        pause(5000);
        System.exit(0);
    }

}
public int getAmt()
{
    return amt;
}
public void paint(Graphics pen)
 {    
        if(whichScreen==0)
            {
                pen.drawImage(myPic,100,200,506,279,this);   //Draws the image
                pen.setFont(new Font("Timesroman", Font.ITALIC, 50));
                pen.drawString("Welcome to the Clicker Test", 200, 75);
                pen.setFont(new Font("Timesroman", Font.ITALIC, 40));
                pen.drawString("Created by Cody Coulter",150,150);
                pen.setFont(new Font("Timesroman", Font.ITALIC, 25));
                pause(200); // 2000 final           
                whichScreen++;
                doubleBuffer(pen);
            }
        else
            {
                myScreen =createImage(getSize().width,getSize().height);
                Graphics o = myScreen.getGraphics();
                doubleBuffer(o);
                pen.drawImage(myScreen,0,0,this);
            }
 }   
public void doubleBuffer(Graphics pen)  // Draws the window
 {     
          pause (500);
          numScreen++;
          if (numScreen > 0)          
               {      
                    setBounds(0,0,SCWIDTH,SCHEIGHT);
                    Color HPRed = new Color(213, 0, 0);
                    pen.setColor(Color.BLACK);
                    setTitle("Clicker Test  -- Cody Coulter."+
                             "To click, press the space bar");
                    pen.setFont(new Font("Timesroman",Font.PLAIN,48));
                    pen.drawString("Clicker Test ",350,75);
                    pen.setFont(new Font("TimesRoman",Font.BOLD,33));
                    pen.fillRect((SCWIDTH/4), (SCHEIGHT/3), 50, maxAmt);
                    pen.drawString(""+timer, 350, 150);

                    pen.setColor(HPRed);
                    pen.fillRect((SCWIDTH/4)+5, (SCHEIGHT/3)+5, 40, amt);


                    if(!gameNotOver)
                     {
                        if(amt >= maxAmt-10)
                        {
                            pen.setColor(HPRed);
                            pen.fillRect(SCWIDTH/4-75, SCHEIGHT/3, SCWIDTH/2+150, SCHEIGHT/3-60);
                            pen.setColor(Color.GRAY);
                            pen.fillRect(SCWIDTH/4-65, SCHEIGHT/3+10, SCWIDTH/2+130, SCHEIGHT/3-80);
                            pen.setColor(Color.YELLOW);
                            pen.setFont(new Font("Verdana", Font.BOLD, 40));
                            pen.drawString("You got it!", SCWIDTH/2-290, SCHEIGHT/2-20);
                        }
                     }
                    this.repaint();
               }
}    
public void keyPressed(KeyEvent e)
{
    keyPressed = true;
    setTitle(""+ KeyEvent.getKeyText(e.getKeyCode()));  
    System.out.println("hit + "+ KeyEvent.getKeyText(e.getKeyCode())+ " " + keyPressed);
    switch(e.getKeyCode())
       {
          case KeyEvent.VK_SPACE: if(amt < maxAmt - 10)
                                      amt= amt + 10;
                                  break; 
          case KeyEvent.VK_A: if(amt < maxAmt - 10)
                                      amt = amt + 10;
                                  break;
       }
}
public void mouseClicked(MouseEvent m)
{
}   
public void mouseEntered(MouseEvent m)
{
}   
public void mouseExited(MouseEvent m)
{
}   
public void mousePressed(MouseEvent m)
{
}   
public void mouseReleased(MouseEvent m)
{
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}

public void update(Graphics G)
{
      paint(G);
}       
public static void pause (long r)
{
    try
       {
           Thread.sleep(r);
       }
    catch (Exception e) 
       {
           out.println(" sleep error " + e);
        }          
}
}  //end class         

这是完全最新的代码:

import javax.swing.JOptionPane;
import javax.swing.*;               
import java.util.*;                             
import static java.lang.System.*;
import static java.lang.Math.*;
import java.awt.*;                              
import java.awt.event.*;                                
import java.io.*;   //for files

public class MyClicker
{
    public static void main(String args[])
    {
        new Clicker();  //Make a window
    }

}
class Clicker extends Frame   implements KeyListener, MouseListener
{
    // global variables
    private final static int SCHEIGHT=768,SCWIDTH=1024;
    // direction constants

    final static int N = 0,NE = 1,E = 2,SE = 3, S = 4, SW = 5, W = 6, NW =7,STILL = 8;
    // movement change constants
    final  int X = 0,Y = 1,Z = 2;
    final int TITLE = 30, STATUS = 40;
    final static int size = 2;
    Image myPic;

    private boolean gameNotOver = true;
    private boolean keyPressed = false;
    private Image myScreen;
    private int whichScreen;
    private int timePassed;
    private int numScreen;
    private int maxAmt=450;
    private int dispAmt;
    private int actAmt;
    private double timer;

    public Clicker()
    {       
        setSize(SCWIDTH,SCHEIGHT);
        addWindowListener(new WindowAdapter()
              {
                  public void windowClosing(WindowEvent e)
                    {
                      System.exit(0);
                    }
               });
       timer = -1;
       this.setVisible(true);
       this.addKeyListener(this);
       gameLoop();
    }
public void gameLoop()
{   
    do   
     {
        if (keyPressed)
           {
             out.println(keyPressed + " " +gameNotOver+" "+ "Time "+timer);
             keyPressed = false;
           }
        if(dispAmt > maxAmt-10)
            dispAmt = maxAmt;
        if(actAmt >= maxAmt-10 || dispAmt >= maxAmt-10)
            gameNotOver = false;
        if(dispAmt < actAmt)
            dispAmt++;
        timer++;
        this.setVisible(true);
//          this.repaint();
//          pause(0);
//          if(actAmt > maxAmt - 10 || dispAmt > maxAmt - 10)   
//              actAmt = maxAmt - 10;

        this.repaint();
     }
   while (gameNotOver);

   if(!gameNotOver)
    {
        pause(5000);
        System.exit(0);
    }

}
public int getAmt()
{
    return actAmt;
}
public void paint(Graphics pen)
 {    
        if(whichScreen==0)
            {
                pen.drawImage(myPic,100,200,506,279,this);   //Draws the image
                pen.setFont(new Font("Timesroman", Font.ITALIC, 50));
                pen.drawString("Welcome to the Clicker Test", 200, 75);
                pen.setFont(new Font("Timesroman", Font.ITALIC, 40));
                pen.drawString("Created by Cody Coulter",150,150);
                pen.setFont(new Font("Timesroman", Font.ITALIC, 25));
                pause(200); // 2000 final           
                whichScreen++;
                doubleBuffer(pen);
            }
        else
            {
                myScreen =createImage(getSize().width,getSize().height);
                Graphics o = myScreen.getGraphics();
                doubleBuffer(o);
                pen.drawImage(myScreen,0,0,this);
            }
 }   
public void doubleBuffer(Graphics pen)  // Draws the window
 {     
          numScreen++;
          if (numScreen > 0)          
               {      
                    setBounds(0,0,SCWIDTH,SCHEIGHT);
                    Color HPRed = new Color(213, 0, 0);
                    pen.setColor(Color.BLACK);
                    setTitle("Clicker Test  -- Cody Coulter."+
                             "To click, press the space bar");
                    pen.setFont(new Font("Timesroman",Font.PLAIN,48));
                    pen.drawString("Clicker Test ",350,75);
                    pen.setFont(new Font("TimesRoman",Font.BOLD,33));
                    pen.fillRect((SCWIDTH/4), (SCHEIGHT/3), 50, maxAmt);
                    pen.drawString(""+timer/1000, 350, 150);
                    pen.drawString(""+dispAmt+"  /  "+actAmt, 350, 200);

                    pen.setColor(HPRed);
                    pen.fillRect((SCWIDTH/4)+5, (SCHEIGHT/3)+5, 40, dispAmt);


                    if(!gameNotOver)
                     {
                        if(actAmt >= maxAmt-10)
                        {
                            pen.setColor(HPRed);
                            pen.fillRect(SCWIDTH/4-75, SCHEIGHT/3, SCWIDTH/2+150, SCHEIGHT/3-60);
                            pen.setColor(Color.GRAY);
                            pen.fillRect(SCWIDTH/4-65, SCHEIGHT/3+10, SCWIDTH/2+130, SCHEIGHT/3-80);
                            pen.setColor(Color.YELLOW);
                            pen.setFont(new Font("Verdana", Font.BOLD, 40));
                            pen.drawString("You got it!", SCWIDTH/2-290, SCHEIGHT/2-20);
                        }
                     }
                    this.repaint();
               }
}    
public void keyPressed(KeyEvent e)
{
    keyPressed = true;
    setTitle(""+ KeyEvent.getKeyText(e.getKeyCode()));  
    System.out.println("hit + "+ KeyEvent.getKeyText(e.getKeyCode())+ " " + keyPressed);
    switch(e.getKeyCode())
       {
          case KeyEvent.VK_SPACE:actAmt = actAmt+10;
                                  break; 
          case KeyEvent.VK_A: actAmt = actAmt+10;
                                  break;
       }
    this.repaint();
}
public void mouseClicked(MouseEvent m)
{
}   
public void mouseEntered(MouseEvent m)
{
}   
public void mouseExited(MouseEvent m)
{
}   
public void mousePressed(MouseEvent m)
{
}   
public void mouseReleased(MouseEvent m)
{
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}

public void update(Graphics G)
{
      paint(G);
}       
public static void pause (long r)
{
    try
       {
           Thread.sleep(r);
       }
    catch (Exception e) 
       {
           out.println(" sleep error " + e);
        }          
}
}  //end class

【问题讨论】:

    标签: java graphics timer refresh


    【解决方案1】:
    • 去掉 pause(1000) 你可以让它 pause(10) 或类似的东西。

    • 每次在循环中(在 if 语句之外)调用 this.repaint()。

    • 将金额拆分为两个变量:实际金额和显示金额。只画显示的金额,按键只会增加实际的金额。

    • 每一帧,如果显示数量小于实际数量,则增加1。

    更新...

    • 从双缓冲例程中删除 pause(500),并从绘画中删除 pause(200)。一般来说,除非你需要“什么都不做”,否则不要暂停。游戏从不“无所事事”,它们几乎总是有一个至少在渲染的核心循环。

    【讨论】:

    • 这非常有帮助。为了澄清您的第三点,您是说我应该为每个 dispAmt 和 actAmt 创建一个私有 int?并且在这样做时,使用 pen.fillRect((SCWIDTH/4)+5, (SCHEIGHT/3)+5, 40, dispAmt);如果这不正确,对不起,只是编程的新手,所以我仍在努力理解所有目的,再次感谢您
    • 是的。听起来你明白了。您将不再拥有“amt”,而是拥有“dispAmt”和“actAmt”。祝你好运!
    • 重读您的观点后,我明白了,之前不理解的感觉很愚蠢......但是,现在我已经取消了暂停,并且增量已经稳定,并且仪表起作用了正是我的意图。感谢您的帮助,但最初的询问并没有真正解决。现在,我的程序完全按照我想要的方式增加,但每次我按下空格键以增加仪表时,它大约每 0.75 秒响应一次。我希望它能够立即响应,就好像它是连续的而不是离散的。如果不可能,还是谢谢你
    • 如果您将 this.repaint() 移动到按键处理程序的末尾,它将立即更新。还要从你的双缓冲例程中去掉 pause(500)。
    • 按键处理程序,您指的是 keyPressed(KeyEvent e) 方法吗?如果是这样,您是说我在 Switch 之后或在每种情况下插入重绘?我想如果你愿意的话,如果它读取在开关/案例“库”中按下的任何键,我想方法的底部会是最好的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多