用HTML5开辟一个小游戏

先上结果图

《用HTML5开辟一个小游戏》

最先之前的预备

  1. game.html
  2. js/ 内里建立game.js
  3. images/ 内里放三张图片,一张背景图片(background.png),一张好汉图片(hero.png),一张怪物的图片(monster.png)

game.html内里写上以下几行简朴的HTML代码:


<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Simple Canvas Game</title> </head> <body> <script src="js/game.js"></script> </body> </html>

我们在game.html引入了game.js文件,没错,剩下的一切事情都是在操纵game.js,为其增加游戏的js代码。

建立画布

在game.js 内里,我们起首须要为游戏的舞台建立一张画布(canvas):

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);

这里经由历程js来建立了一个元素并设置canvas的宽和高,末了将其增加到<body>标签后。var ctx = canvas.getContext("2d");中的ctx变量是我们背面会用到的,细致的canvas用法检察这里的链接:

https://developer.mozilla.org/en/canvas_tutorial

预备图片

游戏须要加载我们之前存放在images文件夹下面的三张图片:

// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
    bgReady = true;
};
bgImage.src = "images/background.png";

// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
    heroReady = true;
};
heroImage.src = "images/hero.png";

// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
    monsterReady = true;
};
monsterImage.src = "images/monster.png";

以上三张图片都是经由历程建立简朴的图片对象来完成加载的,相似bgReady的三个变量用来标识图片是不是已加载完成,假如假如在图片加载未完成情况下举行绘制是会报错的。假如你不太肯定new Image()究竟是个什么东西,你能够在bgImage.src = "images/background.png";今后运用console.log(bgImage);来检察,你看到的将是相似:

<img src="images/background.png" >

游戏对象

我们须要定义一些对象,以便我们在背面会用到:

var hero = {
    speed: 256 // movement in pixels per second
};
var monster = {};
var monstersCaught = 0;

既然是好汉抓获怪物,我们得要有一个好汉怪物的对象。而好汉有一个speed属性用来掌握他每秒挪动若干像素。怪物游戏历程当中不会挪动,所以临时不必设置属性。monstersCaught则用来存储怪物被抓住的次数,初始值固然为0了。

处置惩罚用户的输入

游戏是给人玩的,那末我们怎样晓得用户到底在这个历程当中干了什么?按了键盘?点了鼠标?这些都是用户在玩游戏的时刻的输入,所以我们一旦捕捉到这些输入,我们就能够依据游戏的逻辑对用户的输入举行处置惩罚了:

// Handle keyboard controls
var keysDown = {};

addEventListener("keydown", function (e) {
    keysDown[e.keyCode] = true;
}, false);

addEventListener("keyup", function (e) {
    delete keysDown[e.keyCode];
}, false);

这里我们只是监听两个用户的输入:

  1. keydown
  2. keyup

然后我们将用户的输入先保留起来,并没有马上响应。为此,我们用keysDown这个对象来保留用户按下的键值(keyCode),假如按下的键值在这个对象里,那末我们就做响应处置惩罚。

在前端开辟中,平常是用户触发了点击事宜然后才去实行动画或提议异步要求之类的

最先一轮游戏

游戏在完毕的时刻,我们须要最先新的一轮游戏,所以在game.js增加reset函数

// Reset the game when the player catches a monster
var reset = function () {
    hero.x = canvas.width / 2;
    hero.y = canvas.height / 2;


    // Throw the monster somewhere on the screen randomly
    monster.x = 32 + (Math.random() * (canvas.width - 64));
    monster.y = 32 + (Math.random() * (canvas.height - 64));

};

reset()函数用于最先新一轮和游戏,在这个要领里我们将好汉放回画布中心同时将怪物放到一个随机的处所。

更新对象

在游戏的历程当中,不论是用户在玩(有准确输入的状况)照样游戏完毕,我们都是须要实时更新游戏的对象:

var update = function (modifier) {
    if (38 in keysDown) { // Player holding up
        hero.y -= hero.speed * modifier;
    }
    if (40 in keysDown) { // Player holding down
        hero.y += hero.speed * modifier;
    }
    if (37 in keysDown) { // Player holding left
        hero.x -= hero.speed * modifier;
    }
    if (39 in keysDown) { // Player holding right
        hero.x += hero.speed * modifier;
    }

    // Are they touching?
    if (
        hero.x <= (monster.x + 32)
        && monster.x <= (hero.x + 32)
        && hero.y <= (monster.y + 32)
        && monster.y <= (hero.y + 32)
    ) {

        ++monstersCaught;
        reset();
    }


};

update函数担任更新游戏的各个对象,会被规律地反复挪用。起首它担任搜检用户当前按住的是中方向键,然后将好汉往响应方向挪动。

有点费脑力的或许是这个传入的modifier 变量。你能够背面将要完成的main 要领里看到它的泉源,但这里照样有必要细致解释一下。它是基于1最先且随时候变化的一个因子。比方1秒过去了,它的值就是1,好汉的速率将会乘以1,也就是每秒挪动256像素;假如半秒钟则它的值为0.5,好汉的速率就乘以0.5也就是说这半秒内好汉以一般速率一半的速率挪动。理论上说由于这个update函数被挪用的非常快且频仍,所以modifier的值会很小,但有了这一因子后,不论我们的代码跑得快慢,都能够保证好汉的挪动速率是恒定的。

这里须要申明一下下面的推断怪物和好汉是什么依据:

 if (
        hero.x <= (monster.x + 31)
        && monster.x <= (hero.x + 31)
        && hero.y <= (monster.y + 32)
        && monster.y <= (hero.y + 32)
    )

上面的31,32是由heromonster图片的大小决议的,我们的hero图片是32x32,monster图片是30x32,所以依据坐标的位于图片中心的法制,就能够获得上面的推断前提。

如今好汉的挪动已是基于用户的输入(按下键)了,接下来该搜检挪动历程当中所触发的事宜了,也就是好汉与怪物相遇。这就是本游戏的成功点,monstersCaught +1然后重新最先新一轮。

衬着物体

之前写的代码都是在预备前期事情和处置惩罚一些游戏的状况等,下面将进入正题:我们须要将一切的东西画出来

// Draw everything
var render = function () {
    if (bgReady) {
        ctx.drawImage(bgImage, 0, 0);
    }

    if (heroReady) {
        ctx.drawImage(heroImage, hero.x, hero.y);
    }

    if (monsterReady) {
        ctx.drawImage(monsterImage, monster.x, monster.y);
    }

    // Score
    ctx.fillStyle = "rgb(250, 250, 250)";
    ctx.font = "24px Helvetica";
    ctx.textAlign = "left";
    ctx.textBaseline = "top";
    ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
};

这里的ctx就是最前面我们建立的变量。然后应用canvasdrawImage()起首固然是把背景图画出来。然后依样画葫芦将好汉和怪物也画出来。这个历程当中的递次是有考究的,由于后画的物体味掩盖之前的物体。

这今后我们改变了一下Canvas的画图上下文的款式并挪用fillText来绘制笔墨,也就是记分板那一部份。本游戏没有其他庞杂的动画结果和斗殴排场,绘制部份功德圆满

主轮回函数

我们完成了将画面画出来今后,我们紧接着须要完成的就是游戏的轮回构造,因而将它放在main函数里:

// The main game loop
var main = function () {
    var now = Date.now();

    var delta = now - then;
    //console.log(delta);
    update(delta / 1000);
    render();

    then = now;

    // Request to do this again ASAP
    requestAnimationFrame(main);
};

上面的主函数掌握了全部游戏的流程。先是拿到当前的时候用来盘算时候差(间隔上次主函数被挪用时过了若干毫秒)。获得modifier后除以1000(也就是1秒中的毫秒数)再传入update函数。末了挪用render 函数而且将本次的时候保留下来。

设置requestAnimationFrame()

在上面的main函数中,我们经由历程requestAnimationFrame()挪用了main函数,所以我们须要声明:

var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;


这里这么多的||,不为别的,就是考虑到浏览器兼容问题罢了。

末了启动游戏

万事具备,只欠东风。到此,一切的游戏代码基本就写完了,我们如今须要做的就是挪用响应的函数来启动游戏:


// Let's play this game! var then = Date.now(); reset(); main();

到这里代码就写完了。先是设置一个初始的时候变量then用于起首运转main函数运用。然后挪用 reset 函数来最先新一轮游戏(假如你还记得的话,这个函数的作用是将好汉放到画面中心同时将怪物放到随机的处所以轻易好汉去捉它)

用浏览器翻开game.html,最先玩游戏吧!

进一步思索

在玩游戏的历程当中,你会发明每一次hero捕捉到monsterhero就回到了canvas画布的正中心。那末如今须要做的就是,将hero在捕捉到monster的时刻让hero就停留在捕捉的位置,不再是回到canvas正中心。

这个征象的涌现重要是由于在reset函数中将hero.xhero.y写死了,所以一个最简朴的要领就是在reset中传入参数:

var reset = function (x,y) {
    hero.x = x;
    hero.y = x;
};

然后在update挪用reset的时刻传入捕捉时位置的参数:

var update = function (modifier) {

        //...other codes

        ++monstersCaught;
        reset(heor.x,hero.y);

};


末了在最先游戏的时刻将hero放在canvas最中心即可:


var then = Date.now(); reset(canvas.width / 2,canvas.height / 2); main();

功德圆满!

Hapyy Hacking

    原文作者:JellyBool
    原文地址: https://segmentfault.com/a/1190000002987169
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞