Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

从零开始开发一款H5小游戏(五) 必要的包装,游戏规则和场景设计 #23

Open
fwon opened this issue Jul 21, 2016 · 1 comment

Comments

@fwon
Copy link
Owner

fwon commented Jul 21, 2016

到这里我们已经讲了游戏的整体设计和实现。一个游戏要完整,还需要给它制定一个评分机制,它是整个游戏的关键所在。就好比一部电影,特效再好看,如果剧情狗血,那也是一部烂片。

相信大家都玩过一些简单但很吸引人的小游戏。比如很久以前微信上的打飞机,围住神经猫,还有前段时间大火的slither.io。他们都简单易玩,但却能让人肾上腺素飙升,百玩不腻。

所以一款好玩的小游戏必须具备了这样的特点,简单易玩,却能给人制造紧张感,有时还能利用一些攀比心理。本游戏也基本具备了这样的特点。

计分实现

游戏以秒数作为计分,随着时间的增加,Enemy粒子的运动速度会越来越快,躲避难度也就越来越大。游戏中的计秒实现比较简单,就是用setTimeout来实现,这里不使用setInterval,原因在第一章已经大致讲过了,就是考虑到准确性的问题。

//index.js
function initTimer() {
    holdingTime = 0;
    holdingLevel = 0;
    clearTimeout(timer);
    let time = function() {
        timer = setTimeout(function() {
            holdingTime = +timeEle.innerText + 1;
            timeEle.innerText = holdingTime;
            //每隔10秒加速一次
            if (holdingTime % 10 === 0) {
                holdingLevel++;
                levelEle.innerText = holdingLevel;
                for (let i = 0; i < enemys.length; i++) {
                    //Enemy粒子速度增加
                    enemys[i].speedUp();
                }
            }
            clearTimeout(timer);
            time();
        }, 1000)
    };
    time();
}

每隔10s, Enemy粒子的速度增加一次,Enemy中封装了speedUp方法。

//Enemy.js
speedUp(speed) {
   this.speed += speed || 0.2;
}

在技能粒子中,有一个护盾粒子。吃了护盾后,撞击Enemy粒子能增加分数。实现起来也很简单,直接修改计分板上的分数就行了。

//Player.js
let score = document.getElementById('time').innerText;
document.getElementById('time').innerText = (+score + REDSCORE);

粒子的初始生命值有三条,每次撞击到Enemy粒子都会减少一条,而如果撞击到视界的边界则会直接狗带。这里我们需要增加一个游戏结束的画面。给出最后的分数。

roadmap.path

开始和结束画面都是通过DOM实现的,这部分比较简单,就不做具体介绍了。

其实在游戏的评分机制上还可以做很多改进,比如增加排行榜,或记录自己的最优成绩,并可分享到朋友圈等。这部分可以极大增加游戏的热度。 读者可以自己展开想象,对玩法进行扩展。

预加载

当我在微信打开游戏的时候,发现开始画面和结束画面的图片加载很慢。导致DOM结构出来了,图片却迟迟没看到,没法给玩家准确的提示。所以需要增加一个图片预加载的功能。当然这也是每一个网页游戏框架必备的功能。

这部分功能直接参考了阿里的一个游戏框架Hilo,并把它抽象到loader.js。读者可自行查阅实现细节。

抽象后在入口处预加载所需的图片:

//index.js
let loader = new Loader();
let source = [
    {src: 'assets/images/number.png'},
    {src: 'assets/images/over.png'},
    {src: 'assets/images/sprites.png'}
];
loader.load(source, function() {
    start(); //开始游戏
});

预加载的时候还需要有个提示画面来告知加载进度。

进度条的实现也独立成一个文件loading.js,并暴露一个外部API给游戏使用。

我们还需要将预加载插件和进度条结合起来,每个图片加载完成后,loader会触发一次load事件,用一个计数器统计加载的图片数,除以总数得到一个进度比例。然后将这个比例barRatio传给进度条。让其渲染出相应的进度。

//根据加载进度渲染进度条
let loaded = 0;
loader.on('load', e => {
    ++loaded;
    barRatio = loaded / source.length;
});

//进度条渲染
(function loading() {
    drawLoading(barRatio);
    if (!loadingFinish) {
        raf(loading);    
    }
})();

需要注意的一点是,进度条是通过canvas画布实现的。所以进度canvas的draw方法是在不停运行的。如果每张图片加载完的时候才改变进度条的位置,就会造成进度跳跃式地前进,无法连续顺滑加载的效果。
这个逻辑在loading中通过一个判断来解决。

//loading.js
let currentBarWidth = bar.total * ratio;
if (bar.width < currentBarWidth) {
    bar.width += 2;
}

保证进度条每次增加只能是2。而不是直接让bar.width = currentBarWidth;

结语

至此整个游戏的开发就介绍到这了,主要还是讲游戏的实现思路。 游戏中还是有挺多细节处理的,这些真的要亲自动手写一下才能了解。

本教程的初衷就是想让读者能对H5游戏开发有个宏观的了解,知道怎么入手。想起几周前自己要写这个游戏的时候还无从下手,如今也完成开发并写了几篇总结,算是有所沉淀。

其实H5游戏开发远比这个复杂,本游戏只是基于画笔实现,还没有涉及到图片的绘制,坐标轴转换等等。还有很多了要学习的东西啊。当然这只是自己一时的兴趣尝试,等什么时候心血来潮了,说不定再写一个系列呢。

@fwon fwon changed the title 《从零开始开发一款H5小游戏(五) 必要的包装,游戏规则和场景设计》 从零开始开发一款H5小游戏(五) 必要的包装,游戏规则和场景设计 Jul 21, 2016
@shiyouv
Copy link

shiyouv commented Aug 10, 2020

作者大神感觉很牛X,请问能不能开发出来这种h5手游的大型游戏,如果可以就非常很nice了!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants