很早以前的一个想法,今天终于实现了。此次做了2个版本:
1、第一个版本使用的很多Jlabel做的,数据都是写死的。并且失败了。
2、使用绘画做的,可以更改数据,成功实现。地图使用的二维数组存储,可以更改每行和每列的显示数量,但是我使用的图片是60x60的,不知道会不会自动缩放。目前没遇到BUG。
先上段效果图:
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();
}
}