javascript實(shí)現(xiàn)10個(gè)球隨機(jī)運(yùn)動(dòng)、碰撞實(shí)例詳解
本文實(shí)例講述了javascript實(shí)現(xiàn)10個(gè)球隨機(jī)運(yùn)動(dòng)、碰撞的方法。分享給大家供大家參考。具體如下:
學(xué)了一段時(shí)間的javascript了,做過(guò)一些小案例,目前最有難度的就是10個(gè)小球隨機(jī)碰撞效果,這不,把它上上來(lái)與大家分享一下,相信不少和我一樣的菜鳥(niǎo)在開(kāi)始上手編程時(shí)都會(huì)有不少的困惑,希望它能給一些人帶來(lái)幫助。
效果要求:10個(gè)小球在頁(yè)面隨機(jī)移動(dòng),碰到窗口邊界或其他小球都會(huì)反彈
思路:
1、10個(gè)小球是10個(gè)div;
2、碰窗口反彈,定義vx vy為小球的移動(dòng)變量,以及一個(gè)彈力變量bounce(負(fù)值),小球碰窗口邊界時(shí),vx vy分別乘以bounce,則改變了小球移動(dòng)方向
3、小球相碰反彈,說(shuō)簡(jiǎn)單點(diǎn),當(dāng)兩個(gè)小球的圓心距變量dist小于其最小值(半徑之和)則改變球的移動(dòng)方向,實(shí)現(xiàn)反彈
好了,代碼如下:
html和js是分開(kāi)的文件喲
test.html文件如下:
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
body {
margin:0;
padding:0;
text-align: center;
}
#screen { width: 800px; height: 640px; position: relative; background: #ccccff;margin: 0 auto;vertical-align: bottom}
#inner { position: absolute; left:0px; top:0px; width:100%; height:100%; }
#screen p {color:white;font:bold 14px;}
.one { background-image:url('bubble.png'); background-position: -66px -58px; }
.two { background-image:url('bubble.png'); background-position: -66px -126px;}
.three { background-image:url('bubble.png'); background-position: -66px -194px; }
.four { background-image:url('bubble.png'); background-position: -66px -263px; }
.five { background-image:url('bubble.png'); background-position: -66px -331px; }
.six { background-image:url('bubble.png'); background-position: -66px -399px; }
.seven { background-image:url('bubble.png'); background-position: -66px -194px; }
.eight { background-image:url('bubble.png'); background-position: -66px -263px; }
.nine { background-image:url('bubble.png'); background-position: -66px -331px; }
.ten{ background-image:url('bubble.png'); background-position: -66px -399px; }
</style>
</head>
<body>
<div id="screen" >
<p>hi test it!</p>
<div id="inner"></div>
</div>
<input type="button" id="start" value="start" >
<input type="button" id="stop" value="stop">
<br><br><br>
<script type="text/javascript" src="test.js"></script>
</body>
</html>
test.js文件如下:
var getFlag=function (id) {
return document.getElementByIdx_x(id); //獲取元素引用
}
var extend=function(des, src) {
for (p in src) {
des[p]=src[p];
}
return des;
}
var clss=['one','two','three','four','five','six','seven','eight','nine','ten'];
var Ball=function (diameter,classn) {
var ball=document.createElement_x("div");
ball.className=classn;
with(ball.style) {
width=height=diameter+'px';position='absolute';
}
return ball;
}
var Screen=function (cid,config) {
//先創(chuàng)建類(lèi)的屬性
var self=this;
if (!(self instanceof Screen)) {
return new Screen(cid,config)
}
config=extend(Screen.Config, config) //configj是extend類(lèi)的實(shí)例
self.container=getFlag(cid); //窗口對(duì)象
self.ballsnum=config.ballsnum;
self.diameter=56; //球的直徑
self.radius=self.diameter/2;
self.spring=config.spring; //球相碰后的反彈力
self.bounce=config.bounce; //球碰到窗口邊界后的反彈力
self.gravity=config.gravity; //球的重力
self.balls=[]; //把創(chuàng)建的球置于該數(shù)組變量
self.timer=null; //調(diào)用函數(shù)產(chǎn)生的時(shí)間id
self.L_bound=0; //container的邊界
self.R_bound=self.container.clientWidth;
self.T_bound=0;
self.B_bound=self.container.clientHeight;
};
Screen.Config={ //為屬性賦初值
ballsnum:10,
spring:0.8,
bounce:-0.9,
gravity:0.05
};
Screen.prototype={
initialize:function () {
var self=this;
self.createBalls();
self.timer=setInterval(function (){self.hitBalls()}, 30)
},
createBalls:function () {
var self=this, num=self.ballsnum;
var frag=document.createDocumentFragment(); //創(chuàng)建文檔碎片,避免多次刷新
for (i=0;i<num;i++) {
var ball=new Ball(self.diameter,clss[ Math.floor(Math.random()* num )]);
ball.diameter=self.diameter;
ball.radius=self.radius;
ball.style.left=(Math.random()*self.R_bound)+'px'; //球的初始位置,
ball.style.top=(Math.random()*self.B_bound)+'px';
ball.vx=Math.random() * 6 -3;
ball.vy=Math.random() * 6 -3;
frag.appendChild(ball);
self.balls[i]=ball;
}
self.container.appendChild(frag);
},
hitBalls:function () {
var self=this, num=self.ballsnum,balls=self.balls;
for (i=0;i<num-1;i++) {
var ball1=self.balls[i];
ball1.x=ball1.offsetLeft+ball1.radius; //小球圓心坐標(biāo)
ball1.y=ball1.offsetTop+ball1.radius;
for (j=i+1;j<num;j++) {
var ball2=self.balls[j];
ball2.x=ball2.offsetLeft+ball2.radius;
ball2.y=ball2.offsetTop+ball2.radius;
dx=ball2.x-ball1.x; //兩小球圓心距對(duì)應(yīng)的兩條直角邊
dy=ball2.y-ball1.y;
var dist=Math.sqrt(dx*dx + dy*dy); //兩直角邊求圓心距
var misDist=ball1.radius+ball2.radius; //圓心距最小值
if(dist < misDist) {
//假設(shè)碰撞后球會(huì)按原方向繼續(xù)做一定的運(yùn)動(dòng),將其定義為運(yùn)動(dòng)A
var angle=Math.atan2(dy,dx);
//當(dāng)剛好相碰,即dist=misDist時(shí),tx=ballb.x, ty=ballb.y
tx=balla.x+Math.cos(angle) * misDist;
ty=balla.y+Math.sin(angle) * misDist;
//產(chǎn)生運(yùn)動(dòng)A后,tx > ballb.x, ty > ballb.y,所以用ax、ay記錄的是運(yùn)動(dòng)A的值
ax=(tx-ballb.x) * self.spring;
ay=(ty-ballb.y) * self.spring;
//一個(gè)球減去ax、ay,另一個(gè)加上它,則實(shí)現(xiàn)反彈
balla.vx-=ax;
balla.vy-=ay;
ballb.vx+=ax;
ballb.vy+=ay;
}
}
}
for (i=0;i<num;i++) {
self.moveBalls(balls[i]);
}
},
moveBalls:function (ball) {
var self=this;
ball.vy+=self.gravity;
ball.style.left=(ball.offsetLeft+ball.vx)+'px';
ball.style.top=(ball.offsetTop+ball.vy)+'px';
//判斷球與窗口邊界相碰,把變量名簡(jiǎn)化一下
var L=self.L_bound, R=self.R_bound, T=self.T_bound, B=self.B_bound, BC=self.bounce;
if (ball.offsetLeft < L) {
ball.style.left=L;
ball.vx*=BC;
}
else if (ball.offsetLeft + ball.diameter > R) {
ball.style.left=(R-ball.diameter)+'px';
ball.vx*=BC;
}
else if (ball.offsetTop < T) {
ball.style.top=T;
ball.vy*=BC;
}
if (ball.offsetTop + ball.diameter > B) {
ball.style.top=(B-ball.diameter)+'px';
ball.vy*=BC;
}
}
}
window.onload=function() {
var sc=null;
getFlag('start').onclick=function () {
document.getElementByIdx_x("inner").innerHTML='';
sc=new Screen('inner',{ballsnum:10, spring:0.8, bounce:-0.9, gravity:0.05});
sc.initialize();
}
getFlag('stop').onclick=function() {
clearInterval(sc.timer);
}
}
測(cè)試后的效果還是很不錯(cuò)的,各位也許會(huì)覺(jué)得代碼挺長(zhǎng),但是其思路還是蠻清晰的:
首先創(chuàng)建Screen類(lèi),并在Screen的構(gòu)造函數(shù)中給出了球移動(dòng)、碰撞所需的各種屬性變量,如ballsnum、spring、bounce、gravity等等
然后用原型prototype給出相應(yīng)的函數(shù),如創(chuàng)建球,createBalls,球碰撞hitBalls,球移動(dòng)moveBalls,給每個(gè)函數(shù)添加相應(yīng)的功能、
最后用按鈕點(diǎn)擊事件調(diào)用函數(shù),僅此而已。
希望本文所述對(duì)大家的javascript程序設(shè)計(jì)有所幫助。
- js實(shí)現(xiàn)小球在頁(yè)面規(guī)定的區(qū)域運(yùn)動(dòng)
- JavaScript實(shí)現(xiàn)小球沿正弦曲線(xiàn)運(yùn)動(dòng)
- JS小球拋物線(xiàn)軌跡運(yùn)動(dòng)的兩種實(shí)現(xiàn)方法詳解
- javascript鼠標(biāo)跟隨運(yùn)動(dòng)3種效果(眼球效果,蘋(píng)果菜單,方向跟隨)
- Js實(shí)現(xiàn)簡(jiǎn)單的小球運(yùn)動(dòng)特效
- javascript動(dòng)畫(huà)之圓形運(yùn)動(dòng),環(huán)繞鼠標(biāo)運(yùn)動(dòng)作小球
- JavaScript實(shí)現(xiàn)多球運(yùn)動(dòng)效果
相關(guān)文章
Vue考試系統(tǒng)的后臺(tái)管理功能開(kāi)發(fā)示例解讀
這篇文章主要介紹了Vue考試系統(tǒng)后臺(tái)管理項(xiàng)目的登錄、記住密碼功能具體實(shí)現(xiàn)流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09
TS報(bào)錯(cuò):Parameter?'xxx'?implicitly?has?an?'
這篇文章主要給大家介紹了關(guān)于TS報(bào)錯(cuò):Parameter?'xxx'?implicitly?has?an?'any'?type的解決方式,文中將產(chǎn)生錯(cuò)誤的原因及解決方法都介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
dropdownlist之間的互相聯(lián)動(dòng)實(shí)現(xiàn)(顯示與隱藏)
dropdownlist之間的互相聯(lián)動(dòng)(顯示與隱藏)2009-11-11
JavaScript實(shí)現(xiàn)星級(jí)評(píng)價(jià)效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)星級(jí)評(píng)價(jià)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
JavaScript中關(guān)于遞歸與回溯的實(shí)例詳解
這篇文章主要將為大家介紹一下JavaScript中遞歸與回溯的原理及使用,文中通過(guò)一些例題進(jìn)行了詳細(xì)介紹,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-07-07
JavaScript 創(chuàng)建隨機(jī)數(shù)和隨機(jī)圖片
關(guān)于javascript隨機(jī)數(shù)的,很早以前的文章了,不過(guò)內(nèi)容還是不錯(cuò)的,如果想要更多的效果,可以去腳本之家搜下。2009-12-12
Javascript模擬實(shí)現(xiàn)new原理解析
這篇文章主要介紹了Javascript模擬實(shí)現(xiàn)new原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

