RGP走迷宫游戏就是玩家通过方向键控制主角RGP人物从迷宫左上角走到右下角绿色出口处。游戏可以提高玩家观察力,训练思维力,开发想象力。
本篇博文一共开发了两种难度的走迷宫游戏,简单难度是全图点亮状态的;而正常难度只显示主角身边一个圆的区域(其余区域黑暗,如果实在走不出可以参考辅助地图)运行效果如下:
素材及完整工程源码链接:https://pan.baidu.com/s/1WUyvBR-JwzYSBluNFZFDmQ 提取码: 2i5g
设计一个地图工具类,专门用于迷宫生成,迷宫信息使用二维数组存储;人物的移动是在按键事件中处理的,如果人物的移动不会碰到墙壁则可以移动;使用manX、manY表示人物位于数组的哪个位置,使用manIndex控制人物帧数;当人物移动到出口时,游戏过关。迷宫生成原理可以参考博主之前写的博文:https://blog.csdn.net/A1344714150/article/details/86587307
ⅠRGP人物移动实现
通过按键事件进行处理,如果玩家按的键位是上,判断主角上方一格是不是墙;如果不是,则可以移动,接着判断上方一格是不是出口;判断上一次移动的方向是上吗?如果是向上,帧数变量+1,帧数如果已经是最后一张,帧数变量归零;如果上一次移动的方向不是向上,改变移动方向direction为UP,并且帧数变量归0;先将之前人物所在数组元素置空值,人物所在行数-1,再将人物当前所在数组元素值置为MAN
public static final int BLANK=-1,MAN=0,WALL=1,EXIT=2,UP=1,DOWN=2,LEFT=3,RIGHT=4;
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_UP:
if(map[manX-1][manY]!=WALL){
if(map[manX-1][manY]==EXIT){
JOptionPane.showMessageDialog(this, "恭喜过关");
return ;
}
if(direction==UP){
manIndex=manIndex+1==4?0:++manIndex;
}else{
manIndex=0;
direction=UP;
}
map[manX][manY] = BLANK;
manX -= 1;
map[manX][manY] = MAN;
}
;break;
case KeyEvent.VK_DOWN:
if(map[manX+1][manY]!=WALL){
if(map[manX+1][manY]==EXIT){
JOptionPane.showMessageDialog(this, "恭喜过关");
return ;
}
if(direction==DOWN){
manIndex=manIndex+1==4?0:++manIndex;
}else{
manIndex=0;
direction=DOWN;
}
map[manX][manY] = BLANK;
manX += 1;
map[manX][manY] = MAN;
}
;break;
case KeyEvent.VK_LEFT:
if(map[manX][manY-1]!=WALL){
if(map[manX][manY-1]==EXIT){
JOptionPane.showMessageDialog(this, "恭喜过关");
return ;
}
if(direction==LEFT){
manIndex=manIndex+1==4?0:++manIndex;
}else{
manIndex=0;
direction=LEFT;
}
map[manX][manY] = BLANK;
manY -= 1;
map[manX][manY] = MAN;
}
;break;
case KeyEvent.VK_RIGHT:
if(map[manX][manY+1]!=WALL){
if(map[manX][manY+1]==EXIT){
JOptionPane.showMessageDialog(this, "恭喜过关");
return ;
}
if(direction==RIGHT){
manIndex=manIndex+1==4?0:++manIndex;
}else{
manIndex=0;
direction=RIGHT;
}
map[manX][manY] = BLANK;
manY += 1;
map[manX][manY] = MAN;
}
;break;
}
repaint();
}
Ⅱ 图片的获取及显示
在这里,每张图片边长20像素,leftX和leftY表示迷宫水平和垂直方向的偏移量,墙对应素材pic0.png,地砖对应素材pic1.png,出口对应素材pic2.png,人物素材pic3~18.png,其中3~6人物向上,7~10人物向下,11~14人物向左,15~18人物向右;根据帧数变量manIndex和移动方向direction去显示主角图像;
private void getPics() {
for(int i=0;i<20;i++){
pics[i] = Toolkit.getDefaultToolkit().getImage("D:/Game/MazeGameEasy/pic"+i+".png");
}
}
public void paint(Graphics g){
g.clearRect(0, 0, getWidth(), getHeight());
for(int i=0;i<2*row+1;i++){
for(int j=0;j<2*col+1;j++){
if(map[i][j]==WALL){
g.drawImage(pics[0],leftX+20*j, leftY+20*i, 20, 20, this);
}else if(map[i][j]==MAN){
switch(direction){
case UP:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[3+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
case DOWN:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[7+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
case LEFT:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[11+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
case RIGHT:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[15+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
}
}else if(map[i][j]==BLANK){
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
}else{
g.drawImage(pics[2],leftX+20*j, leftY+20*i, 20, 20,this);
}
}
}
}
Ⅲ 圆形区域的显示
在正常难度的迷宫里,假设了玩家是位于黑暗山洞手持灯笼的情况,只显示了玩家附近一个小圆的区域,其余黑暗;
首先先画出以主角为中心的九宫格图像(这是一个大矩形),然后从矩形的左上角开始,挨个像素遍历到矩形右下角,如果遍历到的像素位于圆外,对该像素点进行擦除;需要说明的是,矩形的左上角像素坐标是(20*(manY-1),20*(manX-1)),矩形的右下角像素坐标是(20*(manY+2),20*(manX+2)),因为图案边长是20,而manX和manY表示的是人物所在的行数和列数。
for(int i=manX-1;i<=manX+1;i++){//画主角周围九宫格图案
for(int j=manY-1;j<=manY+1;j++){
if(map[i][j]==WALL){
g.drawImage(pics[0],leftX+20*j, leftY+20*i, 20, 20, this);
}else if(map[i][j]==MAN){
switch(direction){
case UP:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[3+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
case DOWN:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[7+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
case LEFT:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[11+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
case RIGHT:
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
g.drawImage(pics[15+manIndex], leftX+20*j, leftY+20*i, 20, 20, this);
break;
}
}else if(map[i][j]==BLANK){
g.drawImage(pics[1],leftX+20*j, leftY+20*i, 20, 20,this);
}else{//出口
g.drawImage(pics[2],leftX+20*j, leftY+20*i, 20, 20,this);
}
}
}
g.drawOval(leftX+20*(manY-1), leftX+20*(manX-1), 60, 60);//画圆
for(int i=20*(manY-1);i<=20*(manY+2);i++){
for(int j=20*(manX-1);j<=20*(manX+2);j++){
if((i-(20*manY+10))*(i-(20*manY+10))+(j-(20*manX+10))*(j-(20*manX+10))>30*30){
g.fillRect(i, j, 1, 1);
}
}
}
Ⅳ 辅助地图的显示
基于博主小时候玩的FC游戏(《荆轲新传》)主角走山洞带来的阴影,我觉得非常有必要加入辅助地图的功能;
在游戏面板类GamePanel加入一个getCloneMap()方法,用来返回去除人物后的地图数组,将数组作为辅助地图类HelpPanel的构造参数,HelpPanel用来显示一个全亮的地图。绘制过程和游戏面板一致,默认辅助地图关闭,取消注释显示全亮地图。
public int[][] getCloneMap(){
int[][] temp = new int[map.length][map[0].length];
for(int i=0;i
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.*;
public class HelpPanel extends JPanel{
int[][] map;
int leftX,leftY;
Image[] pics = new Image[20];
public static final int BLANK=-1,MAN=0,WALL=1,EXIT=2,UP=1,DOWN=2,LEFT=3,RIGHT=4;
public HelpPanel(int[][] cloneMap) {
map = cloneMap;
getPics();
setPreferredSize(new Dimension((map[0].length)*20,(map.length)*20));//map[0].length是列数,map.length是行数
}
private void getPics() {
for(int i=0;i<20;i++){
pics[i] = Toolkit.getDefaultToolkit().getImage("D:/Game/MazeGameEasy/pic"+i+".png");
}
}
public void paint(Graphics g){
g.clearRect(0, 0, getWidth(), getHeight());
for(int i=0;i
Ⅰ如何展示辅助地图
Ⅱ 迷宫怎样才算困难难度?
基于当前正常迷宫难度的工程,可以做以下措施提升游戏的难度
①增加迷宫的层数并增加迷宫上下楼的功能;
②让主角初始随机生成在迷宫的某个角落,并将主角始终显示在屏幕中心,不显示主角相对整体迷宫所在位置;
③改变出口及上下楼梯的位置,让其初始情况随机化