简体   繁体   English

如何不断显示形状,但仍重新粉刷屏幕?

[英]how to constantly display shapes, but still repaint the screen?

While writing a simple Tron game with JFrame, I came across a bit of a problem. 在用JFrame编写一个简单的Tron游戏时,我遇到了一个问题。 I'm not sure how I could keep the display for the "light cycle" as a line that stays on the displayed on the screen, but at the same time repainting the screen so that movement is still functional. 我不确定如何将“光周期”的显示保留为一行,一直停留在屏幕上显示的状态,但是同时重新粉刷屏幕以使运动仍然有效。 Here's my code:(fyi, it all compiles and everything works as it's written here perfectly fine) 这是我的代码:(仅供参考,它们都可以编译,并且一切正常,因为这里写的很好)

public class Tron extends JPanel{

    public static int x = 40;
    public static int y = 40;
    public static int h = 360;
    public static int k = 360;
    public final static int size = 10;
    public static int move = 1;
    public static int dir = 0;
    static final Tron m = new Tron();
    static final JFrame frame = new JFrame("1P Tron");

    public static void main(String[] args){

        frame.setSize(400,400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(m);
        m.setBackground(Color.black);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        Action actionRight = new AbstractAction(){
            public void actionPerformed(ActionEvent actionRightEvent){
                dir = 1;
                x += 5;
                if(x > 390){
                    x = -5;
                };
                m.repaint();
            }
        };

        Action actionLeft = new AbstractAction(){
            public void actionPerformed(ActionEvent actionLeftEvent){
                dir = 2;
                x -= 5;
                if(x < 0){
                    x = 395;
                };
                m.repaint();
            }
        };

        Action actionUp = new AbstractAction(){
            public void actionPerformed(ActionEvent actionUpEvent){
                dir = 3;
                y -= 5;
                if(y < 0){
                    y = 375;
                };
                m.repaint();
            }
        };

        Action actionDown = new AbstractAction(){
            public void actionPerformed(ActionEvent actionDownEvent){
                dir = 4;
                y += 5;
                if(y > 370){
                    y = 0;
                };
                m.repaint();
            }
        };


        KeyStroke right = KeyStroke.getKeyStroke("RIGHT");
        KeyStroke left = KeyStroke.getKeyStroke("LEFT");
        KeyStroke up = KeyStroke.getKeyStroke("UP");
        KeyStroke down = KeyStroke.getKeyStroke("DOWN");

        InputMap inputMap = m.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        inputMap.put(right, "RIGHT");
        inputMap.put(left, "LEFT");
        inputMap.put(up, "UP");
        inputMap.put(down, "DOWN");
        m.getActionMap().put("RIGHT", actionRight);
        m.getActionMap().put("LEFT", actionLeft);
        m.getActionMap().put("UP", actionUp);
        m.getActionMap().put("DOWN", actionDown);

    }

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

    public void draw(Graphics g){
        g.setColor(Color.BLUE);
        g.fillRect(x, y, size, size);
        g.drawString("Tron", 190, 390);
    }

}

Also, I want to know how I would go about making it so that when I press an arrow key, instead of just adding or subtracting from the x or y coords once, it continuously adds to it until another arrow is pressed. 另外,我想知道如何制作它,这样当我按下箭头键时,而不是仅从x或y坐标中进行一次加法或减法,而是不断地对其进行添加,直到按下另一个箭头。

edit: To make this question a little easier to understand, the python equivalent would be drawing a character at an x and y coord with the curses library, using the arrow keys to move it around the screen, but never calling stdscr.clear() . 编辑:为了使这个问题更容易理解,python等效项将在curses库的x和y坐标处绘制一个字符,使用箭头键在屏幕上移动它,但不要调用stdscr.clear()

edit: While searching around on the internet trying to figure out how to use g.drawPolygon() as MadProgrammer suggested, I came across an interesting idea to add a variable to help the program "remember" which key was last pressed and to add to the coords based on that. 编辑:在Internet上进行搜索,试图找出如何按照MadProgrammer的建议使用g.drawPolygon() ,我遇到了一个有趣的想法,即添加一个变量来帮助程序“记住”上次按下的键并将其添加到基于此的坐标。 I thought this would eliminate the need for a polygon and that I could just use the Translate() method, but when I added the translation the program stopped working. 我认为这将消除对多边形的需求,而我可以只使用Translate()方法,但是当我添加翻译时,程序停止工作。 Is there a different method I need to use instead, or did I do something else wrong? 是否需要使用其他方法代替,还是做错了其他事情? Here's the new code: 这是新的代码:

import javax.swing.*;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

public class Tron extends JPanel{

    public static int x = 40;
    public static int y = 40;
    public static int h = 360;
    public static int k = 360;
    public static int size = 10;
    public static int move = 1;
    public static int dir = 1;
    static final Tron m = new Tron();
    static final JFrame frame = new JFrame("1P Tron");

    public static void main(String[] args){

        frame.setSize(400,400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(m);
        m.setBackground(Color.black);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        Action actionRight = new AbstractAction(){
            public void actionPerformed(ActionEvent actionRightEvent){
                dir = 1;
            };
        };

        Action actionLeft = new AbstractAction(){
            public void actionPerformed(ActionEvent actionLeftEvent){
                dir = 2;
            };
        };

        Action actionUp = new AbstractAction(){
            public void actionPerformed(ActionEvent actionUpEvent){
                dir = 3;
            };
        };

        Action actionDown = new AbstractAction(){
            public void actionPerformed(ActionEvent actionDownEvent){
                dir = 4;          
            };
        };


        KeyStroke right = KeyStroke.getKeyStroke("RIGHT");
        KeyStroke left = KeyStroke.getKeyStroke("LEFT");
        KeyStroke up = KeyStroke.getKeyStroke("UP");
        KeyStroke down = KeyStroke.getKeyStroke("DOWN");

        InputMap inputMap = m.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        inputMap.put(right, "RIGHT");
        inputMap.put(left, "LEFT");
        inputMap.put(up, "UP");
        inputMap.put(down, "DOWN");
        m.getActionMap().put("RIGHT", actionRight);
        m.getActionMap().put("LEFT", actionLeft);
        m.getActionMap().put("UP", actionUp);
        m.getActionMap().put("DOWN", actionDown);

    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        draw(g);
        p1_move(m);
    }

    public void p1_move(Tron m){
        if(dir == 1){
            if(x > 390){
                x = -5;
            };
            x += 5;
            m.repaint();
        }else if(dir == 2){
            if(x < 0){
                x = 395;
            };
            x -= 5;
            m.repaint();
        }else if(dir == 3){
            if(y < 0){
                y = 375;
            };
            y -= 5;
            m.repaint();
        }else if(dir == 4){
            if(y > 370){
                y = 0;
            };
            y += 5;
            m.repaint();
        }
    }

    public void draw(Graphics g){
        g.setColor(Color.BLUE);
        g.fillRect(40, 40, size, size);
        g.translate(x, y);
    }
}

By the way, in case anyone's wondering why all the java.Util.* 's are imported separately, I was going to use those originally to create an ArrayList , but decided against it and never got around to taking those out. 顺便说一句,如果有人想知道为什么所有java.Util.*都是单独导入的,我将使用最初的那些来创建ArrayList ,但是决定反对它,并且从来没有绕过这些。

edit: one list edit on this question, my program's almost done. 编辑:一个列表编辑此问题,我的程序几乎完成。 The last thing I want to know is how to put a random number generator in for my cpu player. 我想知道的最后一件事是如何为CPU播放器放置一个随机数生成器。 originally it had a set path and "killed" itself after a few seconds if you survived long enough, but I thought it would be more fun if he just went on a random path. 最初它有一条固定的路径,如果您存活足够长的时间,则在几秒钟后“杀死”自己,但我认为如果他只是走一条随机路径,那会更好玩。 I already know how to write random number generators using java.util.Random , but the code for those always ends up being a lot longer than I would lie it to be for my game, so I was wondering if it would be possible to add it in just maybe five or six statements. 我已经知道如何使用java.util.Random编写随机数生成器,但是这些代码的最终结果总是比我在游戏中所想的要长得多,所以我想知道是否可以添加仅用五六个语句就可以了。

The basic idea is you need to place all the shapes into some kind of List so that when you your paintComponent method is called, you call wall the list and paint the shapes 基本思想是需要将所有形状放入某种List以便在调用paintComponent方法时,调用wall列表并绘制形状

My "general" idea would be to add a new Point to a List each time the player makes a turn. 我的“一般”想法是每次玩家转弯时将一个新的Point添加到List In your paintComponent method, you would simply paint lines from one point to the next. paintComponent方法中,您只需绘制从一点到另一点的线。

One of the last actions in your paint process, I would be to simply draw a line from the last point to the players current position... 您绘画过程中的最后一项动作,我就是简单地从最后一点到玩家当前位置划一条线...

Update with example using Path2D 使用Path2D更新示例

This is a very basic example of a concept using Path2D to maintain the cycle path. 这是使用Path2D维护循环路径的概念的非常基本的示例。 Having done it this way, I think you will it easier to use a List of Point s, as this would be easier to build the collision detection. 这样,我认为您将更容易使用PointList ,因为这将更易于构建碰撞检测。

在此处输入图片说明

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
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;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class LightCycles {

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

    public LightCycles() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        private int xVelocity;
        private int yVelocity;

        protected static final int PLAYER_SIZE = 4;
        protected static final int DELTA = 4;

        private Point player;
        private Point lastTurn;
        private Path2D playerPath;

        public TestPane() {
            setBackground(Color.BLACK);
            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "left");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "right");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "down");

            am.put("left", new VelocityAction(-DELTA, 0));
            am.put("right", new VelocityAction(DELTA, 0));
            am.put("up", new VelocityAction(0, -DELTA));
            am.put("down", new VelocityAction(0, DELTA));

            xVelocity = DELTA;

            player = new Point(0, 100);
            lastTurn = new Point(player);
            playerPath = new Path2D.Float();
            playerPath.moveTo(0, 100); // Start position...

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    player.x += xVelocity;
                    if (player.x > getWidth()) {
                        playerPath.lineTo(getWidth(), player.y);
                        playerPath.moveTo(0, player.y);
                        player.x = 0;
                        lastTurn = new Point(player);
                    }
                    if (player.x + PLAYER_SIZE < 0) {
                        playerPath.lineTo(0, player.y);
                        playerPath.moveTo(getWidth() - 1, player.y);
                        player.x = getWidth() - 1;
                        lastTurn = new Point(player);
                    }
                    player.y += yVelocity;
                    if (player.y > getHeight()) {
                        playerPath.lineTo(player.x, getHeight());
                        playerPath.moveTo(player.x, 0);
                        player.y = 0;
                        lastTurn = new Point(player);
                    }
                    if (player.y + PLAYER_SIZE < 0) {
                        playerPath.lineTo(player.x, 0);
                        playerPath.moveTo(player.x, getHeight() - 1);
                        player.y = getHeight() - 1;
                        lastTurn = new Point(player);
                    }
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.BLUE);
            g2d.draw(playerPath);
            g2d.draw(new Line2D.Float(lastTurn, player));
            g2d.drawRect(player.x - (PLAYER_SIZE / 2), player.y - (PLAYER_SIZE / 2), PLAYER_SIZE, PLAYER_SIZE);
            g2d.dispose();
        }

        public class VelocityAction extends AbstractAction {

            private final int xDelta;
            private final int yDelta;

            public VelocityAction(int xDelta, int yDelta) {
                this.xDelta = xDelta;
                this.yDelta = yDelta;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                xVelocity = xDelta;
                yVelocity = yDelta;
                lastTurn = new Point(player);
                playerPath.lineTo(player.x, player.y);
            }

        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM