此次只简单地实现了地图的绘制和基本的碰撞检测,感觉如果再深一步写下去估计要花一年时间才能搞定,目前暂时只支持IE
很多地方的实现没有找到原作者的代码,只靠自己的一点想法简单的完成了类似的功能
(function(){
var _kdGame = {
init:function(id,options){
options = options || {};
this.width = options.width||800;
this.height = options.height||600;
},
addModule:function(moduleName,func){
var moduleArray = moduleName.split('.');
var parent = window;
for(var i = 0;i< moduleArray.length;i++){
if(typeof(parent[moduleArray[i]]) == 'undefined')
parent[moduleArray[i]] = {};
parent = parent[moduleArray[i]];
}
if(func)
func.call(parent,this);
return parent;
}
};
kdGame = _kdGame;
//添加一个功能模块
kdGame.addModule('kdGame.core',function(cg){
this.name = "kdGameCore";
this.$=function(id){
return document.getElementById(id);
};
this.$$=function(tagName,parent){
parent=parent||document;
return parent.getElementsByTagName(tagName);
};
this.extend = function(des,sou){
for(name in sou)
des[name] = sou[name];
return des;
};
this.bindHandler=(function(){
if(window.addEventListener){
return function(elem,type,handler){
elem.addEventListener(type,handler,false);
};
}
else if(window.attachEvent){
return function(elem,type,handler){
elem.attachEvent("on"+type,handler);
};
}
})();
this.removeHandler=(function(){
if(window.removeEventListerner){
return function(elem,type,handler){
elem.removeEventListerner(type,handler,false);
};
}
else if(window.detachEvent){
return function(elem,type,handler){
elem.detachEvent("on"+type,handler);
};
}
})();
/**获取指定元素在数组中的下标*/
Array.prototype.indexOf = function(value){
for ( var i = 0; i < this.length; i++) {
if(this[i] == value)
return i;
}
return -1;
};
});
kdGame.addModule('kdGame',function(cg){
var map = function(gameData){
//判断用什么方式调用,this instanceof arguments.callee这种方式是用来判断是否是用new运算符调用的
if(!(this instanceof arguments.callee)){
return new arguments.callee(gameData);
}
this.init(gameData);
};
map.prototype = {
init:function(gameData){
var defaults = {
cellSize:[40,40],
width:200,
height:200,
beginX:0,
beginY:0
};
options = gameData.startOptions || {};
options = cg.core.extend(defaults,options);
this.mapMatrix = gameData.mapMatrix;
this.cellSize = options.cellSize;
this.beginX = options.beginX;
this.beginY = options.beginY;
this.width = options.width;
this.height = options.height;
this.srcObj = options.srcObj;
this.srcArray = [];
var i = 0;
for(name in this.srcObj){
this.srcArray[i] = this.srcObj[name];
i++;
}
},
getImg:function(type){
if(!this.srcArray[type])
this.srcArray[type] = "images/grass.png";
return this.srcArray[type];
},
draw:function(){
var cellHeight = this.cellSize[1];
var cellWidth = this.cellSize[0];
var beginY = this.beginY;
var beginX = this.beginX;
var selfPosition = this.selfPosition;
var srcObj = this.srcObj;
var curRow = 0;
var curCol = 0;
var curObj;
var mapMatrix = this.mapMatrix;
for(var i = beginY,len = beginY+mapMatrix.length*cellHeight;i < len ;i += cellHeight){
curRow = (i-beginY)/cellHeight;
for ( var j = 0,xlen = beginX+mapMatrix[j].length*cellWidth; j < xlen; j += cellWidth) {
curCol = (j-beginX)/cellWidth;
var curImg = document.createElement("img");
curObj = this.getImg(mapMatrix[curRow][curCol]);
curImg.src = curObj;
curImg.style.position = 'absolute';
curImg.style.left = j;
curImg.style.top = i;
curImg.id = "map"+j+i;
curImg.cellType = mapMatrix[curRow][curCol];
cg.core.$$('body')[0].appendChild(curImg);
}
}
}
};
this.Map = map;
});
kdGame.addModule('kdGame.input',function(cg){
var keydown_callbacks={};
var keyup_callbacks={};
var k=[];
k[8] = "backspace",
k[9] = "tab",
k[13] = "enter",
k[16] = "shift",
k[17] = "ctrl",
k[18] = "alt",
k[19] = "pause",
k[20] = "capslock",
k[27] = "esc",
k[32] = "space",
k[33] = "pageup",
k[34] = "pagedown",
k[35] = "end",
k[36] = "home",
k[37] = "left",
k[38] = "up",
k[39] = "right",
k[40] = "down" ,
k[45] = "insert",
k[46] = "delete",
k[91] = "leftwindowkey",
k[92] = "rightwindowkey",
k[93] = "selectkey",
k[106] = "multiply",
k[107] = "add",
k[109] = "subtract",
k[110] = "decimalpoint",
k[111] = "divide",
k[144] = "numlock",
k[145] = "scrollock",
k[186] = "semicolon",
k[187] = "equalsign",
k[188] = "comma",
k[189] = "dash",
k[190] = "period",
k[191] = "forwardslash",
k[192] = "graveaccent",
k[219] = "openbracket",
k[220] = "backslash",
k[221] = "closebracket",
k[222] = "singlequote";
var numpadkeys = ["numpad1","numpad2","numpad3","numpad4","numpad5","numpad6","numpad7","numpad8","numpad9"];
var fkeys = ["f1","f2","f3","f4","f5","f6","f7","f8","f9"];
var numbers = ["0","1","2","3","4","5","6","7","8","9"];
var letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
for(var i = 0; numbers[i]; i++) { k[48+i] = numbers[i]; }
for(var i = 0; letters[i]; i++) { k[65+i] = letters[i]; }
for(var i = 0; numpadkeys[i]; i++) { k[96+i] = numpadkeys[i]; }
for(var i = 0; fkeys[i]; i++) { k[112+i] = fkeys[i]; }
var timer;
var targetMove = function(eve){
eve = eve||win.event;
var keyname = k[eve.keyCode];
//addKeyPressListener(keyname,listener);
//keydown_callbacks[keyname]();
var target = cg.core.$('targetPlayer');
if(cg.player.dirs[cg.player.dir] != keyname){
var n = cg.player.rotateAngle(keyname);
target.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+n+')';//旋转方向
return;
}
var speed = cg.player.movespeed;
switch(keyname){
case "up":
if(cg.collision.isBottomTo(target))
target.style.top = parseInt(target.style.top) - speed;
break;
case "left":
if(cg.collision.isRightTo(target))
target.style.left = parseInt(target.style.left) - speed;
break;
case "down":
if(cg.collision.isTopTo(target))
target.style.top = parseInt(target.style.top) + speed;
break;
case "right":
if(cg.collision.isLeftTo(target))
target.style.left = parseInt(target.style.left) + speed;
break;
}
};
var targetStopMove = function(eve){
clearInterval(timer);
};
var addKeyPressListener = function(eventType,handler){
keydown_callbacks[eventType] = handler;
};
cg.core.bindHandler(document,'keydown',targetMove);
//cg.core.bindHandler(document,'keyup',targetStopMove);
});
kdGame.addModule('kdGame.collision',function(cg){
//四个判断碰撞检测的方法有点冗余后面再优化
this.isBottomTo = function(curObj){
var curX = parseInt(curObj.style.left);
var curY = parseInt(curObj.style.top);
if(curX <= 0 || curY <= 0)
return false;
curObj.position = [curX,curY];
if(curY%40!=0)
return true;
var nextObjX = curX;
var nextObjY = curY-40;
var result = false;
if(nextObjX%40==0){
result = this.isInner(nextObjX,nextObjY);
if(!result)
return result;
}else{
result = this.isInner(Math.floor(nextObjX/40)*40,nextObjY);
if(!result)
return result;
result = this.isInner(Math.ceil(nextObjX/40)*40,nextObjY);
if(!result)
return result;
}
return true;
};
this.isRightTo = function(curObj){
var curX = parseInt(curObj.style.left);
var curY = parseInt(curObj.style.top);
if(curX <= 0 || curY <= 0)
return false;
curObj.position = [curX,curY];
if(curX%40!=0)//如果已经进入了一个单位,则不需要继续碰撞检测
return true;
var nextObjX = curX-40;
var nextObjY = curY;
var result = false;
if(nextObjY%40==0){
result = this.isInner(nextObjX,nextObjY);
if(!result)
return result;
}else{
result = this.isInner(nextObjX,Math.floor(nextObjY/40)*40);
if(!result)
return result;
result = this.isInner(nextObjX,Math.ceil(nextObjY/40)*40);
if(!result)
return result;
}
return true;
};
this.isTopTo = function(curObj){
var curX = parseInt(curObj.style.left);
var curY = parseInt(curObj.style.top);
if(curX <= 0 || curY <= 0)
return false;
curObj.position = [curX,curY];
if(curY%40!=0)
return true;
var nextObjX = curX;
var nextObjY = curY+40;
var result = false;
if(nextObjX%40==0){
result = this.isInner(nextObjX,nextObjY);
if(!result)
return result;
}else{
result = this.isInner(Math.floor(nextObjX/40)*40,nextObjY);
if(!result)
return result;
result = this.isInner(Math.ceil(nextObjX/40)*40,nextObjY);
if(!result)
return result;
}
return true;
};
this.isLeftTo = function(curObj){
var curX = parseInt(curObj.style.left);
var curY = parseInt(curObj.style.top);
if(curX <= 0 || curY <= 0)
return false;
curObj.position = [curX,curY];
if(curX%40!=0)//如果已经进入了一个单位,则不需要继续碰撞检测
return true;
var nextObjX = curX+40;
var nextObjY = curY;
var result = false;
if(nextObjY%40==0){
result = this.isInner(nextObjX,nextObjY);
if(!result)
return result;
}else{
result = this.isInner(nextObjX,Math.floor(nextObjY/40)*40);
if(!result)
return result;
result = this.isInner(nextObjX,Math.ceil(nextObjY/40)*40);
if(!result)
return result;
}
return true;
};
this.isInner = function(nextObjX,nextObjY){
var nextObj = cg.core.$('map'+nextObjX+nextObjY);
if(nextObj && nextObj.cellType == 3){
alert("you are the winner");
return true;
}
if(nextObj && nextObj.cellType!=0){
return false;
}
return true;
};
});
//add player
kdGame.addModule('kdGame.player',function(cg){
this.init = function(playerObj){
var defaults = {
icon:'images/player1.png',
name:'palyer1',
position:[0,0],
dir:0,
movespeed:10
};
var options = defaults || {};
options = cg.core.extend(options,playerObj);
this.icon = options.icon;
this.name = options.name;
this.dir = options.dir;
this.movespeed = options.movespeed;
this.position = options.selfPosition;
this.dirs = ['left','up','right','down'];
this.draw();
};
this.draw = function(){
var selfPosition = this.position;
var curImg = document.createElement("img");
curImg.id = "targetPlayer";
curImg.src = this.icon;
curImg.style.position = 'absolute';
curImg.style.left = selfPosition[0];
curImg.style.top = selfPosition[1];
kdGame.core.$$('body')[0].appendChild(curImg);
};
this.rotateAngle = function(dir){
var nextDir = this.dirs.indexOf(dir);
this.dir = nextDir;
return nextDir;
};
});
})();
var gameData = {
/* 地图矩阵:0.空地 1.墙壁 2.石头 3.目的地 4.敌人基地*/
mapMatrix:[
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,0,2,2,0,0,0,2,2,0,0,0,1],
[1,0,1,0,0,0,2,0,0,0,4,0,0,0,2,1],
[1,0,1,0,0,0,0,0,2,0,0,0,0,0,0,1],
[1,0,2,0,0,0,0,0,2,0,0,0,0,0,0,1],
[1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,0,0,0,1,1,1,2,0,1],
[1,0,0,0,0,2,0,0,0,1,1,3,0,0,0,1],
[1,0,0,0,0,2,0,2,0,0,1,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
],
startOptions:{
//游戏资源字典
srcObj:{
ground:"images/desert2.png",
wall:"images/wall.png",
stone:"images/stone1.png",
destination:"images/destination.png",
source:"images/source.png",
bullet:"images/bullet1.png",
goods:"images/goods.png",
boom:"images/boom.png",
enemy:"images/enemy2.png",
player:"images/player1.png"
},
movespeed:10
}
};
var playerObj = {//玩家对象
name:'liubei',
selfPosition:[360,360],
movespeed:10
};
var mapObj = new kdGame.Map(gameData); //地图对象
function startGame(){
mapObj.draw();
var player = kdGame.player.init(playerObj);
}