HTML5游戏系列:装B达人

Posted 天码营

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HTML5游戏系列:装B达人相关的知识,希望对你有一定的参考价值。

html5游戏系列(2):装B达人 由David发表在天码营 

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

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

简介

游戏流程

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

技术框架

本游戏的实现借助于HTML5提供的Canvas标签,Canvas是一个基于位图的矩形绘图区域,该标签最初由Safari提供支持,在2014年10月终于被纳入HTML标准。进入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达人”引入了CreateJS来进行更方便的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. EaselJS:提供了更加方便的Canvas操作,这是我们主要使用的一个组件。
  2. TweenJS:更方便地进行HTML5中元素属性的渐变和动画。
  3. SoundJS:提供了丰富的音频处理API。
  4. PreloadJS:用来管理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即可!

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
  <link rel="stylesheet" href="assets/css/main.css">

  <script src="assets/lib/easeljs-NEXT.combined.js"></script>
  <script src="assets/lib/preloadjs-NEXT.min.js"></script>
  <script src="assets/lib/tweenjs-NEXT.min.js"></script>
  <script src="assets/js/main.js"></script>
</head>

<body>
  <canvas id="testCanvas"></canvas>
</body>
</html>

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

全局样式

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

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

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

初始化场景

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

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

// file: js/main.js
manifest = [
    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.js
var 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的上边

可执行的、完整的代码见此处参考代码


更多文章请访问 天码营网站




以上是关于HTML5游戏系列:装B达人的主要内容,如果未能解决你的问题,请参考以下文章

重回童年的经典系列 |捕鱼达人小游戏来啦~ 有源码下载文末送书

HTML5捕鱼人在线小游戏源码

俄罗斯方块游戏开发系列教程4:形状碰撞检测(上)

算数达人小小小游戏,小白写,轻喷。

精品源码Html5捕鱼达人源码分享

源码分享Html5捕鱼达人源码分享