Building JavaScript Games for Phones Tablets and Desktop(4)-游戏资源

游戏资源

前面的章节已经教会了如何用一个构造的Game对象来写一个简单的游戏例子。你也发现JavaScript能够获取canvas和canvasContext的值,用来进行canvas的运算。你也知道了如何改变画布背景色。也知道结合系统时间让一个方块在屏幕上进行移动。这章讲解如何在屏幕上绘画图片,这是创造出好看游戏的第一步。在计算机图形学中,这些图形被称做精灵。精灵通常都从文件里进行加载。这意味着任何绘画精灵的程序再也不仅仅只是一个简单的指令,而是须要知道这些游戏资源放在何处。即将讲的几个事情你须要思考下:web

  • 能够从哪里加载精灵?canvas

  • 怎样从一个图像文件里获取信息浏览器

  • 怎样将精灵显示在屏幕上markdown

这章将会回答这些问题。函数

音乐是另外一种类型的游戏资源。它的处理与精灵十分相似。所以,在本章的最末,你会看到如何在你的游戏中播放音乐和音效。oop

定位精灵

在一个程序可使用任何资源前,须要知道在哪里找到这些资源。默认状况下,浏览器会自动在当前文件夹下寻找精灵,和寻找JavaScript文件同样。看这章的SpriteDrawing例子,你会发现一个spr_balloon.png文件和HTML文件和JavaScript文件在一个文件夹下。网站

加载精灵

如今看如何从一个文件里面加载精灵。经过一个变量来加载精灵。你须要在游戏循环里不一样的地方使用这个变量。在start方法里,加载这个精灵而且存放在一个变量里。所以,在Game对象中添加一个 balloonSprite变量。以下所示:rest

var Game = {
 canvas : undefined,
 canvasContext : undefined,
 balloonSprite : undefined
};

能够定义一个对象来包含关于这个精灵的全部信息。以下:code

Game.balloonSprite = {
 src : "spr_balloon.png",
 width : 35,
 height : 63,
 ...
}

若是你想在你的游戏里加载成百上千的精灵时,上述的就有问题了。每次你都必须定义一个相似上面的对象字变量。另外,你并不肯定是否会用到一个对象里面的其余变量。由于一个图片有不一样的表现。幸亏,你能够经过类来避免这些问题。对象

类的基本定义就是一个对象的原型。它是一个对象的抽象。好比,JavaScript知道一个叫作Image的类,这个类定义一个关于图片的对象,对象有宽和高,有源文件地址等等。经过image类能够很是简单的建立一个对象,只须要只要new关键字:

Game.balloonSprite = new Image();

这比在一个对象里写出全部变量的值轻松多了,表达式new Image()作到了这些。经过使用类,你能够轻松的创造对象。并且能够肯定这些对象都有相同的结构。

你还不知道这个变量里面究竟含有什么。你能够给src变量赋值为图片源文件的地址。

Game.balloonSprite.src = "spr_balloon.png";

当src一设置,浏览器就开始加载文件。并且浏览器自动的获取图片的宽和高。

有时候,加载源文件须要一些时间。好比,这个文件存在于世界另外一边的网站上。这意味着若是你想立刻就看到图片是很困难的。所以,你须要确保在游戏启动以前全部图片都加载完毕。这里有一个很是简洁的方式,使用一个事件处理函数。第七章你就会知道它是如何工做的。如今,想象半秒以内就能够加载这个图片。经过使用setTimeout方法,你能够在500ms后加载mainLoop方法。

window.setTimeout(Game.mainLoop, 500);

完成后的start方法以下:

Game.start = function () {
 Game.canvas = document.getElementById("myCanvas");
 Game.canvasContext = Game.canvas.getContext("2d");
 Game.balloonSprite = new Image();
 Game.balloonSprite.src = "spr_balloon.png";
 window.setTimeout(Game.mainLoop, 500);
};

精灵能够从任何地方加载。若是你用JavaScript开发游戏,思考如何组织你的精灵是个好习惯。好比,你能够把你全部的精灵放在一个叫作sprites的文件夹里。那样你就能够像下面这样设置源文件。

Game.balloonSprite.src = "sprites/spr_balloon.png";

也许你不会使用本身的图片,而是来自互联网的图片:

Game.balloonSprite.src = "http://www.somewebsite.com/images/spr_balloon.png";

JavaScript容许你从任何你想的地方加载图片。只是但从互联网上加载图片时,须要确认图片地址是固定不变的。不然,当网站主人在没有告知你的状况下移动掉这些文件,你的游戏将没法运行。

绘画精灵

加载精灵并不意味着精灵就显示到了屏幕上。想要让精灵显示出来,须要在draw方法里面作些事情。为了在画布上画出精灵,你可使用canvasContext对象的一个方法:drawImage。在JavaScript里,当图片须要显示在固定的位置,这个位置的坐标一般是图片的左上角。下面是显示精灵的指令:

Game.canvasContext.drawImage(sprite, 0, 0, sprite.width, sprite.height,
 0, 0, sprite.width, sprite.height);

drawImage方法有不少不一样的参数。好比,你能够指定在何处绘画精灵,或者是否只是精灵的一部分进行显示。你能够简单的调用此方法达到目的。然而,若是你考虑到你之后建立的游戏,你可使用绘画状态来绘画精灵。

绘画状态从根本上来讲就是一组参数,这些参数用于全部绘画之间的转换。使用绘画状态而不是用单一的drawImage方法的好处是你能够对精灵作更复杂的转换。好比,使用绘画状态,你能够翻转或者比例缩放精灵,这在之后的游戏中很是有用。创造一个新的绘画状态是经过调用save方法。

Game.canvasContext.save();

如今你可使用这个绘画状态来进行各类转换。好比,你能够移动精灵到一个肯定位置:

Game.canvasContext.translate(100, 100);

若是你如今调用drawImage方法,精灵会被绘画在(100,100)处。一旦你完成绘画,你能够像下面这样移除绘画状态。

Game.canvasContext.restore();

为了方便,定义一个能够作上述一切的方法:

Game.drawImage = function (sprite, position) {
 Game.canvasContext.save();
 Game.canvasContext.translate(position.x, position.y);
 Game.canvasContext.drawImage(sprite, 0, 0, sprite.width, sprite.height,
 0, 0, sprite.width, sprite.height);
 Game.canvasContext.restore();
};

经过上述参数看出,这个方法须要两个信息,要被绘画的精灵和绘画精灵所在的位置。精灵应该是image类,这个地址是一个含有x和y部分的对象。当你调用这个方法,你须要提供上述这些信息。好比,像下面这样在(100,100)出画一个气球精灵:

Game.drawImage(Game.balloonSprite, { x : 100, y : 100 });

你使用花括号定义了一个含有x和y的对象。正如你看到的那样,容许在调用方法的指令中定义一个对象。固然,你能够开始就定义一个对象,储存在变量里,好比下面这样:

var balloonPos = {
 x : 100,
 y : 100
};
Game.drawImage(Game.balloonSprite, balloonPos);

这段代码和以前的代码是同样的,只是多写了些。你能够把drawImage方法放在draw方法里面,这样气球就会显示在你想要的位置:

Game.draw = function () {
 Game.drawImage(Game.balloonSprite, { x : 100, y : 100 });
};

在浏览器上看到的结果如图4-1

(省略图4-1)

移动精灵

如今你能够在屏幕上显示一个精灵了,你可使用游戏循环来让它移动,就像上章里面让方块移动那样。在这里咱们让气球的位置基于通过的时间来进行移动。为了完成这个,你须要储存气球的位置。须要在update方法计算位置和在draw方法里绘画气球。所以,在Game对象里面添加一个位置变量:

var Game = {
 canvas : undefined,
 canvasContext : undefined,
 balloonSprite : undefined,
 balloonPosition : { x : 0, y : 50 }
};

如上所示,在game对象里面定义了一个含有两个变量的对象。如今你能够在update方法里面添加一条经过通过的时间来改变位置的指令,就像在移动方块例子里面同样。以下:

Game.update = function () {
 var d = new Date();
 Game.balloonPosition.x = d.getTime() % Game.canvas.width;
};

剩下的就是画出气球:

Game.drawImage(Game.balloonSprite, Game.balloonPosition);

加载和绘画多重精灵

建立一个只有白色背景的游戏怎么看都是乏味的。你可让你的游戏经过绘画一个背景精灵来使其更具备可看性。这意味着你须要在start方法里面加载另外一个精灵而且在draw里面进行显示。这个程序的最终版本叫作FlyingSprite。若是你在浏览器里面打开的话,你会看见两个精灵,一个背景图和一个气球。为了实现这个,增长一个含有背景精灵的变量,以下所示:

var Game = {
 canvas : undefined,
 canvasContext : undefined,
 backgroundSprite : undefined,
 balloonSprite : undefined,
 balloonPosition : { x : 0, y : 50 }
};

固然,在draw里面,如今有两个要绘画方法调用:

Game.draw = function () {
Game.drawImage(Game.backgroundSprite, { x : 0, y : 0 });
Game.drawImage(Game.balloonSprite, Game.balloonPosition);
};

这些方法调用的顺序是很是重要的。由于你想气球显示在背景上面。首先就得画出背景,而后画气球。若是你反过来作,背景会覆盖掉气球,你将什么也看不到。图4-2展现了程序的输出结果:

(省略图4-2)

每次你想在屏幕上绘画一个精灵,你就在draw方法里多调用一次drawImage,你能够一个精灵绘画屡次,显示在不一样的位置。好比,你想在背景上画出一些不一样位置的气球,你只须要调用屡次调用drawImage和睦球的位置参数:

Game.draw = function () {
 Game.drawImage(Game.backgroundSprite, { x : 0, y : 0 });
 Game.drawImage(Game.balloonSprite, { x : 0, y : 0 });
 Game.drawImage(Game.balloonSprite, { x : 100, y : 0 });
 Game.drawImage(Game.balloonSprite, { x : 200, y : 0 });
 Game.drawImage(Game.balloonSprite, { x : 0, y : 300 });
 Game.drawImage(Game.balloonSprite, { x : 200, y : 300 });
};

固然,再次注意绘画的顺序。

你能够同时画出多个移动的精灵。对于每个气球,你能够定义一个专属于它的位置变量,以下所示:

Game.update = function () {
 var d = new Date();
 Game.balloonPosition1.x = d.getTime() % Game.canvas.width;
 Game.balloonPosition2.x = (d.getTime() + 100) % Game.canvas.width;
 Game.balloonPosition3.x = (d.getTime() + 200) % Game.canvas.width;
};

在draw方法里,能够用这些变量画出静止的和移动的气球:

Game.draw = function () {
 Game.drawImage(Game.backgroundSprite, Game.balloonPosition1);
 Game.drawImage(Game.balloonSprite, Game.balloonPosition2);
 Game.drawImage(Game.balloonSprite, Game.balloonPosition3);
 Game.drawImage(Game.balloonSprite, { x : 200, y : 0 });
 Game.drawImage(Game.balloonSprite, { x : 0, y : 300 });
 Game.drawImage(Game.balloonSprite, { x : 200, y : 300 });
};

音乐和音效

另外一个常见的游戏资源是音效。不少游戏都有音效和背景音乐。这有不少重要的缘由。音效能够告诉用户某些重要的线索。好比,当用户按下一个键时有一个肯定的点击音效。听见脚步声表示敌人接近了,即便玩家没有看见他们。老游戏迷雾之岛就是一个典型的这类型的游戏,由于里面的不少线索都是经过音效来找到的。

好的音效能给游戏世界带来更好的感觉。它们让环境更真实,即便屏幕上什么都没有发生。

在JavaScript中播放背景音乐或音效是很是简单的。使用音效以前首先须要音效文件。在FlyingSpriteWithSound这个例子里,文件是snd_music.mp3,被当作背景音乐。跟储存精灵同样,须要一个变量来储存音乐数据。以下:

var Game = {
 canvas : undefined,
 canvasContext : undefined,
 backgroundSprite : undefined,
 balloonSprite : undefined,
 balloonPosition : { x : 0, y : 50 },
 backgroundMusic : undefined
};

在start方法里须要加载音效。JavaScript提供了一个能够操做音效的类。类型叫作Audio,建立方法以下:

Game.backgroundMusic = new Audio();
Game.backgroundMusic.src = "snd_music.mp3";

上面看起来就跟加载精灵同样。如今你能够这个对象的方法了,好比下面这样播放音效:

Game.backgroundMusic.play();

也能够像下面这样减小背景音乐的声音:

Game.backgroundMusic.volume = 0.4;

volume变量的值的大小范围是0到1,0表示没有声音,1表示声音最大。

从技术上来讲,背景音乐和音效之间没有什么不一样。通常,背景音乐声音要小点。不少背景音乐在游戏循环里面播放,完了后又从新开始。后面你将看到怎么实现。这本书的全部游戏都用到了声音来让游戏更有趣。

你学到了什么

这章里,你学到了:

  • 如何加载游戏资源好比精灵和音效
  • 如何在屏幕上绘画多个精灵而且移动它们
  • 如何在你的游戏里播放背景音乐和音效
相关文章
相关标签/搜索