Java画布根本不更新

huangapple go评论81阅读模式
英文:

Java canvas doesn't update at all

问题

我正在尝试制作一个打砖块游戏,在游戏中,初始位于挡板上的球(在下面的代码中称为BAR)以一定的速度(大约100)随机方向发射出去,如果它击中屏幕上的任何砖块,砖块将消失,并且球会相应地改变方向。

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.event.KeyEvent;
import java.awt.event.*;

public class Brick_Breaker extends Canvas implements KeyListener{
    
    // 代码中的各种变量和方法
    
    // ...(省略部分代码)...

    @Override
    public void update(Graphics g){
        BALL_X += BALL_DX;
        BALL_Y += BALL_DY;
        for(int i=0;i<10;i++){
            for(int j=0;j<5;j++){
                // 处理球与砖块的碰撞逻辑
                // ...(省略碰撞检测和碰撞处理的代码)...
            }
        }
        BAR_X = BAR_X +BAR_STATE*BAR_DX;
        repaint();
    }
    
    public static void main(String[] args) {
        Brick_Breaker bb = new Brick_Breaker();
        bb.STaRT();
        for(int i=0;i<10;i++){
            for(int j=0;j<5;j++){
                // 初始化砖块的位置和状态
                // ...(省略初始化砖块的代码)...
            }
        }
    }

    // 代码中的其他方法和事件处理
}

在这里,update 函数似乎根本没有进行更新。我对这个方法的工作原理也不太确定。如果可以的话,希望能得到帮助。

英文:

I'm trying to make a Brick Breaker game where the ball which is initially on the paddle(referred to as BAR in the code below) is launched with a speed(approx 100) in some random direction, if it hits any brick on the screen the brick disappears and the ball changes direction accordingly.

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.event.KeyEvent;
import java.awt.event.*;

public class Brick_Breaker extends Canvas implements KeyListener{
    
    int BRICK_WIDTH=60,BRICK_HEIGHT=30,X=0,Y=0;
    int BAR_X = 390,BAR_Y=560,BAR_WIDTH=120,BAR_HEIGHT=20,BAR_DX=10;
    int BALL_X=440,BALL_Y=540,BALL_SIZE=20,BALL_DX=0,BALL_DY=0;
    int LEFT_WALL=100,RIGHT_WALL=800,TOP_WALL=10;
    boolean GAME_STATE=false;
    int BAR_STATE=0;
    
    
    static int[][] y = new int[10][5];
    static int[][] x = new int[10][5];
    static int[][] status = new int[10][5];
    
    static Canvas canvas;
    static JFrame frame;
    @Override
    public void keyReleased(KeyEvent ke){}
    @Override
    public void keyTyped(KeyEvent ke){}
    
    public void STaRT(){
        frame = new JFrame(&quot;My Drawing&quot;);
        frame.addKeyListener(this);
        canvas = new Brick_Breaker();
        canvas.setSize(900, 600);
        frame.add(canvas);
        frame.pack();
        frame.setVisible(true);
    }
    
    
    @Override
    public void update(Graphics g){
        BALL_X += BALL_DX;
        BALL_Y += BALL_DY;
        for(int i=0;i&lt;10;i++){
            for(int j=0;j&lt;5;j++){
                if(BALL_X&gt;x[i][j]&amp;&amp;BALL_X&lt;(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&lt;=y[i][j]+BAR_HEIGHT+BALL_SIZE &amp;&amp; BALL_Y&gt;y[i][j]&amp;&amp;BALL_DY&lt;0){
                    BALL_DY=-BALL_DY;
                    status[i][j]-=1;
                }else if(BALL_X&gt;x[i][j]&amp;&amp;BALL_X&lt;(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&gt;=y[i][j]-BALL_SIZE &amp;&amp; BALL_Y&lt;y[i][j]+BAR_HEIGHT&amp;&amp;BALL_DY&gt;0){
                    BALL_DY=-BALL_DY;
                    status[i][j]-=1;
                }else if(BALL_X+BALL_SIZE&gt;=x[i][j]&amp;&amp;BALL_X&lt;(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&gt;=y[i][j] &amp;&amp; BALL_Y&lt;y[i][j]+BAR_HEIGHT&amp;&amp;BALL_DY&lt;0){
                    BALL_DX=-BALL_DX;
                    status[i][j]-=1;
                }else if(BALL_X&gt;x[i][j]&amp;&amp;BALL_X-BALL_SIZE&lt;=(x[i][j]+BRICK_WIDTH)&amp;&amp;BALL_Y&gt;=y[i][j] &amp;&amp; BALL_Y&lt;y[i][j]+BAR_HEIGHT&amp;&amp;BALL_DY&lt;0){
                    BALL_DX=-BALL_DX;
                    status[i][j]-=1;
                }else if(BALL_X-BALL_SIZE&lt;LEFT_WALL||BALL_X+BALL_SIZE&gt;RIGHT_WALL){
                    BALL_DX=-BALL_DX;
                }else if(BALL_Y-BALL_SIZE&lt;TOP_WALL){
                    BALL_DY=-BALL_DY;
                }
            }
        }
        BAR_X = BAR_X +BAR_STATE*BAR_DX;
        repaint();
    }
    public static void main(String[] args) {
       Brick_Breaker bb = new Brick_Breaker();
       bb.STaRT();
        for(int i=0;i&lt;10;i++){
            for(int j=0;j&lt;5;j++){
                x[i][j] = 300+60*j;
                y[i][j] = 50+30*i;
                status[i][j] = 1;
            }
        }
    }
    
    @Override
    public void keyPressed(KeyEvent ke){
        if(!GAME_STATE){
            BALL_DX = (int)(100*Math.random());
            BALL_DY = (int)(Math.sqrt(100*100-BALL_DX*BALL_DX));
            GAME_STATE = true;
        }else if(ke.getKeyCode() == KeyEvent.VK_LEFT){
            BAR_STATE=-1;
        }else if(ke.getKeyCode()==KeyEvent.VK_RIGHT){
            BAR_STATE=1;
        }
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.setColor(Color.white);
        g.drawLine(LEFT_WALL,600, LEFT_WALL, TOP_WALL);
        g.drawLine(RIGHT_WALL, 600, RIGHT_WALL, TOP_WALL);
        g.drawLine(LEFT_WALL,TOP_WALL,RIGHT_WALL,TOP_WALL);
        g.fillRect(BAR_X,BAR_Y,BAR_WIDTH,BAR_HEIGHT);
        g.setColor(Color.red);
        g.fillOval(BALL_X, BALL_Y, BALL_SIZE, BALL_SIZE);
        for(int i=0;i&lt;10;i++){
            for(int j=0;j&lt;5;j++){
                if(status[i][j]&gt;0){
                    X = x[i][j];Y=y[i][j];
                    g.setColor(Color.white);
                    g.fillRect(X, Y, BRICK_WIDTH, BRICK_HEIGHT);
                    g.setColor(Color.red);
                    g.fillRect(X+3, Y+3, BRICK_WIDTH-6, BRICK_HEIGHT-6);
                }
            }
        }
        setBackground(Color.black);
    }
}

Here the update function doesn't seem to update at all.
I'm not really sure on how the method works as well.
Any help would be appreciated

答案1

得分: 2

Canvas是一个相当底层的组件,只有在需要使用BufferStrategy时才会考虑使用它。

update在绘制阶段被调用,由于您覆盖了它而没有调用它的super实现,导致绘制工作流程出现问题。

AWT和Swing通常使用被动渲染系统,这意味着只有在系统决定需要更新时才会发生更新,因此以您的方式覆盖update并不合适,也不会对您有所帮助。

一个更好的起点是使用JPanel,主要原因是它具有双缓冲功能,可以避免您烦恼于如何消除闪烁问题。

一个好的起点是查看 执行自定义绘制在AWT和Swing中进行绘制 来更好地理解绘制的工作原理(以及如何与之一起工作)。

KeyListener也不是一个很好的输入监控选择,可以在 Stack Overflow 上搜索所有相关原因。

一个更好、一般来说问题较少的方法是使用键绑定

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;

public class Test {

    // ...(此处省略了您提供的其他代码)...
    
}

我对 delta 值进行了调整,因为球和挡板消失得非常快。

英文:

Canvas is a pretty low level component and one which I'd only consider using if I needed to use a BufferStrategy.

update is called as part of the paint phase and because you've overridden it without calling it's super implementation, you broke the paint workflow.

AWT and Swing generally employ a passive rendering system, this means that updates only occur when the system decides it needs to happen, so overriding update the way you have doesn't really make sense and isn't going to help you.

A better place to start is with a JPanel, the main reason is because it's double buffered and saves you hassles of trying to figure out how to eliminate flickering.

A good place to start is Performing Custom Painting and Painting in AWT and Swing to gain a better understanding of how painting works (and how you should work with it).

KeyListener is also a poor choice for input monitoring, seriously, just do some searching on SO for all the reasons why.

A better, and generally less problematic approach is to use key bindings as well.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        int BRICK_WIDTH = 60, BRICK_HEIGHT = 30, X = 0, Y = 0;
        int BAR_X = 390, BAR_Y = 560, BAR_WIDTH = 120, BAR_HEIGHT = 20, BAR_DX = 1;
        int BALL_X = 440, BALL_Y = 540, BALL_SIZE = 20, BALL_DX = 0, BALL_DY = 0;
        int LEFT_WALL = 100, RIGHT_WALL = 800, TOP_WALL = 10;
        boolean GAME_STATE = false;
        int BAR_STATE = 0;

        int[][] y = new int[10][5];
        int[][] x = new int[10][5];
        int[][] status = new int[10][5];

        private Timer timer;

        public TestPane() {
            for (int i = 0; i &lt; 10; i++) {
                for (int j = 0; j &lt; 5; j++) {
                    x[i][j] = 300 + 60 * j;
                    y[i][j] = 50 + 30 * i;
                    status[i][j] = 1;
                }
            }
            BALL_DX = 0; //(int) (100 * Math.random());
            BALL_DY = -1;//(int) (Math.sqrt(100 * 100 - BALL_DX * BALL_DX));
            setBackground(Color.BLACK);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), &quot;left&quot;);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), &quot;right&quot;);

            ActionMap am = getActionMap();
            am.put(&quot;left&quot;, new KeyAction(this, -1));
            am.put(&quot;right&quot;, new KeyAction(this, 1));
        }

        @Override
        public void addNotify() {
            super.addNotify(); //To change body of generated methods, choose Tools | Templates.
            if (timer == null) {
                timer = new Timer(5, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        tick();
                    }
                });
                timer.start();
            }
        }

        @Override
        public void removeNotify() {
            super.removeNotify();
            if (timer != null) {
                timer.stop();
                timer = null;
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(900, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.white);
            g2d.drawLine(LEFT_WALL, 600, LEFT_WALL, TOP_WALL);
            g2d.drawLine(RIGHT_WALL, 600, RIGHT_WALL, TOP_WALL);
            g2d.drawLine(LEFT_WALL, TOP_WALL, RIGHT_WALL, TOP_WALL);
            g2d.fillRect(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT);
            g2d.setColor(Color.red);
            g2d.fillOval(BALL_X, BALL_Y, BALL_SIZE, BALL_SIZE);
            for (int i = 0; i &lt; 10; i++) {
                for (int j = 0; j &lt; 5; j++) {
                    if (status[i][j] &gt; 0) {
                        X = x[i][j];
                        Y = y[i][j];
                        g2d.setColor(Color.white);
                        g2d.fillRect(X, Y, BRICK_WIDTH, BRICK_HEIGHT);
                        g2d.setColor(Color.red);
                        g2d.fillRect(X + 3, Y + 3, BRICK_WIDTH - 6, BRICK_HEIGHT - 6);
                    }
                }
            }

            g2d.dispose();
        }

        protected void tick() {
            BALL_X += BALL_DX;
            BALL_Y += BALL_DY;
            for (int i = 0; i &lt; 10; i++) {
                for (int j = 0; j &lt; 5; j++) {
                    if (BALL_X &gt; x[i][j] &amp;&amp; BALL_X &lt; (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &lt;= y[i][j] + BAR_HEIGHT + BALL_SIZE &amp;&amp; BALL_Y &gt; y[i][j] &amp;&amp; BALL_DY &lt; 0) {
                        BALL_DY = -BALL_DY;
                        status[i][j] -= 1;
                    } else if (BALL_X &gt; x[i][j] &amp;&amp; BALL_X &lt; (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &gt;= y[i][j] - BALL_SIZE &amp;&amp; BALL_Y &lt; y[i][j] + BAR_HEIGHT &amp;&amp; BALL_DY &gt; 0) {
                        BALL_DY = -BALL_DY;
                        status[i][j] -= 1;
                    } else if (BALL_X + BALL_SIZE &gt;= x[i][j] &amp;&amp; BALL_X &lt; (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &gt;= y[i][j] &amp;&amp; BALL_Y &lt; y[i][j] + BAR_HEIGHT &amp;&amp; BALL_DY &lt; 0) {
                        BALL_DX = -BALL_DX;
                        status[i][j] -= 1;
                    } else if (BALL_X &gt; x[i][j] &amp;&amp; BALL_X - BALL_SIZE &lt;= (x[i][j] + BRICK_WIDTH) &amp;&amp; BALL_Y &gt;= y[i][j] &amp;&amp; BALL_Y &lt; y[i][j] + BAR_HEIGHT &amp;&amp; BALL_DY &lt; 0) {
                        BALL_DX = -BALL_DX;
                        status[i][j] -= 1;
                    } else if (BALL_X - BALL_SIZE &lt; LEFT_WALL || BALL_X + BALL_SIZE &gt; RIGHT_WALL) {
                        BALL_DX = -BALL_DX;
                    } else if (BALL_Y - BALL_SIZE &lt; TOP_WALL) {
                        BALL_DY = -BALL_DY;
                    }
                }
            }
            BAR_X = BAR_X + BAR_STATE * BAR_DX;
            repaint();
        }

        class KeyAction extends AbstractAction {

            private TestPane source;
            private int delta;

            public KeyAction(TestPane source, int delta) {
                this.source = source;
                this.delta = delta;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                source.BAR_STATE = delta;
            }

        }
    }
}

I've messed with delta values, because the ball and bar disappeared real quick

huangapple
  • 本文由 发表于 2020年9月25日 19:16:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/64063073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定