[Silently] efforts fishingGame

The fishing game is very interesting, by firing bullets, fishing. Fishing bullets will consume gold, but fishing if the fish hit, it will reward the number of gold coins.
If I write this, it should draw a background sea, and then generate a lot of pictures of fish, but also have a cannon, gold. Cannon emits a bullet, made in different directions in different camera angles bullets.
Fired bullets on the consumption of gold, if the fish hit on the award of gold, guns on both sides of the plus and minus is the continuous emission control Let the bullets. But this time the angle is not good to send the bomb control.
Next we see results

On first down big projects address: https://github.com/JayHowe/fishingGame
Next, we analyze the code
page initialization draw pictures

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
    body {
        text-align: center;
        background-color: #000;
    }

    #c1 {
        width: 800px;
        height: 600px;
        background: url(img/game_bg_2_hd.jpg) no-repeat;
        margin: 0 auto;
    }
    </style>
    <script type="text/javascript" src="js/common.js"></script>
    <script type="text/javascript" src="js/drawRect.js"></script>
    <script type="text/javascript" src="js/sprite.js"></script>
    <script type="text/javascript" src="js/fish.js"></script>
    <script type="text/javascript" src="js/cannon.js"></script>
    <script type="text/javascript" src="js/button.js"></script>
    <script type="text/javascript" src="js/bullet.js"></script>
    <script type="text/javascript" src="js/coin.js"></script>
    <script>
    window.onload = function() {
        // 绘制背景
        let oC = document.getElementById('c1');
        let gd = oC.getContext('2d');

        let lastFire=0;
        let fired=false;
        let MAX_FISH=30;
        const coinCollector={x:106,y:576};
        //游戏总得分
        let playerScore=1000;

        const W = oC.width,
            H = oC.height;
            // 加载图片
        loadImages(_resources, function() {
            //炮台
            let tower = new Sprite(new DrawRect(_imgs.bottom, 0, 0, 756, 71, ));
            tower.x = 400;
            tower.y = H - 71 / 2 + 1;

            //炮
            let cannon = new Cannon(1);

            cannon.x = 443;
            cannon.y = 574;

            //炮弹
            let bullets=[];

            //鱼
            let fishs=[];

            // 金币
            let coins=[];

            //分数数字
            let scores=[];

            for(let i=0;i<6;i++){
                let sprite=new Sprite(new DrawRect(_imgs.number,0,9*24,20,24));
                sprite.x=51+23*i;
                sprite.y=586;
                scores.push(sprite);
            };

            //鼠标事件
            oC.onmousemove = ev => {
                let a = ev.offsetX - cannon.x;
                let b = ev.offsetY - cannon.y;
                let ang = a2d(Math.atan2(b, a)) + 90;
                cannon.rotation = ang;
            }

            //加号、减号
            let btnMinus = new Button(
                new DrawRect(_imgs.bottom, 135, 75, 36, 28),
                new DrawRect(_imgs.bottom, 91, 75, 36, 28)
            );
            btnMinus.x = 371;
            btnMinus.y = 566;

            let btnPlus = new Button(
                new DrawRect(_imgs.bottom, 47, 75, 36, 28),
                new DrawRect(_imgs.bottom, 3, 75, 36, 28)
            );
            btnPlus.x = 516;
            btnPlus.y = 566;

            btnMinus.onclick = function() {
                if (cannon.type > 1) {
                    cannon.setType(cannon.type - 1);
                } else {
                    cannon.setType(1);
                }
            };
            btnPlus.onclick = function() {
                if (cannon.type < 7) {
                    cannon.setType(cannon.type + 1);
                } else {
                    cannon.setType(7);
                }
            };

            let aBtn = [btnMinus, btnPlus];

            oC.onmousedown = function(ev) {
                //检测按钮
                aBtn.forEach(btn => {
                    btn.down(ev.offsetX, ev.offsetY);
                });

                if(Date.now()-lastFire >= 300) {
                    lastFire=Date.now();
                    //炮弹
                    let bullet=new Bullet(cannon.type, cannon.x,cannon.y,cannon.rotation);
                    bullets.push(bullet);

                    playerScore-=cannon.type*2;

                    fired=true;
                }
                
            };
            oC.onmouseup = function(ev) {
                aBtn.forEach(btn => {
                    btn.up(ev.offsetX, ev.offsetY);
                });
            };

            function animate() {
                requestAnimationFrame(animate);

                //生成鱼
                if(rnd(1,20)==1 && fishs.length<MAX_FISH) {
                    let fish=new Fish(rnd(1,5));
                    if(rnd(0,2)==0) {
                        //左边
                        fish.x=-100;
                        fish.rotation=90;
                    }else {
                        //右边
                        fish.x=W+100;
                        fish.rotation=-90;
                    }
                    fish.y=rnd(0,H-100);
                    fishs.push(fish);
                }

                gd.clearRect(0, 0, oC.width, oC.height);

                coins=coins.filter(coin=>{
                    coin.move(coinCollector.x,coinCollector.y);
                    coin.nextFrame();
                    coin.draw(gd);

                    if(Math.abs(coin.x-coinCollector.x)<5 && Math.abs(coin.y-coinCollector.y)<5) {
                        playerScore+=50;
                        return false;
                    }else {
                        return true;
                    }
                });
                tower.draw(gd);

                bullets=bullets.filter(bullet=>{
                    bullet.move();
                    bullet.draw(gd);
                    return !bullet.outRect(-100,-100,W+200,H+200); 
                });
                // console.log(bullets.length);

                fishs=fishs.filter(fish=>{
                    fish.move();
                    fish.draw(gd); 
                    fish.nextFrame();
                    return !fish.outRect(-100,-100,W+200,H+200); 
                });
                // console.log(fishs.length);



                cannon.draw(gd);
                if(fired) {
                    ret=cannon.nextFrame();
                    if(ret) {
                        fired=false;
                    }
                }

                btnMinus.draw(gd);
                btnPlus.draw(gd);

                //碰撞
                fishs=fishs.filter(fish=>{
                    let colled=false;
                    bullets=bullets.filter(bullet=>{
                        if(!colled && fish.collTest(bullet)){ 
                            if(Math.random()<bullet.type*10/(10+(fish.type-1)*20)) {
                               colled=true;
                            }
                            return false; 
                        }else {
                            return true;
                        }
                    });
                    
                    if(colled) {
                        fish.isdead=true;
                        fish.speed=0;

                        setTimeout(function() {
                            //金币
                            let a=fish.x-coinCollector.x;
                            let b=coinCollector.y-fish.y;

                            let i=0;
                            let timer=setInterval(function(){
                                let coin=new Coin(1,fish.x,fish.y);
                                // coin.x+=rnd(-50,50);
                                // coin.y+=rnd(-50,50);
                                coins.push(coin);
                                i++;

                                if(i==Math.pow(2,fish.type)) {
                                    clearInterval(timer);
                                }
                            },60);
                            
                            fishs=fishs.filter(item=>item!=fish);
                        },500);

                        return true;
                    }else {
                        return true;
                    }
                });

                //分数
                let str=playerScore+'';
                while(str.length<6) {
                   str='0'+str; 
                }
                scores.forEach((score,index)=>{
                    playerScore
                    score.setDrawRect(new DrawRect(_imgs.number,0,(9-parseInt(str[index]))*24,20,24));
                    score.draw(gd);
                });
            }
            requestAnimationFrame(animate);

        });
    }
    </script>
</head>
<body>
    <canvas id="c1" width="800" height="600"></canvas>
</body>
</html>
//bullet
//绘制子弹形状
class Bullet extends Sprite{
    constructor(type,x=0,y=0,rotation=0){
        const SIZE=[
            null,
            new DrawRect(_imgs.bullet,86,0,24,26),
            new DrawRect(_imgs.bullet,61,0,25,29),
            new DrawRect(_imgs.bullet,32,36,29,30),
            new DrawRect(_imgs.bullet,30,82,29,33),
            new DrawRect(_imgs.bullet,0,82,30,34),
            new DrawRect(_imgs.bullet,30,0,31,26),
            new DrawRect(_imgs.bullet,0,44,32,38)
        ];

        super(SIZE[type],x,y,rotation);

        this.type=type;
        this.speed=5;

        this.radius=14;
    }
}

Draw button

//button
class Button extends Sprite{
  constructor(drawRectNormal, drawRectActive, x=0, y=0, rotation=0){
    super(drawRectNormal, x, y, rotation);

    this.drawRectNormal=drawRectNormal;
    this.drawRectActive=drawRectActive;

    this.downAtMe=false;
  }

  down(x, y){
    if(this.inRect(x, y)){
      this.setDrawRect(this.drawRectActive);

      this.downAtMe=true;
    }else{
      this.downAtMe=false;
    }
  }
  up(x, y){
    this.setDrawRect(this.drawRectNormal);

    if(this.inRect(x, y) && this.downAtMe){
      //触发onclick
      this.onclick && this.onclick();
    }
  }
}

Drawing Cannon

//cannon.js
class Cannon extends Sprite {
    constructor(type, x = 0, y = 0, rotation = 0) {
        if (type > 7 || type < 1) {
            throw new Error('unkonw cannon type');
        }
        const SIZE = [
            null,
            { w: 74, h: 74 },
            { w: 74, h: 76 },
            { w: 74, h: 76 },
            { w: 74, h: 83 },
            { w: 74, h: 85 },
            { w: 74, h: 90 },
            { w: 74, h: 94 }
        ];

         //父级
        super(
          new DrawRect(_imgs[`cannon${type}`], 0, 0, SIZE[type].w, SIZE[type].h),
          x, y, rotation
        );

        this.SIZE=SIZE;

        this.setType(type);

        this.MAX_FRAME=5;
    }

    setType(type){
        this.type = type;
        this.setDrawRect(
          new DrawRect(_imgs[`cannon${type}`], 0, 0, this.SIZE[type].w, this.SIZE[type].h)
        );
    }
}

gold

//js\coin.js
class Coin extends Sprite{
    constructor(type,x=0,y=0,rotation=0){
        const SIZE=[
            null,
            new DrawRect(_imgs.coin1,0,0,60,60),
            new DrawRect(_imgs.coin2,0,0,60,60)
        ];

        super(SIZE[type],x,y,rotation);

        this.MAX_FRAME=10;
        this.speed=10;
    }


}

Initialization Load picture

//common.js
let _imgs=null;

const _resources={
  fish1: 'img/fish1.png',
  fish2: 'img/fish2.png',
  fish3: 'img/fish3.png',
  fish4: 'img/fish4.png',
  fish5: 'img/fish5.png',
  cannon1: 'img/cannon1.png',
  cannon2: 'img/cannon2.png',
  cannon3: 'img/cannon3.png',
  cannon4: 'img/cannon4.png',
  cannon5: 'img/cannon5.png',
  cannon6: 'img/cannon6.png',
  cannon7: 'img/cannon7.png',
  bottom: 'img/bottom.png',
  bullet: 'img/bullet.png',
  coin1: 'img/coinAni1.png',
  coin2: 'img/coinAni2.png',
  number: 'img/number_black.png',
};

function loadImages(json, fn){
  let res={};
  let complete=0;
  let total=0;

  for(let name in json){
    total++;

    let oImg=new Image();

    res[name]=oImg;

    oImg.onload=function (){
      complete++;

      if(complete==total){
        _imgs=res;
        fn();
      }
    };

    oImg.onerror=function (){
      alert('图片加载失败'+oImg.src);
    };

    oImg.src=json[name];
  }
}

function d2a(n){
  return n*Math.PI/180;
}
function a2d(n){
  return n*180/Math.PI;
}
function rnd(n, m){
  return Math.floor(Math.random()*(m-n)+n);
}

Square painting class

//js\drawRect.js
class DrawRect{
    constructor(img,sx,sy,sw,sh){
        if(!img || !sw || !sh) {
            throw new Error('img and sw and sh is required');
        }
        this.img=img;
        this.sx=sx;
        this.sy=sy;
        this.sw=sw;
        this.sh=sh;
    }
}

The definition of the type of fish

//js\fish.js
class Fish extends Sprite {
    constructor(type, x = 0, y = 0, rotation = 0) {
        if (type > 5 || type < 1) {
            throw new Error('unkonw fish type');
        }
        const SIZE = [
            null,
            { w: 55, h: 37, r: 12 },
            { w: 78, h: 64, r: 18 },
            { w: 72, h: 56, r: 15 },
            { w: 77, h: 59, r: 15 },
            { w: 107, h: 122, r: 23 }
        ];
        super(new DrawRect(_imgs[`fish${type}`], 0, 0, SIZE[type].w, SIZE[type].h), x, y, rotation);

        this.type = type;
        this.curFrame = 0;
        this.MAX_FRAME = 4;

        this.speed = rnd(1, 4);

        this.frameRate = 5;

        this.radius=SIZE[type].r;

        //死鱼
        this.isdead=false;
    }

    draw(gd) {
        if(this.isdead) {
            this.curFrame+=4;
        }

        if (this.rotation == -90) {
            this.scaleY = -1;
        }

        this.rotation -= 90;
        super.draw(gd);
        this.rotation += 90;


        if (this.rotation == -90) {
            this.scaleY = 1;
        }


        if(this.isdead) {
            this.curFrame-=4;
        }
    }
}

Drawing types of fish

//js\sprite.js

class Sprite {
    //w,h,x,y,rotate
    //draw(),碰撞检测()
    constructor(drawRect, x = 0, y = 0, rotation = 0) {
        if (!(drawRect instanceof DrawRect)) {
            throw new Error('img must be DrawRect');
        }
        this.setDrawRect(drawRect);
        this.x = x;
        this.y = y;
        this.rotation = rotation;

        this.speed = 0;

        //动画
        this.MAX_FRAME=0;
        this.curFrame=0;

        this.scaleX=1;
        this.scaleY=1;

        this.frameRate=1;
        this.frameRateNow=0;

        // 碰撞检测
        this.radius=0;
    }

    setDrawRect(drawRect) {
        this.drawRect = drawRect;
        this.width = drawRect.sw;
        this.height = drawRect.sh;
    }

    nextFrame(){
        this.frameRateNow++;
        // console.log(this.frameRateNow);

        if(this.frameRateNow==this.frameRate) {
            this.frameRateNow=0;

            this.curFrame++;
            if(this.curFrame>=this.MAX_FRAME) {
                this.curFrame=0;
                return true;
            }

            return false;
        }
    }

    draw(gd) {
        gd.save();

        gd.translate(this.x, this.y);
        gd.rotate(d2a(this.rotation));
        gd.scale(this.scaleX,this.scaleY);

        gd.drawImage(
            this.drawRect.img,
            this.drawRect.sx, this.drawRect.sy+this.height*this.curFrame, this.width, this.height,
            -this.width / 2, -this.height / 2, this.width, this.height,
        );
        gd.restore();
    }

    inRect(x, y) {
        if (
            this.x - this.width / 2 <= x && x <= this.x + this.width / 2 &&
            this.y - this.height / 2 <= y && y <= this.y + this.height / 2
        ) {
            return true;
        } else {
            return false;
        }
    }

    outRect(x,y,w,h){
        if(this.x<x || this.y<y || this.x>x+w || this.y>y+h) {
            return true;
        }else {
            return false;
        }
    }

    move(x,y) {
        if(arguments.length == 0) {
            let x_speed = this.speed * Math.sin(d2a(this.rotation));
            let y_speed = this.speed * Math.cos(d2a(this.rotation));
            this.x += x_speed;
            this.y -= y_speed;
        }else {
            this.x+=(x-this.x)/20;
            this.y+=(y-this.y)/20;
        }
        
    }

    collTest(other){
        return Math.sqrt(Math.pow(this.x-other.x,2)+Math.pow(this.y-other.y,2))<this.radius+other.radius;
    }


}

Postscript: I did not fully understand the code

Guess you like

Origin www.cnblogs.com/smart-girl/p/11448026.html