• 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

    .游戏背景滚动

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

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

    <!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结构的取送货管理信息系统系列博文索引

  • 相关阅读:
    sql把一个表的某几列的数据存到另一个表里
    java四舍五入保留两位小数4种方法
    SWT 全接触
    详解Java多线程编程中LockSupport
    详解Java多线程编程中LockSupport类的线程阻塞用法
    Java多线程中join方法的理解
    java 线程方法join的简单总结
    彻底理解ThreadLocal
    recyclerView 列表类控件卡顿优化
    Android中RelativeLayout和LinearLayout性能分析
  • 原文地址:https://www.cnblogs.com/ice-river/p/4146182.html
Copyright © 2020-2023  润新知