很早以前的一个想法,今天终于实现了。此次做了2个版本:

1、第一个版本使用的很多Jlabel做的,数据都是写死的。并且失败了。

2、使用绘画做的,可以更改数据,成功实现。地图使用的二维数组存储,可以更改每行和每列的显示数量,但是我使用的图片是60x60的,不知道会不会自动缩放。目前没遇到BUG。

 

先上段效果图:

关于java 的地图系统 java实现地图_swing

package com.maps;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

/**
 * 绘画Java手游地图<br>
 * 下方未对地图长度作判断,使用的数组下标都是[0]开始<br>
 * 所以只要maps的长度大于[0][0]即可
 * 
 * @author iu_chang
 *
 */
public class Map extends JFrame {
	private static final long serialVersionUID = 1L;
	/**
	 * 20x20 地图:<br>
	 * 1为普通路段:灰色<br>
	 * 2为草地:浅绿<br>
	 * 3为桥:棕色<br>
	 * 4为河流:蓝色<br>
	 * 5为墙壁:白色<br>
	 * 6为树木:深绿<br>
	 * 1、2、3可通过,4、5、6不可通过
	 * 
	 */
	private Integer[][] maps = { { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
			{ 5, 2, 2, 2, 2, 2, 2, 5, 5, 4, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5 },
			{ 5, 2, 2, 2, 2, 2, 2, 5, 5, 4, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5 },
			{ 5, 2, 2, 2, 2, 2, 2, 5, 5, 4, 1, 2, 5, 5, 5, 4, 4, 4, 4, 4 },
			{ 5, 2, 2, 2, 2, 2, 2, 5, 5, 4, 1, 2, 4, 4, 4, 2, 4, 4, 4, 4 },
			{ 5, 2, 2, 2, 2, 2, 2, 5, 5, 4, 3, 4, 4, 4, 4, 4, 4, 2, 2, 4 },
			{ 5, 2, 6, 2, 2, 2, 2, 5, 5, 4, 1, 5, 5, 5, 5, 4, 4, 4, 4, 4 },
			{ 5, 6, 6, 6, 2, 2, 2, 5, 5, 4, 1, 2, 2, 2, 2, 2, 2, 2, 5, 5 },
			{ 5, 6, 6, 6, 2, 2, 2, 5, 5, 4, 1, 2, 2, 2, 2, 2, 2, 2, 2, 5 },
			{ 5, 6, 6, 6, 6, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5 },
			{ 5, 6, 6, 6, 6, 2, 2, 5, 5, 4, 1, 2, 2, 2, 2, 2, 2, 4, 4, 5 },
			{ 5, 2, 6, 6, 2, 2, 2, 5, 5, 4, 1, 2, 2, 2, 2, 2, 2, 4, 4, 5 },
			{ 5, 2, 6, 6, 2, 2, 2, 5, 5, 4, 1, 1, 2, 2, 2, 2, 2, 4, 4, 5 },
			{ 5, 2, 6, 6, 2, 2, 6, 5, 5, 4, 5, 1, 1, 1, 1, 1, 1, 4, 4, 5 },
			{ 5, 2, 6, 2, 2, 6, 2, 5, 5, 4, 5, 5, 5, 5, 5, 5, 1, 4, 4, 5 },
			{ 5, 2, 6, 2, 2, 6, 2, 5, 5, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 5 },
			{ 5, 2, 2, 2, 2, 2, 2, 2, 5, 4, 6, 2, 6, 6, 2, 2, 2, 4, 4, 5 },
			{ 5, 2, 6, 4, 4, 4, 4, 2, 5, 4, 6, 2, 6, 6, 2, 2, 2, 4, 4, 5 },
			{ 5, 2, 6, 6, 2, 2, 2, 2, 5, 4, 6, 6, 6, 6, 2, 2, 2, 4, 4, 5 },
			{ 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, };

	/** 一行多少个 */
	private final int MAP_RANK = 7;
	/** 共多少行 */
	private final int MAP_TRADE = 9;
	/** 方块宽度 */
	private final int BLOCK_WIDTH = 60;
	/** 方块高度 */
	private final int BLOCK_HEIGHT = 60;
	/** 玩家横坐标 */
	private Integer x;
	/** 玩家纵坐标 */
	private Integer y;
	/** 窗口宽度 */
	private Integer width;
	/** 窗口高度 */
	private Integer height;
	/** 玩家图片 */
	private Image user = ImageIO.read(new File(getFilePath("/user.png")));;

	private Image image1 = ImageIO.read(new File(getFilePath("/1.png")));
	private Image image2 = ImageIO.read(new File(getFilePath("/2.png")));
	private Image image3 = ImageIO.read(new File(getFilePath("/3.png")));
	private Image image4 = ImageIO.read(new File(getFilePath("/4.png")));
	private Image image5 = ImageIO.read(new File(getFilePath("/5.png")));
	private Image image6 = ImageIO.read(new File(getFilePath("/6.png")));

	public Map() throws IOException {
		// 玩家位置初始化
		x = 18;
		y = 4;

		setTitle("绘画地图");
		// 获取屏幕宽度
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		width = MAP_RANK * BLOCK_WIDTH;
		height = MAP_TRADE * BLOCK_HEIGHT + 30;
		// 使窗口居中
		setBounds(screenSize.width / 2 - width / 2, screenSize.height / 2 - height / 2, width, height);

		setLayout(null);
		// 设置默认退出方式
		setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
		// 添加按键监听
		addKeyListener(new KeyMoniton());
		setVisible(true);
	}

	public static void main(String[] args) throws IOException {
		new Map();
	}

	/**
	 * 按键监听类
	 */
	private class KeyMoniton extends KeyAdapter {

		@Override
		public void keyPressed(KeyEvent e) {
			super.keyPressed(e);
			switch (e.getKeyCode()) {
			case KeyEvent.VK_UP:
				if (maps[x][y - 1] > 3) {
					return;
				}
				y -= 1;
				break;
			case KeyEvent.VK_DOWN:
				if (maps[x][y + 1] > 3) {
					return;
				}
				y += 1;
				break;
			case KeyEvent.VK_RIGHT:
				if (maps[x + 1][y] > 3) {
					return;
				}
				x += 1;
				break;
			case KeyEvent.VK_LEFT:
				if (maps[x - 1][y] > 3) {
					return;
				}
				x -= 1;
				break;
			}
			repaint();
		}

	}

	/**
	 * 此处绘画地图的方式:<br>
	 * 先找出地图左上角坐标,然后往右和下方画指定格数
	 * 
	 * @param g
	 */
	@Override
	public void paint(Graphics g) {
		// 默认从最左边开始画
		int drawingx = 0;
		int drawingy = 0;
		int minx = MAP_RANK / 2;
		int miny = MAP_TRADE / 2;
		// 如果一行的个数为偶数个,最后不用再次减1
		int maxx = maps.length - minx - (MAP_RANK % 2 == 0 ? 0 : 1);
		// 如果行的个数为偶数个,最后不用再次减1
		int maxy = maps[0].length - miny - (MAP_TRADE % 2 == 0 ? 0 : 1);
		if (x > minx) {// 如果当前位置大于最小位置,则人物固定在中间,起始x为当前位置减去最小位置
			drawingx = x - minx;
		}
		if (x > maxx) {// 如果当前位置大于最大位置则起始x为固定值
			drawingx = maxx - minx;
		}
		if (y > miny) {
			drawingy = y - miny;
		}
		if (y > maxy) {
			drawingy = maxy - miny;
		}
		Image image = null;
		for (int i = 0; i < MAP_RANK * MAP_TRADE; i++) {
			// 每次绘画完一行,则行数下移
			if (i > 0 && i % MAP_RANK == 0) {
				drawingy++;
			}
			image = getImage(maps[drawingx + i % MAP_RANK][drawingy]);
			g.drawImage(image, i % MAP_RANK * BLOCK_WIDTH, i / MAP_RANK * BLOCK_HEIGHT + 30, BLOCK_WIDTH, BLOCK_HEIGHT,
					null);
		}
		// 画人物
		if (x <= minx) {
			minx = x;
		}
		if (x > maxx) {
			minx = MAP_RANK - maps.length + x;
		}
		if (y < miny) {
			miny = y;
		}
		if (y > maxy) {
			miny = MAP_TRADE - maps[0].length + y;
		}
		g.drawImage(user, minx * BLOCK_WIDTH, miny * BLOCK_HEIGHT + 30, BLOCK_WIDTH, BLOCK_HEIGHT, null);
	}

	private Image getImage(Integer i) {
		switch (i) {
		case 1:
			return image1;
		case 2:
			return image2;
		case 3:
			return image3;
		case 4:
			return image4;
		case 5:
			return image5;
		case 6:
			return image6;
		default:
			return null;
		}
	}

	/**
	 * 获取文件路径
	 * 
	 * @param fileName
	 * @return
	 */
	private String getFilePath(String fileName) {
		return Map.class.getResource(fileName).getPath();
	}

}