首页 > 代码库 > Step by Step 使用HTML5开发一个星际大战游戏(1)

Step by Step 使用HTML5开发一个星际大战游戏(1)

本系列博文翻译自以下文章

http://blog.sklambert.com/html5-canvas-game-panning-a-background/

Languages: HTML5, JavaScript

Code: https://github.com/straker/galaxian-canvas-game/tree/master/part1

Part 1

最终的游戏演示界面如下:

控制:移动 –  (↓→)箭头
射击 – 空格

<iframe src="http://blog.sklambert.com/wp-content/uploads/2012/09/space_shooter_part_five.html" width="650" height="410"></iframe>

The HTML5 Page

<!DOCTYPE html><html>    <head>        <title>Space Shooter Demo</title>        <style>            canvas {                position: absolute;                top: 0px;                left: 0px;                background: transparent;            }        </style>    </head>    <body onload="init()">        <!-- The canvas for the panning background -->        <canvas id="background" width="600" height="360">            Your browser does not support canvas. Please try again with a different browser.        </canvas>        <script src="space_shooter_part_one.js"></script>    </body></html>

 

以上代码创建了一个600宽,360高的画布。

基础

创建一个封装全部图像的js对象:

/** * Define an object to hold all our images for the game so images * are only ever created once. This type of object is known as a * singleton. */var imageRepository = new function() {    // Define images    this.background = new Image();    // Set images src    this.background.src = "http://www.mamicode.com/imgs/bg.png";}
 

接下来,我们创建Drawable对象,所有以后的可以运动的物体对象都继承于它,Drawable对象包含一个空的draw方法。

/** * Creates the Drawable object which will be the base class for * all drawable objects in the game. Sets up default variables * that all child objects will inherit, as well as the default * functions. */function Drawable() {    this.init = function(x, y) {        // Default variables        this.x = x;        this.y = y;    }    this.speed = 0;    this.canvasWidth = 0;    this.canvasHeight = 0;    // Define abstract function to be implemented in child objects    this.draw = function() {    };}
接下来我们创建背景Background对象,注意红色部分的代码,红色2句代码是背景移动的核心。
第一句让背景从纵坐标0开始向下移动,第二句让背景从纵坐标(0-画布)高度开始向下移动,这样就产生了背景在不断向下移动的效果。
最后一句蓝色代码是将
Background对象的原形设置为Drawable对象,继承Drawable中的变量和方法。
/** * Creates the Background object which will become a child of * the Drawable object. The background is drawn on the "background" * canvas and creates the illusion of moving by panning the image. */function Background() {    this.speed = 1; // Redefine speed of the background for panning    // Implement abstract function    this.draw = function() {        // Pan background        this.y += this.speed;        this.context.drawImage(imageRepository.background, this.x, this.y);        // Draw another image at the top edge of the first image        this.context.drawImage(imageRepository.background, this.x, this.y - this.canvasHeight);        // If the image scrolled off the screen, reset        if (this.y >= this.canvasHeight)            this.y = 0;    };}// Set Background to inherit properties from DrawableBackground.prototype = new Drawable();
 

最后一步

创建Game对象,Game对象获得web页面中定义的画布,初始化背景对象Background,设置背景对象的context以及画布宽,画布高属性。

/** * Creates the Game object which will hold all objects and data for * the game. */function Game() {    /*     * Gets canvas information and context and sets up all game     * objects.     * Returns true if the canvas is supported and false if it     * is not. This is to stop the animation script from constantly     * running on older browsers.     */    this.init = function() {        // Get the canvas element        this.bgCanvas = document.getElementById(‘background‘);        // Test to see if canvas is supported        if (this.bgCanvas.getContext) {            this.bgContext = this.bgCanvas.getContext(‘2d‘);            // Initialize objects to contain their context and canvas            // information            Background.prototype.context = this.bgContext;            Background.prototype.canvasWidth = this.bgCanvas.width;            Background.prototype.canvasHeight = this.bgCanvas.height;            // Initialize the background object            this.background = new Background();            this.background.init(0,0); // Set draw point to 0,0            return true;        } else {            return false;        }    };    // Start the animation loop    this.start = function() {        animate();    };}

 

以下是动画功能的实现,其中requestAnimFrame类似一个timer,会不定期的回调 animate()函数; animate()函数中调用game.background.draw();不断的重绘背景图片的位置,以实现背景滚动的动画效果。

 
/** * The animation loop. Calls the requestAnimationFrame shim to * optimize the game loop and draws all game objects. This * function must be a gobal function and cannot be within an * object. */function animate() {    requestAnimFrame( animate );    game.background.draw();}/** * requestAnim shim layer by Paul Irish * Finds the first API that works to optimize the animation loop, * otherwise defaults to setTimeout(). */window.requestAnimFrame = (function(){    return  window.requestAnimationFrame   ||            window.webkitRequestAnimationFrame ||            window.mozRequestAnimationFrame    ||            window.oRequestAnimationFrame      ||            window.msRequestAnimationFrame     ||            function(/* function */ callback, /* DOMElement */ element){                window.setTimeout(callback, 1000 / 60);            };})();

 最后启动程序:

/** * Initialize the Game and starts it. */var game = new Game();function init() {    if(game.init())        game.start();}
最后的运行效果如下:

<iframe src="http://blog.sklambert.com/wp-content/uploads/2012/09/space_shooter_part_one.html" width="650" height="400"></iframe>

 

Step by Step 使用HTML5开发一个星际大战游戏(1)