Canvas画布从彩虹到千万方块(下)

609 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天, 点击查看活动详情

31.gif

先上关键的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

图片.png

知识点 碰撞检测

在这个例子中我们并没有两个物体相撞,如果要判断物体相撞,我们可以使用
以下函数

	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;
	}

我们简单判断两个物体相撞的条件也是取反。
一个物体在另一个物体的左边,一定没相撞。
一个物体在另一个物体的右边,一定没相撞。
同样的上边和下边适用,这样四个方向都没相碰,那么两个物体肯定未相撞。