實驗10 瘋狂的大炮
簡介
水平拋出的物體的運動是平拋運動,與水平有一定仰角拋出的物體的運動是斜拋運動。這兩種運動都是曲線運動,統稱拋物運動。
平拋運動
物體以一定的初速度沿水平方向拋出,如果物體僅受重力作用,這樣的運動叫做平拋運動。平拋運動可視為水平方向的勻速直線運動以及豎直方向的自由落體運動的合運動。平拋運動的物體,由于所受的合外力為恒力,所以平拋運動是勻變速曲線運動,平拋物體的運動軌跡為一拋物線。平拋運動是曲線運動,平拋運動的時間僅與拋出點的豎直高度有關;物體落地的水平位移與時間(豎直高度)及水平初速度有關。平拋運動的實驗及頻閃照片如圖2-5所示。

圖2-5 平拋運動
如圖2-5(a)所示,小球A的運動是平拋運動,小球B的運動是自由落體運動,圖2-5(b)為兩個小球的運動軌跡圖。根據運動的獨立性,小球A和B應當是同時落地。現在開始在Canvas中模擬這個過程。
第一步,首先需要兩個小球,一個小球的速度為(x∶0,y∶0),另一個小球的速度為(x∶400,y∶0):
var balls=[]; balls.length=0; var ball1={ x: 70, y: 50, r: 10, vx: 400, vy: 0 }; var ball2={ x: 50, y: 50, r: 10, vx: 0, vy: 0 }; balls.push(ball1); balls.push(ball2);
第二步,利用Jscex循環,讓小球運動起來。
var canvas=document.getElementById("myCanvas");
var cxt=canvas.getContext("2d");
var cyc=110;
var a=80;
cxt.fillStyle="#030303";
cxt.fillRect(0, 0, canvas.width, canvas.height);
var moveAsync=eval(Jscex.compile("async", function () {
while (true) {
cxt.fillStyle="rgba(0, 0, 0, .3)";
cxt.fillRect(0, 0, canvas.width, canvas.height);
cxt.fillStyle="#fff";
for (var i in balls) {
cxt.beginPath(); \注:根據速度,重繪所有小球的位置。\
cxt.arc(balls[i].x, balls[i].y, balls[i].r, 0, Math.PI * 2, true);
cxt.closePath();
cxt.fill();
balls[i].y +=balls[i].vy * cyc / 1000;
balls[i].x +=balls[i].vx * cyc / 1000;
if (balls[i].r+balls[i].y >=canvas.height) {
if (balls[i].vy > 0) {
balls[i].vy *=-0.7;
}
}
else {
balls[i].vy +=a;
}
}
$await(Jscex.Async.sleep(cyc));
}
}))
moveAsync().start();
其效果如圖2-6所示。

圖2-6 在Canvas中模擬平拋運動
斜拋運動之瘋狂的大炮
斜拋運動在很多游戲中都碰到過,如“憤怒的小鳥”,小鳥經過彈弓的作用與水平有一仰角拋出。下面制作一個無限開炮的大炮來模擬斜拋運動。
第一步,需要一張大炮的圖片,如圖2-7所示。

圖2-7 大炮素材
通過如下方式加載圖片:
var img=new Image(); img.src="image/artillery.png"; img.onload=function () { cxt.drawImage(img, 0, 325); }
第二步,模擬炮彈。在每次循環時生成一個炮彈:
var ball={ x: 185, y: 470, r: getRandomNumber(0, 20), vx: getRandomNumber(190, 3000), vy: getRandomNumber(-3000, 0) }; balls.push(ball); if (balls.length > 100) { balls.shift(); }
當炮彈射出數量大于100時,從balls中移除一個小球,以防止瀏覽器堆棧溢出。其中getRandomNumber方法是自定義方法,可以獲得一定范圍內的隨機數:
function getRandomNumber(min, max) { return (min+Math.floor(Math.random() * (max-min+1))) }
第三步,Jscex循環實現大炮的猛烈轟炸:
var fireAsync=eval(Jscex.compile("async", function () { while (true) { var ball={ x: 185, y: 470, r: getRandomNumber(0, 20), vx: getRandomNumber(190, 3000), vy: getRandomNumber(-3000, 0) }; balls.push(ball); if (balls.length > 100) { balls.shift(); } cxt.fillStyle="rgba(0, 0, 0, .3)"; cxt.fillRect(0, 0, canvas.width, canvas.height); cxt.fillStyle="#fff"; cxt.drawImage(img, 0, 425); for (i in balls) { cxt.beginPath(); cxt.arc(balls[i].x, balls[i].y, balls[i].r, 0, Math.PI * 2, true); cxt.closePath(); cxt.fill(); balls[i].y +=balls[i].vy * cyc / 1000; balls[i].x +=balls[i].vx * cyc / 1000; if (balls[i].r+balls[i].y >=canvas.height) { if (balls[i].vy > 0) { balls[i].vy *=-0.7; } } else { balls[i].vy +=a; } } $await(Jscex.Async.sleep(cyc)); } })) fireAsync().start();
以上代碼的運動效果如圖2-8所示。

圖2-8 大炮的猛烈轟炸
總結
通過這個實驗,可以更加深刻地理解運動的獨立性,了解Canvas中繪制圖片的基本方法。但是這還不夠,因為運動不僅僅在線性運動方面是獨立的,它與物體的轉動也是相互獨立的。繪制圖片時不建議直接使用drawImage,當圖片沒有加載完成,調用drawImage方法會在一些瀏覽器中拋異常。所以要在drawImage之前進行圖片的預加載。
- Dreamweaver CS5網頁設計與制作教程
- Dreamweaver CC中文版網頁設計與制作從新手到高手
- 網頁制作實用教程(第3版)
- HTML+CSS+JavaScript網頁制作案例教程(第2版)
- 全能網頁設計師精煉手冊
- HTML5+CSS3網頁設計與制作基礎教程
- Photoshop網頁設計從入門到精通
- 電子商務網頁設計(第二版)
- Photoshop熱門手機APP與網頁游戲界面設計從入門到精通
- Linux系統與網絡服務管理技術大全(第二版)
- 寬帶接入技術
- 在實戰中成長:JSP開發之路
- Dreamweaver CS6網頁設計入門、進階與提高
- H5頁面設計與制作(全彩慕課版)
- Dreamweaver,Flash,Fireworks網頁設計百練成精(CS3版)