首先先附上我的游戏地址:https://yating.online/easyGame/protectBall.html
喜欢就给我点个星吧:https://github.com/Chenyating/easyGame
pc端!!!!!!移动端没做处理;
一、简单介绍:
简单的介绍一下我的小游戏:
这个是个单恋,爱而不得的悲伤爱情故事;
索性最后是有情人终成眷属的美好故事;
外面的小球球说:你就是那个中心的小圆,而我只会朝那冲去,纵使铜墙铁壁阻拦,粉身碎骨照样前进;
操作说明:
- 点击游戏开始;
- 通过鼠标旋转外框角度,防止黄色小球进入内框;
游戏规则:
- 黄色小球球进入中心球,中心球半径变大;
- 随着分数越来越大,防御外框半径变小,防御角度变小;
- 蓝色小球进入中心,分数加10;外框半径增加;(蓝色小球起的是保护防御作用)
结束条件:
- 预防角度为0度时;
- 中心球的半径始终大于外框的半径;
二、技术难点
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;