博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HTML5游戏系列(2):装B达人
阅读量:4090 次
发布时间:2019-05-25

本文共 5413 字,大约阅读时间需要 18 分钟。

游戏系列(2):装B达人 由发表在

小编的第一款HTML游戏:“”引起了微信圈不错的反响,这更加激发了“天码营”团队以及小编本人的斗志。此次小编带来了可玩性更强的HTML5游戏:“装B达人”!还没有玩过的可以关注天码营公众号“TMY-EDE”并获取最新文章即可得到游戏链接。也可以直接打开链接: 

下面便开始详述“装B达人”是怎样炼就的!先上图,一睹为快:

简介

游戏流程

B会不断地从天而降,玩家可以移动篮子来装B,我们会给出装B计数。一旦B已经接触地面在本次装B失败,游戏结束(Game Over~)。

技术框架

本游戏的实现借助于HTML5提供的标签,Canvas是一个基于位图的矩形绘图区域,该标签最初由Safari提供支持,在2014年10月终于被纳入。进入HTML标准意味着主流浏览器都将对此提供支持,Google在Android4.0中便对Canvas提供了硬件加速。这意味着在HTML中复杂的游戏也可以做到很好的性能。

Canvas: a resolution-dependent bitmap canvas which can be used for rendering graphs, game graphics, or other visual images on the fly. -- HTML5, W3C

“装B达人”引入了来进行更方便的Canvas操作,以及Sprite素材的载入。

CreateJS: A suite of modular libraries and tools which work together or independently to enable rich interactive content on open web technologies via HTML5.

CreateJS是一个组件库,它提供了四部分的工具:

  1. :提供了更加方便的Canvas操作,这是我们主要使用的一个组件。
  2. :更方便地进行HTML5中元素属性的渐变和动画。
  3. :提供了丰富的音频处理API。
  4. :用来管理Web资源的载入,我们用它来载入图片素材,并形成一个Sprite对象以供使用。

实现流程

理论上HTML文件只需提供一个canvas标签,其它的交给JS来处理。最终的实现也是这样的,HTML框架非常简单,只需引入需要的样式的脚本即可。在脚本中完成游戏的初始化过程与交互动画。

首先利用PreloadJS载入需要的图片素材;然后用这些素材来初始化整个场景。此后游戏就可以开始啦!游戏开始后,我们需要在Tick(时钟)事件到达时重新绘图,完成如下几个操作:

  1. 让B下落。只需增加该元素的y属性。
  2. 检测B与地面的碰撞。如果发生碰撞则游戏结束。
  3. 检测B与篮子的碰撞。如果发生碰撞则分数+1,从天上再掉下一个B。

为了让玩家能够移动篮子,需要监听mousedownpressmove事件:

  1. mousedown时,记录按下的位置。
  2. pressmove时,计算与mousedown时的位置差,并相应地移动篮子。

HTML框架

“装B达人”使用HTML5 Canvas实现,因此HTML框架非常简单。只需定义一个<canvas>并在HTML头部引入相应的样式和JS即可!

  

其中的easeljs-NEXTpreloads-NEXTtweenjs-NEXT是提供的Canvas工具,这三个文件可以在参考代码中下载;我们的所有编程工作都在main.cssmain.js中,请手动新建这两个文件!

全局样式

样式很简单啦,只需要样canvas全屏即可:

/* css/main.css */html, body{    padding: 0;    margin: 0;}

因为有些浏览器的UA默认样式表会为htmlbody提供边距,所以我们需要设置它们的内外边距为0.

初始化场景

说道游戏,你首先想到的概念可能是:场景、模型、灯光、动画。游戏引擎们尽可能地封装了这些数据和操作,尤其在JavaScript中这些概念只会更简单!我们看看CreateJS中,如何创建一个初始的场景!

首先你需要从参考代码中把图片素材都解压出来。然后建立一个素材清单:

// file: js/main.jsmanifest = [    {src: "sky.png", id: "sky"},    {src: "ground.png", id: "ground"},    {src: "hill1.png", id: "hill"},    {src: "hill2.png", id: "hill2"},    {src: "b.png", id: "b"},    {src: 'basket.png', id: 'basket'}];

接着,我们需要载入这些素材,并初始化场景。

// file: js/main.jsvar score = 0, w, h, bs = [];    // 全局变量:得分、画布宽高、B的数组document.addEventListener('DOMContentLoaded', function(){    $canvas = document.getElementById('testCanvas');    $canvas.setAttribute('width', window.innerWidth);    $canvas.setAttribute('height', window.innerHeight);    stage = new createjs.Stage($canvas);    w = stage.canvas.width;    h = stage.canvas.height;    loader = new createjs.LoadQueue(false);    loader.addEventListener("complete", handleComplete);    loader.loadManifest(manifest, true, "assets/art/");});

在CreateJS中,出于性能考虑,图片清单是异步加载的。当我们给出的图片清单加载完毕时,handleComplete()会被调用。在handleComplete中素材都已下载完毕,我们需要设置这些图片的位置,变换,以及平铺属性:

function handleComplete() {    // 分数文本:放在右上角,红色    scoreText = new createjs.Text("", "bold 28px Impact", "red");    scoreText.x = w - 20;    scoreText.y = 10;    // 天空:横向平铺。地面和山丘也是类似的,请见参考代码    var skyImg = loader.getResult("sky");    sky.graphics.beginBitmapFill(skyImg, 'repeat-x').drawRect(0, 0, w, h);    // 篮筐:为了方便动画,将中心点设为参考点    basketImg = loader.getResult('basket');    basket = new createjs.Bitmap(basketImg);    basket.regX = basketImg.width / 2;    basket.regY = basketImg.height / 2;    basketRange = {        x: basket.regX,        y: basket.regY,        width: w - basketImg.width,        height: h - groundImg.height - basketImg.height    };    // 把上述对象添加到场景中    stage.addChild(skybg, sky, hill, ground, trolley, scoreText);    // 获取B的图片    bImg = loader.getResult("b");    brange = {        width: w - bImg.width,        height: h - groundImg.height    };    // 把它们都添加到场景中    for (var i = 0; i < 5; i++) {    // 为什么是5?见下一节        var b = new createjs.Bitmap(bImg);        initB(b);                    // 初始化B,见下一节        bs.push(b); stage.addChild(b);    }    // 更新这个场景,触发canvas刷新    stage.update();}

初始化B

游戏中会有大量的B从天而降,为了保证性能我们手动地管理B的缓存。基于我们的观察,在任何一刻的画面中B的数量都是有限的。不妨就此规定B的数量,比如5个。当一个B被收集或者落地时,我们回收它,让它重新从天而降。回收和初始化B都是用initB()函数:

function initB(b){      b.regX = bImg.width / 2;    b.regY = bImg.height / 2;      // 随机生成一个在当前场景上方的位置。    b.x = Math.random() * (brange.width - bImg.width) + b.regX;    b.y = Math.random() * brange.height - brange.height - bImg.height / 2;}

掉落动画

随着时间的推移,B应当从天而降。为了逐帧地更新动画,在handleComplete()函数最后监听时钟:

createjs.Ticker.addEventListener("tick", tick);

其中的tick函数中,我们需要让B往下落,同时要检测B是否被收集了,以及B是否碰到地面了。

function tick(){    // event.delta是距离上次`tick`的时间,以毫秒计    // 将时间变换为距离,0.15是可调参数,其物理意义是下落速度 v = s/t    var deltaS = event.delta * 0.15;    // 遍历所有的B    bs.forEach(function (b) {        if (b.inCollision) return;    // 如果它已经触地,则返回        b.y += deltaS;                // 让它下落!        if (collisionX(b, basket)) {  // b和basket的碰撞检测,见下一节            b.inCollision = true;            score ++;                 // 更新分数            scoreText.text = score + 'B';            initB(b);                 // 初始化B,让它重新从天而降        }        else if (b.y + b.regY >= brange.height) {            b.inCollision = true;     // b碰到地面啦,游戏结束            gameOver();        }    });    // 刷新canvas    stage.update(event);}function gameOver(){    // 游戏结束!    // 以任何形式告知用户}

碰撞检测

上述的掉落动画中,我们调用了B和basket的碰撞检测,CreateJS并未提供这样的高阶功能,但矩形的碰撞检测并不困难!

function collisionX(a, b) {    return a.x + a.regX > b.x - b.regX    // a的右边超出了b的左边        && a.x - a.regX < b.x + b.regX    // b的右边超出了a的左边        && a.y + a.regY > b.y - b.regY    // a的下边超出了b的上边        && a.y - a.regY < b.y + b.regY;   // b的下边超出了a的上边}

可执行的、完整的代码见。

更多文章请访问

你可能感兴趣的文章
WTF?GitHub 疑似遭受大范围中间人攻击?!
查看>>
天秀!只用 280 字,把一条推特长度的代码玩出花...
查看>>
天秀!GitHub 硬核项目:动漫生成器让照片秒变手绘日漫风!!!
查看>>
面试了 15 位来自 985/211 高校的 2020 届研究生,我熬夜赶出了这篇文章
查看>>
连苹果都在用的开源库:core-js 作者被判入狱 18 个月!
查看>>
没用过这些 IDEA 插件?怪不得你写代码头疼...
查看>>
这款超级搜索神器,我爱了!
查看>>
太赞了,RTC 2020 编程挑战赛终于正式开启!
查看>>
不用一行代码,就写了个爬虫!这款谷歌插件已经打包好了!
查看>>
Chrome,你够了!
查看>>
嫌官方文档太烂?TensorFlow 开源工具书,助你快速上手开发!
查看>>
Java 依然很牛逼
查看>>
从罗永浩抖音带货一晚成交 1.1 个亿,我看到了未来应届生这几个新求职机遇......
查看>>
这个 Python 代码自动补全神器搞得我卧槽卧槽的!
查看>>
卧槽!为鼓励民众居家隔离,国外这些计算机学习资源将免费对外开放!
查看>>
Eclipse Theia 1.0 发布,这才是 VS Code 真正的开源替代方案?!
查看>>
堪称开挂!印度裔 00 后 7 岁教人编程,12 岁成 IBM 荣誉顾问,还出过书!
查看>>
为什么魂斗罗只有 128KB 却可以实现那么长的剧情?
查看>>
全球呼吸机告急!医疗科技巨头美敦力 "开源" 设计图和源代码!
查看>>
哇!动辄上千台服务器,到底在干嘛?
查看>>