Java游戏编程第1部分:平滑运动

时间:2013-11-04 15:08:57

标签: java swing pacman

我是计算机班(高中新生)三人小组的三分之一。对于我们的项目,我们决定用Java制作Pac-Man风格的游戏。我们都没有太多的经验,所以我们基本上都在自我教育。我们取得了相当大的进步,但我们现在似乎已经停滞不前了。以下是我们的主要问题:

  1. 我们怎样才能使我们的Pacman(Fatman)在瓷砖上顺利移动?他按瓦片移动,但看起来不专业。此外,当您按住箭头键时,他会在屏幕上拉链。我们怎样才能防止这种情况发生?
  2. (我还有其他需要帮助的事情,但他们有不同的问题)

    感谢您的帮助!

    到目前为止,这是我们的代码:

    迷宫课程:

    package Fatman;
    
    import javax.swing.*;
    
    public class Maze {
        public static void main(String[] args){
            new Maze();
        }
    
        public Maze(){
            JFrame f = new JFrame();
            f.setTitle("Fatman!");
            f.add(new Board());
            f.setSize(816, 838);
            f.setLocationRelativeTo(null);
            f.setVisible(true);
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }
    }
    

    地图类

        package Fatman;
    
    import java.awt.*;
    import java.io.*;
    import java.util.*;
    import javax.swing.*;
    
    public class Map {
    
        private Scanner m;
        private String Map[] = new String[25]; 
    
        private Image spaceregcandy,
                      srcb,
                      safehouse,
                      spacebigcandy,
                      blackspace,
                      space,
                      portal1,
                      portal2,
                      wall;
    
        public Map(){
    
            ImageIcon img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spaceregcandy.png");
            spaceregcandy = img.getImage();
            //image icon has already been initiated, so it doesn't have to be written again
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spaceregcandyblue.png");
            srcb = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\safehouse.png");
            safehouse = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\wall232x.png");
            wall = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\spacebigcandy.png");
            spacebigcandy = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\blackspace.png");
            blackspace = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\space.png");
            space = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\portal1.png");
            portal1 = img.getImage();
            img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\portal2.png");
            portal2 = img.getImage();
    
            openFile();
            readFile();
            closeFile();
            }
    
        public Image getSpaceregcandy(){
            return spaceregcandy;
        }
        public Image getSrcb(){
            return srcb;
        }
        public Image getSafehouse(){
            return safehouse;
        }
        public Image getWall(){
            return wall;
        }
        public Image getSpacebigcandy(){
            return spacebigcandy;
        }
        public Image getBlackspace(){
            return blackspace;
        }
        public Image getSpace(){
            return space;
        }
        public Image getPortal1(){
            return portal1;
        }
        public Image getPortal2(){
            return portal2;
        }
    
        public String getMap(int x, int y){
            String index = Map[y].substring(x, x + 1);
            return index;
            //in y position, if y = 2, goes to second row (substring gets x position)
        }
    
        public void openFile(){
    
            try{
            m = new Scanner(new File("C:\\Users\\Martin\\Desktop\\Fatman Project\\map3.txt"));
            }catch(Exception e){
                System.out.println("error loading map");
            }
        }
    
        public void readFile(){
            while(m.hasNext()){
                for(int i = 0; i < 25; i++){
                    Map[i] = m.next();
                }
            }
    
        }
    
        public void closeFile(){
            m.close();
        }
    }
    

    董事会成员

    package Fatman;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    import javax.swing.*;
    
    public class Board extends JPanel implements ActionListener{
    
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        private Timer timer;
    
        private Image player;
    
        private Map m;
        private Player p;
    
        public Board(){
    
            m = new Map();
            p = new Player();
            addKeyListener(new Al());
            setFocusable(true);
            timer = new Timer(1, this);
            timer.start();
        }
    
        public void actionPerformed(ActionEvent e){
            repaint();
    
        }
    
        public void paint(Graphics g){
            super.paint(g);
    
            for(int y = 0; y < 25; y++){
                for(int x = 0; x <25; x++){
                    if(m.getMap(x, y).equals("o")){
                        g.drawImage(m.getSpaceregcandy(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("O")){
                        g.drawImage(m.getSrcb(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("x")){
                        g.drawImage(m.getWall(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("H")){
                        g.drawImage(m.getSafehouse(), x *32, y *32, null);
                    }   
                    if(m.getMap(x, y).equals("C")){
                        g.drawImage(m.getSpacebigcandy(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("b")){
                        g.drawImage(m.getBlackspace(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("s")){
                        g.drawImage(m.getSpace(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("p")){
                        g.drawImage(m.getPortal1(), x *32, y *32, null);
                    }
                    if(m.getMap(x, y).equals("P")){
                        g.drawImage(m.getPortal2(), x *32, y *32, null);
                    }
            }
    
    
        }
    
    
            g.drawImage(p.getPlayer(), p.getTileX() * 32, p.getTileY() * 32, null);
    
    }
    
        public class Al extends KeyAdapter{
    
            public void keyPressed(KeyEvent e){
                int keycode = e.getKeyCode();
    
                if(keycode == KeyEvent.VK_UP){
                    if(!m.getMap(p.getTileX(), p.getTileY() -1).equals("x")){
                        if(!m.getMap(p.getTileX(), p.getTileY() -1).equals("b")){                       
                            }
                            p.move(0, -1);                  
    
                            System.out.println(m.getMap(p.getTileX(), p.getTileY()));
    
                }
                    }
    
                if(keycode == KeyEvent.VK_DOWN){
                    if(!m.getMap(p.getTileX(), p.getTileY() +1).equals("x")){
                        if(!m.getMap(p.getTileX(), p.getTileY() +1).equals("b")){
                            p.move(0, 1);
                            System.out.println(m.getMap(p.getTileX(), p.getTileY()));
                }
                    }
                }
                if(keycode == KeyEvent.VK_LEFT){
                    if(!m.getMap(p.getTileX() - 1, p.getTileY()).equals("x")){
                        if(!m.getMap(p.getTileX() - 1, p.getTileY()).equals("b")){
                            p.move(-1, 0);
                            System.out.println(m.getMap(p.getTileX(), p.getTileY()));
                }
                    }
                }
                if(keycode == KeyEvent.VK_RIGHT){
                    if(!m.getMap(p.getTileX() + 1, p.getTileY()).equals("x")){
                        if(!m.getMap(p.getTileX() + 1, p.getTileY()).equals("b")){
                            p.move(1, 0);
                            System.out.println(m.getMap(p.getTileX(), p.getTileY()));
                }
                }
                }
                }
    
    
            public void keyReleased(KeyEvent e){
    
            }
    
            public void keyTyped(KeyEvent e){
    
    }
    }
    }
    

    玩家等级

    package Fatman;
    
    import java.awt.Image;
    
    import javax.swing.ImageIcon;
    
    public class Player {
    
        private int tileX, tileY;
        private int dx, dy;
    
        private Image player; 
    
        public Player(){
    
            ImageIcon img = new ImageIcon("C:\\Users\\Martin\\Desktop\\Fatman Project\\FATMANsimplified32xbrown.png");
            player = img.getImage();
    
            tileX = 12;
            tileY = 18;
        }
    
        public Image getPlayer(){
            return player;
        }
        public int getTileX(){
            return tileX;
        }
        public int getTileY(){
            return tileY;
        }
    
        public void move(int dx, int dy){
    
            tileX += dx;
            tileY += dy;
        }
    
    }
    

    有什么想法吗?

4 个答案:

答案 0 :(得分:1)

对于您的第一个问题,请注意您只是在移动方法中递增切片编号,然后在该位置重新绘制播放器(增量为32像素)。您需要更精细的粒度级别,即不是通过图块本身递增,而是通过图块的一部分递增(例如,通过2个像素)。因此,FatMan的图像将需要更多步骤才能从1个图块移动到另一个图块。显然,如果FatMan的图像播放器在那段时间内是一个行走/跑步的动画,那么看起来会更好看,让动作看起来更自然。

所以......在无耻的自我推销中,我邀请你在这里看看我的旧教程: https://sites.google.com/site/javagamescorner/home/animated-sprites

答案 1 :(得分:0)

有两个问题:

首先,你需要在每次更新之间进行某种睡眠/暂停以模拟时间,否则如果你按下按键,玩家将立即跳到地图的末尾。由于你希望玩家在每一步之后都有一些时间过去。

一种可能性是在每次调用后添加Thread.sleep。

其次,您需要将玩家移动与拼贴坐标系分离。如果你想让玩家能够“在瓷砖之间移动”。他应该使用自己的坐标系统让他移动更小的步骤。

答案 2 :(得分:0)

为避免你的胖子从右向左滑动,反之亦然,你可以参考这个问题:Java KeyListener keyPressed method fires too fast

对于你的动画,你必须编写一些东西来自己将1个瓷砖移动到另一个。

答案 3 :(得分:0)

我已阅读您的代码,我建议您进行以下修改:

  • 当您按下某个键时,您可以设置一个方向,可以向上,向下,向左或向右作为下一个方向(因为方向必须保持到移动结束)。您可以使用两个类变量实现:direction和nextDirection。您还可以使用图块边缘大小的值设置另一个类变量(例如,32)。此变量称为animationFrame。
  • 在此示例中,您可以将计时器频率设置为32 Hz(1000/32毫秒)。您可以使用计时器来适应动画。
  • 每次调用计时器时,您都会向方向移动1个像素的胖子(读取方向变量)并减少animationFrame。当你达到0然后胖子被放在下一个瓷砖中。您可以通过设置direction = nextDirection来重新设置操作。现在你必须在这一点上应用游戏的逻辑(碰撞等)。

这只是一个粗略的方法,但我认为你可以从这个想法开始。这让我想起了我16岁时用Java编写的蛇游戏。