本篇为《『HTML5挑战经典』是英雄就下100层-开源讲座》第二篇,需要用到开源引擎lufylegend,可以到这里下载:

下载地址:http://lufylegend.googlecode.com/files/lufylegend-1.7.1.rar

API文档:http://lufylegend.com/lufylegend/api

却说我们的英雄能顺利地从天而降了,不过丝毫没有悬念,他一定会被摔死的,因为还没有跳板出现。我每次路过时都看到我们的英雄是边下降边大叫:help! help!然后就摔死了。怪可怜的,于是我今天便完善了一下游戏,也好让我们的英雄活动活动筋骨。

这一次我们来实现不断上升的跳板。如果你想了解了解上一讲的内容,可以点击以下地址:

『HTML5挑战经典』是英雄就下100层-开源讲座(一)从天而降的英雄

http://blog.csdn.net/yorhomwang/article/details/8764748

一,加入跳板

首先,我们要几张图片:

跳板(一):

跳板(二):

由于在下素材不足,就只好先搞了两个主要的跳板。说到素材,我们的英雄便有话说了:“我本是Yorhom帐下一小卒,不想人长帅了点,被强征去当英雄,还不给我跳板踩,害得我摔死几回!本想摔死了投胎成一个程序员,这样就可以把Yorhom拉去当英雄,然后让他尝尝摔死的滋味。不想万恶的浏览器加了缓存,害得在下摔死了又投胎成英雄,然后又接着摔死!!苦哉苦哉。。。”

我听了他的话心中只有一句话想说:”投胎和缓存有多大关系?小卒果真就是没文化,只有干替死这一行了。。。“

我们的英雄悲伤地哭了。。。算了不管他,我们继续学习游戏开发,哈!

回入正题,我们有了图片接着上代码,首先是一些变量:

  1. var hitStage = false;
  2. var stageSpeed = 5;
  3. //是否已经扣血变量
  4. var isCutHp = false;

hitStage是用来检测是否碰撞,如果是就改为true。stageSpeed是跳板下降速度。isCutHp是判断是否已经扣血,每当英雄落到有钉子的跳板上时,我们就给英雄扣血,但因为我们的页面是不断刷新的,所以每当一扣血就会一次性地扣完,所以给它一个变量,控制页面刷新时是否让英雄扣血。这里只提一下,减血等留到后面讲。

接着是跳板Stage类构造器代码:

  1. /**
  2. *Stage障碍物类
  3. */
  4. function Stage(speed,data){
  5. base(this,LSprite,[]);
  6. var self = this;
  7. //取出一个整数,使0<=index<=10成立
  8. var index = Math.floor(Math.random()*10);
  9. var bitmapIndex;
  10. if(index == 0){
  11. bitmapIndex = 1;
  12. }else{
  13. bitmapIndex = 0;
  14. }
  15. //将index的值取出对应的图片
  16. var bitmap = new LBitmap(new LBitmapData(imglist["stage"+bitmapIndex]));
  17. //定义障碍物的模式
  18. self.mode = "";
  19. //判断障碍物是否可以触碰
  20. self.value = 0 == index ? -1:1;
  21. self.addChild(bitmap);
  22. }

可以结合注释看一下,如果你对lufylegend是十分了解,那么看起来就很简单了。

只简单说明一个地方。就是index这个变量,首先给它随机弄一个1~10的整数,接着判断,如果index值为0,则为有钉子的跳板,否则为可以站立的跳板。这样的话,出现有钉子的跳板的概率则为十分之一。

其中mode属性和上一讲中Character类的mode属性是一样的。它用于判断跳板当前状况。

value属性判断是否可以触碰。

当然光有构造器还不行,我们为了让跳板能上升,添加run方法:

  1. /**
  2. *Stage类中run函数
  3. */
  4. Stage.prototype.run = function(){
  5. var self = this;
  6. //让障碍物不断上升
  7. self.y -= stageSpeed;
  8. //使用Stage中checkHit函数,判断是否碰撞
  9. var hit = self.checkHit();
  10. //判断是否到达边缘
  11. if(self.y < 0){
  12. self.mode = "die";
  13. }
  14. //判断碰撞
  15. if(!hit){ //当没有碰撞时……
  16. //将模式设为up
  17. self.mode = "up";
  18. }else{ //当产生碰撞时……
  19. //将模式设为hit
  20. self.mode = "hit";
  21. }
  22. }

因为Stage继承自LSprite类,所以当你改变y属性时,跳板就会上升。代码的逻辑是这样的:

判断跳板是否移出屏幕,如果是,则将mode改为die ---> 判断是否碰到人物,如果没有则将mode改为up,让它自己不断上升;如果是则将mode改为hit

这样设计的话,我们可以在页面每刷新一次就调用checkHit。在checkHit里判断这个mode,根据它的值判断它要做的处理。

当然,大家可能已经想看看checkHit里的代码了,那我也不好再隐瞒代码了,贴出来给大家看看:

  1. /**
  2. *Stage类中检测碰撞的checkHit函数
  3. */
  4. Stage.prototype.checkHit = function(){
  5. var self = this;
  6. //检测碰撞
  7. if(LStage.hitTest(self,hero)){
  8. //将碰撞变量设定为true
  9. hitStage = true;
  10. //判断碰到的是可触碰的还是不可碰的以及有没有扣血
  11. if(isCutHp == false){ //当为没有扣血时……
  12. //将层数加一
  13. layer++;
  14. //显示层数
  15. showLayer();
  16. if(self.value == -1){ //当为不可触碰时……
  17. //hp减一
  18. hp--;
  19. //显示hp
  20. showHp();
  21. }
  22. }
  23. if(self.mode == "hit"){
  24. //将isCutHp设为ture
  25. isCutHp = true;
  26. if(self.value == 1){ //当是可触碰物时……
  27. //将人物坐标移到障碍物上一个人的身高减8
  28. hero.y = (self.y - hero.height) + 5;
  29. }else if(self.value == -1){ //当是不可触碰物时……
  30. //将人物坐标移到障碍物上一个人的身高减30
  31. hero.y = (self.y - hero.height) + 27;
  32. }
  33. }else{
  34. //将isCutHp设为false
  35. isCutHp = false;
  36. }
  37. }else{
  38. //将hitStage设为false
  39. hitStage = false;
  40. }
  41. }

首先我们用lufylegend中提供的检测碰撞方法LStage.hitText,第一个参数是检测碰撞的区域A,第一个参数是检测碰撞的区域B,它的用法可以去API上看看。

我们的if里有一大段代码。接下来由我为大家逐一解释。

首先,如果我们的英雄碰到了跳板就将碰撞变量hitStage设为true,否则设为false,这样的话就可以在别处检测是否碰撞了。接着我们将英雄的层数加1并显示,然后判断是否碰到带钉子的跳板。如果碰到就让英雄的hp减1并显示。接着我们判断mode,如果值是hit,说明还处于碰撞之中,然后就将isCurHp改为true,说明已经减血,不需要再减了。其实无论是碰到带钉子的跳板还是没有都要把这个变量改了,目的在于判断人物是否在跳板上。

接着我们将人物的坐标y移到当前跳板上,为了让人物停止下降,我们改一下Charactor中的run方法,更改后的代码:

  1. /**
  2. *Charactor类中run函数
  3. */
  4. Charactor.prototype.run = function (){
  5. var self = this;
  6. if(hitStage == false){ //当没有碰到障碍物时……
  7. //将人物不断下落
  8. self.y += fallSpeed;
  9. }
  10. //减少动画切换的频率
  11. if(self.stepindex++ > self.step){
  12. self.stepindex = 0;
  13. self.anime.onframe();
  14. }
  15. //判断人物模式,以便用来移动人物
  16. if(self.mode == "left"){ //向左移动时的处理
  17. //判断人物是否到了最左画布边缘
  18. if(self.x > 10){
  19. self.x -= heroSpeed;
  20. }
  21. }else if(self.mode == "right"){ //向右移动时的处理
  22. //判断人物是否到了最右画布边缘
  23. if(self.x < LStage.width - self.getWidth()-20){
  24. self.x += heroSpeed;
  25. }
  26. }else if(self.mode == "stand"){
  27. return;
  28. }
  29. }

其实就也只改了人物下降方式了:

  1. if(hitStage == false){ //当没有碰到障碍物时……
  2. //将人物不断下落
  3. self.y += fallSpeed;
  4. }

在上面已经说了,如果碰到跳板就将hitStage设为true,这时判断不通过,人物就不动了。当然如果没有碰撞,那么判断就通过,英雄还是得往下落。

这些都好理解,好好看几分钟,理解了就自然简单了。

我们的Stage类已经搞定了,接着我们要把它实例化出来,因此添加addStage函数:

  1. function addStage(){
  2. //创建一个障碍物
  3. var stage = new Stage();
  4. stage.x = Math.floor(Math.random()*300);
  5. stage.y = LStage.height;
  6. stageLayer.addChild(stage);
  7. stageLayer.scaleX = 1.2;
  8. stageLayer.scaleY = 1.2;
  9. }

很简单,就是把当前这个stage对象放入stageLayer中,这样才能让它显现。至于scaleX,scaleY什么的,是我因为感觉跳板太小,所以把它们拉大了。scaleX,scaleY是lufylgend中专门用来拉图的。大家可以看看API,了解了解。

我以前说过,我们的游戏画面是不断刷新的,在刷新的时候是可以响应时间的,因此我们修改刷新事件触发的函数onframe:

  1. function onframe(){
  2. //使用Charactor中run函数,让人物动起来
  3. hero.run();
  4. //循环遍历stageLayer成员,以便用来判断是否移除该成员
  5. for(var key in stageLayer.childList){
  6. //使用Stage中run函数,让障碍物动起来
  7. stageLayer.childList[key].run();
  8. if(stageLayer.childList[key].mode == "die"){ //当障碍物移出屏幕时……
  9. //移除该成员
  10. stageLayer.removeChild(stageLayer.childList[key]);
  11. }
  12. //让人物不断下落或者随障碍物上升
  13. if(hero.y < LStage.height && hero.y > 0 && hp != 0){ //正常时……
  14. if(hitStage == true){ //当碰到障碍物时……
  15. //将该成员的模式设为hit
  16. stageLayer.childList[key].mode = "hit";
  17. }
  18. }else{ //当人物降到屏幕外或没有hp时……
  19. gameover();
  20. return;
  21. }
  22. }
  23. //减少障碍物出现的频率
  24. if(stageStepIndex++ > stageStep){
  25. stageStepIndex = 0;
  26. //加入障碍物
  27. addStage();
  28. }
  29. }

由于我们的跳板是加到一个名叫stageLayer的LSprite中的,所以我们就遍历一下stageLayer的成员列表,每遍历到一个,就对那一个进行run操作。然后判断那一个的mode是否为die,如果是,就把它移除掉。

接着我们进行对人物的操作。首先我们如果人物坐标不为0也就是说没有接触了最上层的钉子并且没有掉到屏幕下以及hp不为0时,就进行正常的操作。如果我们的人物发生了碰撞就将与其碰撞的那个跳板mode设为hit,表示已经碰撞。

如果我们的英雄接触了最上层的钉子并且掉到屏幕下甚至hp为0时,就将游戏结束,我们通过gameover函数实现它。

然后我们加入几个全局变量:

  1. //障碍物频率变量
  2. var stageStepIndex = 0,stageStep = 30;

它们是控制跳板出现频率的。由于onframe里的东西是页面每刷新一次就调用的,所以在onframe中我们将stageStepIndex加1,并判断是否大于stageStep,如果是的话就加一个障碍物。这个做法在上一讲中也提到过,可以去看看。

经过这样一设计,我们就可以让跳板不断出现并且不断上升。

接下来看几个显示hp和层数的函数:

  1. function addPoint(){
  2. //定义layerText为一个文本
  3. layerText = new LTextField();
  4. //显示人物hp图片
  5. hpBitmapdata = new LBitmapData(imglist["hp"]);
  6. //显示hp
  7. showHp();
  8. //显示层数
  9. showLayer();
  10. }
  11. function showHp(){
  12. //设定显示图片的长度,以便用来显示扣hp
  13. hpBitmapdata.setProperties(0,0,20*hp,18);
  14. var hpBitmap = new LBitmap(hpBitmapdata);
  15. //设定hp显示位置
  16. hpBitmap.x = 20;
  17. hpBitmap.y = LStage.height - 55;
  18. overLayer.addChild(hpBitmap);
  19. }
  20. function showLayer(){
  21. //设定字体
  22. layerText.font = "HG行書体";
  23. //设定颜色
  24. layerText.color = "white";
  25. //设定文本
  26. layerText.text = "Layer:"+layer;
  27. //设定x坐标
  28. layerText.x = 23;
  29. //设定y坐标
  30. layerText.y = LStage.height - 35;
  31. //设定字的大小
  32. layerText.size = 15;
  33. overLayer.addChild(layerText);
  34. }

代码很简单,看看注释就能懂。

另外加如一个暂停功能,原理很简单,就是将刷新事件移除:

  1. function addSetButton(){
  2. //显示一个暂停按钮
  3. btnPause = new LButton(new LBitmap(new LBitmapData(imglist["pause"])),
  4. new LBitmap(new LBitmapData(imglist["pause"])));
  5. btnPause.x = LStage.width - 60;
  6. btnPause.y = LStage.height - 40;
  7. btnPause.scaleX = 0.5;
  8. btnPause.scaleY = 0.5;
  9. overLayer.addChild(btnPause);
  10. //添加按钮事件
  11. btnPause.addEventListener(LMouseEvent.MOUSE_DOWN,function(){
  12. if(isPlay == 1){ //当没有暂停时……
  13. //将isPlay设为0
  14. isPlay = 0;
  15. //移除鼠标事件
  16. backLayer.removeEventListener(LMouseEvent.MOUSE_DOWN,onDown);
  17. backLayer.removeEventListener(LMouseEvent.MOUSE_UP,onUp);
  18. //移除onframe调用
  19. backLayer.removeEventListener(LEvent.ENTER_FRAME,onframe);
  20. }else if(isPlay == 0){ //当暂停时……
  21. //将isPlay设为1
  22. isPlay = 1;
  23. //加入鼠标事件
  24. backLayer.addEventListener(LMouseEvent.MOUSE_DOWN,onDown);
  25. backLayer.addEventListener(LMouseEvent.MOUSE_UP,onUp);
  26. //加入onframe调用
  27. backLayer.addEventListener(LEvent.ENTER_FRAME,onframe);
  28. }
  29. });
  30. }

运行代码看看:

二,英雄威名

我们上面提到了gameover函数,我们在这里看看它的代码:

  1. function gameover(){
  2. //将人物模式设为die
  3. hero.mode = "die";
  4. //移除人物
  5. charaLayer.removeAllChild();
  6. //移除所有事件
  7. removeEvent();
  8. //获得玩家称号
  9. getName();
  10. //添加游戏结束文字
  11. overLayer.graphics.drawRect(5,"gray",[40,80,330,200],true,"lightgray");
  12. overLayer.alpha = 0.8;
  13. for(var i=0;i<gameoverContentArr.length;i++){
  14. //字的公共属性
  15. gameoverText = new LTextField();
  16. gameoverText.font = "HG行書体";
  17. gameoverText.text = gameoverContentArr[i];
  18. //字的私有属性
  19. if(i == 0){ //当字是GAME OVER时……
  20. gameoverText.x = 50;
  21. gameoverText.color = "dimgray";
  22. gameoverText.size = 40;
  23. gameoverText.y = 100;
  24. }else if(i == 1){ //当字是Tap to Restart时……
  25. gameoverText.x = 120;
  26. gameoverText.color = "dimgray";
  27. gameoverText.size = 20;
  28. gameoverText.y = 170;
  29. }
  30. overLayer.addChild(gameoverText);
  31. }
  32. //定义nameText为一个文本
  33. nameText = new LTextField();
  34. //设定字体
  35. nameText.font = "HG行書体";
  36. //设定颜色
  37. nameText.color = "white";
  38. //设定字体粗细
  39. nameText.weight = "bold";
  40. //设定字体大小
  41. nameText.size = 15;
  42. //设定x坐标
  43. nameText.x = 100;
  44. //设定y坐标
  45. nameText.y = 220;
  46. nameText.text = "你的称号是:"+getName();
  47. overLayer.addChild(nameText);
  48. //添加重新开始游戏的事件
  49. backLayer.addEventListener(LMouseEvent.MOUSE_DOWN,
  50. function (event){
  51. //移除场上所有东西
  52. backLayer.removeAllChild();
  53. backLayer.die();
  54. //变量设为初始值
  55. hp = 3;
  56. layer = 0;
  57. isPlay = 1;
  58. //游戏重开
  59. initLayer();
  60. startGame();
  61. });
  62. }

注释写得很清楚,不用我多说了。其中调用了一个getName(),其中的代码很后意思:

  1. function getName(){
  2. if(layer < 10){
  3. return "小试身手者";
  4. }else if(layer >= 10 &&layer < 20){ //当分数在10~20时……
  5. return "英勇无畏者";
  6. }else if(layer >= 20 &&layer < 30){ //当分数在20~30时……
  7. return "行如风行者";
  8. }else if(layer >= 30 &&layer < 40){ //当分数在30~40时……
  9. return "影身如风者";
  10. }else if(layer >= 40 &&layer < 50){ //当分数在40~50时……
  11. return "深渊掌控者";
  12. }else if(layer >= 50 &&layer < 60){ //当分数在50~60时……
  13. return "极限飞登者";
  14. }else if(layer >= 60 &&layer < 70){ //当分数在60~70时……
  15. return "可谓英雄者";
  16. }else if(layer >= 70 &&layer < 80){ //当分数在70~80时……
  17. return "冲锋陷阵者";
  18. }else if(layer >= 80 &&layer < 90){ //当分数在80~90时……
  19. return "身如疾风者";
  20. }else{ //当分数在90以上……
  21. return "再现武魂者";
  22. }
  23. }

代码当然很简单,但是值得一提的是,其中“再现武魂者”和“身如疾风者”都是出自真三国无双5,我想不出称号了,借用了一下。

运行代码:

演示地址:http://www.cnblogs.com/yorhom/archive/2013/04/14/3020566.html

话说我们的小卒已经死了九亿九千九百九十九万次了,趁我写文章这段时间,他叫了不下九千九百九十九万次help,我写完文章按下F5运行下代码,小卒愤怒地大叫道:“我X,我都死了九亿九千九百九十九万次了,就算去见阎王也要当个无常什么的。恩。。。人生自古谁无死,留取丹心照汗青!!!”没等他说下一句鬼话,他忽然眼前一亮,看见一个跳板向他飞来。小卒高兴地大叫:“老夫有救了!!!”他飞快地冲到跳板上,又接着往下一块上跳,不想下一块是一个钉板,小卒刚一碰到就被戳了一下。“Yorhom,你到底要怎样???你已经困俺500年了!!家中老小早不知死活了,如今还要拿钉板来陷害本人,是何意思???”小卒大骂。

Yorhom:“只有你跨越一道道难关才能修成正果,最终成为再现武魂者,加油!”

小卒:“。。。”

路过高僧:“阿弥陀佛,善哉善哉”

本次讲座就到这里,谢谢大家的捧场。

源代码下载:http://files.cnblogs.com/yorhom/jump(2).rar

『HTML5挑战经典』是英雄就下100层-开源讲座(二)危险!英雄的更多相关文章

  1. 『HTML5挑战经典』是英雄就下100层-开源讲座(一)从天而降的英雄

    是英雄就下100层是一款经典的手机小游戏,以前是在诺基亚手机上十分有名.今天我们就用HTML5和lufylegend一步步地实现它. 一,准备工作 首先,你需要下载lufylegend,下载地址如下: ...

  2. HTML5游戏开发_是男人就下100层

    项目流程 市场调研(可行性分析)--> 可行性报告书  需求分析师.客户经理 需求分析--> 需求说明书  项目经理.需求分析师 概要设计--> 概要设计说明书(ER图, UML)  ...

  3. 超多经典 canvas 实例,动态离子背景、移动炫彩小球、贪吃蛇、坦克大战、是男人就下100层、心形文字等等等

    超多经典 canvas 实例 普及:<canvas> 元素用于在网页上绘制图形.这是一个图形容器,您可以控制其每一像素,必须使用脚本来绘制图形. 注意:IE 8 以及更早的版本不支持 &l ...

  4. 『HTML5实现人工智能』小游戏《井字棋》发布,据说IQ上200才能赢【算法&代码讲解+资源打包下载】

    一,什么是TicTacToe(井字棋) 本游戏为在下用lufylegend开发的第二款小游戏.此游戏是大家想必大家小时候都玩过,因为玩它很简单,只需要一张草稿纸和一只笔就能开始游戏,所以广受儿童欢迎. ...

  5. 『与善仁』Appium基础 — 5、常用ADB命令(二)

    目录 9.查看手机运行日志 (1)Android 日志 (2)按级别过滤日志 (3)按 tag 和级别过滤日志 (4)日志格式 (5)清空日志 10.获取APP的包名和启动名 方式一: 方式二: 11 ...

  6. 『与善仁』Appium基础 — 18、元素定位工具(二)

    目录 1.Appium Inspector介绍 2.Appium Inspector打开方式 3.Appium Inspector布局介绍 4.Appium Inspector工具的配置 5.Appi ...

  7. HTML5小游戏【是男人就下一百层】UI美化版

    之前写的小游戏,要么就比较简单,要么就是比较难看,或者人物本身是不会动的. 结合了其它人的经验,研究了一下精灵运动,就写一个简单的小游戏来试一下. 介绍一下几个主要的类: Frame:帧的定义,主要描 ...

  8. Unity经典游戏教程之:是男人就下100层

    版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...

  9. 『HTML5梦幻之旅』-缤纷多姿的烟花效果

    天花无数月中开,五采祥云绕绛台.堕地忽惊星彩散,飞空旋作雨声来.怒撞玉斗翻晴雪,勇踏金轮起疾雷.更漏已深人渐散,闹竿挑得彩灯回. ——明·瞿佑·<烟火戏> 记得每年过春节的那段时间,除了欣 ...

随机推荐

  1. 比特币交易本质--UTXO(Unspent Transaction Output)

    UTXO 代表 Unspent Transaction Output. Transaction 被简称为 TX,所以上面这个短语缩写为 UTXO. 现在的银行也好.信用卡也好.证券交易系统也好,互联网 ...

  2. js生成唯一的uuid

    ---恢复内容开始--- 在做项目的时候出现这样的一种情况,需要动态生成唯一的uuid,刚开始我的思路是这样的,我可以根据时间来做,然后出现了下面的思路: var uuid = "cms&q ...

  3. JAVASCRIPT+DHTML实现表格拖动

    自已做的,本来想在网上找前辈们做的,可是总找不到这种例子,要么找出来的太复杂, 要么就没法用,索性自己写了一个.看看还可以用!贡献出来,估计和我一样的菜鸟用的着! <html> <s ...

  4. C++ 函数的扩展③--函数重载

    //函数扩展--函数重载(C语言不支持函数重载) #include<iostream> using namespace std; //函数重载在本质上是相互独立的不同函数(静态链编),在c ...

  5. ubuntu 安装dlib 出现dlib.so: undefined symbol: png_set_longjmp_fn

    参考网上的教程安装dlib 安装教程1 sudo apt-get install libboost-python-dev cmake sudo pip install dlib 安装教程2ubuntu ...

  6. 小结:hash

    概要: 判重的时候可以用手写hash,也可以用stl中的map,手写hash的好处是快,解决冲突的方案较好,map慢.但是手写hash要求的空间高,而且有时处理得不好的话会wa. 注意及技巧: 注意的 ...

  7. 【C语言】求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素

    //求旋转数组的最小数字,输入一个递增排序的数组的一个旋转,输出其最小元素 #include <stdio.h> #include <string.h> int find_mi ...

  8. 终端利用ssh登录远程服务器

    第一步: 安装ssh:yum  install ssh 第二步: 启动ssh服务:service sshd start 第三步: 连接远程服务器: ssh -p 端口号 用户名@ip地址      然 ...

  9. Linux命令之乐--nmap

    Nmap是一款非常强大的实用工具,可用于:检测活在网络上的主机(主机发现)检测主机上开放的端口(端口发现或枚举)检测到相应的端口(服务发现)的软件和版本检测操作系统,硬件地址,以及软件版本检测脆弱性的 ...

  10. 88、android 插件开发教程(转载)

    http://blog.csdn.net/qq435757399/article/details/46521085 http://blog.csdn.net/t12x3456/article/deta ...