×

用JS和canvas简单模拟打飞机的游戏

作者:andy0012018.06.13来源:Web前端之家浏览:14743评论:0
关键词:H5canvas动画

简单模拟打飞机的游戏,核心技术用javascriptcanvas开发的,一起来了解下:

鼠标右键移动,鼠标左键攻击,移动的时候不能攻击,飞机有效射程是 300 码,敌机会侦察周围 300 码的地方,如果你与敌机的距离低于 300 码,敌机会主动追踪你,但是敌机需要飞到距离你 200 码的时候才会射击,因为敌机的有效射程是 200 码,当前版本里你的飞机是无敌的,要死亡的话把底下 2 行注释改过来就行了。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>飞机大战</title>
    <style>
      html,body,canvas {
        margin: 0;
        width: 100vw;
        height: 100vh;
        background-color: #000;
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <canvas></canvas>
    <script>
      window.onload = function() {
        var canvas = document.querySelector("canvas");
        var width = window.innerWidth;
        var height = window.innerHeight;
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext("2d");
        var effects = [];
        var count = 0;

        function random(min, max) {
          return Math.floor(Math.random() * (max - min) + min);
        }

        function collision(a, b) {
          var ax1 = a.x - a.size / 2;
          var ax2 = a.x + a.size / 2;
          var ay1 = a.y - a.size / 2;
          var ay2 = a.y + a.size / 2;
          var bx1 = b.x - b.size / 2;
          var bx2 = b.x + b.size / 2;
          var by1 = b.y - b.size / 2;
          var by2 = b.y + b.size / 2;
          return !(ax1 > bx2 || ax2 < bx1 || ay1 > by2 || ay2 < by1);
        }

        function Airplane() {
          var texture = new Image();
          texture.src = "http://pic.yupoo.com/pines/fabd3716/342bfcb9.png";
          this.x = width / 2;
          this.y = height / 2;
          this.orginX = this.x;
          this.orginY = this.y;
          this.size = 50;
          this.anchorX = 0 - this.size / 2;
          this.anchorY = 0 - this.size / 2;
          this.texture = texture;
          this.blood = 100;
          this.angle = -45 * Math.PI / 180;
          this.speed = 5;
          this.isMove = false;
          this.rockets = [];
          this.count = 0;
          this._dist = 0;
          this.dist = 0;
        }

        Airplane.prototype = {
          render: function() {
            this.draw();
            if (this.isMove) {
              this.move();
            }
          },
          draw: function() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.angle);
            ctx.drawImage(this.texture, this.anchorX, this.anchorY, this.size, this.size);
            ctx.restore();
          },
          attack: function(angle) {
            this.angle = angle;
            var texture = new Image();
            texture.src = "http://pic.yupoo.com/pines/fb85d82b/f6bd8b88.png";
            var speed = 10;
            for (var i = 0; i < 2; i++) {
              var x = this.x + this.size / 3 * Math.cos(this.angle + (1 - 4 * i) * Math.PI / 4);
              var y = this.y + this.size / 3 * Math.sin(this.angle + (1 - 4 * i) * Math.PI / 4);
              var rocket = new Rocket(x, y, this.angle, speed, texture, 300);
              this.rockets[this.count] = rocket;
              this.count += 1;
            }
          },
          move: function() {
            this.x += this.speed * Math.cos(this.angle - Math.PI / 4);
            this.y += this.speed * Math.sin(this.angle - Math.PI / 4);
            this._dist = Math.pow(this.x - this.orginX, 2) + Math.pow(this.y - this.orginY, 2);
            if (this._dist >= this.dist) {
              this.isMove = false;
            }
          },
          hit: function(n) {
            this.blood -= n;
            if (this.blood <= 0) {
              this.die = true;
            }
          },
          explosion: function() {
            var x = this.x - this.size * Math.cos(Math.PI / 4);
            var y = this.y - this.size * Math.sin(Math.PI / 4);
            var effect = new Effect(x, y, this.size);
            effects[count] = effect;
            count += 1;
          }
        };

       function Enemy() {
          var texture = new Image();
          texture.src = "http://pic.yupoo.com/pines/35de8b71/a1b87dde.png";
          this.size = 40;
          this.x = Math.random() * (width - this.size * 2) + this.size;
          this.y = Math.random() * (height - this.size * 2) + this.size;
          this.orginX = this.x;
          this.orginY = this.y;
          this.anchorX = 0 - this.size / 2;
          this.anchorY = 0 - this.size / 2;
          this.texture = texture;
          this.blood = 10;
          this.angle = Math.random() * Math.PI * 2;
          this.speed = 1;
          this.disX = 0;
          this.disY = 0;
          this.rockets = [];
          this.count = 0;
          this._dist1 = 0;
          this._dist2 = 0;
          this.dist1 = random(100, 300);
          this.dist2 = 300;
          this.dx = 0;
          this.dy = 0;
          this.die = false;
          this.interval = 0;
        }

        Enemy.prototype = {
          initState: function() {
            this.orginX = this.x;
            this.orginY = this.y;
            this._dist1 = 0;
            this.dist1 = random(100, 300);
          },
          render: function() {
            this.move();
            this.draw();
          },
          draw: function() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.angle);
            ctx.drawImage(this.texture, this.anchorX, this.anchorY, this.size, this.size);
            ctx.restore();
          },
          move: function() {
            this.disX = this.speed * Math.cos(this.angle - Math.PI / 4);
            this.disY = this.speed * Math.sin(this.angle - Math.PI / 4);
            this.x += this.disX;
            this.y += this.disY;
            this._dist1 = Math.pow(this.x - this.orginX, 2) + Math.pow(this.y - this.orginY, 2);
            if (this._dist1 >= Math.pow(this.dist1, 2)) {
              this.angle += random(-45, 45) * Math.PI / 180;
              this.angle %= Math.PI * 2;
              this.initState();
            }
            this.dx = airplane.x - this.x;
            this.dy = airplane.y - this.y;
            this._dist2 = Math.pow(this.dx, 2) + Math.pow(this.dy, 2);
            if (this._dist2 <= Math.pow(this.dist2, 2)) {
              this.angle = Math.atan2(this.dy, this.dx) + Math.PI / 4;
              if (this._dist2 <= Math.pow(200, 2)) {
                this.speed = 0;
                if (this.interval % 50 === 0) {
                  this.interval = 0;
                  this.attack();
                }
                this.interval += 1;
              } else {
                this.speed = 1;
                this.initState();
                this.dist1 = 100;
              }
            }
            if (this.x < -this.size && this.disX < 0 || this.x > width + this.size && this.disX > 0 || this.y < -this.size && this.disY < 0 || this.y > height + this.size && this.disY > 0) {
              this.angle += Math.PI / 2;
              this.angle %= Math.PI * 2;
              this.initState();
            }
          },
          attack: function() {
            var texture = new Image();
            texture.src = "http://pic.yupoo.com/pines/b3bf2b4a/5ebf09f8.png";
            var speed = 3;
            var x = this.x + this.size / 2 * Math.cos(this.angle - Math.PI / 4);
            var y = this.y + this.size / 2 * Math.sin(this.angle - Math.PI / 4);
            var rocket = new Rocket(x, y, this.angle, speed, texture, 200);
            this.rockets[this.count] = rocket;
            this.count += 1;
          },
          explosion: function() {
            var x = this.x - this.size * Math.cos(Math.PI / 4);
            var y = this.y - this.size * Math.sin(Math.PI / 4);
            var effect = new Effect(x, y, this.size);
            effects[count] = effect;
            count += 1;
            effects = effects.filter(function(effect) {
              return !!effect;
            });
          },
          hit: function() {
            this.blood -= 1;
            if (this.blood <= 0) {
              this.die = true;
            }
          }
        }

        var airplane = new Airplane();
        var enemys = [];
        for (var i = 0; i < 20; i++) {
          enemys.push(new Enemy());
        }

        function Rocket(x, y, angle, speed, texture, maxDist) {
          this.x = x;
          this.y = y;
          this.orginX = this.x;
          this.orginY = this.y;
          this.size = 20;
          this.anchorX = 0 - this.size / 2;
          this.anchorY = 0 - this.size / 2;
          this.texture = texture;
          this.angle =  angle;
          this.speed = speed;
          this._dist = 0;
          this.maxDist = maxDist;
          this.die = false;
        }

        Rocket.prototype = {
          render: function() {
            if (!this.die) {
              this.x += this.speed * Math.cos(this.angle - Math.PI / 4);
              this.y += this.speed * Math.sin(this.angle - Math.PI / 4);
              this._dist = Math.pow(this.x - this.orginX, 2) + Math.pow(this.y - this.orginY, 2);
              this.draw();
              if (this._dist >= Math.pow(this.maxDist, 2)) {
                this.die = true;
                this.explosion();
              }
            }
          },
          draw: function() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.angle);
            ctx.drawImage(this.texture, this.anchorX, this.anchorY, this.size, this.size);
            ctx.restore();
          },
          explosion: function() {
            var x = this.x - this.size * Math.cos(Math.PI / 4);
            var y = this.y - this.size * Math.sin(Math.PI / 4);
            var effect = new Effect(x, y, this.size);
            effects[count] = effect;
            count += 1;
          }
        };

        function Effect(x, y, size) {
          var texture = new Image();
          texture.src = "http://pic.yupoo.com/pines/eb59179b/4d5a9fac.png";
          this.x = x;
          this.y = y;
          this.i = 0;
          this.size = size * 1.5;
          this.texture = texture;
          this.die = false;
        }

        Effect.prototype = {
          render: function() {
            var x = (this.i % 8) * 256;
            var y = Math.floor(this.i / 8) * 256;
            ctx.drawImage(this.texture, x, y, 256, 256, this.x, this.y, this.size, this.size);
            if (this.i >= 31) {
              this.die = true;
            }
            this.i += 1;
          }
        }

        canvas.addEventListener("click", function(ev) {
          if (!airplane.isMove) { 
            var x = ev.offsetX;
            var y = ev.offsetY;
            var angle = Math.atan2(y - airplane.y, x - airplane.x) + Math.PI / 4;
            airplane.attack(angle);
          }
        }, false);

        canvas.addEventListener("contextmenu", function(ev) {
          var targetX = ev.offsetX;
          var targetY = ev.offsetY;
          var dx = targetX - airplane.x;
          var dy = targetY - airplane.y;
          airplane.dist = Math.pow(dx, 2) + Math.pow(dy, 2);
          if (airplane.dist >= 20) {
            airplane.orginX = airplane.x;
            airplane.orginY = airplane.y;
            airplane.angle = Math.atan2(dy, dx) + Math.PI / 4;
            airplane.isMove = true;
          }
          ev.preventDefault();
        });

        function animate() {
          if (!airplane.die) {
            ctx.clearRect(0, 0, width, height);
            for (var i in airplane.rockets) {
              var rocket = airplane.rockets[i];
              if (rocket && !rocket.die) {
                rocket.render();
                for (var j in enemys) {
                  var enemy = enemys[j]; 
                  if (collision(rocket, enemy)) {
                    rocket.die = true;
                    rocket.explosion();
                    enemy.hit();
                    if (enemy.die) {
                      enemy.explosion();
                      delete enemys[m];
                    }
                  }
                }
              } else {
                delete airplane.rockets[i];
              }
            }
            airplane.render();
            for (var m in enemys) {
              var enemyAir = enemys[m];
              if (enemyAir && !enemyAir.die) {
                for (var n in enemyAir.rockets) {
                  var enemyRocket = enemyAir.rockets[n];
                  if (enemyRocket && !enemyRocket.die) {
                    enemyRocket.render();
                    if (collision(enemyRocket, airplane)) {
                      enemyRocket.die = true;
                      enemyRocket.explosion();
                      //airplane.hit(1);
                      if (airplane.die) {
                        airplane.explosion();
                      }
                    }
                  } else if (enemyRocket && enemyRocket.die) {
                    delete enemyAir.rockets[n];
                  }
                }
                enemyAir.render();
                if (collision(enemyAir, airplane)) {
                  enemyAir.die = true;
                  enemyAir.explosion();
                  //airplane.hit(10);
                  if (airplane.die) {
                    airplane.explosion();
                  }
                }
              } else if (enemyAir && enemyAir.die) {
                delete enemys[m];
                enemys = enemys.filter(function(enemy) {
                  return !!enemy;
                });
                if (enemys.length < 20) {
                  setTimeout(function() {
                    enemys.push(new Enemy());
                  }, 2000)
                }
              }
            }
            for (var e in effects) {
              var effect = effects[e];
              if (effect && !effect.die) {
                effect.render();
              } else if (effect && effect.die) {
                delete effects[e];
              }
            }
          }
          requestAnimationFrame(animate)
        }
        animate();
      };
    </script>
  </body>
</html>

您的支持是我们创作的动力!
温馨提示:本文作者系 ,经Web前端之家编辑修改或补充,转载请注明出处和本文链接:
https://jiangweishan.com/article/feiji124124124.html

网友评论文明上网理性发言 已有0人参与

发表评论: