html5移動(dòng)游戲開(kāi)發(fā)高級(jí)編程chapter3

觸摸事件的屬性

Paste_Image.png

js中的utf-8符號(hào)編碼

Paste_Image.png
Paste_Image.png

檢測(cè)移動(dòng)端

Paste_Image.png
Paste_Image.png
this.setupMobile = function () {
        var container = document.getElementById("container"), hasTouch = !!('ontouchstart' in window), w = window.innerWidth , h = window.innerHeight;
        if (hasTouch) {Game.mobile = true;}
        if (screen.width >= 1280 || !hasTouch) {return false}
        if (w > h) {
            alert('旋轉(zhuǎn)屏幕');
            w = window.innerWidth; h = window.innerHeight;
        }

        container.style.height = h * 2 +"px";
        window.scrollTo(0, 1);
        h = window.innerHeight + 2;
        container.style.height = h + 'px';
        container.style.width = w + 'px';
        container.style.padding = 0;
        if (h >= this.canvas.height * 1.75 || w >= this.canvas.height * 1.75) {
            this.canvasMultiplier = 2;
            this.canvas.width = w / 2;
            this.canvas.height = h / 2;
            this.canvas.style.width = w + "px";
            this.canvas.style.height = h + "px";
        } else {
            this.canvas.width = w;
            this.canvas.height = h;
        }
        this.canvas.style.position = 'absolute';
        this.canvas.style.left = "0px";
        this.canvas.style.top = "0px";
    }

GamePoints

var GamePoints = function () {
    Game.points = 0;
    var pointsLength = 8;
    this.draw = function (ctx) {
        ctx.save();
        ctx.font = "bold 18px arial";
        ctx.fillStyle = "#fff";
        var txt = "" + Game.points;
        var i = pointsLength - txt.length, zeros = "";
        while (i-- >0) {zeros += "0"}
        ctx.fillText(zeros + txt, 10, 20);
        ctx.restore();
    };

    this.step = function (dt) {}
}

TouchControls

var TouchControls = function () {
    var gutterWidth = 10;
    var unitWidth = Game.width/5;
    var blockWidth = unitWidth - gutterWidth;

    this.drawSquare = function (ctx, x, y, txt, on) {
        ctx.globalAlpha = on ? 0.9 : 0.6;
        ctx.fillStyle = "#ccc";
        ctx.fillRect(x, y, blockWidth, blockWidth);

        ctx.fillStyle = "#fff";
        ctx.textAlign = "center";
        ctx.globalAlpha = 1.0;
        ctx.font = "bold" + (3 * unitWidth/4) + "px arial";

        ctx.fillText(txt, x + blockWidth / 2, y + 3* blockWidth/4 + 5);
    }

    this.draw = function (ctx) {
        ctx.save();
        var yLoc = Game.canvas.height - unitWidth;
        this.drawSquare(ctx, gutterWidth, yLoc, "\u25c0", Game.keys['left']);
        this.drawSquare(ctx, unitWidth + gutterWidth, yLoc, "\u25b6", Game.keys['right']);
        this.drawSquare(ctx, Game.canvas.width - gutterWidth - unitWidth, yLoc, "A", Game.keys['fire']);
        ctx.restore();
    };

    this.step = function(dt) {};

    this.trackTouch = function (e) {
        console.log('fuck')
        var touch, x;
        e.preventDefault();
        Game.keys['left'] = false;
        Game.keys['right'] = false;
        for (var i = 0; i< e.targetTouches.length; i++) {

            touch = e.targetTouches[i];
            //console.log(Game.canvasMultiplier)
            x = touch.pageX / Game.canvasMultiplier - Game.canvas.offsetLeft;
            
            if (x < unitWidth) {
    
                Game.keys['left'] = true;
            }
            if (x > unitWidth && x  < 2 * unitWidth) {
                Game.keys['right'] = true;
            }
        }
        //console.log(e.type)
        if (e.type == 'touchstart') {
            for (var i = 0; i < e.changedTouches.length; i++) {
                touch = e.changedTouches[i];
                x = touch.pageX / Game.canvasMultiplier - Game.canvas.offsetLeft;
                if (x > 4 * unitWidth) {
                    Game.keys['fire'] = true;
                }
            }
        }
    };
    Game.canvas.addEventListener('touchstart', this.trackTouch, false);
    Game.canvas.addEventListener('touchmove', this.trackTouch, false);
    Game.canvas.addEventListener('touchend', this.trackTouch, false);
    Game.canvas.addEventListener('touchcancel', this.trackTouch, false);
    Game.playerOffset = unitWidth + 20;
    //console.log(unitWidth,Game.playerOffset)
}

EnemyMissile

var EnemyMissile = function (x, y) {
    this.setup('enemy_missile', {vy: 200, damage: 10});
    this.x = x - this.w / 2;
    this.y = y;
}

EnemyMissile.prototype = new Sprite();
EnemyMissile.prototype.step = function (dt) {
    this.y += this.vy * dt;
    var collision = this.board.collide(this, OBJECT_PLAYER);
    if (collision) {
        collision.hit(this.damage);
        this.board.remove(this);
    } else if (this.y > Game.height) {
        this.board.remove(this);
    }
};

requestAnimationFrame兼容處理

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = 
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

前三章總結(jié)

游戲流程:

  1. 數(shù)據(jù)流:
var sprites = {
    ship: {sx: 0, sy: 0, w: 37, h: 42, frames: 1},
    missile : {sx: 0, sy: 30, w: 2, h: 10, frames: 1},
    enemy_purple : {sx: 37, sy: 0, w:42, h: 43, frames: 1},
    enemy_bee: {sx: 79, sy: 0, w: 37, h: 43, frames: 1},
    enemy_ship: {sx: 116, sy: 0, w: 42, h: 43, frames: 1},
    enemy_circle: {sx: 158, sy:0, w: 32, h: 33, frames: 1},
    explosion: {sx: 0, sy: 64, w: 64, h: 64, frames: 12},
    enemy_missile :{sx: 9, sy: 42, w:3, h: 20, frame: 1}
};
var level1 = [
    [0, 4000, 500, 'step'],
    [6000, 13000, 800, 'ltr'],
    [12000, 16000,400, 'circle'],
    [18200, 20000, 500, 'straight', {x: 150}],
    [18200, 20000, 500, 'straight', {x: 100}],
    [18400, 20000, 500, 'straight', {x: 200}],
    [22000, 25000, 400, 'wiggle', {x: 300}],
    [22000, 25000, 400, 'wiggle', {x: 200}],

]
var enemies = {
  straight: { x: 0,   y: -50, sprite: 'enemy_ship', health: 10, 
              E: 100,firePercentage: 0.001 },
  ltr:      { x: 0,   y: -100, sprite: 'enemy_purple', health: 10, 
              B: 75, C: 1, E: 100 ,missile:2 },
  circle:   { x: 250,   y: -50, sprite: 'enemy_circle', health: 10, 
              A: 0,  B: -100, C: 1, E: 20, F: 100, G: 1, H: Math.PI/2 },
  wiggle:   { x: 100, y: -50, sprite: 'enemy_bee', health: 20, 
              B: 50, C: 4, E: 100, firePercentage: 0.001, missile: 2 },
  step:     { x: 0,   y: -50, sprite: 'enemy_circle', health: 10,
              B: 150, C: 1.2, E: 75 }
};

2.文檔加載完成,初始化游戲并開(kāi)始游戲
window.addEventListener("load", function(){Game.initialize("game", sprites, startGame};})

在Game.initialize中完成了畫(huà)布初始化,移動(dòng)檢測(cè),輸入檢測(cè),并開(kāi)始游戲循環(huán)邏輯,如果檢測(cè)為移動(dòng)設(shè)備,則添加觸摸檢測(cè)。加載精靈圖。將傳入的回調(diào)作為加載完成的回調(diào)。

3.資源加載完成后,調(diào)用回調(diào)startGame,繪制星空和標(biāo)題版塊。標(biāo)題版塊中傳入回調(diào),其中監(jiān)聽(tīng)了Game.keys['fire'],即空格按鍵,當(dāng)其按下時(shí),調(diào)用回調(diào)playGame;

4.playGame中調(diào)用 了新的對(duì)象GameBoard,一個(gè)管理著動(dòng)態(tài)游戲?qū)ο蟮念?lèi),其中游戲開(kāi)始時(shí)應(yīng)該出現(xiàn) 的游戲人,和關(guān)卡數(shù)據(jù)。然后將這個(gè)對(duì)象傳入Game中的board進(jìn)入循環(huán)。

5.游戲主體完成,然后就是各個(gè)內(nèi)容的step函數(shù)和draw函數(shù)隨著時(shí)間不停的更新和重繪

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = 
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());
  
var OBJECT_PLAYER = 1,
    OBJECT_PLAYER_PROJECTILE = 2,
    OBJECT_ENEMY = 4,
    OBJECT_ENEMY_PROJECTILE = 8,
    OBJECT_POWERUP = 16;

//精靈類(lèi),load初化圖片,draw負(fù)責(zé)進(jìn)行繪制
var SpriteSheet = new function() {
    this.map = {};
    this.load = function(spriteData, callback) {
        this.map = spriteData;
        this.image = new Image();
        this.image.onload = callback;
        this.image.src = 'sprites.png';
    };
    this.draw = function(ctx, sprite, x, y, frame) {
        var s = this.map[sprite];
        if (!frame) frame = 0;
        ctx.drawImage(this.image, s.sx + frame * s.w, s.sy, s.w, s.h, x, y, s.w, s.h);
    }
}

var Sprite = function () {}
Sprite.prototype.setup = function (sprite, props) {
    this.sprite = sprite;
    this.merge(props);
    this.frame = this.frame || 0;
    this.w = SpriteSheet.map[sprite].w;
    this.h = SpriteSheet.map[sprite].h;
}

Sprite.prototype.merge = function (props) {
    if (props) {
        for (var prop in props) {
            this[prop] = props[prop];
        }
    }
}

Sprite.prototype.hit = function() {
    this.board.remove(this);
}

Sprite.prototype.draw = function (ctx) {
    SpriteSheet.draw(ctx, this.sprite, this.x, this.y, this.frame);
}

//游戲類(lèi), initialize,融合canvas屬性,setupInput檢測(cè)輸入,loop對(duì)Game中的boards組件進(jìn)行循環(huán)運(yùn)行step和draw方法
var Game = new function() {
    this.initialize = function(canvasElementId, sprite_data, callback) {
        this.canvas = document.getElementById(canvasElementId);
        this.canvasMultiplier = 1;
        this.playerOffset = 0;
        this.setupMobile();
        this.width =this.canvas.width;
        this.height = this.canvas.height;
        this.ctx = this.canvas.getContext && this.canvas.getContext('2d');
        if (!this.ctx) {return alert('請(qǐng)升級(jí)瀏覽器');}

        this.setupInput();

        this.loop();
        if (this.mobile) {
            this.setBoard(4, new TouchControls());
        }
        SpriteSheet.load(sprite_data, callback);
    }   
    var KEY_CODES = {37:'left', 39:'right', 32:'fire'};
    this.keys = {};
    this.setupInput = function(){
        window.addEventListener('keydown', function(e){
            if (KEY_CODES[e.keyCode]) {
                Game.keys[KEY_CODES[e.keyCode]] = true;
                e.preventDefault();
            }
        },false);
        window.addEventListener('keyup', function(e){
            if (KEY_CODES[e.keyCode]) {
                Game.keys[KEY_CODES[e.keyCode]] = false;
                e.preventDefault();
            }
        },false); 
    };
    var boards = [];
    // this.loop = function(){
    //  console.log(boards)
    //  var dt = 16/1000;
    //  for (var i = 0;i < boards.length; i ++) {
    //      if (boards[i]) {
    //          boards[i].step(dt);
    //          boards[i] && boards[i].draw(Game.ctx);
    //      }
    //  }
    //  setTimeout(Game.loop, 30);
    // };
    var lastTime = new Date().getTime();
    var maxTime = 1/30;
      this.loop = function() { 
        var curTime = new Date().getTime();
        requestAnimationFrame(Game.loop);
        var dt = (curTime - lastTime)/1000;
        if(dt > maxTime) { dt = maxTime; }

        for(var i=0,len = boards.length;i<len;i++) {
          if(boards[i]) { 
            boards[i].step(dt);
            boards[i].draw(Game.ctx);
          }
        }
        lastTime = curTime;
      };

    this.setBoard = function(num, board) {
        boards[num] = board;
        console.log(boards)
    }

    this.setupMobile = function () {
        var container = document.getElementById("container"), hasTouch = !!('ontouchstart' in window), w = window.innerWidth , h = window.innerHeight;
        if (hasTouch) {Game.mobile = true;}
        if (screen.width >= 1280 || !hasTouch) {return false}
        if (w > h) {
            alert('旋轉(zhuǎn)屏幕');
            w = window.innerWidth; h = window.innerHeight;
        }

        container.style.height = h * 2 +"px";
        window.scrollTo(0, 1);
        h = window.innerHeight + 2;
        container.style.height = h + 'px';
        container.style.width = w + 'px';
        container.style.padding = 0;
        if (h >= this.canvas.height * 1.75 || w >= this.canvas.height * 1.75) {
            this.canvasMultiplier = 2;
            this.canvas.width = w / 2;
            this.canvas.height = h / 2;
            this.canvas.style.width = w + "px";
            this.canvas.style.height = h + "px";
        } else {
            this.canvas.width = w;
            this.canvas.height = h;
        }
        this.canvas.style.position = 'absolute';
        this.canvas.style.left = "0px";
        this.canvas.style.top = "0px";
    }
}




//星空類(lèi),組件式,用一個(gè)canvas在作為背景來(lái)繪制
var Starfield = function(speed, opacity, numStarts, clear){
    var stars = document.createElement("canvas");
    stars.width = Game.canvas.width;
    stars.height = Game.canvas.height;
    var starCtx = stars.getContext('2d');
    var offset = 0;
    //繪制黑色背景
    if (clear) {
        starCtx.fillStyle = "#000";
        starCtx.fillRect(0,0, stars.width, stars.height);
    }

    starCtx.fillStyle = "#FFF";
    starCtx.globalAlpha = opacity;

    for (var i = 0; i < numStarts; i ++) {
        starCtx.fillRect(Math.floor(Math.random()*stars.width), Math.floor(Math.random()*stars.height), 2, 2);
    }

    this.draw = function(ctx){
        var intOffset = Math.floor(offset);
        var remaining = stars.height - intOffset;
        if (intOffset > 0) {
            ctx.drawImage(stars,0, remaining, stars.width, intOffset, 0, 0, stars.width, intOffset);
        }
        if (remaining > 0 ) {
            ctx.drawImage(stars, 0, 0, stars.width, remaining, 0, intOffset, stars.width, remaining);
        }
    }
    //console.log(offset)
    this.step = function(dt) {
        offset += dt * speed;
        //console.log(dt)
        offset = offset % stars.height;
    }
}


var PlayerShip = function() {
    this.setup('ship', {vx: 0, frame: 0, reloadTime: 0.25, maxVel: 200});
    // this.w = SpriteSheet.map['ship'].w;
    // this.h = SpriteSheet.map['ship'].h;
    this.x = Game.canvas.width / 2 - this.w / 2;
    this.y = Game.canvas.height - Game.playerOffset - 10 - this.h;
    // this.vx = 0;
    //重裝彈間隔
    // this.reloadTime = 0.1;
    this.reload = this.reloadTime;
    // this.maxVel = 200;
    this.step = function(dt) {
        if (Game.keys['left']) {this.vx = -this.maxVel; }
        else if (Game.keys['right']) {this.vx = this.maxVel;}
        else { this.vx = 0;}

        this.x += this.vx * dt;
        if (this.x < 0) {this.x = 0;}
        else if (this.x > Game.width - this.w) {
            this.x = Game.width - this.w;
        }
        this.reload -= dt;
        //在發(fā)射時(shí)檢測(cè)是否到達(dá)冷卻時(shí)間
        if (Game.keys['fire'] && this.reload < 0) {
            Game.keys['fire'] = false;
            this.reload = this.reloadTime;
            this.board.add(new PlayerMissile(this.x, this.y + this.h / 2));
            this.board.add(new PlayerMissile(this.x + this.w, this.y + this.h / 2));
        }
    }
    // this.draw = function(ctx) {
    //  SpriteSheet.draw(ctx, 'ship', this.x, this.y, 0);
    // }
}

PlayerShip.prototype = new Sprite();
PlayerShip.prototype.type = OBJECT_PLAYER;
PlayerShip.prototype.hit = function() {
    this.board.remove(this);
    this.board.add(new Explosion(this.x +this.w/2 , this.y + this.h/2,loseGame))
;}

//object[],cnt[],removed[]
var GameBoard = function() {
    var board = this;
    this.objects = [];
    this.cnt = [];

    this.add = function(obj){
        obj.board = this;
        this.objects.push(obj);
        this.cnt[obj.type] = (this.cnt[obj.type] || 0) + 1;
        return obj;
    };
    this.remove = function(obj) {
        var wasStillAlive = this.removed.indexOf(obj) == -1;
        //console.log(wasStillAlive)
        if (wasStillAlive) {
            this.removed.push(obj);
        }
        return wasStillAlive;
    }

 
    this.iterate = function(funcName){
        var args = Array.prototype.slice.call(arguments, 1);
        for (var i = 0, len = this.objects.length; i < len; i++) {
            var obj = this.objects[i];
            obj[funcName].apply(obj, args);
        }
    };

    this.detect = function(func){
        for (var i= 0, val = null, len = this.objects.length; i < len; i ++) {
            if (func.call(this.objects[i])) return this.objects[i];
        }
        return false;
    }

    this.step = function(dt) {
        //console.log('sdf')
        this.resetRemoved();
        this.iterate('step', dt);
        this.finalizeRemoved();
    }

    this.draw = function(ctx) {
        this.iterate('draw', ctx);
    }

    this.overlap = function(o1, o2) {
        return !((o1.y + o1.h -1 < o2.y) || (o1.y > o2.y + o2.h - 1) || (o1.x + o1.w -1 < o2.x) || (o1.x > o2.x + o2.w -1));
    }

    this.collide = function(obj, type) {
        return this.detect(function(){
            if (obj != this) {
                var col = (!type || this.type & type) && board.overlap(obj, this)
                return col ? this : false;
            }
        });
    };

    this.resetRemoved = function(){this.removed = [];}

    this.finalizeRemoved = function () {

        for (var i = 0, len = this.removed.length; i < len; i ++) {
            var idx = this.objects.indexOf(this.removed[i]);
            if (idx != -1) {
                this.cnt[this.removed[i].type]--;
                this.objects.splice(idx, 1);
            }
        }
    }
}


var PlayerMissile = function(x, y) {
    this.setup('missile', {vy: -700, damage: 10})
    // this.w = SpriteSheet.map['missile'].w;
    // this.h = SpriteSheet.map['missile'].h;
    this.x = x - this.w / 2;
    this.y = y -this.h;
    // this.vy = -700;
};

PlayerMissile.prototype = new Sprite();
PlayerMissile.prototype.type = OBJECT_ENEMY_PROJECTILE;

PlayerMissile.prototype.step = function(dt) {
    this.y += this.vy * dt;
    var collision = this.board.collide(this, OBJECT_ENEMY);
    if (collision) {
        collision.hit(this.damage);
        this.board.remove(this);
    } else if (this.y < -this.h) {
        this.board.remove(this);
    }
    if (this.y < - this.h) {
        this.board.remove(this);
    }
};




var TitleScreen = function (title, subtitle, callback) {
    this.step = function (dt) {
        if (Game.keys['fire'] && callback) callback();
    };

    this.draw = function (ctx) {
        ctx.fillStyle =  "#fff";
        ctx.textAlign = "center"
        ctx.font = "bold 40px bangers";
        ctx.fillText(title, Game.width/2, Game.height/2);
        ctx.font = "bold 20px bangers";
        ctx.fillText(subtitle, Game.width/2, Game.height/2 + 40);
    }
}

var Enemy = function (blueprint, override) {
    this.merge(this.baseParameters);
    this.setup(blueprint.sprite, blueprint);
    this.merge(override);

    var baseParameters = {A: 0, B: 0, C: 0, D: 0, E: 0, F: 0, G: 0, H: 0};
    // for (var prop in baseParameters) {
    //  this[prop] = baseParameters[prop];
    // }

    // for (var prop in blueprint) {
    //  this[prop] = blueprint[prop];
    // }

    // if (override) {
    //  for (prop in override) {
    //      this[prop] = override[prop];
    //  }
    // }
    // console.log(this.sprite)
    // this.w = SpriteSheet.map[this.sprite].w;
    // this.h = SpriteSheet.map[this.sprite].h;
    // this.t = 0;
} 

Enemy.prototype = new Sprite();
Enemy.prototype.type = OBJECT_ENEMY;
Enemy.prototype.baseParameters = {A: 0, B: 0, C: 0, D: 0, E: 0, F: 0, G: 0, H: 0, t: 0,firePercentage: 0.01, reloadTime: 0.75, reload: 0};

Enemy.prototype.step = function (dt) {
    this.t += dt;
    this.vx = this.A + this.B * Math.sin(this.C * this.t + this.D);
    this.vy = this.E + this.F * Math.sin(this.G * this.t + this.H);
    this.x += this.vx * dt;
    this.y += this.vy * dt;
    var collision = this.board.collide(this, OBJECT_PLAYER);
    if (collision) {
        collision.hit(this.damage);
        this.hit(10);
    }

    if (this.reload <= 0 && Math.random() < this.firePercentage) {
        this.reload = this.reloadTime;
        if (this.missiles == 2) {
            this.board.add(new EnemyMissile(this.x + this.w/2, this.y + this.h/2))
        }else{
            this.board.add(new EnemyMissile(this.x + this.w/2, this.y + this.h));
        };
    }
    this.reload -= dt;

    if (this.y > Game.canvas.height || this.x < -this.w || this.x > Game.canvas.width) {
        this.board.remove(this);
    }
}

Enemy.prototype.hit = function(damage) {
    this.health -= damage;
    if (this.health <= 0) {
        if (this.board.remove(this)) {
            Game.points += this.points || 100;
            this.board.add(new Explosion(this.x + this.w/2, this.y +this.h/2));
        }
    }
}

// Enemy.prototype.draw = function (ctx) {
//  SpriteSheet.draw(ctx, this.sprite, this.x, this.y);
// }


var Explosion = function (centerX, centerY, callback) {
    this.setup('explosion', {frame: 0});
    this.x = centerX - this.w / 2;
    this.y = centerY - this.h / 2;
    this.subFrame = 0;
    this.callback = callback;
}

Explosion.prototype = new Sprite();

Explosion.prototype.step = function (dt) {
    this.frame = Math.floor((this.subFrame++) / 3);
    if (this.subFrame >= 36) {
        this.board.remove(this);
        if (this.callback) this.callback();
    }
}

var Level = function (levelData, callback) {
    this.levelData = [];
    for (var i = 0; i < levelData.length; i ++) {
        this.levelData.push(Object.create(levelData[i]));
    }
    this.t = 0;
    this.callback = callback;
}

Level.prototype.step = function (dt) {
    //console.log(this.levelData)
    var idx = 0, remove = [], curShip = null;
    this.t += dt * 1000;
    while ((curShip = this.levelData[idx]) && (curShip[0] < this.t + 2000)) {
        if (this.t > curShip[1]) {
            remove.push(curShip);
        } else if (curShip[0] < this.t) {
            var enemy = enemies[curShip[3]], override = curShip[4];
            this.board.add(new Enemy(enemy, override));
            curShip[0] += curShip[2];
        }
        //console.log(curShip)
        idx++;

    }
    for (var i = 0,len = remove.length; i< len; i++) {
        var idx = this.levelData.indexOf(remove[i]);
        if (idx != -1) this.levelData.splice(idx,1);
    }
    if (this.levelData.length === 0 && this.board.cnt[OBJECT_ENEMY] === 0) {
        if (this.callback) this.callback();
    }
}

Level.prototype.draw = function(ctx) {}


var GamePoints = function () {
    Game.points = 0;
    var pointsLength = 8;
    this.draw = function (ctx) {
        ctx.save();
        ctx.font = "bold 18px arial";
        ctx.fillStyle = "#fff";
        var txt = "" + Game.points;
        var i = pointsLength - txt.length, zeros = "";
        while (i-- >0) {zeros += "0"}
        ctx.fillText(zeros + txt, 10, 20);
        ctx.restore();
    };

    this.step = function (dt) {}
}

var TouchControls = function () {
    var gutterWidth = 10;
    var unitWidth = Game.width/5;
    var blockWidth = unitWidth - gutterWidth;

    this.drawSquare = function (ctx, x, y, txt, on) {
        ctx.globalAlpha = on ? 0.9 : 0.6;
        ctx.fillStyle = "#ccc";
        ctx.fillRect(x, y, blockWidth, blockWidth);

        ctx.fillStyle = "#fff";
        ctx.textAlign = "center";
        ctx.globalAlpha = 1.0;
        ctx.font = "bold" + (3 * unitWidth/4) + "px arial";

        ctx.fillText(txt, x + blockWidth / 2, y + 3* blockWidth/4 + 5);
    }

    this.draw = function (ctx) {
        ctx.save();
        var yLoc = Game.canvas.height - unitWidth;
        this.drawSquare(ctx, gutterWidth, yLoc, "\u25c0", Game.keys['left']);
        this.drawSquare(ctx, unitWidth + gutterWidth, yLoc, "\u25b6", Game.keys['right']);
        this.drawSquare(ctx, Game.canvas.width - gutterWidth - unitWidth, yLoc, "A", Game.keys['fire']);
        ctx.restore();
    };

    this.step = function(dt) {};

    this.trackTouch = function (e) {
        console.log('fuck')
        var touch, x;
        e.preventDefault();
        Game.keys['left'] = false;
        Game.keys['right'] = false;
        for (var i = 0; i< e.targetTouches.length; i++) {

            touch = e.targetTouches[i];
            //console.log(Game.canvasMultiplier)
            x = touch.pageX / Game.canvasMultiplier - Game.canvas.offsetLeft;
            
            if (x < unitWidth) {
    
                Game.keys['left'] = true;
            }
            if (x > unitWidth && x  < 2 * unitWidth) {
                Game.keys['right'] = true;
            }
        }
        //console.log(e.type)
        if (e.type == 'touchstart') {
            for (var i = 0; i < e.changedTouches.length; i++) {
                touch = e.changedTouches[i];
                x = touch.pageX / Game.canvasMultiplier - Game.canvas.offsetLeft;
                if (x > 4 * unitWidth) {
                    Game.keys['fire'] = true;
                }
            }
        }
    };
    Game.canvas.addEventListener('touchstart', this.trackTouch, false);
    Game.canvas.addEventListener('touchmove', this.trackTouch, false);
    Game.canvas.addEventListener('touchend', this.trackTouch, false);
    Game.canvas.addEventListener('touchcancel', this.trackTouch, false);
    Game.playerOffset = unitWidth + 20;
    //console.log(unitWidth,Game.playerOffset)
}

var EnemyMissile = function (x, y) {
    this.setup('enemy_missile', {vy: 200, damage: 10});
    this.x = x - this.w / 2;
    this.y = y;
}

EnemyMissile.prototype = new Sprite();
EnemyMissile.prototype.step = function (dt) {
    this.y += this.vy * dt;
    var collision = this.board.collide(this, OBJECT_PLAYER);
    if (collision) {
        collision.hit(this.damage);
        this.board.remove(this);
    } else if (this.y > Game.height) {
        this.board.remove(this);
    }
};


var sprites = {
    ship: {sx: 0, sy: 0, w: 37, h: 42, frames: 1},
    missile : {sx: 0, sy: 30, w: 2, h: 10, frames: 1},
    enemy_purple : {sx: 37, sy: 0, w:42, h: 43, frames: 1},
    enemy_bee: {sx: 79, sy: 0, w: 37, h: 43, frames: 1},
    enemy_ship: {sx: 116, sy: 0, w: 42, h: 43, frames: 1},
    enemy_circle: {sx: 158, sy:0, w: 32, h: 33, frames: 1},
    explosion: {sx: 0, sy: 64, w: 64, h: 64, frames: 12},
    enemy_missile :{sx: 9, sy: 42, w:3, h: 20, frame: 1}
};
var level1 = [
    [0, 4000, 500, 'step'],
    [6000, 13000, 800, 'ltr'],
    [12000, 16000,400, 'circle'],
    [18200, 20000, 500, 'straight', {x: 150}],
    [18200, 20000, 500, 'straight', {x: 100}],
    [18400, 20000, 500, 'straight', {x: 200}],
    [22000, 25000, 400, 'wiggle', {x: 300}],
    [22000, 25000, 400, 'wiggle', {x: 200}],

]

var playGame = function () {
    //Game.setBoard(3, new PlayerShip());

    var board = new GameBoard();
    board.add(new PlayerShip());
    //board.add(new Player)
    board.add(new Level(level1, winGame));
    // board.add(new Enemy(ememies.basic));
    // board.add(new Enemy(ememies.basic, {x: 200}));
    Game.setBoard(5, new GamePoints(0));

    Game.setBoard(3, board);
}

var winGame = function() {
    Game.setBoard(3, new TitleScreen('你贏了','點(diǎn)擊重新游戲', playGame));

}

var loseGame = function () {
    Game.setBoard(3, new TitleScreen("你輸了",'點(diǎn)擊重新游戲',playGame))
}

// var ememies = {basic: {x:100, y: -50, sprite: 'enemy_purple',B: 100, C: 2, E: 100, health: 20}};

// var enemies = {
//  straight: {x: 0, y: -50, sprite: 'enemy_ship', health: 10, E: 100},
//  'ltr': {x: 0, y: -100, sprite: 'enemy_purple', health: 10, B: 200, C: 1, E: 200},
//  circle: {x: 400, y:-50, sprite: 'enemy_circle', health: 10, A: 0, B: -200, C: 1, E: 20, F: 200, G: 1, H: Math.PI/2},
//  wiggle: {x: 0, y: -50, sprite: 'enemy_bee', health: 20, B: 100, C: 4, E :100},
//  step: {x: 0, y:-50, sprite: 'enemy_circle', health: 10, B:300, C: 1.5, E: 60}
// }
var enemies = {
  straight: { x: 0,   y: -50, sprite: 'enemy_ship', health: 10, 
              E: 100,firePercentage: 0.001 },
  ltr:      { x: 0,   y: -100, sprite: 'enemy_purple', health: 10, 
              B: 75, C: 1, E: 100 ,missile:2 },
  circle:   { x: 250,   y: -50, sprite: 'enemy_circle', health: 10, 
              A: 0,  B: -100, C: 1, E: 20, F: 100, G: 1, H: Math.PI/2 },
  wiggle:   { x: 100, y: -50, sprite: 'enemy_bee', health: 20, 
              B: 50, C: 4, E: 100, firePercentage: 0.001, missile: 2 },
  step:     { x: 0,   y: -50, sprite: 'enemy_circle', health: 10,
              B: 150, C: 1.2, E: 75 }
};



var startGame = function() {
    //SpriteSheet.draw(Game.ctx, "ship", 100, 100, 0);
    Game.setBoard(0, new Starfield(20, 0.4, 100, true));
    Game.setBoard(1, new Starfield(50, 0.6, 100));
    Game.setBoard(2, new Starfield(100, 1, 50));
    Game.setBoard(3, new TitleScreen("打飛機(jī)", "單擊開(kāi)始", playGame))
}

window.addEventListener("load", function(){
    Game.initialize("game", sprites, startGame);
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,905評(píng)論 25 709
  • 點(diǎn)擊查看原文 Web SDK 開(kāi)發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 14,299評(píng)論 0 15
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,167評(píng)論 4 61
  • This article is a record of my journey to learn Game Deve...
    蔡子聰閱讀 4,100評(píng)論 0 9
  • 影視劇那些橋段,好的基本不會(huì)發(fā)生,壞的倒是會(huì)。
    lazeghost閱讀 144評(píng)論 0 0

友情鏈接更多精彩內(nèi)容