html5移动游戏开发高级编程chapter3

触摸事件的属性

Paste_Image.png

js中的utf-8符号编码

Paste_Image.png
Paste_Image.png

检测移动端

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('旋转屏幕');
            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);
        };
}());

前三章总结

游戏流程:

  1. 数据流:
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.文档加载完成,初始化游戏并开始游戏
window.addEventListener("load", function(){Game.initialize("game", sprites, startGame};})

在Game.initialize中完成了画布初始化,移动检测,输入检测,并开始游戏循环逻辑,如果检测为移动设备,则添加触摸检测。加载精灵图。将传入的回调作为加载完成的回调。

3.资源加载完成后,调用回调startGame,绘制星空和标题版块。标题版块中传入回调,其中监听了Game.keys['fire'],即空格按键,当其按下时,调用回调playGame;

4.playGame中调用 了新的对象GameBoard,一个管理着动态游戏对象的类,其中游戏开始时应该出现 的游戏人,和关卡数据。然后将这个对象传入Game中的board进入循环。

5.游戏主体完成,然后就是各个内容的step函数和draw函数随着时间不停的更新和重绘

(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;

//精灵类,load初化图片,draw负责进行绘制
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);
}

//游戏类, initialize,融合canvas属性,setupInput检测输入,loop对Game中的boards组件进行循环运行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('请升级浏览器');}

        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('旋转屏幕');
            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";
    }
}




//星空类,组件式,用一个canvas在作为背景来绘制
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;
        //在发射时检测是否到达冷却时间
        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('你赢了','点击重新游戏', playGame));

}

var loseGame = function () {
    Game.setBoard(3, new TitleScreen("你输了",'点击重新游戏',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("打飞机", "单击开始", playGame))
}

window.addEventListener("load", function(){
    Game.initialize("game", sprites, startGame);
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,051评论 25 707
  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,590评论 0 15
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,945评论 4 60
  • This article is a record of my journey to learn Game Deve...
    蔡子聪阅读 3,716评论 0 9
  • 影视剧那些桥段,好的基本不会发生,坏的倒是会。
    lazeghost阅读 124评论 0 0