Java canvas根本不更新

如何解决Java canvas根本不更新

我正在尝试制作打砖块游戏,其中最初在桨上的球(在下面的代码中称为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{
    
    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("My Drawing");
        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<10;i++){
            for(int j=0;j<5;j++){
                if(BALL_X>x[i][j]&&BALL_X<(x[i][j]+BRICK_WIDTH)&&BALL_Y<=y[i][j]+BAR_HEIGHT+BALL_SIZE && BALL_Y>y[i][j]&&BALL_DY<0){
                    BALL_DY=-BALL_DY;
                    status[i][j]-=1;
                }else if(BALL_X>x[i][j]&&BALL_X<(x[i][j]+BRICK_WIDTH)&&BALL_Y>=y[i][j]-BALL_SIZE && BALL_Y<y[i][j]+BAR_HEIGHT&&BALL_DY>0){
                    BALL_DY=-BALL_DY;
                    status[i][j]-=1;
                }else if(BALL_X+BALL_SIZE>=x[i][j]&&BALL_X<(x[i][j]+BRICK_WIDTH)&&BALL_Y>=y[i][j] && BALL_Y<y[i][j]+BAR_HEIGHT&&BALL_DY<0){
                    BALL_DX=-BALL_DX;
                    status[i][j]-=1;
                }else if(BALL_X>x[i][j]&&BALL_X-BALL_SIZE<=(x[i][j]+BRICK_WIDTH)&&BALL_Y>=y[i][j] && BALL_Y<y[i][j]+BAR_HEIGHT&&BALL_DY<0){
                    BALL_DX=-BALL_DX;
                    status[i][j]-=1;
                }else if(BALL_X-BALL_SIZE<LEFT_WALL||BALL_X+BALL_SIZE>RIGHT_WALL){
                    BALL_DX=-BALL_DX;
                }else if(BALL_Y-BALL_SIZE<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<10;i++){
            for(int j=0;j<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,RIGHT_WALL,TOP_WALL);
        g.drawLine(LEFT_WALL,TOP_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<10;i++){
            for(int j=0;j<5;j++){
                if(status[i][j]>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);
    }
}

这里,更新功能似乎根本没有更新。 我不确定该方法的工作原理。 任何帮助将不胜感激

解决方法

Canvas是一个相当低级的组件,只有在需要使用BufferStrategy时才考虑使用。

update被称为绘制阶段的一部分,因为您没有调用super实现就覆盖了它,所以您中断了绘制工作流程。

AWT和Swing通常使用被动渲染系统,这意味着更新仅在系统确定需要进行时才发生,因此以update的方式覆盖您的做法并没有实际意义,也不会继续为您提供帮助。

一个更好的起点是JPanel,主要原因是它具有双重缓冲,并且省去了试图消除闪烁的麻烦。

Performing Custom PaintingPainting in AWT and Swing是一个很好的起点,以便更好地了解绘画的工作方式(以及您应该如何使用它)。

KeyListener也是输入监视的不佳选择,说真的,出于所有原因,只需对SO进行一些搜索即可。

一种更好且通常没有问题的方法是也使用key bindings

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 < 10; i++) {
                for (int j = 0; j < 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),"left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT,"right");

            ActionMap am = getActionMap();
            am.put("left",new KeyAction(this,-1));
            am.put("right",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,RIGHT_WALL,TOP_WALL);
            g2d.drawLine(LEFT_WALL,TOP_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 < 10; i++) {
                for (int j = 0; j < 5; j++) {
                    if (status[i][j] > 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 < 10; i++) {
                for (int j = 0; j < 5; j++) {
                    if (BALL_X > x[i][j] && BALL_X < (x[i][j] + BRICK_WIDTH) && BALL_Y <= y[i][j] + BAR_HEIGHT + BALL_SIZE && BALL_Y > y[i][j] && BALL_DY < 0) {
                        BALL_DY = -BALL_DY;
                        status[i][j] -= 1;
                    } else if (BALL_X > x[i][j] && BALL_X < (x[i][j] + BRICK_WIDTH) && BALL_Y >= y[i][j] - BALL_SIZE && BALL_Y < y[i][j] + BAR_HEIGHT && BALL_DY > 0) {
                        BALL_DY = -BALL_DY;
                        status[i][j] -= 1;
                    } else if (BALL_X + BALL_SIZE >= x[i][j] && BALL_X < (x[i][j] + BRICK_WIDTH) && BALL_Y >= y[i][j] && BALL_Y < y[i][j] + BAR_HEIGHT && BALL_DY < 0) {
                        BALL_DX = -BALL_DX;
                        status[i][j] -= 1;
                    } else if (BALL_X > x[i][j] && BALL_X - BALL_SIZE <= (x[i][j] + BRICK_WIDTH) && BALL_Y >= y[i][j] && BALL_Y < y[i][j] + BAR_HEIGHT && BALL_DY < 0) {
                        BALL_DX = -BALL_DX;
                        status[i][j] -= 1;
                    } else if (BALL_X - BALL_SIZE < LEFT_WALL || BALL_X + BALL_SIZE > RIGHT_WALL) {
                        BALL_DX = -BALL_DX;
                    } else if (BALL_Y - BALL_SIZE < 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;
            }

        }
    }
}

我搞砸了增量值,因为球和杠很快就消失了

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-