使用h5制作简易球球大作战
闲暇之余写的球球大作战,实现了球球之间的吃和被吃,体重增长函数,体重随时间减小函数,和自己的分身功能和敌人的简单ai,有不对的地方,往大佬们指正!!!多的不说直接看代码。
HTML部分
<div class="chuangkou">
<canvas id="huaban"></canvas>
</div>
css部分
body {
margin: 0;
padding: 0;
background: black;
}
.chuangkou {
width: 500px;
height: 800px;
}
最主要的js部分来了
var huabu = document.querySelector('#huaban');
var huaban = huabu.getContext('2d');
var w, h, qiu = [], s_X = 0, s_Y = 0, c_x = 0, c_y = 0, c, d, time = 0, r = 30, Food = [];//游戏的一些变量,还没有养成对象的方式来写,大家将就着看一下
var color = ['#1db0b8', '#de8100', '#3b200c', '#ff534d', '#edd0be'];//球球的颜色,从这几个颜色中来随机
function daXiao() {
window.onresize = arguments.callee;
w = window.innerWidth;
h = window.innerHeight;
huabu.width = w;
huabu.height = h;
}//获取浏览器的宽高,可以用onload函数来实现,为了方便调试我写的是一个普通函数
daXiao();//浏览器宽高
function mouseMove(ev) {
ev = ev || window.event;
var mousePos = mouseCords(ev);
s_X = mousePos.x, s_Y = mousePos.y;
}//传递鼠标实时的位置
function mouseCords(ev) {
if (ev.pageX || ev.pageY) {
return {
x: ev.pageX, y: ev.pageY
};
}
//将鼠标实时位置传递给s_x和s_y,便于计算
}
function suiJi(max, min) {
return Math.random() * (max - min) + min;
}//在max和min中随机一个数
function qiuQiu() { };
qiuQiu.prototype = {
weiZhi: function () {//比较标准的写法,方便初学者
this.r = 2 * Math.sqrt(30);//球球的半径,使用体重来计算,自己的球球体重是固定的
this.x = suiJi(this.r, w - this.r);
this.y = suiJi(this.r, h - this.r);
//球球圆心的位置
this.color = color[Math.floor(suiJi(0, 5))];
//随机的颜色
this.tiZhong = 30;
//球球自己的体重
},
yanSe: function () {
huaban.beginPath();
huaban.fillStyle = this.color;
huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
huaban.fill();
//画球球
},
jiSuan: function () {
c = Math.sqrt((s_X - this.x) ** 2 + (s_Y - this.y) ** 2);
//当鼠标指向不同位置时都能匀速运动的计算方法,分成了两个部分来写
},
yiDong: function () {
//球球的移动包括边界的算法
if (c != 0) {
if (this.x > this.r && this.x < w - this.r && this.y > this.r && this.y < h - this.r) {
this.x += ((s_X - this.x) / c) * r / this.r;
this.y += ((s_Y - this.y) / c) * r / this.r;
} else if (this.x <= this.r) {
this.x += 0.1;
} else if (this.y <= this.r) {
this.y += 0.1;
}
else if (this.x >= w - this.r) {
this.x -= 0.1;
} else if (this.y >= this.r) {
this.y -= 0.1;
}
} else { }
this.yanSe();
//每时每刻画球球,更新球球的位置
}
}
var qiuqiu = new qiuQiu();
qiuqiu.weiZhi();
qiuqiu.yanSe();
//玩家球球运动判定,运动方式
function enemy() { };
enemy.prototype = {
weiZhi: function () {
this.r = suiJi(5, 30);
this.tiZhong = this.r ** 2 / 4;
this.x = suiJi(this.r, w - this.r);
this.y = suiJi(this.r, h - this.r);
this.color = color[Math.floor(suiJi(0, 5))];
},//敌人小球球半径根据体重来计算,体重随机,位置随机,颜色随机,
yanSe: function () {
huaban.beginPath();
huaban.fillStyle = this.color;
huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
huaban.fill();
},//画敌人球球
jiSuan: function () {
this.d = Math.sqrt((qiuqiu.x - this.x) ** 2 + (qiuqiu.y - this.y) ** 2);
},//敌人的不同方向匀速运动的算法
yiDong: function () {//敌人和自己都会随着体重的增加速度变慢,具体算法参照下列
this.r = 2 * Math.sqrt(this.tiZhong);
if (time == 0) this.b_x = (this.x - qiuqiu.x) / this.d, this.b_y = (this.y - qiuqiu.y) / this.d;
if (this.d < 200 && this.y >= this.r && this.y <= h - this.r && this.x >= this.r && this.x <= w - this.r) {
if (qiuqiu.r > this.r) {
this.b_x = (this.x - qiuqiu.x) / this.d;
this.b_y = (this.y - qiuqiu.y) / this.d;
} else {
this.b_x = (qiuqiu.x - this.x) / this.d;
this.b_y = (qiuqiu.y - this.y) / this.d;
}
if (this.y < this.r || this.y > h - this.r) {
this.b_y = -this.b_y;
}
if (this.x < this.r || this.x > w - this.r) {
this.b_x = -this.b_x;
}
this.x += this.b_x * r / this.r;
this.y += this.b_y * r / this.r;
} else {
if (this.y < this.r || this.y > h - this.r) {
this.b_y = -this.b_y;
}
if (this.x < this.r || this.x > w - this.r) {
this.b_x = -this.b_x;
}
this.x += this.b_x * r / this.r;
this.y += this.b_y * r / this.r;
}
this.yanSe();
},
beiChi: function () {
//遍历所有小球球来判断是否被吃,这个函数写得非常不好
if (this.d <= qiuqiu.r && qiuqiu.r > this.r) {
qiuqiu.tiZhong += this.tiZhong;
qiuqiu.r = 2 * Math.sqrt(qiuqiu.tiZhong);
delete this.tiZhong, delete this.x, delete this.y, delete this.r;
} else if (this.d <= this.r && qiuqiu.r < this.r) {
this.tiZhong += qiuqiu.tiZhong;
delete qiuqiu.tiZhong, delete qiuqiu.x, delete qiuqiu.y, delete qiuqiu.r;//一旦被吃清楚他们的属性
}
}
}
function creatDiRen(num) {//创造敌人num为敌人的数量
for (var i = 0; i < num; i++) {
var diRen = new enemy();
diRen.weiZhi();
diRen.yanSe();
qiu.push(diRen);
}
}
creatDiRen(5);
//敌人算法属性,还有运动轨迹;
function food() { };
food.prototype = {//食物的函数
weiZhi: function () {//食物的位置体重大小颜色
this.tiZhong = 1;
this.r = 2;
this.x = suiJi(this.r, w - this.r);
this.y = suiJi(this.r, h - this.r);
this.color = '#00FFF7';
},
yanSe: function () {//画食物
huaban.beginPath();
huaban.fillStyle = this.color;
huaban.arc(this.x, this.y, this.r, 0, Math.PI * 2);
huaban.fill();
},
beiChi: function () {//遍历被吃函数
this.d_w = Math.sqrt((qiuqiu.x - this.x) ** 2 + (qiuqiu.y - this.y) ** 2);
if (this.d_w < this.r + qiuqiu.r) {
qiuqiu.tiZhong += this.tiZhong;
delete this.tiZhong, delete this.x, delete this.y, delete this.r;
qiuqiu.r = 2 * Math.sqrt(qiuqiu.tiZhong);
}
for (item of qiu) {
this.d_d = Math.sqrt((item.x - this.x) ** 2 + (item - this.y) ** 2);
}
}
}
function creatFood(num) {//创造食物函数
for (var i = 0; i < num; i++) {
var shiWu = new food();
shiWu.weiZhi();
shiWu.yanSe();
Food.push(shiWu);
}
}
creatFood(300);
setInterval(function () {//定时器来计算没1000/60时间段所发生的事情
huaban.clearRect(0, 0, w, h);
qiuqiu.jiSuan();
qiuqiu.yiDong();
for (item of qiu) {
item.jiSuan();
item.yiDong();
item.beiChi();
}
for (item of Food) {
item.yanSe();
item.beiChi();
}
if (time % 120 == 0 && time != 0) {
qiuqiu.tiZhong -= 0.5;
console.log(qiuqiu.r, qiuqiu.x, qiuqiu.y)
}
time++;
}, 1000 / 60);
document.onmousemove = mouseMove;//鼠标位置