简体   繁体   English

Java-移动随机生成的图块图

[英]Java - Moving Randomly Generated Tilemap

I'm pretty fresh to java but I wanted to create a exploration type game. 我对Java非常了解,但是我想创建一个探索类游戏。 I researched for the last 2 weeks and was able to implement the diamond square algorithm for some pretty sweet terrain. 我研究了过去的两周,并能够在一些非常漂亮的地形上实现菱形平方算法。 But now I'm having trouble trying figure out how to move the map and how to continue the random generation. 但是现在我在尝试弄清楚如何移动地图以及如何继续随机生成方面遇到了麻烦。 Here's what I have so far. 到目前为止,这就是我所拥有的。

Game.java Game.java

package com.game.main;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.util.Random;
//import java.util.Random;

public class Game extends Canvas implements Runnable{

    private static final long serialVersionUID = 5420209024354289119L;

    public static final int WIDTH = 1000, HEIGHT = WIDTH / 12 * 9;

    private Thread thread;
    private boolean running = false;

    //private Random r;
    private Handler handler;

    public Game(){
        handler = new Handler();
        this.addKeyListener(new KeyInput(handler));

        new Window(WIDTH, HEIGHT, "Game", this);
        final int[][] map = DSAlgorithm.makeHeightMap(10, 45, 200);

        //r = new Random();


        handler.addObject(new Player(WIDTH/2 - 32, HEIGHT/2 - 32, ID.Player));
        //handler.addObject(new World(0, 0, ID.World));
        int squareSize = 10;
        for(int y = 0; y < map.length; y+=squareSize){
            for(int x = 0; x < map.length; x+=squareSize){
                int value = map[x][y];
                handler.addObject(new TerrianTile(x, y, value));
            }
        }
    }

    public synchronized void start(){
        thread = new Thread(this);
        thread.start();
        running = true;
    }

    public synchronized void stop(){
        try {
            thread.join();
            running = false;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run(){
        long lastTime = System.nanoTime();
        double amountOfTicks = 60.0;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;
        long timer = System.currentTimeMillis();
        int frames = 0;
        while (running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            while(delta >= 1){
                tick();
                delta --;

            }
            if (running)
                render();
            frames++;

            if (System.currentTimeMillis() - timer > 1000){
                timer += 1000;
                System.out.println("FPS: " + frames);
                frames = 0;
            }
        }
        stop();
    }

    private void tick(){
        handler.tick();
    }

    private void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null){
            this.createBufferStrategy(3);
            return;
        }

        Graphics g = bs.getDrawGraphics();

        g.setColor(Color.black);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        handler.render(g);

        g.dispose();
        bs.show();
    }

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

    public static int randInt(int min, int max){
        Random rand = new Random();
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }

}

Window.java Window.java

package com.game.main;

import java.awt.Canvas;
import java.awt.Dimension;

import javax.swing.JFrame;

public class Window extends Canvas {

    private static final long serialVersionUID = -1478604005915452565L;

    public Window(int width, int height, String title, Game game) {
        JFrame frame = new JFrame(title);

        frame.setPreferredSize(new Dimension(width, height));
        frame.setMaximumSize(new Dimension(width, height));
        frame.setMinimumSize(new Dimension(width, height));

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.add(game);
        frame.setVisible(true);
        game.start();
    }
}

DSAlgorithm.java DSAlgorithm.java

package com.game.main;

public class DSAlgorithm {

    /**
     * This method uses the seed value to initialize the four corners of the
     * map. The variation creates randomness in the map. The size of the array
     * is determined by the amount of iterations (i.e. 1 iteration -> 3x3 array,
     * 2 iterations -> 5x5 array, etc.).
     * 
     * @param iterations
     *            the amount of iterations to do (minimum of 1)
     * @param seed
     *            the starting value
     * @param variation
     *            the amount of randomness in the height map (minimum of 0)
     * @return a height map in the form of a 2-dimensional array containing
     *         integer values or null if the arguments are out of range
     */
    public static int[][] makeHeightMap(int iterations, int seed, int variation) {
         if (iterations < 1 || variation < 0) {
              return null;
         }

         int size = (1 << iterations) + 1;
         int[][] map = new int[size][size];
         final int maxIndex = map.length - 1;

         // seed the corners
         map[0][0] = seed;
         map[0][maxIndex] = seed;
         map[maxIndex][0] = seed;
         map[maxIndex][maxIndex] = seed;

         for (int i = 1; i <= iterations; i++) {
              int minCoordinate = maxIndex >> i;// Minimum coordinate of the
                                                        // current map spaces
              size = minCoordinate << 1;// Area surrounding the current place in
                                              // the map

              diamondStep(minCoordinate, size, map, variation);
              squareStepEven(minCoordinate, map, size, maxIndex, variation);
              squareStepOdd(map, size, minCoordinate, maxIndex, variation);

              variation = variation >> 1;// Divide variation by 2
         }

         return map;
    }

    /**
     * Calculates average values of four corner values taken from the smallest
     * possible square.
     * 
     * @param minCoordinate
     *            the x and y coordinate of the first square center
     * @param size
     *            width and height of the squares
     * @param map
     *            the height map to fill
     * @param variation
     *            the randomness in the height map
     */
    private static void diamondStep(int minCoordinate, int size, int[][] map,
              int variation) {
         for (int x = minCoordinate; x < (map.length - minCoordinate); x += size) {
              for (int y = minCoordinate; y < (map.length - minCoordinate); y += size) {
                   int left = x - minCoordinate;
                   int right = x + minCoordinate;
                   int up = y - minCoordinate;
                   int down = y + minCoordinate;

                   // the four corner values
                   int val1 = map[left][up];   // upper left
                   int val2 = map[left][down]; // lower left
                   int val3 = map[right][up];  // upper right
                   int val4 = map[right][down];// lower right

                   calculateAndInsertAverage(val1, val2, val3, val4, variation,
                             map, x, y);
              }
         }
    }

    /**
     * Calculates average values of four corner values taken from the smallest
     * possible diamond. This method calculates the values for the even rows,
     * starting with row 0.
     * 
     * @param minCoordinate
     *            the x-coordinate of the first diamond center
     * @param map
     *            the height map to fill
     * @param size
     *            the length of the diagonals of the diamonds
     * @param maxIndex
     *            the maximum index in the array
     * @param variation
     *            the randomness in the height map
     */
    private static void squareStepEven(int minCoordinate, int[][] map,
              int size, int maxIndex, int variation) {
         for (int x = minCoordinate; x < map.length; x += size) {
              for (int y = 0; y < map.length; y += size) {
                   if (y == maxIndex) {
                        map[x][y] = map[x][0];
                        continue;
                   }

                   int left = x - minCoordinate;
                   int right = x + minCoordinate;
                   int down = y + minCoordinate;
                   int up = 0;

                   if (y == 0) {
                        up = maxIndex - minCoordinate;
                   } else {
                        up = y - minCoordinate;
                   }

                   // the four corner values
                   int val1 = map[left][y]; // left
                   int val2 = map[x][up];   // up
                   int val3 = map[right][y];// right
                   int val4 = map[x][down]; // down

                   calculateAndInsertAverage(val1, val2, val3, val4, variation,
                             map, x, y);
              }
         }
    }

    /**
     * Calculates average values of four corner values taken from the smallest
     * possible diamond. This method calculates the values for the odd rows,
     * starting with row 1.
     * 
     * @param minCoordinate
     *            the x-coordinate of the first diamond center
     * @param map
     *            the height map to fill
     * @param size
     *            the length of the diagonals of the diamonds
     * @param maxIndex
     *            the maximum index in the array
     * @param variation
     *            the randomness in the height map
     */
    private static void squareStepOdd(int[][] map, int size, int minCoordinate,
              int maxIndex, int variation) {
         for (int x = 0; x < map.length; x += size) {
              for (int y = minCoordinate; y < map.length; y += size) {
                   if (x == maxIndex) {
                        map[x][y] = map[0][y];
                        continue;
                   }

                   int left = 0;
                   int right = x + minCoordinate;
                   int down = y + minCoordinate;
                   int up = y - minCoordinate;

                   if (x == 0) {
                        left = maxIndex - minCoordinate;
                   } else {
                        left = x - minCoordinate;
                   }

                   // the four corner values
                   int val1 = map[left][y]; // left
                   int val2 = map[x][up];   // up
                   int val3 = map[right][y];// right
                   int val4 = map[x][down]; // down

                   calculateAndInsertAverage(val1, val2, val3, val4, variation,
                             map, x, y);
              }
         }
    }

    /**
     * Calculates an average value, adds a variable amount to that value and
     * inserts it into the height map.
     * 
     * @param val1
     *            first of the values used to calculate the average
     * @param val2
     *            second of the values used to calculate the average
     * @param val3
     *            third of the values used to calculate the average
     * @param val4
     *            fourth of the values used to calculate the average
     * @param variation
     *            adds variation to the average value
     * @param map
     *            the height map to fill
     * @param x
     *            the x-coordinate of the place to fill 
     * @param y
     *            the y-coordinate of the place to fill
     */
    private static void calculateAndInsertAverage(int val1, int val2, int val3,
              int val4, int variation, int[][] map, int x, int y) {
         int avg = (val1 + val2 + val3 + val4) >> 2;// average
         int var = (int) ((Math.random() * ((variation << 1) + 1)) - variation);
         map[x][y] = avg + var;
    }

    public static void main(String[] args) {

    }

}

Handler.java Handler.java

package com.game.main;

import java.awt.Graphics;
import java.util.LinkedList;

public class Handler {

    LinkedList<GameObject> object = new LinkedList<GameObject>();
    LinkedList<Tiles> tile = new LinkedList<Tiles>();

    public void tick(){
        for (int i = 0; i < object.size(); i++){
            GameObject tempObject = object.get(i);

            tempObject.tick();
        }

        for (int t = 0; t < tile.size(); t++){
            Tiles tempObject = tile.get(t);

            tempObject.tick();
        }
    }

    public void render(Graphics g){
        for (int i = 0; i < object.size(); i++){
            GameObject tempObject = object.get(i);

            tempObject.render(g);
        }

        for (int t = 0; t < tile.size(); t++){
            Tiles tempObject = tile.get(t);

            tempObject.render(g);
        }
    }

    public void addObject(GameObject object){
        this.object.add(object);
    }

    public void removeObject(GameObject object){
        this.object.remove(object);
    }

    public void addObject(Tiles tile){
        this.tile.add(tile);
    }

    public void removeObject(Tiles tile){
        this.tile.remove(tile);
    }

}

Tiles.java Tiles.java

package com.game.main;

import java.awt.Graphics;
import java.util.LinkedList;

public class Handler {

    LinkedList<GameObject> object = new LinkedList<GameObject>();
    LinkedList<Tiles> tile = new LinkedList<Tiles>();

    public void tick(){
        for (int i = 0; i < object.size(); i++){
            GameObject tempObject = object.get(i);

            tempObject.tick();
        }

        for (int t = 0; t < tile.size(); t++){
            Tiles tempObject = tile.get(t);

            tempObject.tick();
        }
    }

    public void render(Graphics g){
        for (int i = 0; i < object.size(); i++){
            GameObject tempObject = object.get(i);

            tempObject.render(g);
        }

        for (int t = 0; t < tile.size(); t++){
            Tiles tempObject = tile.get(t);

            tempObject.render(g);
        }
    }

    public void addObject(GameObject object){
        this.object.add(object);
    }

    public void removeObject(GameObject object){
        this.object.remove(object);
    }

    public void addObject(Tiles tile){
        this.tile.add(tile);
    }

    public void removeObject(Tiles tile){
        this.tile.remove(tile);
    }

}

TerrianTile.java TerrianTile.java

package com.game.main;

import java.awt.Color;
import java.awt.Graphics;

public class TerrianTile extends Tiles {

    public TerrianTile(int x, int y, int tileType) {
        super(x, y, tileType);
    }

    public void tick(){

    }

    public void render(Graphics g){
        if (tileType <= 0){
            g.setColor(Color.BLUE);
            g.fillRect(x, y, 10, 10);
        }
        //water
        if (tileType > 0 && tileType < 40){
            g.setColor(Color.BLUE);
            g.fillRect(x, y, 10, 10);
        }
        //sand
        if (tileType >= 40 && tileType < 55){
            g.setColor(Color.YELLOW);
            g.fillRect(x, y, 10, 10);
        }
        //grass
        if (tileType >= 55 && tileType < 120){
            g.setColor(Color.GREEN);
            g.fillRect(x, y, 10, 10);
        }
        //forest
        if (tileType >= 120 && tileType < 140){
            g.setColor(Color.LIGHT_GRAY);
            g.fillRect(x, y, 10, 10);
        }
        //stone
        if (tileType >= 140 && tileType < 170){
            g.setColor(Color.GRAY);
            g.fillRect(x, y, 10, 10);
        }
        //snow
        if (tileType >= 170){
            g.setColor(Color.WHITE);
            g.fillRect(x, y, 10, 10);
        }
    }
}

KeyInput.java KeyInput.java

package com.game.main;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class KeyInput extends KeyAdapter{

    private Handler handler;

    public KeyInput(Handler handler){
        this.handler = handler;
    }

    public void keyPressed(KeyEvent e){
        int key = e.getKeyCode();

        for (int i = 0; i < handler.object.size(); i++){
            GameObject tempObject = handler.object.get(i);

            if (tempObject.getId() == ID.Player){
                // key events for player 1
                if (key == KeyEvent.VK_W) tempObject.setVelY(-5);
                if (key == KeyEvent.VK_S) tempObject.setVelY(5);
                if (key == KeyEvent.VK_D) tempObject.setVelX(5);
                if (key == KeyEvent.VK_A) tempObject.setVelX(-5);
            }
        }
    }

    public void keyReleased(KeyEvent e){
        int key = e.getKeyCode();

        for (int i = 0; i < handler.object.size(); i++){
            GameObject tempObject = handler.object.get(i);

            if (tempObject.getId() == ID.Player){
                // key events for player 1
                if (key == KeyEvent.VK_W) tempObject.setVelY(0);
                if (key == KeyEvent.VK_S) tempObject.setVelY(0);
                if (key == KeyEvent.VK_D) tempObject.setVelX(0);
                if (key == KeyEvent.VK_A) tempObject.setVelX(0);
            }
        }
    }

}

Not sure if there is way to container the tiles in a rectangle and then move the rectangle. 不知道是否有办法将图块包装成一个矩形,然后移动该矩形。 Any help would be much appreciated. 任何帮助将非常感激。

I dont really know what you mean by moving the tiles in a rectangle but if you just simply want to move all of them in a certain direction you could use g.translate(dx, dY) before you draw them. 我真的不知道通过将矩形移动到矩形中是什么意思,但是如果您只是想将它们全部朝某个方向移动,则可以在绘制它们之前使用g.translate(dx,dY)。

Or if the terrain doesnt change you could draw them on an image at the beginning and then draw the image each frame at diffrent positions. 或者,如果地形没有变化,则可以在开始时将其绘制在图像上,然后在不同位置的每一帧绘制图像。

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

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