lufylegend引擎 rpg开发之2D地图的碰撞检测

原创 2015年04月07日 23:08:41

对于一款rpg来说,地图是不可缺少的内容,对于2D游戏来说,常用的地图一般为tiledmap,也就是有一片片的小地图单元拼接成的地图,具体的如何使用瓦片地图,可以参考一下下面的blog,写的非常详细:

        http://blog.csdn.net/yorhomwang/article/details/8892305

今天要说的主要是2D地图的碰撞检测,所以上面的地图类实现就略过不谈,下面开始介绍2D地图的碰撞检测,在常规的游戏中一般都会有能够走动的地方和不能够走动的地方,地图的碰撞检测就是为了实现这个目的,常用的方法一般是事先给地图设定好能去的地方和不能去的地方,也就是可以在已经设定好的瓦片地图数据中多添加一个参数,就是是否可以行走的参数,在这里可以简化一下,0为可以走,1为不可走,下面就是修改后的地图数组:

    var mapData=[[[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[55,1],[55,1],[18,1]],    
                 [[18,1],[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[55,1],[55,1],[18,1]],    
                 [[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[55,1],[55,1],[18,1]],    
                 [[18,1],[17,0],[17,0],[17,0],[18,1],[18,1],[18,1],[18,1],[18,1],[17,0],[17,0],[55,1],[55,1],[17,0],[18,1]],    
                 [[18,1],[17,0],[17,0],[18,1],[22,1],[23,1],[23,1],[23,1],[24,1],[18,1],[17,0],[55,1],[55,1],[17,0],[18,1]],    
                 [[18,1],[17,0],[17,0],[18,1],[25,1],[28,1],[26,1],[79,1],[27,1],[18,1],[55,1],[55,1],[17,0],[17,0],[18,1]],    
                 [[18,1],[17,0],[17,0],[17,0],[17,0],[10,0],[11,0],[12,0],[18,1],[18,1],[55,1],[55,1],[17,0],[17,0],[18,1]],    
                 [[18,1],[18,1],[17,0],[17,0],[10,0],[16,0],[16,0],[16,0],[11,0],[55,1],[55,1],[17,0],[17,0],[17,0],[18,1]],    
                 [[18,1],[18,1],[17,0],[17,0],[77,0],[16,0],[16,0],[16,0],[16,0],[21,0],[21,0],[17,0],[17,0],[17,0],[18,1]],    
                 [[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[55,1],[55,1],[18,1],[18,1],[18,1],[18,1]]];

可以看到将原本的数字变成了数组,添加了地图的碰撞检测参数也就是mapData[i][j][1]这个参数,i,j为行号列号。并在原本的map类中添加了一个获得mapdata的数据:

LTileMap.prototype.GetMapData = function(){
var s=this;
return s.mapData;


}

之后就是修改人物的行走函数,来保证人物不会走到不该走的地方,具体的人物类实现可以参考下面的文章:

http://blog.csdn.net/qq_26786555/article/details/44539719

在原本的行走函数判断左右上下行走是否越限时添加判断下一个地图块是否是可以行走的地图块,不是就不移动人物,可以行走则移动人物坐标,修改后的函数如下,在这里我们修改了一下人物的行走速度,使行走速度是一个地图块的大小方便计算,如果不这样需要另外在另外判断一下人物的坐标位置所处的地图块,另外还需要注意的是在这里y才是行,x才是列,理解了这个,下面的函数也就不难理解了

LCharcter.prototype.move=function(moveto){
//仅设置一次action避免重复设置导致图形不断重置
  var s=this;
  if(moveto==40){
    if(down==0){
     player.setAction(0,1,1,false);
 down++;
}
 if(s.y<352-bitmapData.height&&(mapData[(s.y+speed)/32][s.x/32][1]!=1)){
       s.y=s.y+speed;
 }
  }else if(moveto==39){
  if(left==0){
     player.setAction(2,1,1,false);
 left++;
}   
 if(s.x<480-bitmapData.width&&(mapData[s.y/32][(s.x+speed)/32][1]!=1)){
       s.x=s.x+speed;
}
  }else if(moveto==38){
   if(up==0){
     player.setAction(3,1,1,false); 
 up++;
}   
  if(s.y>0&&(mapData[(s.y-speed)/32][s.x/32][1]!=1)){
       s.y=s.y-speed;
}
  }else if(moveto==37){
    if(right==0){
     player.setAction(1,1,1,false);
 right++;
}   
   if(s.x>0&&(mapData[s.y/32][(s.x-speed)/32][1]!=1)){
       s.x=s.x-speed;
}   
  }
  s.addEventListener(LEvent.ENTER_FRAME,s.onmove);
}

这样就实现了人物行走时的碰撞检测

源代码如下:index.php

<!DOCTYPE html>  
<html lang="en">  
    <head>  
    <meta charset="utf-8" />  
    <title>LTileMap</title>  
    <script type="text/javascript" src="lufylegend.js-lufylegend-1.9.7/lufylegend-1.9.7.min.js"></script>
<script type="text/javascript" src="LCharcter.js"></script>
<script type="text/javascript" src="map.js"></script>
    <script>  
    LInit(30,"legend",448,320,main);
LGlobal.setDebug(true);  
    var backLayer,loadingLayer,mapLayer,playerLayer;
var loadData = [  
        {name:"cr",path:"./images/charc.jpg"},   
{name:"map",path:"./images/map.jpg"},
{name:"money",path:"./images/bird.png"}
    ]; 
    var mapData=[[[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[55,1],[55,1],[18,1]],    
                 [[18,1],[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[17,0],[55,1],[55,1],[18,1]],    
                 [[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[18,1],[18,1],[17,0],[17,0],[17,0],[17,0],[55,1],[55,1],[18,1]],    
                 [[18,1],[17,0],[17,0],[17,0],[18,1],[18,1],[18,1],[18,1],[18,1],[17,0],[17,0],[55,1],[55,1],[17,0],[18,1]],    
                 [[18,1],[17,0],[17,0],[18,1],[22,1],[23,1],[23,1],[23,1],[24,1],[18,1],[17,0],[55,1],[55,1],[17,0],[18,1]],    
                 [[18,1],[17,0],[17,0],[18,1],[25,1],[28,1],[26,1],[79,1],[27,1],[18,1],[55,1],[55,1],[17,0],[17,0],[18,1]],    
                 [[18,1],[17,0],[17,0],[17,0],[17,0],[10,0],[11,0],[12,0],[18,1],[18,1],[55,1],[55,1],[17,0],[17,0],[18,1]],    
                 [[18,1],[18,1],[17,0],[17,0],[10,0],[16,0],[16,0],[16,0],[11,0],[55,1],[55,1],[17,0],[17,0],[17,0],[18,1]],    
                 [[18,1],[18,1],[17,0],[17,0],[77,0],[16,0],[16,0],[16,0],[16,0],[21,0],[21,0],[17,0],[17,0],[17,0],[18,1]],    
                 [[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[18,1],[55,1],[55,1],[18,1],[18,1],[18,1],[18,1]]];
var imglist=[];
function main(){  
        //加入进度条  
        loadingLayer = new LoadingSample3();   
        addChild(loadingLayer);   
        //加载图片并显示进度  
        LLoadManage.load(  
            loadData, 
            function(progress){  
                loadingLayer.setProgress(progress);  
            },  
            gameInit  
        );  
      
    }  
function gameInit(result){
removeChild(loadingLayer);  
        imglist = result;  
backLayer = new LSprite();  
        addChild(backLayer); 
mapLayer = new LTileMap(mapData,imglist["map"],32,32);
backLayer.addChild(mapLayer);
playerLayer=new LCharcter(imglist["cr"]);
backLayer.addChild(playerLayer);
   //加入动画和按键事件监听
//backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);
LEvent.addEventListener(LGlobal.window, LKeyboardEvent.KEY_DOWN,move); 
        LEvent.addEventListener(LGlobal.window, LKeyboardEvent.KEY_UP,stop);
       
}
   function move(e){  
 playerLayer.move(e.keyCode);
   }
   function stop(e){
 playerLayer.stop();
   }
</script>  





</head>  
    <body>  
            <div id="legend"></div>  
    </body>  
</html>

角色类:

var player;
var speed=32;
var bitmapDate;
var moveto;
var right=0;
var left=0;
var up=0;
var down=0;
var mapData;
function LCharcter(imgdata){
var s=this;
base(s,LSprite,[]);
s.x=64;
s.y=128;
s.imgdata=imgdata;
var list=LGlobal.divideCoordinate(640,728,8,8);
bitmapData=new LBitmapData(s.imgdata);
s.width=bitmapData.width/8;
s.height=bitmapData.height/8;
player= new LAnimation(s,bitmapData,list);
    player.setAction(0,1,1,false);
player.scaleX=0.4;
player.scaleY=0.4;
s.addChild(player);
//s.addBodyPolygon(bitmapData.width,bitmapData.height,1,0,0,0);
mapData=backLayer.getChildByName("map").GetMapData();
}
LCharcter.prototype.move=function(moveto){
//仅设置一次action避免重复设置导致图形不断重置
  var s=this;
  if(moveto==40){
    if(down==0){
     player.setAction(0,1,1,false);
 down++;
}
 if(s.y<352-bitmapData.height&&(mapData[(s.y+speed)/32][s.x/32][1]!=1)){
       s.y=s.y+speed;
 }
  }else if(moveto==39){
  if(left==0){
     player.setAction(2,1,1,false);
 left++;
}   
 if(s.x<480-bitmapData.width&&(mapData[s.y/32][(s.x+speed)/32][1]!=1)){
       s.x=s.x+speed;
}
  }else if(moveto==38){
   if(up==0){
     player.setAction(3,1,1,false); 
 up++;
}   
  if(s.y>0&&(mapData[(s.y-speed)/32][s.x/32][1]!=1)){
       s.y=s.y-speed;
}
  }else if(moveto==37){
    if(right==0){
     player.setAction(1,1,1,false);
 right++;
}   
   if(s.x>0&&(mapData[s.y/32][(s.x-speed)/32][1]!=1)){
       s.x=s.x-speed;
}   
  }
  s.addEventListener(LEvent.ENTER_FRAME,s.onmove);
}
LCharcter.prototype.onmove=function(){
player.onframe();
}
LCharcter.prototype.stop=function(){
    var s=this;
moveto=0;
if(left!=0)
left=0;
if(right!=0)
right=0;
if(up!=0)
up=0;
if(down!=0)
down=0;
}
LCharcter.prototype.CheckContact=function(money){
    var s=this;
//money在右侧
if((s.x>money.x)&&(money.x+money.width<s.x)){
return false;
    //money在左侧
}else if((s.x<money.x)&&(s.x+s.width<money.x)){

return false;
//money在下测
}else if((s.y<money.y)&&(s.y+s.height<money.y)){

return false;
//money在上测
}else if((s.y>money.y)&&(money.y+money.height<s.y)){
return false;
}else{
money.mode="die";
return true;
}
}

地图类:

function LTileMap(data,img,width,height){  
    var s = this;  
    base(s,LSprite,[]);  
    s.x = 0;  
    s.y = 0;  
    s.mapData = data;  
    s.imgData = img;  
s.name="map";
    if(!width){  
        var wbitmap = new LBitmapData(s.imgData);  
        s.partWidth = wbitmap.image.width;
    }else{  
        s.partWidth = width;
    }  
    if(!height){  
        var hbitmap = new LBitmapData(s.imgData);  
        s.partHeight = hbitmap.image.height;  
    }else{  
        s.partHeight = height;  
    }  
    s.onshow();  
}  
LTileMap.prototype.GetMapData = function(){
var s=this;
return s.mapData;


}
LTileMap.prototype.onshow = function(){  
    var s = this;  
    var mapdata = s.mapData;  
    var partWidth = s.partWidth;  
    var partHeight = s.partHeight;  
      
    var i,j;  
    var index,indexY,indexX;  
    var bitmapdata,bitmap;  
  
    for(i=0;i<mapdata.length;i++){  
        for(j=0;j<mapdata[0].length;j++){  
   var sprite=new LSprite();
            index = mapdata[i][j][0];  
            indexY = Math.floor(index/mapdata.length);  
            indexX = index - indexY*mapdata.length;  
            bitmapdata = new LBitmapData(s.imgData,indexX*partWidth,indexY*partHeight,partWidth,partHeight);  
            bitmap = new LBitmap(bitmapdata);  
            bitmap.x = j*partWidth + s.x;    
            bitmap.y = i*partHeight + s.y; 
            sprite.addChild(bitmap);
            s.addChild(sprite);
            }  
    }  
}  

版权声明:本文为博主原创文章,未经博主允许不得转载。

ue4 碰撞检测测试

记录几条物理相关   测试条件,1使用setActorLocation移动,3使用控制器的移动 1 moveCube  2 targetCube  3 Character     1和2的关系描述,先...
  • OnafioO
  • OnafioO
  • 2017年11月10日 11:19
  • 197

游戏中的碰撞检测

游戏中的碰撞检测方式有很多,不同的算法之间主要是在精度和速度之间权衡。以下几种方式按照速度排序说明。以2D为例,3D不过是增加了一维罢了,算法理解上没太大区别。 一、地图格子划分检测       ...
  • ruanjianxiong
  • ruanjianxiong
  • 2011年08月24日 17:20
  • 7616

如何制作一款HTML5 RPG游戏引擎——第一篇,地图类的实现

一,话说天下大事 前不久看到lufy的博客上,有一位朋友想要一个RPG游戏引擎,出于兴趣准备动手做一做。由于我研究lufylegend有一段时间了,对它有一定的依赖性,因此就准备将这个引擎基于luf...
  • yorhomwang
  • yorhomwang
  • 2013年05月06日 21:49
  • 22037

RPG游戏地图设计与实现

先占个坑,有空写文章,时间长了,忘了写什么了,国庆快到了,我是多想立即给zhugu...
  • tyxkzzf
  • tyxkzzf
  • 2014年09月28日 20:42
  • 926

Android研究之游戏开发碰撞检测

游戏碰撞的大致可以分为这几种类 1.主角与边界的碰撞,限制主角不能走出手机屏幕外。 2.主角与物理层的碰撞,与地图中的房子 桌子 椅子等等。 3.主角与游戏人物之间的碰撞,这里指NPC等。 4.主角与...
  • donghong2008
  • donghong2008
  • 2014年07月25日 09:52
  • 775

[OpenGL] 二维游戏:网格布局与碰撞检测

二维游戏中的经典布局方式莫过于网格布局。在网格布局的基础上,还可以实现基于网格的碰撞检测,算法实现简单,且效果较好。碰撞检测的精度主要取决于网格的大小。         (图片素材来源:rgp mak...
  • ZJU_fish1996
  • ZJU_fish1996
  • 2016年07月28日 16:18
  • 2200

lufylegend引擎 实现2D RPG地图的切换

对于一款游戏来说,丰富的地形可以成为很出色的买点,特别是对于RPG这个类型来说,翻箱倒柜洗劫各场景中的道具无疑是一种乐趣,所以这篇文章主要的目的就是通过lufylegend这款引擎来实现RPG地图的切...
  • qq_26786555
  • qq_26786555
  • 2015年05月03日 16:49
  • 265

unity RPG小地图的制作

Unity1小地图的制作 using UnityEngine; using System.Collections; public class TestMap : MonoBehav...
  • peanut__love
  • peanut__love
  • 2015年03月04日 23:44
  • 525

Unity 3D中的射线与碰撞检测

在我们的游戏开发过程中,有一个很重要的工作就是进行碰撞检测。例如在射击游戏中子弹是否击中敌人,在RPG游戏中是否捡到装备等等。在进行碰撞检测时,我们最常用的工具就是射线,Unity 3D的物理引擎也为...
  • u014805066
  • u014805066
  • 2016年09月06日 22:44
  • 11514

《Little Runner》(五)——怪物碰撞检测

上一章中,虽然怪物已经出现了,但是怪物对玩家没有造成任何伤害,所以我们接下来要加入碰撞检测,如果怪物碰到主角,则扣主角的血。 我们给Player类添加点东西,如下代码显示: Player类...
  • u010778159
  • u010778159
  • 2015年02月13日 15:37
  • 433
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:lufylegend引擎 rpg开发之2D地图的碰撞检测
举报原因:
原因补充:

(最多只允许输入30个字)