【JavaScript】基于canvas的小游戏

之前在写的打小怪兽游戏总算初步完工了,上代码喽~

//显示元素
var score = document.querySelectorAll(".score");
// 画布元素
var container = document.getElementById('game');
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
//游戏元素图片
var plane_img = new Image();
plane_img.src = "img/plane.png";
var enemy_img = new Image();
enemy_img.src = "img/enemy.png"
var boom_img = new Image();
boom_img.src = "img/boom.png"
// 背景音乐
var audio_menu = document.getElementById('menu');
var audio_play = document.getElementById('play');
/**
 * @description 飞机对象
 * @constructor
 * @param {number} x 表示飞机在画布上的期望横坐标
 * @param {string} direction 表示飞机的移动方向
 * @param {boolean} shoot 表示飞机是否正在射击
 */
function Plane(x) {
    this.x = x;
    this.direction = "stop";
    this.shoot_status = false;
};
Plane.prototype.moveLeft = function () {
    this.direction = "left";
};
Plane.prototype.moveRight = function () {
    this.direction = "right";
};
Plane.prototype.stop = function () {
    this.direction = "stop";
}
Plane.prototype.shoot = function () {
    Game.bullets.push(new Bullet(this.x + 30, 475));

};
/**
 * @description 子弹对象
 * @constructor
 * @param {number} x 表示子弹在画布上的横坐标
 * @param {number} y 表示子弹在画布上的纵坐标
 */
function Bullet(x, y) {
    this.x = x;
    this.y = y;
}
Bullet.prototype.fly = function () {
    this.y -= 10;
};
/** 
 * @description 怪兽对象
 * @constructor
 * @param {number} x 表示怪兽在画布上的横坐标
 * @param {number} y 表示怪兽在画布上的纵坐标
 * @param {string} direction 表示怪兽的移动方向,该属性由所有怪兽共享
 * alive 表示怪兽存活
 * boom 表示命中
 * die 表示死亡
 */
function Enemy(x, y) {
    this.x = x;
    this.y = y;
    this.status = "alive";
};
Enemy.prototype.direction = "right";
Enemy.prototype.move = function () {
    if (this.direction == "right") {
        this.x += 2;
    } else {
        this.x -= 2;
    }
};
Enemy.prototype.boom = function () {
    this.status = "boom";
    var self = this;
    var interval = setInterval(function () {
        self.status = "die";
        clearInterval(interval);
    }, 100);
};
/**
 * 整个游戏对象
 */
var GameWindow = {
    /**
     * 初始化函数,这个函数只执行一次
     */
    init: function () {
        var self = this;
        var playBtn = document.querySelector('.js-play');
        var replayBtn = document.querySelectorAll('.js-replay');
        this.status = 'start';
        // 开始游戏按钮绑定
        playBtn.onclick = function () {
            self.play();
        };
        replayBtn[0].onclick = function () {
            self.play();
        };
        replayBtn[1].onclick = function () {
            self.play();
        };
    },
    /**
     * 更新游戏状态,分别有以下几种状态:
     * start  游戏前
     * playing 游戏中
     * failed 游戏失败
     * success 游戏成功
     */
    setStatus: function (status) {
        this.status = status;
        container.setAttribute("game-status", status);
    },
    play: function () {
        Game.init();
        audio_menu.pause();
        this.setStatus('playing');
        Game.animate();
        audio_play.currentTime = 0;
        audio_play.play();
    },
    fail: function () {
        audio_play.pause();
        audio_menu.currentTime = 0;
        audio_menu.play();
        score[1].innerHTML = Game.score;
        context.clearRect(0, 0, canvas.width, canvas.height);
        GameWindow.setStatus("failed");
    },
    success: function () {
        audio_play.pause();
        audio_menu.currentTime = 0;
        audio_menu.play();
        context.clearRect(0, 0, canvas.width, canvas.height);
        score[2].innerHTML = Game.score;
        GameWindow.setStatus("success");
    },
};
// 初始化
GameWindow.init();
/**
 * 游戏实时数据对象
 * 包含一个游戏初始化方法
 */
var Game = {
    init: function () {
        this.plane = new Plane(320);
        this.enemys = this.createEnemys(7);
        this.bullets = [];
        this.score = 0;
        document.onkeydown = this.keydown_listener;
        document.onkeyup = this.keyup_listener;
    },
    animate: function () {
        // 游戏成功检测
        if (Game.score == Game.enemys.length) {
            var interval = setInterval(function () {
                GameWindow.success();
                clearInterval(interval);
            }, 500);
            return;
        }
        // 更新飞机坐标
        if (Game.plane.direction == "left" && Game.plane.x > 30) Game.plane.x -= 5;
        else if (Game.plane.direction == "right" && Game.plane.x < 610) Game.plane.x += 5;
        // 更新子弹坐标
        for (var i = 0; i < Game.bullets.length; i++) {
            Game.bullets[i].fly();
            if (Game.bullets[i].y < -5) {
                Game.bullets.splice(i, 1);
                i--;
            }
        }
        // 更新怪兽坐标
        for (var i = 0; i < Game.enemys.length; i++) {
            if (Game.enemys[i].direction == "left") {
                Game.enemys[i].x -= 2;
            } else {
                Game.enemys[i].x += 2;
            }
        }
        // 怪兽触边检测
        for (var i = 0; i < Game.enemys.length; i++) {
            if (Game.enemys[i].status == "alive" && Game.enemys[i].x < 30) { // 左侧碰撞
                Game.enemys[i].__proto__.direction = "right"; // 改变方向
                for (var j = 0; j < Game.enemys.length; j++) {
                    Game.enemys[j].x += 2; // 撤销移动
                    Game.enemys[j].y += 35; // 下移
                    if (Game.enemys[j].y > 425) { // 触底游戏失败
                        GameWindow.fail();
                        return;
                    }
                }
                break;
            } else if (Game.enemys[i].status == "alive" && Game.enemys[i].x > 620) { //右侧碰撞
                Game.enemys[i].__proto__.direction = "left"; // 改变方向
                for (var j = 0; j < Game.enemys.length; j++) {
                    Game.enemys[j].x -= 2; // 撤销移动
                    Game.enemys[j].y += 35; // 下移
                    if (Game.enemys[j].y > 425) { // 触底游戏失败
                        GameWindow.fail();
                        return;
                    }
                }
                break;
            }
        }
        // 子弹命中检测
        for (var i = 0; i < Game.enemys.length; i++) {
            for (var j = 0; j < Game.bullets.length; j++) {
                if (Game.bullets[j].x > Game.enemys[i].x &&
                    Game.bullets[j].x < Game.enemys[i].x + 50 &&
                    Game.bullets[j].y > Game.enemys[i].y &&
                    Game.bullets[j].y < Game.enemys[i].y + 50 &&
                    Game.enemys[i].status == "alive") {
                    // 确认命中
                    Game.enemys[i].boom();
                    Game.bullets.splice(j, 1);
                    Game.score++;
                }
            }
        }
        // 更新分数
        score[0].innerHTML = Game.score;
        // 擦除画布
        context.clearRect(0, 0, canvas.width, canvas.height);
        // 画出怪兽
        for (var i = 0; i < Game.enemys.length; i++) {
            if (Game.enemys[i].status == "alive") {
                context.drawImage(enemy_img, Game.enemys[i].x, Game.enemys[i].y, 50, 50);
            } else if (Game.enemys[i].status == "boom") {
                context.drawImage(boom_img, Game.enemys[i].x, Game.enemys[i].y, 50, 50);
            }
        }
        //画出子弹
        for (var i = 0; i < Game.bullets.length; i++) {
            context.beginPath();
            context.moveTo(Game.bullets[i].x, Game.bullets[i].y);
            context.lineTo(Game.bullets[i].x, Game.bullets[i].y + 10);
            context.strokeStyle = "white";
            context.stroke();
        }
        //画出飞机
        context.drawImage(plane_img, Game.plane.x, 475, 60, 100);
        requestAnimationFrame(Game.animate);
    },
    createEnemys: function (num) {
        var enemys = [];
        for (var i = 0; i < num; i++) {
            enemys.push(new Enemy(30 + i * 60, 75));
        }
        return enemys;
    },
    keydown_listener: function (e) {
        var keyNum = window.event ? e.keyCode : e.which;
        if (keyNum == 37) {
            //按下←键
            Game.plane.moveLeft();
        } else if (keyNum == 39) {
            //按下→键
            Game.plane.moveRight();
        } else if (keyNum == 32) {
            //按下空格
            if (!Game.plane.shoot_status) { // 每次按下空格都只能进行一次射击
                Game.plane.shoot();
                Game.plane.shoot_status = true;
            }
            return false; // 禁止屏幕滚动
        }
    },
    keyup_listener: function (e) {
        var keyNum = window.event ? e.keyCode : e.which;
        if (keyNum == 37 && Game.plane.direction == "left") {
            Game.plane.stop();
        } else if (keyNum == 39 && Game.plane.direction == "right") {
            Game.plane.stop();
        } else if (keyNum == 32) {
            Game.plane.shoot_status = false;
        }
    }
};
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值