JavaFX横幅类游戏开发 教训 游戏贴图

  上一节课,我们即将完成战旗Demo有了一个大概的了解。教训这,我们将学习绘制游戏地图。

 由于JavaFX 2.2中添加了Canvas相关的功能,我们就能够使用Canvas来实现游戏绘制了。

 游戏地图绘制主要用到GraphicsContext.drawImage方法。

 drawImage(Image image,double sx,double sy,double sw,double sh,double dx,double dy,double dw,double dh);

 当中image 表示源图片。

 sx,sy,sw,sh表示相对于源图片的x,y坐标和截取的宽度和高度。

 dx,dy,dw,dy表示绘制到画布上的x, y坐标和绘制的宽度和高度。

 单元图片例如以下:

  

 地图绘制就是将单元格进行拼接。

 通常使用一个二维数组来表示地图数据例如以下:

int[][] mapIndex = { 
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, };

以下来看看我们的游戏地图类:

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;

public class GameMap {
	private int[][] mapIndex = { 
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 18, 18, 18, 18, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, };
	
	private int tileWidth;
	private int tileHeight;
	private int cols;
	private Image image;
	
	public GameMap(int tileWidth,int tileHeight, Image map){
		this.tileWidth = tileWidth;
		this.tileHeight = tileHeight;
		this.image = map;
		cols = (int) (map.getWidth() / tileWidth);
	}

	public void drawMap(GraphicsContext gc) {
		int mapWidth = mapIndex[0].length;
		int mapHeight = mapIndex.length;
		for (int y = 0; y < mapHeight; y++) {
			for (int x = 0; x < mapWidth; x++) {
				int px = mapIndex[y][x] % cols;
				int py = mapIndex[y][x] / cols;
				gc.drawImage(image, px * tileWidth, py * tileHeight, tileWidth, tileHeight, x * tileWidth, y
						* tileHeight, tileWidth, tileHeight);
			}
		}
	}

	public int[][] getMapIndex() {
		return mapIndex;
	}

	public void setMapIndex(int[][] mapIndex) {
		this.mapIndex = mapIndex;
	}
}

  在实际游戏开发中。游戏地图数据通常存储在文件里。从文件读取,因为我这仅仅是个Demo,写进来方便大家直观的了解。

  首先,我们通过地图贴图的宽度和单元格的宽度来计算地图贴图单元格的列数,然后在绘制的时候,就能够通过地图索引和单元格列数,计算当前绘制的贴图的行和列。通过drawImage绘制出来。


接下来,创建我们的Canvas类:

import javafx.application.Platform;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;

public class MainCanvas extends Canvas {
	
	// 游戏地图
	private GameMap gameMap;
	private GraphicsContext gContext;
	private Image map;
	private int tileWidth = 32;
	private int tileHeight = 32;

	private boolean isRunning = true;
	private long sleep = 100;
	// 主线程
	private Thread thread = new Thread(new Runnable() {

		@Override
		public void run() {
			while (isRunning) {
				Platform.runLater(new Runnable() {

					@Override
					public void run() {
						draw();
						update();
					}
				});
				try {
					Thread.sleep(sleep);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	});
	public MainCanvas(double width, double height) {
		super(width, height);
		map = new Image(getClass().getResourceAsStream("map0.png"));
		gContext = getGraphicsContext2D();

		// 初始化游戏地图
		gameMap = new GameMap(tileWidth, tileHeight, map);

		thread.start();
	}

	public void draw() {
		gameMap.drawMap(gContext);		
	}

	public void update() {

	}
}

  MainCanvas类比較简单,创建一个线程,用于运行draw和update方法。

然后加载地图贴图,初始化GameMap,并完毕绘制工作。

最后,在Main类中,将我们的Canvas增加到布局中。

import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;

public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			AnchorPane root = new AnchorPane();
			Scene scene = new Scene(root,640,480);
			MainCanvas mainCanvas = new MainCanvas(640, 480);
			root.getChildren().add(mainCanvas);
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}

以下看看执行效果:


  这样,游戏地图就绘制成功了。有兴趣的朋友也能够自行改动地图索引。来绘制不同的地图。

当然在实际开发中,我们还是会用地图编辑器来编辑的。

  这一节课就到此结束了,下一节再见。

  本文章为个人原创。版权全部,转载请注明出处:http://blog.csdn.net/ml3947。另外我的个人博客:http://www.wjfxgame.com.


版权声明:本文博客原创文章,博客,未经同意,不得转载。

原文地址:https://www.cnblogs.com/yxwkf/p/4640841.html