h1 {
font-size: 2rem;
letter-spacing: -1px;
position: absolute;
margin: 0;
top: -4px;
right: 5px;
color: transparent;
text-shadow: 0 0 4px white;
}
p{
position: absolute;
margin: 0;
top:35px;
right: 5px;
color:#aaa;
}
}
弹球
还剩25个球
</canvas>
<script type="text/javascript">
const BALLS_COUNT = 25;
const BALL_SIZE_MIN = 10;
const BALL_SIZE_MAX = 20;
const BALL_SPEED_MAX = 7;
let count = 0;
// 设定画布
const canvas = document.querySelector(‘canvas’);
const ctx = canvas.getContext(‘2d’);
// 将画布窗尺寸置为窗口内尺寸
const width = canvas.width = window.innerWidth;
const height = canvas.height = window.innerHeight;
// 定义剩余球数
let ballCnt = document.getElementById(‘ballCnt’);
// 定义一个数组来保存所有的球
const balls = [];
// 生成随机数的函数
function random(min,max) {
return Math.floor(Math.random()*(max-min)) + min;
}
// 生成随机颜色的函数
function randomColor() {
return ‘rgb(’ +
random(0, 255) + ', ’ +
random(0, 255) + ', ’ +
random(0, 255) + ‘)’;
}
//定义Shape 构造器
function Shape(x,y,velX,velY,exists){
this.x=x;
this.y=y;
this.velX=velX;
this.velY=velY;
this.exists=exists;
}
//Ball继承Shape构造器
function Ball(x,y,velX,velY,exists,color,size){
Shape.call(this,x,y,velX,velY,exists);
this.color=color;
this.size=size;
}
// Ball 生成原型属性
Ball.prototype= Object.create(Shape.prototype);
// 构造器修改为Ball
Ball.prototype.constructor = Ball;
// 恶魔圈
function EvilCircle(x,y,exists){
Shape.call(this,x,y,20,20,exists);
this.color=‘white’;
this.size = 10;
}
// EvilCircle 原型属性
EvilCircle.prototype = Object.create(Shape.prototype);
// 定义EvilCircle 构造器属性
EvilCircle.prototype.constructor=EvilCircle;
// EvilCircle 方法
EvilCircle.prototype.draw=function(){
ctx.save();
ctx.beginPath();
ctx.strokeStyle=this.color;
ctx.arc(this.x,this.y,this.size,0,2*Math.PI);
ctx.stroke();
ctx.restore();
}
// 定义 Ball 构造器
// function Ball(x, y, velX, velY, color, size) {
// this.x = x;
// this.y = y;
// this.velX = velX;
// this.velY = velY;
// this.color = color;
// this.size = size;
// }
// 定义绘制球的函数
Ball.prototype.draw = function() {
ctx.save();
ctx.beginPath();
ctx.lineWidth=3;
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
};
EvilCircle.prototype.checkBounds = function(){
if((this.x + this.size) >= width) {
this.x -= this.size;
}
if((this.x - this.size) <= 0) {
this.x += this.size;
}
if((this.y + this.size) >= height) {
this.y -= this.size;
}
if((this.y - this.size) <= 0) {
this.y += this.size;
}
}
//
EvilCircle.prototype.setControls =function(){
window.onkeydown = e=>{
if(e.key === ‘a’){
this.x -= this.velX;
}else if(e.key === ‘d’){
this.x +=this.velX;
}else if(e.key === ‘w’){
this.y -= this.velY;
}else if(e.key === ‘s’){
this.y += this.velY;
}
}
}
// 定义更新球的函数
Ball.prototype.update = function() {
if((this.x + this.size) >= width) {
this.velX = -(this.velX);
}
if((this.x - this.size) <= 0) {
this.velX = -(this.velX);
}
if((this.y + this.size) >= height) {
this.velY = -(this.velY);
}
if((this.y - this.size) <= 0) {
this.velY = -(this.velY);
}
this.x += this.velX;
this.y += this.velY;
};
// EvilCircle 恶魔圈
EvilCircle.prototype.collisionDetect=function(){
for(let j = 0; j < balls.length; j++) {
if(balls[j].exists) {
const dx = this.x - balls[j].x;
const dy = this.y - balls[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + balls[j].size) {
balls[j].exists = false;
count++;
ballCnt.textContent = BALLS_COUNT - count;
clearCircle(balls[j].x,balls[j].y,balls[j].size,ctx);
}
}
}
}
// 擦圆函数;
function clearCircle(x,y,r,ctx){
let stepClear =1;
clearArc(x,y,r);
function clearArc(x,y,radius){
let calcWidth = radius-stepClear;
let calcHeight = Math.sqrt(radiusradius-calcWidthcalcWidth);
let posX = x-calcWidth;
let posY = y-calcHeight;
let WidthX = 2calcWidth;
let heightY = 2calcHeight;
if(stepClear <= radius){
ctx.clearRect(posX,posY,WidthX,heightY);
stepClear+=1;
clearArc(x,y,radius);
}
}
}
// 定义碰撞检测函数
Ball.prototype.collisionDetect = function() {
for(let j = 0; j < balls.length; j++) {
if( this !== balls[j]) {
const dx = this.x - balls[j].x;
const dy = this.y - balls[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < this.size + balls[j].size) {
balls[j].color = this.color = randomColor();
}
}
}
};
let evil = new EvilCircle(100,200,true);
// 定义一个循环来不停地播放
function loop() {
ctx.fillStyle = ‘rgb(0, 0, 0, 0.25)’;
ctx.fillRect(0, 0, width, height);
while(balls.length < BALLS_COUNT) {
const size = random(BALL_SIZE_MIN, BALL_SIZE_MAX);
const ball = new Ball(
// 为避免绘制错误,球至少离画布边缘球本身一倍宽度的距离
random(0 + size, width - size),
random(0 + size, height - size),
random(-BALL_SPEED_MAX, BALL_SPEED_MAX),
random(-BALL_SPEED_MAX, BALL_SPEED_MAX),
true,
randomColor(),
size
);
balls.push(ball);
}
for(let i = 0; i < balls.length; i++) {
if(balls[i].exists){
balls[i].draw();
balls[i].update();
balls[i].collisionDetect();
}
}
evil.draw();
evil.checkBounds();
evil.collisionDetect();
requestAnimationFrame(loop);
}
loop();
evil.setControls();