最近在玩小程序中一个比较火的游戏,最!强!弹!一!弹!!!,真的是超级模型的一款小游戏,打发时间堪比抖音。。。。。。,今天就来研究下关于小球如何有
重力效果
和互相碰撞反弹
的效果。
1. 重力效果实现
- 首先我们当然是要先画个球球啦!
.ball {
width: 100px;
height: 100px;
border-radius: 50%;
background: #ff5532;
position: absolute;
}
复制代码
- 然后我们需要给小球规定一个初始的
X
,Y
上的速度和一个让小球运动起来的定时器timer
。
var speedX = 6;
var speedY = 0;
var timer = null;
复制代码
- 定义小球在
X,Y
上可以移动的最大距离。
//document.documentElement.clientHeight(屏幕高度)
//ball.offsetHeight(小球的高度)
var maxMoveH = document.documentElement.clientHeight - ball.offsetHeight;
var maxMoveW = document.documentElement.clientWidth - ball.offsetWidth;
复制代码
- 如果达到最小或最大距离,折返运动。
//y轴横向移动超过做大可移动高度,就反弹折回。
if(ballMoveY >= maxMoveH || ballMoveY <= 0){
speedY = -speedY;
ballMoveY = maxMoveH;
}
//x轴横向移动超过做大可移动宽度,就反弹折回。
if(ballMoveX >= maxMoveW){
speedX = -speedX;
//定死最大宽度
ballMoveX = maxMoveW;
speedX = speedX*0.95;
}
//移动到右边边界就自动折返。
if(ballMoveX <= 0){
speedX = -speedX;
speedX = speedX*0.95;
}
复制代码
- 为了防止小球不在弹起后,还在x轴上移动。
if(Math.abs(speedX) < 0.2 && ballMoveY >= maxMoveH){
clearInterval(timer);
}
复制代码
- 下面是完整代码。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<style type="text/css">
.ball {
width: 100px;
height: 100px;
border-radius: 50%;
background: #ff6632;
position: absolute;
}
style>
head>
<body>
<button id="moveStart">点击触发button>
<div id="ball" class="ball">div>
body>
<script>
window.onload = function() {
var ball = document.getElementById("ball");
var moveStart = document.getElementById("moveStart");
moveStart.onclick = function() {
var speedX = 6;
var speedY = 0;
var timer = null;
moveStart();
function moveStart() {
clearInterval(timer);
timer = setInterval(function(){
var ballMoveY, ballMoveX;
var maxMoveH = document.documentElement.clientHeight - ball.offsetHeight;
var maxMoveW = document.documentElement.clientWidth - ball.offsetWidth;
speedY += 6;
//横向移动会有能量损耗
speedX = speedX*0.99;
ballMoveY = ball.offsetTop + speedY;
ballMoveX = ball.offsetLeft + speedX;
if(ballMoveY >= maxMoveH || ballMoveY <= 0){
speedY = -speedY;
ballMoveY = maxMoveH;
}
//x轴横向移动超过做大可移动宽度,就反弹折回
if(ballMoveX >= maxMoveW){
speedX = -speedX;
ballMoveX = maxMoveW;
speedX = speedX*0.95;
}
if(ballMoveX <= 0){
speedX = -speedX;
speedX = speedX*0.95;
}
//如果速度小于0.2且小球不在弹起,则不让小球在移动了
if(Math.abs(speedX) < 0.2 && ballMoveY >= maxMoveH){
clearInterval(timer);
}
ball.style.top = ballMoveY + 'px';
ball.style.left = ballMoveX + 'px';
},30)
}
}
}
script>
html>
复制代码
上述大概就是简单的一个js仿重力的简单实现。
现在我们来看一看神奇的碰撞效果。
首先,我们需要知道实现小球碰撞需要哪些方法。
- 随机生成方法。
function random(type) {
switch(type){
case 'color':
return 'rgb(' + Math.floor(Math.random()*255) + ',' + Math.floor(Math.random()*255) + ',' + Math.floor(Math.random()*255) + ')';
case 'top':
return Math.floor(Math.random()*280) + 'px';
case 'left':
return Math.floor(Math.random()*280) + 'px';
case 'speed':
return Math.floor((Math.random() - 0.5)*20);
default:
return false;
}
}
复制代码
- 定义一个碰撞区域。
#content {
width: 300px;
height: 300px;
border: 1px solid #f00;
position: relative;
}
复制代码
- 创建小球。
function createBall(num){
var p = null;
for(var i=0; i < num; i++){
p = document.createElement('p');
p.innerHTML = i + 1;
p.style.background = random('color');
p.style.color = '#fff';
p.style.top = random('top');
p.style.left = random('left');
p.style['textAlign'] = 'center';
p.id = 'ball' + i;
content.appendChild(p);
ballList.push(p);
moveBall(p);
}
}
复制代码
- 小球移动。
function moveBall(ball, startSX, startSY) {
var speedX = random('speed'),
speedY = random('speed'),
ballMoveX = null,
speedObj = {},
ballMoveY = null;
timer = setInterval(function(){
ballMoveY = ball.offsetTop + speedY;
ballMoveX = ball.offsetLeft + speedX;
if(ballMoveX >= maxMoveX || ballMoveX <= 0){
speedX = -speedX;
}
if(ballMoveY >= maxMoveY || ballMoveY <= 0){
speedY = -speedY;
}
ball.style.top = ballMoveY + 'px';
ball.style.left = ballMoveX + 'px';
speedObj = crashBall(ball, speedX, speedY);
speedX = speedObj.speedX;
speedY = speedObj.speedY;
}, 30)
}
复制代码
- 小球碰撞。
存在8种位置碰撞的情况。
function crashBall(ball, speedX, speedY) {
var speedObj = {};
for(var i = 0; i//自己不跟自己比较
if(ball.id !== ballList[i].id && Math.abs(ball.offsetLeft - ballList[i].offsetLeft) <= 20 && Math.abs(ball.offsetTop - ballList[i].offsetTop) <= 20){
//**********对象小球在碰撞小球方位的8个情况***********
//左上方
if(ball.offsetLeft < ballList[i].offsetLeft && ball.offsetTop < ballList[i].offsetTop){
speedX > 0 && (speedX = -speedX);
speedY > 0 && (speedY = -speedY);
}
//正上方(不会影响水平运动的速度)
if(ball.offsetLeft === ballList[i].offsetLeft && ball.offsetTop < ballList[i].offsetTop){
speedY > 0 && (speedY = -speedY);
}
//右上方
if(ball.offsetLeft > ballList[i].offsetLeft && ball.offsetTop < ballList[i].offsetTop){
speedX < 0 && (speedX = -speedX);
speedY > 0 && (speedY = -speedY);
}
//正右方
if(ball.offsetLeft > ballList[i].offsetLeft && ball.offsetTop === ballList[i].offsetTop){
speedX < 0 && (speedX = -speedX);
}
//右下方
if(ball.offsetLeft > ballList[i].offsetLeft && ball.offsetTop > ballList[i].offsetTop){
speedX < 0 && (speedX = -speedX);
speedY < 0 && (speedY = -speedY);
}
//正下方
if(ball.offsetLeft === ballList[i].offsetLeft && ball.offsetTop > ballList[i].offsetTop){
speedY < 0 && (speedY = -speedY);
}
//左下方
if(ball.offsetLeft < ballList[i].offsetLeft && ball.offsetTop > ballList[i].offsetTop){
speedX > 0 && (speedX = -speedX);
speedY < 0 && (speedY = -speedY);
}
//正左方
if(ball.offsetLeft < ballList[i].offsetLeft && ball.offsetTop === ballList[i].offsetTop){
speedX > 0 && (speedX = -speedX);
}
}
}
speedObj.speedX = speedX;
speedObj.speedY = speedY;
return speedObj;
}
复制代码
完整代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Documenttitle>
<style type="text/css">
html,body {
margin: 0;
padding: 0;
}
#content {
width: 300px;
height: 300px;
border: 1px solid #f00;
position: relative;
}
#content p {
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
margin: 0;
}
style>
head>
<body>
<div id="content">div>
body>
<script>
window.onload = function() {
var content = document.getElementById('content');
var maxMoveX = content.clientWidth - 20;
var maxMoveY = content.clientHeight - 20;
var timer = null;
var ballList = [];
//0. 公共方法(随机创建)
function random(type) {
switch(type){
case 'color':
return 'rgb(' + Math.floor(Math.random()*255) + ',' + Math.floor(Math.random()*255) + ',' + Math.floor(Math.random()*255) + ')';
case 'top':
return Math.floor(Math.random()*280) + 'px';
case 'left':
return Math.floor(Math.random()*280) + 'px';
case 'speed':
return Math.floor((Math.random() - 0.5)*20);
default:
return false;
}
}
//1. 创建小球
function createBall(num){
var p = null;
for(var i=0; i < num; i++){
p = document.createElement('p');
p.innerHTML = i + 1;
p.style.background = random('color');
p.style.color = '#fff';
p.style.top = random('top');
p.style.left = random('left');
p.style['textAlign'] = 'center';
p.id = 'ball' + i;
content.appendChild(p);
ballList.push(p);
moveBall(p);
}
}
//2. 移动小球
function moveBall(ball, startSX, startSY) {
var speedX = random('speed'),
speedY = random('speed'),
ballMoveX = null,
speedObj = {},
ballMoveY = null;
timer = setInterval(function(){
ballMoveY = ball.offsetTop + speedY;
ballMoveX = ball.offsetLeft + speedX;
if(ballMoveX >= maxMoveX || ballMoveX <= 0){
speedX = -speedX;
}
if(ballMoveY >= maxMoveY || ballMoveY <= 0){
speedY = -speedY;
}
ball.style.top = ballMoveY + 'px';
ball.style.left = ballMoveX + 'px';
speedObj = crashBall(ball, speedX, speedY);
speedX = speedObj.speedX;
speedY = speedObj.speedY;
}, 30)
}
//3. 处理小球间的碰撞
function crashBall(ball, speedX, speedY) {
var speedObj = {};
for(var i = 0; i//自己不跟自己比较
if(ball.id !== ballList[i].id && Math.abs(ball.offsetLeft - ballList[i].offsetLeft) <= 20 && Math.abs(ball.offsetTop - ballList[i].offsetTop) <= 20){
//**********对象小球在碰撞小球方位的8个情况***********
//左上方
if(ball.offsetLeft < ballList[i].offsetLeft && ball.offsetTop < ballList[i].offsetTop){
speedX > 0 && (speedX = -speedX);
speedY > 0 && (speedY = -speedY);
}
//正上方(不会影响水平运动的速度)
if(ball.offsetLeft === ballList[i].offsetLeft && ball.offsetTop < ballList[i].offsetTop){
speedY > 0 && (speedY = -speedY);
}
//右上方
if(ball.offsetLeft > ballList[i].offsetLeft && ball.offsetTop < ballList[i].offsetTop){
speedX < 0 && (speedX = -speedX);
speedY > 0 && (speedY = -speedY);
}
//正右方
if(ball.offsetLeft > ballList[i].offsetLeft && ball.offsetTop === ballList[i].offsetTop){
speedX < 0 && (speedX = -speedX);
}
//右下方
if(ball.offsetLeft > ballList[i].offsetLeft && ball.offsetTop > ballList[i].offsetTop){
speedX < 0 && (speedX = -speedX);
speedY < 0 && (speedY = -speedY);
}
//正下方
if(ball.offsetLeft === ballList[i].offsetLeft && ball.offsetTop > ballList[i].offsetTop){
speedY < 0 && (speedY = -speedY);
}
//左下方
if(ball.offsetLeft < ballList[i].offsetLeft && ball.offsetTop > ballList[i].offsetTop){
speedX > 0 && (speedX = -speedX);
speedY < 0 && (speedY = -speedY);
}
//正左方
if(ball.offsetLeft < ballList[i].offsetLeft && ball.offsetTop === ballList[i].offsetTop){
speedX > 0 && (speedX = -speedX);
}
}
}
speedObj.speedX = speedX;
speedObj.speedY = speedY;
return speedObj;
}
createBall(3);
}
script>
html>
复制代码
关键的地方是要向清楚,两个小球间碰撞后的运动方向,和碰到方框以后的碰撞方向。
好啦,上面就是今天的全部内容啦。
end。。。