网页游戏开发入门教程三(简单程序应用) |
本文标签:网页游戏,开发入门 网页游戏开发入门教程二(游戏模式+系统) http://www.jb51.net/article/20724.htm 一、选择开发语言 复制代码 代码如下: <div style=\"position:absolute;z-index:10;left:2px;top:2px;width:".$mapwidth."px;height:".$mapheight."px;\" onmousedown=\"fDragging(this, event,false);\"> //处理拖动的js代码 。(网上抄的 。 。感谢这位大大 。) <script> function fDragging(obj, e, limit){ if(!e) e=window.event; var x=parseInt(obj.style.left); var y=parseInt(obj.style.top); var x_=e.clientX-x; var y_=e.clientY-y; if(document.addEventListener){ document.addEventListener(mousemove, inFmove, true); document.addEventListener(mouseup, inFup, true); document.body.style.cursor="move"; } else if(document.attachEvent){ document.attachEvent(onmousemove, inFmove); document.attachEvent(onmouseup, inFup); document.body.style.cursor="move"; } inFstop(e); inFabort(e) function inFmove(e){ var evt; if(!e)e=window.event; if(limit){ var op=obj.parentNode; var opX=parseInt(op.style.left); var opY=parseInt(op.style.top); if((e.clientX-x_)<0) return false; else if((e.clientX-x_+obj.offsetWidth+opX)>(opX+op.offsetWidth)) return false; if(e.clientY-y_<0) return false; else if((e.clientY-y_+obj.offsetHeight+opY)>(opY+op.offsetHeight)) return false; //status=e.clientY-y_; } obj.style.left=e.clientX-x_+px; obj.style.top=e.clientY-y_+px; inFstop(e); } // shawl.qiu script function inFup(e){ var evt; if(!e)e=window.event; if(document.removeEventListener){ document.removeEventListener(mousemove, inFmove, true); document.removeEventListener(mouseup, inFup, true); } else if(document.detachEvent){ document.detachEvent(onmousemove, inFmove); document.detachEvent(onmouseup, inFup); } inFstop(e); document.body.style.cursor="auto"; //实现类似google地图的拖动效果 。 ajaxRead(map.php?mapx=+(e.clientX-x_)+&mapy=+(e.clientY-y_)+,2); } // shawl.qiu script function inFstop(e){ if(e.stopPropagation) return e.stopPropagation(); else return e.cancelBubble=true; } // shawl.qiu script function inFabort(e){ if(e.preventDefault) return e.preventDefault(); else return e.returnValue=false; } // shawl.qiu script } //]]> </script> 注意下面这段代码: ajaxRead(map.php?mapx=+(e.clientX-x_)+&mapy=+(e.clientY-y_)+,2); 这句代码的位置,是在拖动层后,释放鼠标的时候触发的 。你可以用alert(“地图拖动到了这里”); 替换 。测试下效果 。这句代码的意思是,根据当前地图被拖动的坐标 。调用一个ajax 。也就是重新从数据库里获得地图信息 。AjaxRead()是一个ajax的调用函数 。你可以全部自己写 。也可以用如prototype.js之类的框架写 。 //处理ajax的代码 。(还是网上抄的,有轻微的改动 。 。 。唉,怎么老抄呢 。 。主要是为了节约开发时间 。 。还有一点就是我的JavaScript很垃圾的(*^__^*) 嘻嘻) 复制代码 代码如下: function ajaxRead(file,action) { var xmlObj = null; if(window.XMLHttpRequest) { xmlObj = new XMLHttpRequest(); } else if(window.ActiveXObject) { xmlObj = new ActiveXObject("Microsoft.XMLHTTP"); } else { return; } function ajaxDo(action) { switch(action) { case "2": document.getElementById(display).innerHTML = xmlObj.responseText;//这里的display是你在页面上层的id 。上面的地图代码都需要放到这个层里 。如<div id=display name=display></div>写id和name,是为了方便firefox和ie的兼容 。 break; } } xmlObj.onreadystatechange = function() { /* if(xmlObj.readyState == 1 )//loading状态 。 { document.getElementById(xianshi2).innerHTML = "正在载入"; } */ if(xmlObj.readyState == 4)//完成状态时 。 { ajaxDo(action); } } xmlObj.open (GET, file, true); //xmlObj.reload(GET, file, true); xmlObj.send (null); //xmlObj.abort (); } 整个代码的意思就是: 当拖动地图释放鼠标后,显示层重新获得数据 。并无刷新的显示出来 。地图里的图片都用的png32的透明图 。Ie7和ff3都没问题 。遇到ie6的话 。 。用gif的替代吧 。map.php的功能 。根据获得的x,y显示相应的一谢谢小图块 。这个功能其实就是上面说的showMap(x,y),这个很像google地图的拖动 。不过简单了很多 。简单,效果还不错 。2、角2、角色属性 因为设定的要求 。角色需要有装备加成,有状态加成(buff,debuff) 。这时候,把所有需要的加成,都放到角色类里 。是一个很好的方法 。 大概像这样: 复制代码 代码如下: class role { //获得角色数据 。 getRloe() { 从数据库里获得角色信息 。 } //获得装备加成 。 getEquip() { 获得装备加成信息 。 } //获得状态加成 getState() { 获得状态加成信息 。 } //把上面获得的信息相加或者相减,或者调整 。 //返回角色数据 。 Return xxx } 专门把这条提出来说 。是因为没把加成放到角色对象里时 。每次要战斗或者要干点什么的时候 。获得角色数据后,还要加一大堆代码处理加成 。重复太多 。一让代码前置,世界就清静了 。 。 。 、道具 道具比较特殊 。因为种类繁多,使用方式多,可能有多个存放地点,可能有唯一道具 。有天看了web魔兽的代码 。发现他的道具只有一个表 。有一个字段,来处理道具位置,如(1,拍卖行,2,背包,3,仓库,4,商店)这个办法挺好的 。不过,如果道具的复杂度上去了 。比如不同的仓库,不同的拍卖行,需要合成等等 。还是只有分表 。 基础道具表: id itemname 名称 itemprice 价格 itemimage 图片 itemtype 类型 uptype 增加类型 uppoint 增加点数 addtype 增加类型(永久) addpoint 增加点数(永久) cleardebuff 清除debuff addbuff 增加buff 从uptype开始 。都可以写成xx|yy|zz的形式 。最好一一对应 。分割符号可以自己选 。 调用和处理数据的时候,可以用类似下面的方式: 复制代码 代码如下: $uptype = explode("|", $iteminfo[uptype]); $uppoint = explode("|", $iteminfo[uppoint]); for ($j=0;$j<count($uptype);$j++) { echo $uptype[$j]; echo $uppoint[$j]; } 仓库,拍卖行,商店,背包等等 。承载道具的地方 。只要有个id字段来存道具id就可以 。至于是横表或者是纵表,根据实际需要选择 。目前为止,道具看上去处理得还不错 。这时候,策划说 。道具需要有唯一的,需要能附魔 。ok,那么你把所有组合都填到道具表里吧 。合成也就是a+b=c而已 。 。一计算 。比如40个可能附魔的东西 。200个可以附魔的道具 。40*200=8000 。显然,策划不会同意的 。那么头痛的就是程序了 。怎么处理呢 。加表吧 。 唯一道具表: id 唯一道具id(与普通道具id不能重复 。方便背包等等调用) temp_id 临时id(默认0 。合成道具的时候可能会用到 。) itemid 原始道具id(获得道具的初始值) fumo_id 附魔id 。(默认0,即无附魔) 附魔表:(即增加的属性) id uptype 增加类型 uppoint 增加点数 cleardebuff 清除debuff addbuff 增加buff 现在看功能修改 首先是道具类: class Item { getItem() { //以前是直接根据id获得道具信息就ok了 。 //现在增加了附魔 //首先判断道具id是否属于唯一道具 。(比如普通道具1-10000 。唯一道具id的从10001开始 。如果觉得这样不好,那么基础道具表里,加个字段 。判断道具是否唯一) if (道具唯一) { //从唯一道具表获得原始道具id和附魔id //根据原始道具id,或者道具基础信息 。 //根据附魔id,获得附魔加成信息 。 //两边值相加 。 Return 道具信息 。 } else { 直接获得道具信息 。 } } } 附魔功能: 道具A 。(基础道具)+道具B 。(基础道具) =道具C 。(唯一道具) 也就是唯一道具是在附魔功能执行的时候生成 。以背包举例 。没附魔前 。 背包内道具A 。id为1 。 背包内道具B 。id为2 。 当执行附魔功能后 。道具A,道具B的id都置0(横表),或者删除了(纵表) 。生成一个唯一数 。temp_id 。(md5生成就行了 。)生成一个唯一道具 。这时候,根据temp_id,让A的背包再次获得唯一道具的id 。道具,比较完善的解决了 。 以下部分均涉及到一些商业问题,所以只能给思路,及很少的代码 。 -------------------------------------------------------------------------------- 、记时器 处理等待xx时间后,执行xx的问题 。php自带一个sleep()函数 。等待时间也可以控制 。 但是显然,不管从运用还是效率上讲 。都不足以支持游戏计时的 。思路很简单 。将需要倒计时的事件的所有参数,以及开始时间、结束时间 。都存储到一个表里 。前台用javascript倒计时,时间到后,通过ajax调用时间到后的处理程序 。后台每隔一定时间,自动执行一次调用时间到后的处理程序 。 至少需要三个php页面 。 一个用来写存取定时的内容 。 一个处理前台时间到时,结束操作 。 一个处理后台定时刷新,判断时间到了就执行结束,时间未到不作处理 。 miracle:计时器是不同的计时器对应不同的事件,还是可以多个事件都调用同一个计时器,如果一个玩家他调用了一个计时器计时一个建筑建设多长时间,在之中又调用了这个计时器用来计时另一个建筑建设多长时间,这样行不行的?会不会有冲突? 键盘上的烟灰: 多个事件对应1个计时器 。 你可以在timer里增加一个字段 。比如叫做actiontype(事件类型) 每个用户可以同时处理多件事 。只是每个事情都有固定编号 。 比如你的用户允许同时做5件事情 。那么actiontype里直接编号为1-5 。调用计时器的时候,根据不同的编号,你就知道这是用户的第某个“线程” 。 miracle 如果是不同的用户,调用同一个计时器是不会发生冲突的吧 键盘上的烟灰: 当然不会 。你看 。userid可以用来确定某一个用户 。actiontype可以用来确定是第几个线程 。 、事件控制 结合记时器,处理开始(),过程(),结束() 复制代码 代码如下: interface Action { function doAction(); function beginAction(); function processAction(); function endAction(); } //简单事件工厂 class ActionFactory { public function getAction($what) { $ActionName = $what; return new $ActionName; } } //比如移动 class Move implements Action { function doAction() { 具体执行函数 什么时候该这行哪一个过程 。都在这里判断 。 } function beginAction() { 事件开始时候执行 。 这里可以把数据存到记时器里 。以后就从记时器里取数据了 。 } function processAction() { 从记时器里取数据 。 事件执行的过程 。比如用户刷新页面的时候 。如果仍然在倒计时 。那么就是调用这里了 。 } function endAction() { 从记时器里取数据 。 事件结束的过程 。 记时到后,完成事件 。 } } //第一次调用的时候 。 $Action = new ActionFactory(); $InstanceAction = $Action->getAction("Move"); $InstanceAction->set ($parameter); $InstanceAction->doAction(); //以后调用的时候 。 $Action = new ActionFactory(); $InstanceAction = $Action->getAction("Move"); //这时候,事件的参数或数据都从记时器里取得 。 $InstanceAction->doAction(); 、战斗 即时和半即时的回合战斗(两人或多人即时回合制战斗)比较繁琐 。 至少包含: 前台: 自动接收邀请信息 。Ajax 显示战斗过程 。Ajax 回合倒计时间 。javascript 后台: 发送邀请,接受,拒绝,超时 。一个表 。战斗数据 。一个表 。保存双方或多方的数据,包括回合时间,第几回合等 。 战斗控制 。一系列函数 。处理玩家的操作,将操作存到战斗数据表里 。时间到后执行操作 。 出兵后,直接返回战报 。 写在事件里就行了 。 function endAction() { 从记时器里取数据 。 生成回合,生成战报 。 } 注:由于本人工作原因,此系列可能要暂停一段时间才更新,望大家见谅 。 。 。 |