对于一款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);
}
}
}