如何为游戏创建2D游戏场?

时间:2013-09-20 11:20:49

标签: java

在JAVA中,我使用Path2D制作了这个: Before

我使用此代码:

// First Bezier curve points
P1 = new Point2D.Double(0, 480); // Start Point
P2 = new Point2D.Double(400, 350); // End Point
ctrl1 = new Point2D.Double(50, 450); // Control Point 1
ctrl2 = new Point2D.Double(200, 260); // Control Point 2
// Second Bezier curve points
P3 = new Point2D.Double(400, 350); // Start Point
P4 = new Point2D.Double(800, 600); // End Point
ctrl3 = new Point2D.Double(600, 440); // Control Point 1
ctrl4 = new Point2D.Double(700, 310); // Control Point 2

// path bezier curve
path = new Path2D.Double();
path.moveTo(P1.x, P1.y);
path.curveTo(ctrl1.x, ctrl1.y, ctrl2.x, ctrl2.y, P2.x, P2.y);
path.lineTo(P2.x, 600);
path.lineTo(0, 600);
path.closePath();
// path2 bezier curve
path2 = new Path2D.Double();
path2.moveTo(P3.x, P3.y);
path2.curveTo(ctrl3.x, ctrl3.y, ctrl4.x, ctrl4.y, P4.x, P4.y);
path2.lineTo(800, 600);
path2.lineTo(400, 600);
path2.closePath();

球员将在此基础上前进。 我的游戏就像一个射击游戏,如果有人没有击中敌人但是击中了地面,我想要摧毁它轰击它的地面。像这样: After

我该怎么做?我认为分割给定的贝塞尔曲线并绘制更多的曲线很难。所以我认为我将使用arrayList用1x1px矩形填充这个区域并从arrayList中删除一个shell撞击地面的矩形,但我想,这不是最好的解决方案,因为arrayList太大而且使用了太多资源刷新绘画区域:(那你觉得怎么样,最好的办法是什么呢?

1 个答案:

答案 0 :(得分:3)

  1. 使用BufferedImage来保存地面图像。
  2. 直接使用其处理图像的像素值 Raster
  3. 更新图片视图。
  4. 就是这么简单,第2步有很多不同的方法,但我建议创建一个半径为R的圆(取决于击中地面的物体的大小,可能是它的高度?),找到所有当物体撞击地面并将它们变成白色时,它们位于物体的R内。

    编辑:所以这里的例子是,我试图找到我的游戏的源而没有运气所以这里是一个非常简单的例子,一个矩形落在图像上并摧毁它落在的部分。请注意,我使用的图片是enter image description here

    这是几个矩形落下后的样子。 enter image description here

    来源 的 Terrain.java

    package explodingimage;
    
    import java.awt.Dimension;
    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.awt.image.WritableRaster;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    public class Terrain {
    private FallingRectangle rectangle;
    private BufferedImage image;
    private WritableRaster raster;
    private int centerX, centerY;
    private int[][] bitmap;
    private int pixelSize;
    
    public Terrain() {
        try {
            this.image = ImageIO.read(getClass().getResourceAsStream(
                    "before.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.rectangle = new FallingRectangle(getBounds());
        this.raster = image.getRaster();
        setupBitmap();
    }
    
    public Dimension getBounds() {
        return new Dimension(image.getWidth(), image.getHeight() * 3);
    }
    
    public BufferedImage getImage() {
        return image;
    }
    
    public int getImageX() {
        return 0;
    }
    
    public int getImageY() {
        return image.getHeight() * 2;
    }
    
    public FallingRectangle getFallingRectangle() {
        return rectangle;
    }
    
    public void update() {
        rectangle.update();
        if (collidesWithRectangle())
            explode();
    }
    
    private void explode() {
        int explosionRadius = 100;
        double distance = 0;
        Rectangle r = new Rectangle(centerX - explosionRadius, centerY
                - explosionRadius, 2 * explosionRadius, 2 * explosionRadius);
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                distance = Math.sqrt((x - centerX) * (x - centerX)
                        + (y - centerY) * (y - centerY));
                if (r.contains(x, y) && distance < explosionRadius) {
                    raster.setPixel(x, y, new int[] { 255, 255, 255 });
                }
            }
        }
        rectangle.reset();
    }
    
    // Notice since the image we use as terrain/background doesn't cover the
    // entire frame we have to use offsets, it covers the frame in width but not
    // height
    private boolean collidesWithRectangle() {
        int xOffset = 0;
        int yOffset = (int) (getBounds().getHeight() - image.getHeight());
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                if (bitmap[x][y] == 0
                        && rectangle.getRectangle().contains(x + xOffset,
                                y + yOffset)) {
                    centerX = x;
                    centerY = y;
                    return true;
                }
            }
        }
        return false;
    }
    
    
    // Set up the bitmap, check if pixel colorvalue is white or transparent
    // 1 = pixel is solid, 0 pixel is transparent to objects
    // Assuming length of 3 is RBG and length 4 is RBGA
    private void setupBitmap() {
        bitmap = new int[image.getWidth()][image.getHeight()];
        for (int x = 0; x < image.getWidth(); x++) {
            for (int y = 0; y < image.getHeight(); y++) {
                int[] pixel = null;
                pixel = raster.getPixel(x, y, pixel);
    
                if (pixel.length == 3) {
                    pixelSize = 3;
                    if(pixel[0]==255 && pixel[1] ==255 && pixel[2]==255)
                        bitmap[x][y] = 1;
                }
    
                if (pixel.length == 4) {
                    pixelSize = 4;
                    if (pixel[3] == 0) {
                        bitmap[x][y] = 1;
                    }
                }
            }
        }
    }
    
    }
    

    <强> Fallingrectangle.java

    package explodingimage;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Rectangle;
    import java.util.Random;
    
    public class FallingRectangle {
    private static final int MAXWIDTH = 150;
    private static final int MINWIDTH = 100;
    private static final int MAXHEIGHT = 150;
    private static final int MINHEIGHT = 100;
    private final double MINX, MAXX, MINY, MAXY;
    private static final Random rnd = new Random();
    private Rectangle rectangle;
    private Color color;
    private int speed;
    
    public FallingRectangle(Dimension bounds) {
        this.MAXX = bounds.getWidth() * 0.9;
        this.MINX = bounds.getWidth() * 0.1;
        this.MINY = 0;
        this.MAXY = bounds.getHeight();
        setup();
    }
    
    private void setup() {
        int x = (int) (rnd.nextInt((int) (MAXX - MINX)) + MINX);
        int y = 0;
        int w = rnd.nextInt(MAXWIDTH - MINWIDTH) + MINWIDTH;
        int h = rnd.nextInt(MAXHEIGHT - MINHEIGHT) + MINHEIGHT;
        int R = rnd.nextInt(256);
        int G = rnd.nextInt(256);
        int B = rnd.nextInt(256);
        speed = rnd.nextInt(3) + 1;
    
        rectangle = new Rectangle(x, y, w, h);
        color = new Color(R, G, B);
    }
    
    public Rectangle getRectangle() {
        return rectangle;
    }
    
    public Color getColor() {
        return color;
    }
    
    public void update() {
        int x = rectangle.x;
        int y = rectangle.y + speed;
        int w = rectangle.width;
        int h = rectangle.height;
        rectangle = new Rectangle(x, y, w, h);
    
        if (y >= MAXY)
            reset();
    }
    
    public void reset() {
        setup();
    }
    
    public void stop() {
        this.speed = 0;
    }
    }
    

    <强> GamePanel.java

    package explodingimage;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.beans.Transient;
    
    import javax.swing.JPanel;
    
    @SuppressWarnings("serial")
    public class GamePanel extends JPanel {
    private Terrain terrain;
    
    public GamePanel() {
        this.terrain = new Terrain();
    }
    
    @Override
    @Transient
    public Dimension getPreferredSize() {
        return terrain.getBounds();
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
    
        // Draw background image of terrain
        g2d.drawImage(terrain.getImage(), terrain.getImageX(),
                terrain.getImageY(), null);
    
        // Draw the rectangular object
        Rectangle r = terrain.getFallingRectangle().getRectangle();
        g2d.setColor(Color.black);
        g2d.drawString(r.x + "," + r.y, r.x, r.y);
        g2d.draw(r);
        g2d.setColor(terrain.getFallingRectangle().getColor());
        g2d.fill(r);
    }
    
    public Terrain getTerrain() {
        return terrain;
    }
     }
    

    <强> Game.java

    package explodingimage;
    
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JFrame;
    import javax.swing.Timer;
    
    public class Game {
    private JFrame frame;
    private GamePanel panel;
    
    public Game() {
        this.frame = new JFrame();
        this.panel = new GamePanel();
    
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    
    public void start(){
        new Timer(10, new ActionListener() {
    
            @Override
            public void actionPerformed(ActionEvent arg0) {
                panel.getTerrain().update();
                panel.repaint();
            }
        }).start();
    }
    
    public static void main(String[] args) {
        new Game().start();
    }
    
     }