所有的

【开发实录】HTML5游戏开发历程(一)
1911
2013-10-11

本篇将以零基础的视点,来讲解如何开发一款RPG游戏。

在游戏的世界里,我们可以看到各种地图,各种游戏人物,看到人物在地图上行走,对话等,无论是地图还是人物,其实都是图片的处理与显示,把不同的图片显示到屏幕上,我们就看到不同的游戏界面,要想让这些图片同时显示到界面上,我们就需要处理好层次,让他们来分层显示,我们可以想象,如果游戏人物显示在地图的下层的话,显然会被地图遮挡住。
一款RPG游戏,我简单把它分为地图层,人物层,效果层(一些法术效果等),对话层,控制层(按钮菜单等)。

如下图



我们只要依次将图片画在屏幕上,游戏人物将站在地图上,如果有对话,对话将出现在人物和地图的上面,而按钮等控件会出现在游戏的最外层

下面,我们一步步来实现一个简单的RPG游戏的开发


准备工作

一,库件下载

本游戏开发,需要用到开源库件:lufylegend,下载地址为http://lufylegend.com/lufylegend


库件的开发过程请看这里

http://blog.csdn.net/lufy_legend/article/details/6844949

二,库件配置

首先建立一个文件夹rpg(你也可以起其他的名字)

然后将下载的库件解压,解压后将legend文件夹放到与rpg文件夹同目录
然后,在rpg文件夹里建一个index.html文件和一个js文件夹,在js文件夹里建一个Main.js文件

最后,在index.html里加入下面的代码

<!DOCTYPE html>  
<html>  
<head>  
<meta charset="UTF-8">  
<title>rpg</title>  
</head>  
<body>  
<div id="mylegend">loading……</div>  
<!-- 引入LegendForHtml5Programming库件 -->
<script type="text/javascript" src="../legend/legend.js"></script>   
<script type="text/javascript" src="./js/Main.js"></script>   
</body></html>


当然,你也可以将legend文件夹放到其他地方,但是你需要修改legend文件夹下的legend.js文件中的LEGEND_PATH的值,来配置库件的路径


游戏地图的实现

接下来,我们先来画最底层的地图层,
地图当然就是是由图片来组成的,如何在画面上显示一张图片,我之前已经写过专门的文章,代码如下

  1. var loader;    

  2. function main(){    

  3.    loader = new LLoader();    

  4.    loader.addEventListener(LEvent.COMPLETE,loadBitmapdata);    

  5.    loader.load("map.jpg","bitmapData");    

  6. }    

  7. function loadBitmapdata(event){    

  8.    var bitmapdata = new LBitmapData(loader.content);    

  9.    var bitmap = new LBitmap(bitmapdata);    

  10.    addChild(bitmap);    

  11. }    

如果想更详细了解的话,看下面的帖子
用仿ActionScript的语法来编写html5——第一篇,显示一张图片
http://blog.csdn.net/lufy_legend/article/details/6753032


游戏中的地图可以是一张比较大的图片,即整个图片就是游戏的地图,当人物或者地图移动的时候,改变图片显示的区域范围,从而实现地图的滚动和显示等,这样的话,必须为每个场景准备一张地图。

另外,地图也可以是由许多小的地图块儿来组成,比如,我们熟悉的《吞食天地》,《勇者斗恶龙》等经典小型rpg游戏,这样的地图,我们需要准备一张或几张地图块儿,把这些地图块组合成地图来显示,比如下图



在地图显示的时候,首先把图片切割,然后在根据预先设定好的位置显示到地图层上,这样我们就看到了一张完整的地图了


接下来,打开Main.js

在里面加入


  1. init(50,"mylegend",480,320,main);  

在lufylegend.js引擎中,用init这个函数来初始化canvas,上面的代码表示,初始化一个速度为50,名字为mylegend,大小为480*320的游戏界面,初始化完成后调用main(),这个速度值是说每个多少毫秒游戏循环一次,所以这个值设定的越小,游戏运行的速度就越快


因为要调用main方法,所以我们要写一个main方法,main方法里做一些简单的准备工作。

虽说读取图片只需要一个


  1. loader.load("map.jpg","bitmapData");    

但是游戏中往往用到很多张图片,你可以用到哪一张再加载哪一张,也可以一次性全部加载完,然后再开始显示游戏


为了一次性把图片加载完,我的做法是,将需要的图片放到一个数组里,然后设定一个索引,每加载一个图片,让这个索引加1,当这个索引小于数组的长度,则继续加载,直到将数组中的图片全部加载完,然后开始进行下一步的工作

具体实现看下面的代码


  1. //图片path数组  

  2. var imgData = new Array();  

  3. //读取完的图片数组  

  4. var imglist = {};  

  5.  

  6. function main(){  

  7.    //准备读取图片  

  8.    imgData.push({name:"map",path:"./image/map.jpg"});  

  9.    imgData.push({name:"mingren",path:"./image/mingren.png"});  

  10.    imgData.push({name:"e1",path:"./image/e1.png"});  

  11.    imgData.push({name:"e2",path:"./image/e2.png"});  

  12.    //实例化进度条层  

  13.    loadingLayer = new LSprite();  

  14.    loadingLayer.graphics.drawRect(1,"black",[50, 200, 200, 20],true,"#ffffff");  

  15.    addChild(loadingLayer);  

  16.    //开始读取图片  

  17.    loadImage();  

  18. }  

  19. function loadImage(){  

  20.    //图片全部读取完成,开始初始化游戏  

  21.    if(loadIndex >= imgData.length){  

  22.        removeChild(loadingLayer);  

  23.        gameInit();  

  24.        return;  

  25.    }  

  26.    //开始读取图片  

  27.    loader = new LLoader();  

  28.    loader.addEventListener(LEvent.COMPLETE,loadComplete);  

  29.    loader.load(imgData[loadIndex].path,"bitmapData");  

  30. }  

  31. function loadComplete(event){  

  32.    //进度条显示  

  33.    loadingLayer.graphics.clear();  

  34.    loadingLayer.graphics.drawRect(1,"black",[50, 200, 200, 20],true,"#ffffff");  

  35.    loadingLayer.graphics.drawRect(1,"black",[50, 203, 200*(loadIndex/imgData.length), 14],true,"#000000");  

  36.    //储存图片数据  

  37.    imglist[imgData[loadIndex].name] = loader.content;  

  38.    //读取下一张图片  

  39.    loadIndex++;  

  40.    loadImage();  

  41. }  

上面的代码不难明白,当图片没有读取完之前,会不断循环loadImage和loadComplete两个方法,当读取完之后,移除进度条,用legendLoadOver告诉游戏已经读取完成,然后调用gameInit方法,进行游戏的初始化工作。


看gameInit方法


  1. function gameInit(event){  

  2.    //游戏层显示初始化  

  3.    layerInit();  

  4.    //添加地图  

  5.    addMap();  

  6.    //添加人物  

  7.    addChara();  

  8. }  

在gameInit方法中,首先进行游戏层的初始化,然后添加游戏地图,然后添加人物
游戏层显示初始化,按照我们一开始所说,我们一次来初始化地图层,人物层,效果层,对话层,控制层


  1. //游戏层显示初始化  

  2. function layerInit(){  

  3.    //游戏底层添加  

  4.    backLayer = new LSprite();  

  5.    addChild(backLayer);  

  6.    //地图层添加  

  7.    mapLayer = new LSprite();  

  8.    backLayer.addChild(mapLayer);  

  9.    //人物层添加  

  10.    charaLayer = new LSprite();  

  11.    backLayer.addChild(charaLayer);  

  12.    //效果层添加  

  13.    effectLayer = new LSprite();  

  14.    backLayer.addChild(effectLayer);  

  15.    //对话层添加  

  16.    talkLayer = new LSprite();  

  17.    backLayer.addChild(talkLayer);  

  18.    //控制层添加  

  19.    ctrlLayer = new LSprite();  

  20.    backLayer.addChild(ctrlLayer);  

  21. }  

有了游戏层次的划分,我们在添加游戏对象的时候,将地图添加到地图层,人物添加到人物层,他们就会依次显示在游戏的界面上


下面开始添加地图

首先我们需要准备好显示地图的数组


  1. //地图图片数组  

  2. var map = [  

  3. [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18],  

  4. [18,18,18,17,17,17,17,17,17,17,17,17,55,55,18],  

  5. [18,18,17,17,17,17,18,18,17,17,17,17,55,55,18],  

  6. [18,17,17,17,18,18,18,18,18,17,17,55,55,17,18],  

  7. [18,17,17,18,22,23,23,23,24,18,17,55,55,17,18],  

  8. [18,17,17,18,25,28,26,79,27,18,55,55,17,17,18],  

  9. [18,17,17,17,17,10,11,12,18,18,55,55,17,17,18],  

  10. [18,18,17,17,10,16,16,16,11,55,55,17,17,17,18],  

  11. [18,18,17,17,77,16,16,16,16,21,21,17,17,17,18],  

  12. [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18]  

  13. ];  

这些数字分别对应着图中如下位置




然后看下面代码


  1. //添加地图  

  2. function addMap(){  

  3.    var i,j,index,indexX,indexY;  

  4.    var bitmapdata,bitmap;  

  5.    //地图图片数据  

  6.    bitmapdata = new LBitmapData(imglist["map"]);  

  7.    //将地图图片拆分,得到拆分后的各个小图片的坐标数组  

  8.    imageArray = LGlobal.divideCoordinate(bitmapdata.image.width,bitmapdata.image.height,10,10);  

  9.  

  10.    //在地图层上,画出15*10的小图片  

  11.    for(i=0;i<10;i++){  

  12.        for(j=0;j<15;j++){  

  13.            //从地图数组中得到相应位置的图片坐标  

  14.            index = map[i][j];  

  15.            //小图片的竖坐标  

  16.            indexY = Math.floor(index /10);  

  17.            //小图片的横坐标  

  18.            indexX = index - indexY*10;  

  19.            //得到小图片  

  20.            bitmapdata = new LBitmapData(imglist["map"],indexX*32,indexY*32,32,32);  

  21.            bitmap = new LBitmap(bitmapdata);  

  22.            //设置小图片的显示位置  

  23.            bitmap.x = j*32;  

  24.            bitmap.y = i*32;  

  25.            //将小图片显示到地图层  

  26.            mapLayer.addChild(bitmap);  

  27.        }  

  28.    }  

  29. }  

这样,我们就把预先设置好的图片显示到了游戏界面上,形成了地图


先把addChara方法加上


  1. //添加人物  

  2. function addChara(){  

  3. }  

然后运行游戏


可以得到下面画面




游戏人物的实现

为了更好的实现游戏人物的控制,我们新建一个游戏人物类Character.js

里面代码如下


  1. function Character(data,row,col,speed){  

  2.    base(this,LSprite,[]);  

  3.    var self = this;  

  4.    //设定人物动作速度  

  5.    self.speed = speed==null?3:speed;  

  6.    self.speedIndex = 0;  

  7.    //设定人物大小  

  8.    data.setProperties(0,0,data.image.width/col,data.image.height/row);  

  9.    //得到人物图片拆分数组  

  10.    var list = LGlobal.divideCoordinate(data.image.width,data.image.height,row,col);  

  11.    //设定人物动画  

  12.    self.anime = new LAnimation(this,data,list);  

  13. };  

  14. Character.prototype.onframe = function (){  

  15.    var self = this;  

  16.    if(self.speedIndex++ < self.speed)return;  

  17.    self.speedIndex = 0;  

  18.    self.anime.onframe();  

  19. };  

在legendForHtml5Programming里,有一个LAnimation类,用来实现图片数组顺序播放,形成动画


使用LAnimation类需要三个参数,一个是显示动画的层,一个是图片,一个是图片的坐标数组

然后,调用LAnimation类的onframe方法,就可以实现动画的播放了

在index.html中引入Character类,然后修改addChara方法,


  1. //添加人物  

  2. function addChara(){  

  3.    bitmapdata = new LBitmapData(imglist["mingren"]);  

  4.    player = new Character(bitmapdata,4,4);  

  5.    player.x = 32*5;  

  6.    player.y = 32*6;  

  7.    charaLayer.addChild(player);  

  8.      

  9. }  

在gameInit的末尾添加循环事件



  1. //添加贞事件,开始游戏循环  

  2.    backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);  

最后,添加onframe方法
  1. /**

  2. * 循环

  3. * */  

  4. function onframe(){  

  5.    player.onframe();  

  6. }  


运行代码,看到了吗


一个会动的鸣人出现在游戏的地图上了


游戏演示

http://lufylegend.com/demo/rpg/index.html

原文地址

http://blog.csdn.net/lufy_legend/article/details/7063316



lufylegend.js引擎包内包含这个demo,请直接下载lufylegend.js引擎,查看引擎包内源码

lufylegend.js引擎下载地址

http://lufylegend.com/lufylegend


下次,就要添加控制层,实现人物的走动和地图的滚动等,希望大家多多支持。

全部评论
(1)
评论速度
  • 2013-11-15
    1楼
    2013-11-15 12:30:59
    回复
  • 2013-11-11
    有没有打包下载啊
    2楼
    2013-11-11 15:17:35
    回复
  • 2013-11-11
    抽空试一下
    3楼
    2013-11-11 14:41:18
    回复
  • 2013-11-11
    学习了
    4楼
    2013-11-11 14:29:28
    回复
  • 2013-11-11
    不错
    5楼
    2013-11-11 14:22:41
    回复
  • 2013-11-11
    学习了
    6楼
    2013-11-11 14:21:23
    回复
mores++

还可以输入 2000 个字符
添加表情