(小游戏)详解球球保卫大作战:html+js+canvas实现原理

首先先附上我的游戏地址:https://yating.online/easyGame/protectBall.html

喜欢就给我点个星吧:https://github.com/Chenyating/easyGame

pc端!!!!!!移动端没做处理;

一、简单介绍:

简单的介绍一下我的小游戏:

这个是个单恋,爱而不得的悲伤爱情故事

索性最后是有情人终成眷属的美好故事

外面的小球球说:你就是那个中心的小圆,而我只会朝那冲去,纵使铜墙铁壁阻拦,粉身碎骨照样前进

操作说明:

  1. 点击游戏开始;
  2. 通过鼠标旋转外框角度,防止黄色小球进入内框;

游戏规则:

  1. 黄色小球球进入中心球,中心球半径变大;
  2. 随着分数越来越大,防御外框半径变小,防御角度变小;
  3. 蓝色小球进入中心,分数加10;外框半径增加;(蓝色小球起的是保护防御作用)

结束条件:

  1. 预防角度为0度时;
  2. 中心球的半径始终大于外框的半径;

二、技术难点

1、需要你对canvas的方法熟悉;

2、本次我使用的框架是vue.js;

3、仅对pc端适用;

通过开发的过程,该游戏最大的难点如下:

  • 外框随鼠标的移动旋转;
  • 小球随机从四周向中心移动;
  • 小球到达中心点,经历的总总,条件到达中心的条件;(爱一个人好难,要感动一个人更难;【手动滑稽】)
  • 小球碰壁瞬间的炸裂效果;(爱一个人受伤了,那是心碎的感觉【手动狗头】)
  • 外框角度的变化;(被感动慢慢敞开心扉【手动猫头】)

三、实现步骤

接下来我开始详细的说明这个游戏设计过程,实现的逻辑;

首先先了解一下我的自定义的变量:了解一下,黄小圆(bgStage)与球球(ballStage)的信息;

世界背景:高度400*800;

黄小圆心扉开口,默认值为:2Π-3/2Π——也就是90度;

data: {
    bgStage: null, //背景旋转的圈圈
    ballStage: null, //这是小球球
    // 画布长宽
    canvasWidth: 400,
    canvasHeight: 800,
    // 大圆圈
    circleDeg: 1.5 * Math.PI,
    circleX: 200,
    circleY: 400,
    circleR: 50,
    // 中心小球
    centerCircleR: 10,
    smallBallDeg: 2 * Math.PI,
    smallBallR: 5,
    // 框框旋转的角度
    oldDeg: 0,
    angle: null,
    // 炸开特性例子半径;
    dotR: 1, //像素大小

    scope: 0, //分数
    subDeg: Math.PI / 12, //每次减少的度数
    changgeNum: 20, //变化的条件,分数每增加n分就,角度减少
    gameState: 0, //游戏状态

    gameTime: 0,
    // 颜色设置:
    safeColor: "#00FFFF", //安全颜色
    dangerColor: "#DC143C", //危险颜色
    nomalColor: "yellow" //正常颜色
  },

方法不多就几个:

1、绘制:

 drawCenterCircle(x, y, r, deg)、drawCircle(x, y, r, deg)

首先我们用canvas在画布上画小圆的心;

以及她的情感系统绿色外框——我们叫心扉,算了,我叫它框框;

由于黄小圆的心会被小球球入侵而被感动,终有一天占满爱意的心(黄小圆半径),会冲破防御爆发出来;这个时候游戏就结束了;

在这个过程中,它们的坐标半径会随时变化(x,y,r,deg);

不过在这里我暂未对x,y做出其他的改变,哪有人的心会流动来流动去哇!!

以下是绘制中心球以及外框圈的方法;

 // 绘制内部小球球:没毛病;
    drawCenterCircle(x, y, r, deg) {
      this.bgStage.beginPath();
      this.bgStage.fillStyle = "#FFFF00";
      this.bgStage.arc(x, y, r, 0, deg);
      this.bgStage.fill();
    },
    // 绘制外部大框框:没毛病;
    drawCircle(x, y, r, deg) {
      this.bgStage.beginPath();
      this.bgStage.strokeStyle = "#00FF80";
      this.bgStage.arc(x, y, r, 0, deg);
      this.bgStage.stroke();
    },

2、外框旋转:

 ballRotate(newDeg)

外框的旋转需要用到canvas的rotate()、和translate()方法;

  • rotate(角度值):通过(0,0)坐标旋转;其中图形是以y轴为0度;
  • translate():可自定义旋转以何处为原点,旋转;

每次旋转以后都要把旋转点换回去,具体会发生什么?那大概会上演一场轰轰烈烈的爱情吧……【手动滑稽】

  ballRotate(newDeg) {
      this.bgStage.clearRect(this.circleX - this.circleR, this.circleY - this.circleR, 2 * this.circleR, 2 * this.circleR);
      this.drawCenterCircle(
        this.circleX,
        this.circleY,
        this.centerCircleR,
        this.smallBallDeg
      );
      this.bgStage.translate(this.circleX, this.circleY);
      this.bgStage.rotate(newDeg);
      this.bgStage.beginPath();
      this.bgStage.arc(0, 0, this.circleR, 0, this.circleDeg);
      this.bgStage.stroke();
      this.bgStage.translate(-this.circleX, -this.circleY); //坐标转换必须为旋转回去之后
    },

鼠标旋转的过程决定了,框框的旋转;所以获取旋转的角度最为重要;


3、获取旋转的角度:

getMousePosition(event)

在画布中我们通过鼠标的点击,把界面分为4个象限;

1、通过计算鼠标点击象限的坐标,可以计算出鼠标相对于x轴的斜率,从而计算出与x方向的夹角;

这里需要我们用三角函数acrtan得出鼠标的角度;所以,最后我们可以得到蓝色区域为鼠标相对于x轴的角度;

2、得出鼠标的夹角还不能结束,因为这不是框框该旋转的角度;

框框该旋转的角度 = 新鼠标点与旧鼠标点的夹角;

// 获取鼠标在界面上的位置:旋转:没毛病;
    getMousePosition(event) {
      // 全部都化成绝对值;
      if (event.layerX > this.circleX) {
        var x = event.layerX - this.circleX;
      } else {
        var x = this.circleX - event.layerX;
      }
      if (event.layerY > this.circleY) {
        var y = event.layerY - this.circleY;
      } else {
        var y = this.circleY - event.layerY;
      }
      // 现在鼠标的角度;
      this.angle = Math.atan(y / x);

      // 第一象限
      if (event.layerX > this.circleX && event.layerY < this.circleY) {
        this.angle = Math.PI - this.angle;
        // 第二象限
      } else if (event.layerX < this.circleX && event.layerY < this.circleY) {
        this.angle = this.angle;
        // 第三象限
      } else if (event.layerX < this.circleX && event.layerY > this.circleY) {
        this.angle = 2 * Math.PI - this.angle;
        // 第四象限
      } else if (event.layerX > this.circleX && event.layerY > this.circleY) {
        this.angle = Math.PI + this.angle;
      }

      if (this.oldDeg == 0) {
        this.ballRotate(this.angle);
        this.oldDeg = this.angle;
      } else {
        //   需要移动的角度
        var newDeg = this.angle - this.oldDeg;
        //   于是新的鼠标角度将成为旧的鼠标角度;
        this.oldDeg = this.angle;
        this.ballRotate(newDeg);
      }
    },

4、小球球向中心移动的过程:

getLineFunction(x1, y1, color)、moveSmallBall(k, b, x1, y1, color)

作为一个小球球,它的坐标(x,y)一直都在变动,我们要知道它的运动轨迹、和自身颜色;

1、小球球向中心移动的过程是一条直线距离,只要我们已知小球球坐标(x1,y1),那么我们就可以计算出它的运动轨迹:y=kx+b;

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值