开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天, 点击查看活动详情
先上关键的JS主代码,在这里我们把每个小方块当作一个飞船。
let canvas = document.querySelector('#A').getContext('2d')
let shipArr = []
let crr = ['red','orange','yellow','green','cyan','blue','purple','black']
for(let i=0;i< 27;i++){
let x = 750+200*Math.random() -100
let y = 400+200*Math.random() -100
let n = parseInt( Math.random() * crr.length )
let c = crr[n]
let one = new Ship(x,y,c)
shipArr.push( one)
}
animate();//循环动画函数
function animate(t){
canvas.clearRect(0,0,1500,800) //清空画布
for(let one of shipArr){
one.draw(canvas)
}
requestAnimationFrame(animate);//每隔16.67ms去调用,即每秒绘制60次
}
我们通过循环随机生成27个飞船的代码,并且让x,y坐标随机,这样每个飞船的出生点
就会不一样。因为涉及多个物体的运动,所以我们需要用面向对象的方法来写控制飞船
这样我们通过new Ship(x,y,c) 来创建对象。
在另一个js文件中我们来声明飞船类。
class Ship{ //飞船类,模板
constructor(x,y,c){ //构造方法,创建对象时自动
this.x = x
this.y = y
this.w = 10
this.h = 10
this.vx = Math.random()*10 -5 //水平速度00
this.vy = Math.random()*10 -5 //垂直速度
this.c = c //颜色
}
draw(canvas){ //画图方法
this.move()
canvas.strokeStyle = this.c
canvas.strokeRect(this.x, this.y,10,10)
}
move(){ //移动
if(this.y<-10 || this.y>810 ){
this.vy = -this.vy
}
if( this.x< -10 || this.x>1510 ){
this.vx = -this.vx
}
this.x+=this.vx
this.y+=this.vy
}
}
每个飞船具有两个方法,一个画图draw(canvas),接受 canvas绘图环境作为参数,
一个移动move(),同时我们可以在主动画函数中看到这个绘图方法的调用,在动画
循环函数中,让每个飞船绘制自身。
知识点 碰撞反弹
针对画布区域,我们考虑四个方向上的临界点,如果快要出界了,速度方向就取反值。如代码:
this.x+=this.vx
this.y+=this.vy
知识点 碰撞检测
在这个例子中我们并没有两个物体相撞,如果要判断物体相撞,我们可以使用
以下函数
pz(A,B){ //碰撞
let isPz = false; //假设没有碰撞
//B 在A的
let f1 = (A.x+A.w )<=B.x; //B在A的右边
let f2 = (A.y+A.h )<=B.y; //B在A的下边
let f3 = A.x>=(B.x +B.w); //B在A的左边
let f4 = A.y>=(B.y +B.h); //B在A的上边
// f1||f2||f3||f4 以上任何一种 结果为真
if( !(f1||f2||f3||f4) ){//不在4种情况中的任一种
isPz = true;//碰撞
}
return isPz;
}
我们简单判断两个物体相撞的条件也是取反。
一个物体在另一个物体的左边,一定没相撞。
一个物体在另一个物体的右边,一定没相撞。
同样的上边和下边适用,这样四个方向都没相碰,那么两个物体肯定未相撞。