`

【纯JAVA语言做RPG游戏】3.地图碰撞检测和角色行走的实现

阅读更多

额⊙▽⊙...

上次做好了游戏的基本界面,地图也能成功的显示出来了,不过前面的游戏还没有实现角色与地图的碰撞检测,也就是说角色可以在地图上到处跑,无视那些树啊,石头什么的,这次的第一件事就是要检测角色与地图上物体的碰撞......再加上前面程序的玩家角色是用一个小球替代的,太丑了,这次换成一个动态的小LOLI,让它能够在地图上跑动起来 (╯▔▽▔)╯.....

 

首先,对上次的一些BUG进行改进:

上次说到角色的偏移量,我直接把它设为0了,这是严重的错误,导致我后面出BUG测试了2个多小时,因为如果角色从出生点直接向左或者是上移动的话,它的x和y偏移量就会变成负数,变成负数去对50求余,得到的结果就和正数求余不协调了,就会出现地图突然向左跳了一格的情况....

 

处理掉BUG,接下来就是这次的任务了(先把我的处理思路整理一下,接着上代码....)

1.首先是角色与地图的检测.

由于在游戏的过程中,程序可以得到角色中点的坐标,那么就可以通过这个中点坐标计算出角色在地图数组中对应的位置,接着通过人物所在的这个数组元素位置,找出这个坐标上下左右的数组元素的值,也就相当于知道了人物在当前地图中的上下左右有什么物体.

接着就对人物移动的方法进行改造,在人物向上移动时,判断人物所在位置上方数组map2中的值是否为0(为0就代表没物体阻挡了嘛..),如果为0就继续前面移动的方式,如果不为0的话就不执行前面移动的方式...下左右移动同理.

2.然后是实现角色的动态行走.

我首先从网上找了这么两张角色行走图,图出自《东方苍神行》如下(PS:其实楼主找到了一整套( ´´ิ∀´ิ` )...):




 

一张是角色走路的图,还有一张是角色跑步的图,这里我就不做这么复杂了,统一用跑步的,不过角色停下来的时候要用角色走路图里面的那4张站立不动的画面..

可以看到这素材是由上下左右,每个方向4张图片构成的,所以要实现角色的动态行走的话就必须要在鼠标按下某一个方向时,让角色图片在这个方向的4张连续的图中循环不停的变化,这样看起来角色就真正的动起来了,而不是僵直的平移...

那么怎么达成这种效果呢,首先要知道怎么从这一张图品中把这16张小图片给分解开来,我查了下API,发现Graphics的drawimage()方法,不仅可以直接画出一张图,还可以选择一张图的某一个矩形区域,然后画到面板的指定的矩形区域上,这样就能分开处理这16张小图片了,(当然也可以事先将这行走图用图片处理工具分开成16张图,这样也能减少许多卡顿现象,不过这就不是程序猿的事了,好吧,我承认是我是PS新手,怕麻烦  - -! )具体如下:

----------------------------------------------------------------------------------------------

g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
img - 要绘制的指定图像。如果 img 为 null,则此方法不执行任何操作。
dx1 - 目标矩形第一个角的 x 坐标。
dy1 - 目标矩形第一个角的 y 坐标。
dx2 - 目标矩形第二个角的 x 坐标。
dy2 - 目标矩形第二个角的 y 坐标。
sx1 - 源矩形第一个角的 x 坐标。
sy1 - 源矩形第一个角的 y 坐标。
sx2 - 源矩形第二个角的 x 坐标。
sy2 - 源矩形第二个角的 y 坐标。
observer - 当缩放并转换了更多图像时要通知的对象。

------------------------------------------------------------------------------------------------

接着便是这些图片如何显示的问题,我的思路为,当按下左键时,角色开始向左边移动,这时候循环的变化人物的图片,就是上面行走图中向左走的那4张,其他方向也是这样。这里用一个int变量来控制,初始为0,每按下左键就给这变量+1,当变量达到某个最大值时,又给它置回0...然后再在画人物的方法中判断这个数的值,通过这个值的变化来决定画哪一张图...

 

基本思路就是这样了,接着代码如下(有些前面写过的类,这次没有发生改变我也就不贴出来了,只贴这次处理过的类吧,至于完整的程序源码,我会上传在后面的,有兴趣的一起玩玩,找找BUG(O ^ ~ ^ O) ):

 

/**
 * 角色类
 * @author yy
 *
 */
public class Player extends Thread implements gameConfig{
	//角色中点相对游戏面板的位置(在游戏中是不变的)
	static int px = panelX/2;
	static int py = panelY/2;
	//角色中点在整张地图中的位置(设置人最开始中点的位置一定要是一个元素中心的位置,要不然这种移动就会出问题 - -!)
	static int x = 375;
	static int y = 375;
	//角色的偏移量(实现像素点移动关键的部分,一定要给个初始值,要不然到边界出现负数哭死,害我找错误找了一个晚上)
	static int mx = 50;
	static int my = 50;
	//角色的步长
	static int step = 5;
	//角色是否移动
	static boolean up = false;
	static boolean down = false;
	static boolean left = false;
	static boolean right = false;
	//角色的朝向    1,2,3,4分别代表上下左右(用来处理角色不移动时的朝向问题,后面要写与npc对话之类的估计用得上)
	static int towards = 2;
	//角色的移动累积量(这个就是用来控制循环的变化4张角色图片来达成动态移动的)
	static int up1 = 0;
	static int down1 = 0;
	static int left1 = 0;
	static int right1 = 0;
	@Override
	public void run() {
		while(true){
			moveUD();
			moveLR();
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 角色上下移动的方法
	 */
	public void moveUD(){
		if(up){
			//当按住上键时,给up1加1,当up1大于20时候又置为0,达成循环
			up1++;
			if(up1>=20){
				up1=0;
			}
			//如果角色当前位置上方的数组值不为0(角色上方有物体挡着):这里处理的是角色一个格子内部的移动,不能移动到上面一格
			if(ReadMapFile.map2[y/elesize-1][x/elesize]!=0){
				int y1 = (y/elesize-1)*elesize+elesize/2;
				int x1 = (x/elesize)*elesize+elesize/2;
				if((y-y1)*(y-y1)>=elesize*elesize){
					y=y-step;
					my=my-step;
				}
			}else if(ReadMapFile.map2[y/elesize-1][x/elesize]==0){//上方没物体,可以继续向上移动
				y=y-step;
				my=my-step;
			}
		}else if(down){
			down1++;
			if(down1>=20){
				down1=0;
			}
			if(ReadMapFile.map2[y/elesize+1][x/elesize]!=0){
				int y1 = (y/elesize+1)*elesize+elesize/2;
				int x1 = (x/elesize)*elesize+elesize/2;
				if((y-y1)*(y-y1)>=elesize*elesize){
					y=y+step;
					my=my+step;
				}
			}else if(ReadMapFile.map2[y/elesize+1][x/elesize]==0){
				y=y+step;
				my=my+step;
			}
		}
	}
	
	/**
	 * 角色左右移动的方法
	 */
	public void moveLR(){
		if(left){
			left1++;
			if(left1>=20){
				left1=0;
			}
			if(ReadMapFile.map2[y/elesize][x/elesize-1]!=0){
				int y1 = (y/elesize)*elesize+elesize/2;
				int x1 = (x/elesize-1)*elesize+elesize/2;
				if((x-x1)*(x-x1)>=elesize*elesize){
					x=x-step;
					mx=mx-step;
				}
			}else if(ReadMapFile.map2[y/elesize][x/elesize-1]==0){
				x=x-step;
				mx=mx-step;
			}
		}else if(right){
			right1++;
			if(right1>=20){
				right1=0;
			}
			if(ReadMapFile.map2[y/elesize][x/elesize+1]!=0){
				int y1 = (y/elesize)*elesize+elesize/2;
				int x1 = (x/elesize+1)*elesize+elesize/2;
				if((x-x1)*(x-x1)>=elesize*elesize){
					x=x+step;
					mx=mx+step;
				}
			}else if(ReadMapFile.map2[y/elesize][x/elesize+1]==0){
				x=x+step;
				mx=mx+step;
			}
		}
	}
	
	
	public static void draw(Graphics g){
		//如果角色不在移动中
		if(!up&&!down&&!left&&!right){
			if(towards==1){//如果角色移动的最后朝向为上
				g.drawImage(walk1.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 96*3, 96, 96*4, null);
			}else if(towards==2){//最后移动朝向下
				g.drawImage(walk1.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 0, 96, 96, null);
			}else if(towards==3){//最后移动朝向左
				g.drawImage(walk1.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 96, 96, 96*2, null);
			}else if(towards==4){//最后移动朝向右
				g.drawImage(walk1.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 96*2, 96, 96*3, null);
			}
		}else{//如果角色在移动中
			if(up){
				//通过up1的值,来决定画哪一张图片
				if(up1<5){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 96*3, 96, 96*4, null);
				}else if(up1<10){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96, 96*3, 96*2, 96*4, null);
				}else if(up1<15){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*2, 96*3, 96*3, 96*4, null);
				}else{
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*3, 96*3, 96*4, 96*4, null);
				}
			}else if(down){
				if(down1<5){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 0, 96, 96, null);
				}else if(down1<10){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96, 0, 96*2, 96, null);
				}else if(down1<15){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*2, 0, 96*3, 96, null);
				}else{
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*3, 0, 96*4, 96, null);
				}
			}else if(left){
				if(left1<5){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 96, 96, 96*2, null);
				}else if(left1<10){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96, 96, 96*2, 96*2, null);
				}else if(left1<15){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*2, 96, 96*3, 96*2, null);
				}else{
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*3, 96, 96*4, 96*2, null);
				}
				
			}else if(right){
				if(right1<5){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 0, 96*2, 96, 96*3, null);
				}else if(right1<10){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96, 96*2, 96*2, 96*3, null);
				}else if(right1<15){
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*2, 96*2, 96*3, 96*3, null);
				}else{
					g.drawImage(walk.getImage(), Player.px-elesize/2-15, Player.py-elesize/2-25, Player.px-elesize/2+65, Player.py-elesize/2+55, 96*3, 96*2, 96*4, 96*3, null);
				}
			}
		}
	}
	
	
	//得到角色在数组中的位置I
	public static int getI(){
		return (y-(playersize/2))/50;
	}
	//得到角色在数组中的位置J
	public static int getJ(){
		return (x-(playersize/2))/50;
	}
}

 这次的处理大概也就是这么多了,还有就是将游戏面板中以前画小球的地方改成调用人物类的Draw方法了,这都是些小改动

上一上效果图:



 

 再来张gif,同样gif画质惨不忍睹,卡顿纯属gif问题,实际程序没卡顿的....  0 0、   神呐,谁教教我怎么做无损的gif啊....



 

这次处理碰撞和实现角色动态行走写的代码没有多少,但是比前面难弄多了,写这种逻辑性强的代码,必须要保持思路清晰,我很多时候都写着写着就不知道自己要干嘛了  = =!   前路漫漫,仍需努力啊...

 

下次就把和NPC对话的功能实现吧,现在的游戏还是玩家一个人的世界啊....下次就加点小伙伴进来,嘿嘿

 

当前阶段完整代码放在下面了,还有地图文件也放在下面(前面那个版本都忘记传地图了,真是大失败啊  - -! ),想要玩一玩这个程序的,在程序的test类中改好地图文件的存放路径,就能运行了....

 

 

  • 大小: 24.2 KB
  • 大小: 17.2 KB
  • 大小: 317.3 KB
  • 大小: 647 KB
分享到:
评论
4 楼 幻神舞动 2017-03-09  
 
3 楼 三千世界五道轮回枯骨 2016-05-22  
我的运行不对啊,行走的指令就是按鼠标左键对吧
2 楼 Y_1746119035 2014-11-08  
人生难得糊涂 写道
       

= =!
1 楼 人生难得糊涂 2014-11-01  
       

相关推荐

    【纯JAVA语言做RPG游戏】1.做个瓷砖地图生成器

    在本项目中,我们将探讨如何使用纯Java语言开发一个RPG(角色扮演游戏)中的瓷砖地图生成器。这个生成器能够自动生成游戏世界的基础布局,为玩家提供丰富的探索环境。地图生成是游戏开发的重要组成部分,特别是在2D...

    【纯java语言做RPG游戏】4.用XML导入NPC并与NPC对话

    在本教程中,我们将深入探讨如何使用纯Java语言制作角色扮演游戏(RPG)并利用XML文件导入非玩家角色(NPC)以及实现与NPC的交互。这个项目不仅涵盖了基础的Java编程,还涉及到游戏开发中的重要概念,如数据结构、...

    【纯JAVA语言做个RPG游戏】2.游戏界面及角色移动的基本实现

    在本项目中,我们将探讨如何使用纯Java语言创建一个简单的角色扮演游戏(RPG)游戏界面以及实现角色的移动功能。这个教程将引导我们逐步构建一个基础的2D游戏框架,涉及核心的游戏逻辑、用户交互以及图形渲染。 ...

    Github基于Java的Rpg游戏

    【标题】:“Github基于Java的Rpg游戏”指的是在GitHub上可以找到的一种使用Java编程语言开发的角色扮演游戏(Role-Playing Game,简称RPG)。这种类型的游戏通常包含丰富的剧情、角色发展和互动元素,而通过使用...

    c#游戏开发基于unity3d的回合制RPG游戏源码.zip

    c#游戏开发基于unity3d的回合制RPG游戏源码.zipc#游戏开发基于unity3d的回合制RPG游戏源码.zipc#游戏开发基于unity3d的回合制RPG游戏源码.zipc#游戏开发基于unity3d的回合制RPG游戏源码.zipc#游戏开发基于unity3d的...

    基于java语言的RPG游戏源代码+说明书

    RPG游戏以其丰富的剧情、深度的角色定制和策略性战斗系统深受玩家喜爱,而通过Java实现这样的游戏,可以提供稳定且具有高度可扩展性的基础架构。 首先,让我们深入理解Java在RPG游戏中的应用。Java提供了强大的图形...

    Unity 3D的Ultimate MMO RPG Kit 在线 mmo rpg 游戏开发.zip

    Unity 3D是一款强大的跨平台游戏开发引擎,广泛应用于创建各种类型的游戏,包括单机、多人在线(MMO)和角色扮演游戏(RPG)。"Ultimate MMO RPG Kit" 是一个专为开发在线MMO RPG游戏设计的工具包,它包含了各种预设...

    JavaRPG-游戏

    《JavaRPG-游戏》是一款基于Java编程语言开发的角色扮演游戏,体现了Java在游戏开发领域的应用。游戏虽然简单,但包含了游戏设计的基本要素,如角色、环境、交互等,展现了Java在构建复杂逻辑和实时交互系统方面的...

    unity 3D多人在线RPG网络游戏源码.rar

    unity 3D多人在线RPG网络游戏源码.rarunity 3D多人在线RPG网络游戏源码.rarunity 3D多人在线RPG网络游戏源码.rarunity 3D多人在线RPG网络游戏源码.rarunity 3D多人在线RPG网络游戏源码.rarunity 3D多人在线RPG网络...

    纯java开发的一个RPG游戏,亲测可用

    这个标题揭示了一个基于Java编程语言的RPG(角色扮演游戏)项目,表明该游戏是完全使用Java语言编写的,没有依赖其他非Java技术。"纯Java开发"通常意味着游戏的所有核心逻辑、图形渲染和用户界面都是用Java Swing...

    javaRPG游戏.zip

    Java RPG游戏是一款基于Java编程语言开发的角色扮演游戏。Java作为一种跨平台的编程语言,因其高效、稳定和可移植性,常被用于开发各种类型的游戏,包括RPG(角色扮演游戏)。RPG游戏通常包含丰富的剧情、角色养成、...

    java文字RPG小游戏

    Java编程语言是开发“java文字RPG小游戏”的基础工具,这是一种基于文本的角色扮演游戏,玩家通过输入指令来控制角色行动,探索虚拟世界,与各种怪物战斗,例如描述中的哥布林。在这样的游戏中,核心功能包括游戏...

    基于JAVA的手机RPG游戏图形引擎的实现

    - **物理引擎**:处理游戏中物体间的碰撞检测和物理交互,如角色与环境之间的互动等。 - **音频引擎**:负责游戏中的音效和背景音乐的播放,提升玩家的沉浸感。 - **脚本引擎**:支持使用脚本语言来编写游戏逻辑,...

    java写的RPG小游戏

    Java编写的RPG小游戏是一款基于Java编程语言开发的角色扮演游戏(Role-Playing Game,简称RPG)。这类游戏通常包含丰富的故事情节、角色设定、任务系统和战斗机制,为玩家提供沉浸式的游戏体验。在Java环境下,...

    JAVARPG小游戏

    在Java ME中,可以使用Java的Sprite类来处理游戏对象,如角色和敌人,每个Sprite有自己的坐标、动作和碰撞检测机制。地图滚动和场景切换则是通过对游戏世界进行分块管理,当玩家接近地图边缘时,动态加载新的区域。...

    JAVA RPG 游戏 控制上下左右

    3. **碰撞检测**:当角色移动时,需要检查是否与其他游戏元素(如障碍物、NPC等)发生碰撞。这可以通过比较角色和目标对象的边界框来实现,例如使用轴对齐边界盒(AABB)算法。如果存在重叠,角色则不能通过。 4. *...

Global site tag (gtag.js) - Google Analytics