天天看點

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

1.遊戲背景滾動

最終的遊戲示範界面如下:

控制:移動 –  (←↑↓→)箭頭

射擊 – 空格

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 = "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 Drawable
Background.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();
}      
最後的運作效果如下:      

 部落客其他系列博文推薦:

1.網絡采集軟體核心技術剖析系列博文索引

2.手把手教你使用FineUI開發一個b/s結構的取送貨管理資訊系統系列博文索引

上一篇: 指針和引用
下一篇: 指針轉引用

繼續閱讀