lufylegend.js 엔진이 1.6 이상으로 업데이트되었지만 나중에 몇 가지 튜토리얼을 공개했습니다. 다른 , 또한 몇 가지 간단한 게임 예제를 제공하지만 저는 여러 가지 완전한 작품을 제작한 적이 없습니다. 사실 시간이 너무 제한되어 있습니다. 다음에는 lufylegend.js 엔진을 사용하여 가능한 한 여러 게임을 개발하겠습니다. 이것은 이 엔진의 설득력을 높이기 위한 완전한 작업입니다. HTML5와 게임 개발을 좋아하는 친구들이 더 많은 의견을 제시할 수 있기를 바랍니다.
이번에는 고전적인 Sokoban 게임을 살펴 보겠습니다. Sokoban 게임은 일본에서 시작되었으며 매우 논리적인 사고 게임입니다. 게임에서는 상자를 밀기만 할 수 있고 당길 수는 없습니다. 플레이어는 아래 그림과 같이 제한된 공간에 모든 상자를 다시 제자리에 놓아야 합니다.
그림 1
이것은 최신 버전의 lufylegend.js 엔진을 사용하여 제가 개발한 것입니다. 도전하고 싶다면 아래 게임 링크를 클릭하여 몇 레벨을 통과할 수 있는지 확인할 수 있습니다.
http://lufylegend.com/demo/box
게임에는 총 6개의 레벨이 있으며 순위 시스템을 추가했습니다. 레벨을 통과한 후 자신의 결과를 업로드하고 다른 사람과 경쟁할 수도 있고, 레벨 통과 방법에 대한 자신의 경험을 아래 기사에 답글로 올릴 수도 있습니다.
자, 이제 이 게임을 만드는 방법을 살펴보겠습니다.
다음은 제가 포스팅한 lufylegend-1.6.0 릴리스입니다. 내 블로그 게시물
http://blog.csdn.net/lufy_legend/article/details/8593968
개발에 들어가 보겠습니다. 단계별로.
먼저 그림을 준비하고
그림 2
위 그림을 5개로 균등하게 나누면 일련번호는 0,1입니다. ,2,3,4.
위의 작은 그림 5개를 사용하여 방을 연결하고 방에 상자를 배치할 수 있습니다.
예를 들어 제 블로그 시작 부분의 예시 그림 1은 게임의 첫 번째 레벨 스크린샷입니다. 이 방을 그리려면 먼저 이 그림들이 어디에 있어야 하는지 알아야 합니다. 배열을 준비합니다.
var stage01 = [ [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1], [-1,-1, 1, 1, 1, 1, 1, 1,-1,-1,-1], [-1,-1, 1, 0, 0, 0, 0, 1, 1,-1,-1], [-1,-1, 1, 0, 0, 4, 0, 0, 1,-1,-1], [-1,-1, 1, 4, 4, 0, 4, 4, 1,-1,-1], [-1,-1, 1, 0, 0, 4, 0, 0, 1,-1,-1], [-1,-1, 1, 1, 0, 0, 0, 0, 1,-1,-1], [-1,-1,-1, 1, 1, 1, 1, 1, 1,-1,-1], [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1] ];
위의 -1은 넣지 않는다는 뜻이고, 0, 1, 4 등은 각각 그림 2의 일련번호에 해당한다.
이 배열에 따라 방을 그리는 것은 간단합니다. 아래 함수를 보세요.
function drawFloor(x,y){ if(list[y][x] < 0)return; var bitmap = new LBitmap(bitmapDataList[list[y][x]]); bitmap.x = x*STEP; bitmap.y = y*STEP; boxLayer.addChild(bitmap); }
LSprite 정보, LBitmap 및 기타 개체는 lufylegend.js 엔진에서 매우 일반적으로 사용되는 개체입니다. 자세한 내용은 공식 API 문서를 참조하거나 이전 기사를 읽어보세요. . 여기서 자세히 설명할 필요가 없습니다.
물론 처음에는 방에 상자가 있어야 하고 상자의 초기 위치도 미리 설정해 주어야 합니다.
var box01 = [ {x:3,y:3}, {x:4,y:3}, {x:5,y:3}, {x:5,y:5}, {x:6,y:5}, {x:7,y:5} ];
function drawBox(){ var bitmap; for(var i=0;i<boxList[stageIndex].length;i++){ bitmap = new LBitmap(bitmapDataList[2]); bitmap.x = boxList[stageIndex][i].x*STEP; bitmap.y = boxList[stageIndex][i].y*STEP; boxLayer.addChild(bitmap); nowBoxList.push(bitmap); } }
위에서도 LBitmap 개체를 사용하여 이러한 상자를 표시하고 nowBoxList 배열을 사용하여 이를 저장합니다. 게임 인터페이스에 로드된 상자입니다. 상자 개체는 나중에 게임 통과 여부를 결정하는 데 사용됩니다.
stage01 배열의 4는 복원해야 할 상자의 위치를 나타내므로 게임 통과 여부를 판단할 때 이 위치가 일치하는지 여부만 판단하면 됩니다. 모든 상자의 위치는 다음과 같습니다.
function checkBox(){ var bitmap,x,y,win=true; list = []; for(var i=0;i<stageList[stageIndex].length;i++){ list.push(stageList[stageIndex][i].join(",").split(",")); } for(var i=0;i<nowBoxList.length;i++){ bitmap = nowBoxList[i]; x = bitmap.x / STEP; y = bitmap.y / STEP; if(list[y][x] == 4){ bitmap.bitmapData = bitmapDataList[3]; }else{ bitmap.bitmapData = bitmapDataList[2]; win = false; } list[y][x] += 10; } if(win)gameClearShow(); }
stageList储存了所有的关卡信息,stageIndex是当前关卡的序号,stageList[stageIndex]就可以获取当前关卡的信息,bitmapDataList数组储存了图1中小图片的LBitmapData对象,这些暂且不说,关键是下面。
if(list[y][x] == 4){ bitmap.bitmapData = bitmapDataList[3]; }else{ bitmap.bitmapData = bitmapDataList[2]; win = false; }
函数中循环了所有箱子的位置,如果他们的位置的序号为4,则表示该箱子已经归位,全部归位表示过关,否则游戏继续,返回false。
同样准备一张图片,如下
图3
人物走动动画,当然就需要lufylegend引擎中另一个重要的对象LAnimation,它专门用来顺序播放图片以形成动画,具体用法请参照官方API文档。
下面是主人公的构造器
/** * 循环事件 * @param data 图片数据 * @param row 图片分割行数 * @param col 图片分割列数 **/ function Character(data,row,col){ base(this,LSprite,[]); var self = this; //设定人物动作速度 self.speed = 2; self.speedIndex = 0; //设定人物大小 data.setProperties(0,0,data.image.width/col,data.image.height/row); //得到人物图片拆分数组 var list = LGlobal.pideCoordinate(data.image.width,data.image.height,row,col); //设定人物动画 self.anime = new LAnimation(this,data,list); //设定不移动 self.move = false; //在一个移动步长中的移动次数设定 self.moveIndex = 0; };
主人公如何推动箱子,看下面的onmove函数
/** * 开始移动 **/ Character.prototype.onmove = function (){ var self = this; //设定一个移动步长中的移动次数 var ml_cnt = 4; //计算一次移动的长度 var ml = STEP/ml_cnt; //根据移动方向,开始移动 switch (self.direction){ case UP: self.y -= ml; if(box)box.y -= ml; break; case LEFT: self.x -= ml; if(box)box.x -= ml; break; case RIGHT: self.x += ml; if(box)box.x += ml; break; case DOWN: self.y += ml; if(box)box.y += ml; break; } self.moveIndex++; //当移动次数等于设定的次数,开始判断是否继续移动 if(self.moveIndex >= ml_cnt){ self.moveIndex = 0; box = null; self.move = false; checkBox(); } };
可以看到,箱子是不是跟着主人公一起走,关键是要看box这个变量,这个变量的值是在下面的checkRoad函数中设置的。
Character.prototype.checkRoad = function (dir){ var self = this; var tox,toy; //开始计算移动目的地的坐标 switch (dir){ case UP: tox = 0; toy = -1; break; case LEFT: tox = -1; toy = 0; break; case RIGHT: tox = 1; toy = 0; break; case DOWN: tox = 0; toy = 1; break; } if(list[self.y/STEP + toy][self.x/STEP + tox]==1)return false; if(list[self.y/STEP + toy][self.x/STEP + tox]>4){ if(list[self.y/STEP + toy*2][self.x/STEP + tox*2]==1 || list[self.y/STEP + toy*2][self.x/STEP + tox*2]>4)return false; box = getBox(self.x + tox*STEP,self.y + toy*STEP); } return true; };
其实,就是判断一下主人公要走的方向的前方是不是有障碍物,如果障碍物是墙则不可移动,如果是箱子的话,就要看看箱子的后面是不是有障碍物,如果有则不可移动,否则箱子就需要跟着主人公一起移动,将box设置为主人公前方的箱子即可。
上面这个函数,是在人物即将发生移动的时候被调用的,如下。
/** * 改变人物方向,并判断是否可移动 **/ Character.prototype.changeDir = function (dir){ var self = this; if(self.move)return; self.direction = dir; self.anime.setAction(dir); if(!self.checkRoad(dir))return; self.move = true; steps.text = parseInt(steps.text) + 1; };
当图1中的方向图标被按下的时候,根据点击的方向,来实现人物的移动。
点击方向图标的方法当然是鼠标事件
ctrlLayer.addEventListener(LMouseEvent.MOUSE_UP,onCtrl);
然后在onCtrl函数中根据点击的位置,来进行相应的移动。
function onCtrl(event){ var ctrlSize = 60; if(event.selfX >= ctrlSize && event.selfX <= ctrlSize*2){ if(event.selfY >= 0 && event.selfY <= ctrlSize){ player.changeDir(UP); }else if(event.selfY >= ctrlSize*2 && event.selfY <= ctrlSize*3){ player.changeDir(DOWN); } }else if(event.selfY >= ctrlSize && event.selfY <= ctrlSize*2){ if(event.selfX >= 0 && event.selfX <= ctrlSize){ player.changeDir(LEFT); }else if(event.selfX >= ctrlSize*2 && event.selfX <= ctrlSize*3){ player.changeDir(RIGHT); } } }
这样,游戏的主要功能部分,就介绍完了。
如下。
图4
使用lufylegend.js引擎做个界面,可以说毫无难度,代码如下。
function GameLogo(){ base(this,LSprite,[]); var self = this; var logolist = [[1,1,1,1],[1,2,4,1],[1,4,2,1],[1,1,1,1]]; var bitmap,logoLayer; logoLayer = new LSprite(); logoLayer.graphics.drawRect(6,"#FF7F50",[0,0,LGlobal.width,LGlobal.height],true,"#FFDAB9"); self.addChild(logoLayer); logoLayer = new LSprite(); logoLayer.x = 50; logoLayer.y = 50; for(var i=0;i<logolist.length;i++){ for(var j=0;j<logolist.length;j++){ bitmap = new LBitmap(bitmapDataList[logolist[i][j]]); bitmap.x = j*STEP; bitmap.y = i*STEP; logoLayer.addChild(bitmap); } } bitmap = new LBitmap(new LBitmapData(imglist["player"],0,0,STEP,STEP)); bitmap.x = STEP; bitmap.y = 2*STEP; logoLayer.addChild(bitmap); self.addChild(logoLayer); labelText = new LTextField(); labelText.rotate = -20; labelText.color = "#4B0082"; labelText.font = "HG行書体"; labelText.size = 100; labelText.x = 300; labelText.y = 50; labelText.stroke = true; labelText.lineWidth = 4; labelText.text = "推"; self.addChild(labelText); labelText = new LTextField(); labelText.color = "#4B0082"; labelText.font = "HG行書体"; labelText.size = 100; labelText.x = 450; labelText.y = 60; labelText.stroke = true; labelText.lineWidth = 4; labelText.text = "箱"; self.addChild(labelText); labelText = new LTextField(); labelText.rotate = 20; labelText.color = "#4B0082"; labelText.font = "HG行書体"; labelText.size = 100; labelText.x = 600; labelText.y = 60; labelText.stroke = true; labelText.lineWidth = 4; labelText.text = "子"; self.addChild(labelText); labelText = new LTextField(); labelText.color = "#B22222"; labelText.font = "HG行書体"; labelText.size = 40; labelText.x = 100; labelText.y = 250; labelText.stroke = true; labelText.lineWidth = 4; labelText.text = "Click to Start Game !!"; self.addChild(labelText); var social = new Social(); social.x = 220; social.y = 330; self.addChild(social); labelText = new LTextField(); labelText.font = "HG行書体"; labelText.size = 14; labelText.x = 400; labelText.y = 390; labelText.text = "- Html5 Game Engine lufylegend.js"; self.addChild(labelText); labelText = new LTextField(); labelText.color = "#006400"; labelText.font = "HG行書体"; labelText.size = 14; labelText.x = 400; labelText.y = 410; labelText.text = "http://www.lufylegend.com/lufylegend"; self.addChild(labelText); self.addEventListener(LMouseEvent.MOUSE_UP,menuShow); };
就是显示几张图片,以及添加一些文字,LTextField对象的使用方法请参考官方API文档。
如下。
图5
代码如下。
function GameMenu(){ base(this,LSprite,[]); var self = this; var menuLayer; menuLayer = new LSprite(); menuLayer.graphics.drawRect(6,"#ADD8E6",[0,0,LGlobal.width,LGlobal.height],true,"#E6E6FA"); self.addChild(menuLayer); labelText = new LTextField(); labelText.color = "#B22222"; labelText.font = "HG行書体"; labelText.size = 40; labelText.x = 200; labelText.y = 30; labelText.stroke = true; labelText.lineWidth = 4; labelText.text = "Please select !!"; menuLayer.addChild(labelText); for(var i=0;i<stageMenu.length;i++){ self.stageVsMenu(stageMenu[i]); } }; GameMenu.prototype.stageVsMenu = function(obj){ var self = this; var menuButton,btn_up; if(obj.open){ btn_up = new LSprite(); btn_up.graphics.drawRect(2,"#000",[0,0,150,90],true,"#191970"); labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 20; labelText.x = 40; labelText.y = 5; btn_up.addChild(labelText) labelText.text = "第"+(obj.index+1)+"关"; labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 12; labelText.x = 10; labelText.y = 40; btn_up.addChild(labelText) labelText.text = "step:"+obj.step; labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 12; labelText.x = 10; labelText.y = 60; btn_up.addChild(labelText) labelText.text = "times:"+obj.times; var btn_down = new LSprite(); btn_down.graphics.drawRect(2,"#000",[0,0,150,90],true,"#2F4F4F"); labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 20; labelText.x = 40; labelText.y = 5; labelText.text = "第"+(obj.index+1)+"关"; btn_down.addChild(labelText); labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 12; labelText.x = 10; labelText.y = 40; btn_down.addChild(labelText) labelText.text = "step:"+obj.step; labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 12; labelText.x = 10; labelText.y = 60; btn_down.addChild(labelText) labelText.text = "times:"+obj.times; menuButton = new LButton(btn_up,btn_down); menuButton.obj = obj; menuButton.addEventListener(LMouseEvent.MOUSE_UP,function(event,self){ gameStart(self.obj.index); }); }else{ btn_up = new LSprite(); btn_up.graphics.drawRect(2,"#000",[0,0,150,90],true,"#708090"); labelText = new LTextField(); labelText.color = "#ffffff"; labelText.font = "HG行書体"; labelText.size = 20; labelText.x = 40; labelText.y = 5; btn_up.addChild(labelText) labelText.text = "???"; menuButton = btn_up; }; self.addChild(menuButton); menuButton.x = obj.x * 220 + 100; menuButton.y = obj.y * 140 + 130; }
好了,游戏主要的代码已经都贴出来了。
由于上面的代码比较零碎,而且我也只是挑中心部分说了一下,下面提供完整游戏源代码,想研究一下的朋友可以点击下面的连接下载。
http://lufylegend.com/lufylegend_download/box.rar
注意:该附件只包含本次文章源码,lufylegend.js引擎请到http://lufylegend.com/lufylegend进行下载。
以上就是[html5游戏开发]经典的推箱子的内容,更多相关内容请关注PHP中文网(www.php.cn)!