軟件工程師-用HTML5打造斯諾克桌球俱樂部設(shè)計(jì)案例_第1頁
軟件工程師-用HTML5打造斯諾克桌球俱樂部設(shè)計(jì)案例_第2頁
軟件工程師-用HTML5打造斯諾克桌球俱樂部設(shè)計(jì)案例_第3頁
軟件工程師-用HTML5打造斯諾克桌球俱樂部設(shè)計(jì)案例_第4頁
軟件工程師-用HTML5打造斯諾克桌球俱樂部設(shè)計(jì)案例_第5頁
已閱讀5頁,還剩24頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、用html5打造斯諾克桌球俱樂部設(shè)計(jì)案例本文介紹了如何利用html5技術(shù)來打造一款非??岬乃怪Z克桌球游戲,文章中詳細(xì)地列出了開發(fā)的全過程,并解說了實(shí)現(xiàn)這個游戲的幾個關(guān)鍵點(diǎn)。在文章末尾我向大家提供了游戲的在線實(shí)例頁面和源碼下載鏈接,如果你只是想玩玩(需要使用支持html5的瀏覽器,建議使用chrome 12, internet explorer 9 或者 fire fox 5及其以上版本),那你可以跳過正文拉到頁面最底端去玩玩那個游戲或者下載源碼,但我建議你好好看看實(shí)現(xiàn)過程,對我們學(xué)習(xí)html5非常有幫助。 毫無疑問,我們已經(jīng)目睹了html5背后的那場偉大的web開發(fā)革命。經(jīng)過那么多年html4

2、的統(tǒng)治,一場全新的運(yùn)動即將完全改變現(xiàn)在的web世界。正是他釋放出來的現(xiàn)代化氣息和豐富的用戶體驗(yàn),讓它很快地成為了一個獨(dú)特的插件運(yùn)行在類似flash和silverlight的框架之上。如果你是一個非常年輕的開發(fā)者,也許你是剛剛在開始學(xué)習(xí)html5,所以可能你并沒有注意到他有太大的變化。在任何時候,我希望這篇文章能夠幫助到你,當(dāng)然,也希望像我一樣的老手能從中學(xué)到一些新的花樣。你的點(diǎn)評對我來說非常重要,所以我很期待你的來信。當(dāng)然能讓我更興奮的是當(dāng)你在那個游戲畫面上右擊時暗暗地說一句“hey,這居然不是flash!也不是silverlight!”系統(tǒng)要求想要使用本文提供的html5桌球應(yīng)用,你必須安裝

3、下面的這些瀏覽器:chrome 12, internet explorer 9 or fire fox 5游戲規(guī)則也許你已經(jīng)知道這是一個什么樣的游戲了,是的,這是“英式斯諾克”,實(shí)際上更確切的說是“簡易版英式斯諾克”,因?yàn)闆]有實(shí)現(xiàn)所有的斯諾克游戲規(guī)則。你的目標(biāo)是按順序?qū)⒛繕?biāo)球灌入袋中,從而比其他選手得到更多的分?jǐn)?shù)。輪到你的時候,你就要出桿了:根據(jù)提示,你必須先打進(jìn)一個紅色球得到1分,如果打進(jìn)了,你就可以繼續(xù)打其他的球 - 但是這次你只能打彩色球了(也就是除紅色球以外的球)。如果成功打進(jìn),你將會得到各自彩球?qū)?yīng)的分?jǐn)?shù)。然后被打進(jìn)的彩球會回到球桌上,你可以繼續(xù)擊打其他的紅球。這樣周而復(fù)始,直到你失

4、敗為止。當(dāng)你把所有的紅球都打完以后,球桌上就只剩下6個彩球了,你的目標(biāo)是將這6個彩球按以下順序依次打入袋中:黃(2分)、綠(3分)、棕(4分)、藍(lán)(5分)、粉(6分)、黑(7分)。如果一個球不是按上面順序打進(jìn)的,那它將會回到球桌上,否則,它最終會留在袋里。當(dāng)所有球都打完后,游戲結(jié)束,得分最多的人勝出。犯規(guī)處理為了處罰你的犯規(guī),其他選手將會得到你的罰分: 白球掉入袋中罰4分 白球第一次擊中的球是錯誤的話罰第一個球的分值 第一個錯誤的球掉入袋中罰第一個球的分值 處罰的分?jǐn)?shù)至少是4下面的這段代碼展示了我是如何來計(jì)算犯規(guī)的:1. var strokenballscount =

5、60;0;  2. console.log('strokenballs.length: ' + strokenballs.length);  3.     for (var i = 0; i < strokenballs.length; i+)   4.         var ball 

6、;= strokenballsi;  5.         /causing the cue ball to first hit a ball other than the ball on  6.         if (strokenballscount =

7、 0)   7.             if (ball.points != teamsplayingteamid - 1.ballon.points)   8.                 if (ba

8、ll.points = 1 | teamsplayingteamid - 1.ballon.points = 1 |   9.                 fallenredcount = redcount)   10.      &#

9、160;              if (teamsplayingteamid - 1.ballon.points < 4)   11.                     &#

10、160;   teamsplayingteamid - 1.foullistteamsplayingteamid - 1  12.                         .foullist.length = 4;  13.  &#

11、160;                      $('#gameevents').append('  14. foul 4 points :  expected ' +  15.       &

12、#160;                  teamsplayingteamid - 1.ballon.points + ', but hit ' + ball.points);  16.          &#

13、160;            17.                     else   18.               

14、          teamsplayingteamid - 1.foullistteamsplayingteamid - 1  19.                         .foullist.le

15、ngth = teamsplayingteamid - 1.ballon.points;  20.                         $('#gameevents').append('  21. foul ' + teams

16、playingteamid - 1  22.                         .ballon.points + ' points :  expected ' + teamsplayingteamid 

17、;- 1  23.                         .ballon.points + ', but hit ' + ball.points);  24.       &

18、#160;               25.                     break;  26.            

19、60;      27.               28.           29.    30.         strokenballscount+;  31.     

20、 32.    33.     /foul: causing the cue ball to miss all object balls  34.     if (strokenballscount = 0)   35.         teamsplayin

21、gteamid - 1.foullistteamsplayingteamid - 1.foullist.length = 4;  36.         $('#gameevents').append('  37. foul 4 points :  causing the cue ball   38.  

22、       to miss all object balls');  39.       40.    41.     for (var i = 0; i < pottedballs.length; i+)   42.    

23、;     var ball = pottedballsi;  43.         /causing the cue ball to enter a pocket  44.         if (ball.points = 0)

24、60;  45.             teamsplayingteamid - 1.foullistteamsplayingteamid - 1.foullist.length = 4;  46.             $('#gameevents').ap

25、pend('  47. foul 4 points :  causing the cue ball  48.              to enter a pocket');  49.           50. 

26、0;       else   51.             /causing a ball different than the target ball to enter a pocket  52.      

27、60;      if (ball.points != teamsplayingteamid - 1.ballon.points)   53.                 if (ball.points = 1 | teamsplayingteamid&#

28、160;- 1.ballon.points = 1  54.                  | fallenredcount = redcount)   55.               

29、60;     if (teamsplayingteamid - 1.ballon.points < 4)   56.                         teamsplayingteamid - 1.

30、foullistteamsplayingteamid - 1  57.                         .foullist.length = 4;  58.           

31、60;             $('#gameevents').append('  59. foul 4 points : '  60.                     

32、;     + ball.points + ' was potted, while ' + teamsplayingteamid - 1  61.                       &

33、#160;  .ballon.points + ' was expected');  62.                         $('#gameevents').append('  63. ball.points: 

34、' + ball.points);  64.                         $('#gameevents').append('  65. teamsplayingteamid - 1  66.     

35、;                    .ballon.points: ' + teamsplayingteamid - 1.ballon.points);  67.              

36、60;          $('#gameevents').append('  68. fallenredcount: ' + fallenredcount);  69.                     

37、60;   $('#gameevents').append('  70. redcount: ' + redcount);  71.                       72.        

38、0;            else   73.                         teamsplayingteamid - 1.foullistteamsplayingteamid&#

39、160;- 1  74.                         .foullist.length = teamsplayingteamid - 1.ballon.points;  75.        

40、0;                $('#gameevents').append('  76. foul ' + teamsplayingteamid - 1  77.               

41、;          .ballon.points + ' points : ' + ball.points + ' was potted, while '  78.              &#

42、160;           + teamsplayingteamid - 1.ballon.points + ' was expected');  79.                    

43、0;  80.                   81.               82.           83.      得分我們根據(jù)下面

44、的規(guī)則來計(jì)算得分:紅(1分)、黃(2分)、綠(3分)、棕(4分)、藍(lán)(5分)、粉(6分)、黑(7分)。代碼如下:1. if (teamsplayingteamid - 1.foullist.length = 0)   2.            for (var i = 0; i < pottedballs.length; i+)&

45、#160;  3.                var ball = pottedballsi;  4.                /legally potting reds or colors 

46、0;5.                wonpoints += ball.points;  6.                $('#gameevents').append('  7. potted +' 

47、;+ ball.points + ' points.');  8.              9.          10.        else   11.        

48、;    teamsplayingteamid - 1.foullist.sort();  12.            lostpoints = teamsplayingteamid - 1.foullistteamsplayingteamid - 1.foullist.length - 1;  13.   

49、;         $('#gameevents').append('  14. lost ' + lostpoints + ' points.');  15.          16.        teamsplayingtea

50、mid - 1.points += wonpoints;  17.        teamsawaitingteamid - 1.points += lostpoints; 選手的閃動動畫頭像游戲是有兩位選手參與的,每一位選手都有自己的昵稱和頭像,選手的昵稱我們就簡單地以“player 1”和“player 2”來命名了(也許讓用戶自己輸入會更漂亮)。每位選手的頭像是一只正在打桌球的可愛小狗。當(dāng)輪到其中一位選手時,他的頭像就會

51、有一閃一閃的動畫效果,同時對手的頭像會停止閃動。這個效果我們是通過改變img元素的css3屬性opacity的值來實(shí)現(xiàn)的:我們使用jquery的animatio函數(shù)讓opacity的值在0-1.0之間變化。1. function animatecurrentplayerimage()   2.     var otherplayerimageid = 0;  3.     if (playingteamid = 1)

52、  4.         otherplayerimageid = 'player2image'  5.     else  6.         otherplayerimageid = 'player1image'  7.     var

53、60;playerimageid = 'player' + playingteamid + 'image'  8.     $('#' + playerimageid).animate(  9.         opacity: 1.0  10.     , 5

54、00, function ()   11.         $('#' + playerimageid).animate(  12.             opacity: 0.0  13.         ,&

55、#160;500, function ()   14.             $('#' + playerimageid).animate(  15.                 opacity: 1.0  

56、16.             , 500, function ()   17.             );  18.         );  19.     ); &

57、#160;20.    21.     $('#' + otherplayerimageid).animate(  22.         opacity: 0.25  23.     , 1500, function ()   24.     );  

58、25.  力量控制條一個優(yōu)秀的斯諾克選手都能很好地把握住每一桿的力度.不同的技巧需要不同的擊球方式:直接的,間接的,或者利用邊角的等等。不同方向和不同力度的組合可以構(gòu)造成千上萬種可能的路徑。幸運(yùn)的是,這個游戲提供了一個非常漂亮的力度控制條,可以幫助選手在擊球前調(diào)整他們的球桿。為了達(dá)到這一點(diǎn),我們使用了html5的meter元素標(biāo)簽,它可以完成測量距離的工作。meter標(biāo)簽最好在知道這次測量的最小值和最大值的情況下使用。在我們的這個例子中,這個值在0到100之間,因?yàn)閕e9不支持meter,所以我用了一張背景圖來替代,這樣效果也是一樣的。1. #strengthbar 

59、60;position: absolute; margin:375px 0 0 139px;   2.     width: 150px; color: lime; background-color: orange;   3.     z-index: 5; 當(dāng)你點(diǎn)擊了力度條后,你實(shí)際上是選擇了一個新的力度。一開始你可能不是很熟練,但在真實(shí)世界中,這是需要時

60、間來訓(xùn)練自己的能力的。點(diǎn)擊力度條的代碼如下:1. $('#strengthbar').click(function (e)   2.     var left = $('#strengthbar').css('margin-left').replace('px', '');  3.     var x = e.pagex

61、0;- left;  4.     strength = (x / 150.0);  5.     $('#strengthbar').val(strength * 100);  6. );  在當(dāng)前選手的頭像框里面,你會注意到有一個小球,我叫他“ball on”,就是當(dāng)前選手在規(guī)定時間內(nèi)應(yīng)該要擊打的那個球。如果這個球消失了,那選手將失去4分。同樣如果選手第一次擊中的球不是框內(nèi)顯示的球,那他

62、也將失去4分。這個“ball on”是直接將canvas元素覆蓋在用戶頭像上的,所以你在頭像上看到的那個球,他看起來像是在標(biāo)準(zhǔn)的div上蓋了一個img元素,但是這個球并不是img實(shí)現(xiàn)的。當(dāng)然我們也不能直接在div上畫圓弧和直線,這就是為什么我要將canvas覆蓋到頭像上的原因了??纯创a吧:1. <canvas id="player1ballon" class="player1ballon">   2. </canvas>     <c

63、anvas id="player2ballon" class="player2ballon">   3. </canvas> 1. var player1balloncontext = player1balloncanvas.getcontext('2d');  2. var player2balloncontext = player2balloncanvas.getcontext('2d

64、9;);  3. .  4. .  5. .  6. function renderballon()   7.     player1balloncontext.clearrect(0, 0, 500, 500);  8.     player2balloncontext.clearrect(0, 0, 500, 500);  9.    

65、; if (playingteamid = 1)   10.         if (teams0.ballon != null)  11.             drawball(player1balloncontext, teams0.ballon, new ve

66、ctor2d(30, 120), 20);  12.       13.     else   14.         if (teams1.ballon != null)  15.             drawba

67、ll(player2balloncontext, teams1.ballon, new vector2d(30, 120), 20);  16.         player1balloncontext.clearrect(0, 0, 133, 70);  17.       18.  旋轉(zhuǎn)屋頂上的電風(fēng)扇在這個游戲中這把電風(fēng)扇純屬拿來玩玩有趣一把的。那為什么

68、這里要放一把電風(fēng)扇?是這樣的,這個游戲的名字叫html5斯諾克俱樂部,放一把電風(fēng)扇就有俱樂部的氣氛了,當(dāng)然,我也是為了說明如何實(shí)現(xiàn)css3的旋轉(zhuǎn)。實(shí)現(xiàn)這個非常簡單:首先我們需要一張png格式的電扇圖片。只是我們并沒有用電扇本身的圖片,我們用他的投影。通過顯示風(fēng)扇在球桌上的投影,讓我們覺得它在屋頂上旋轉(zhuǎn),這樣就達(dá)到了我們目的:1. #rooffan  position:absolute; left: 600px; top: -100px; width: 500px; height: 500px;&

69、#160;  2.     border: 2px solid transparent; background-image: url('/content/images/rooffan.png');   3.     background-size: 100%; opacity: 0.3; z-index: 2;  4. .  5. .  6.

70、 .  7. <div id="rooffan"> </div> 為了獲得更為逼真的氣氛,我用paint.net軟件將電扇圖片平滑化了,現(xiàn)在你再也看不到電扇的邊緣了。我覺得這是達(dá)到如此酷的效果最為簡單的辦法。除了用了這圖像處理的把戲,我們僅僅使用了一個帶背景圖的普通的div元素,這并沒有什么特別。既然我們已經(jīng)得到了電扇圖片,我們就要讓它開始旋轉(zhuǎn)了。這里我們使用css3的rotate屬性來實(shí)現(xiàn)這一切。球桿動畫球桿的動畫對于這個游戲也不是必需的,但是這的確為此添加了不少樂趣。當(dāng)你開始用鼠標(biāo)在球桌上移動時,你會注意到

71、球桿的確是跟著你的鼠標(biāo)在轉(zhuǎn)動。這就是說球桿會一直保持跟隨鼠標(biāo)的移動,就像你身臨其境一般真實(shí)。因?yàn)檫x手只能用他的眼睛來瞄準(zhǔn),所以這個效果也會對選手有所幫助。球桿是單獨(dú)一張png圖片,圖片本身不直接以img的形式展現(xiàn),也不以背景的形式展現(xiàn),相反,它是直接展現(xiàn)在一個專門的canvas上的。當(dāng)然我們也可以用div和css3來達(dá)到同樣的效果,但我覺得這樣能更好的說明如何在canvas上展現(xiàn)圖片。首先,canvas元素會占據(jù)幾乎整個頁面的寬度。請注意這個特別的canvas有一個很大的z-index值,這樣球桿就可以一直在每個球的上方而不會被球遮蓋。當(dāng)你在球桌上移動鼠標(biāo)時,目標(biāo)點(diǎn)會實(shí)時更新,這時候球桿圖片會

72、進(jìn)行2次轉(zhuǎn)換:首先,通過計(jì)算得到母球的位置,其次翻轉(zhuǎn)母球周圍的球桿,通過這2步我們就得到了鼠標(biāo)所在點(diǎn)和母球的中心點(diǎn)。1. #cue  position:absolute;   2. .  3. .  4. .  5. if (drawingtopcanvas.getcontext)   6.     var cuecontext = drawingtopcanvas.getcontext('2d'); 

73、0;7.  8. .  9. .  10. .  11. var cuecenter = 15, -4;  12. var cue = new image;  13. cue.src = '<%: url.content("./content/images/cue.png") %>'  14.    15. var shadowc

74、ue = new image;  16. shadowcue.src = '<%: url.content("./content/images/shadowcue.png") %>'  17. cuecontext.clearrect(0, 0, topcanvaswidth, topcanvasheight);  18.    19.     if 

75、;(isready)   20.         cuecontext.save();  21.         cuecontext.translate(cueball.position.x + 351, cueball.position.y + 145);  22.       

76、60; cuecontext.rotate(shadowrotationangle - math.pi / 2);  23.         cuecontext.drawimage(shadowcue, cuecenter0 + cuedistance, cuecenter1);  24.         cuecontext

77、.restore();  25.         cuecontext.save();  26.         cuecontext.translate(cueball.position.x + 351, cueball.position.y + 140);  27.        &#

78、160;cuecontext.rotate(angle - math.pi / 2);  28.         cuecontext.drawimage(cue, cuecenter0 + cuedistance, cuecenter1);  29.         cuecontext.restore();  30. 

79、60;    為了讓球桿變得更真實(shí)我們?yōu)榍驐U添加了投影,并且我們故意讓球桿投影的旋轉(zhuǎn)角度和球桿的角度不一樣,我們這樣做是為了讓球桿有3d的效果。最終的效果實(shí)在是太酷了。推拉球桿這個球桿動畫模仿了真實(shí)人類的特征:你是否看到過斯諾克選手在瞄準(zhǔn)的時候會推拉球桿?我們通過html5改變母球和球桿的距離實(shí)現(xiàn)了這一效果。當(dāng)達(dá)到一個極點(diǎn)是球桿會被拉回來,然后到達(dá)另一個極點(diǎn)時又會被向前推。這樣周而復(fù)始,知道選手停止移動鼠標(biāo)。1. var cuedistance = 0;  2. var cuepulling =

80、 true;  3. .  4. .  5. .  6.         function render()   7.             .  8.             . 

81、60;9.             .  10.    11.             if (cuepulling)   12.               

82、  if (lastmousex = mousex |  13.                 lastmousey = mousey)   14.                

83、;     cuedistance += 1;  15.                   16.                 else   17.  &

84、#160;                  cuepulling = false;  18.                     getmousexy();  19. 

85、60;                 20.               21.             else   22.    23. 

86、60;               cuedistance -= 1;  24.               25.    26.            

87、60;if (cuedistance > 40)   27.                 cuedistance = 40;  28.                 cuepulling&

88、#160;= false;  29.               30.             else if (cuedistance < 0)   31.         

89、60;       cuedistance = 0;  32.                 cuepulling = true;  33.               34.

90、            .  35.             .  36.             . 顯示目標(biāo)路徑當(dāng)選手移動鼠標(biāo)時,我們會在母球和當(dāng)前鼠標(biāo)點(diǎn)之間畫一條虛線。這對選手們長距離瞄準(zhǔn)相當(dāng)?shù)谋憷?。這條

91、目標(biāo)路徑只有在等待用戶擊球時才會顯示:1. if (!cueball.pocketindex)   2.     context.strokestyle = '#888'  3.     context.linewidth = 4;  4.     context.linecap = 'round'  5.  

92、60;  context.beginpath();  6.    7.     /here we draw the line  8.     context.dashedline(cueball.position.x, cueball.position.y, targetx, targety);  9.    10.    &#

93、160;context.closepath();  11.     context.stroke();  12.  需要注意的是在html5 canvas中并沒有內(nèi)置函數(shù)來畫虛線。幸運(yùn)的是有一個叫phrogz的家伙在stackoverflow網(wǎng)站上發(fā)布了一個關(guān)于這個畫虛線的帖子:1. /function kindly provided by phrogz at:  2. /  3. var cp = window.canvas

94、renderingcontext2d && canvasrenderingcontext2d.prototype;  4. if (cp && cp.lineto)   5.     cp.dashedline = function (x, y, x2, y2, dasharray)   6.      &

95、#160;  if (!dasharray) dasharray = 10, 5;  7.         var dashcount = dasharray.length;  8.         this.moveto(x, y);  9.     

96、60;   var dx = (x2 - x), dy = (y2 - y);  10.         var slope = dy / dx;  11.         var distremaining =

97、0;math.sqrt(dx * dx + dy * dy);  12.         var dashindex = 0, draw = true;  13.         while (distremaining >= 0.1)   1

98、4.             var dashlength = dasharraydashindex+ % dashcount;  15.             if (dashlength > distremaining) dashlength

99、60;= distremaining;  16.             var xstep = math.sqrt(dashlength * dashlength / (1 + slope * slope);  17.    18.        

100、     var signal = (x2 > x ? 1 : -1);  19.    20.             x += xstep * signal;  21.       

101、0;     y += slope * xstep * signal;  22.             thisdraw ? 'lineto' : 'moveto'(x, y);  23.       &#

102、160;     distremaining -= dashlength;  24.             draw = !draw;  25.           26.       27.  顯示跟蹤路徑當(dāng)選手擊打

103、母球后,母球會在球桌上留下一條跟蹤線,用來標(biāo)明其上一個點(diǎn)的位置。創(chuàng)建這個跟蹤路徑比前面提到的目標(biāo)路徑復(fù)雜一點(diǎn)。首先我必須去實(shí)例化一個queue對象,這個項(xiàng)目中的queue對象原型由stephen morley提供。1. var tracingqueue = new queue(); 一旦球開始運(yùn)動,我們就將母球的實(shí)時位置壓入這個queue中:1. if (renderstep % 2 = 0)   2.     draw(); 

104、0;3.     enqueueposition(new vector2d(cueball.position.x, cueball.position.y);  4.  enqueueposition函數(shù)確保了我們只保存前20個點(diǎn)的位置,這也就是為什么我們只讓顯示最近的母球的運(yùn)動路徑的原因。1. function enqueueposition(position)   2.     tracingqueue.enqueue(position); &

105、#160;3.     var len = tracingqueue.getlength();  4.    5.     if (len > 20)   6.         tracingqueue.dequeue();  7.       8.  

106、接下來,我們要遍歷queue中的數(shù)據(jù),從而來創(chuàng)建這條跟蹤路徑:1. /drawing the tracing line  2. var lastposx = cueball.position.x;  3. var lastposy = cueball.position.y;  4.    5. var arr = tracingqueue.getarray();  6.    7. if 

107、;(!cueball.pocketindex)   8.     context.strokestyle = '#363'  9.     context.linewidth = 8;  10.     context.linecap = 'round'  11.    12.    &

108、#160;context.beginpath();  13.     var i = arr.length;  14.     while (-i > -1)   15.         var posx = arri.x;  16.      

109、;   var posy = arri.y;  17.         context.dashedline(lastposx, lastposy, posx, posy, 10,200,10,20);  18.         lastposx = posx;  19.  &#

110、160;      lastposy = posy;  20.       21.    22.     context.closepath();  23.     context.stroke();  24.  繪制小球小球和他們的投影都是呈現(xiàn)在一個特殊的canvas上(在球桿canvas下方)。在呈現(xiàn)小球時,我們先要呈現(xiàn)其投

111、影,這樣做主要是為了模擬3d的環(huán)境。每一個小球必須有投影,我們對每個小球的投影位置都會有一點(diǎn)細(xì)微的不同,這些細(xì)微差別表明了小球是在不同方向被投射的,也說明了光源所在的位置。每個小球是由一個公共函數(shù)來畫的,函數(shù)有兩個參數(shù):1)canvas context;2)小球?qū)ο?。函?shù)先畫出一個完整的圓弧然后根據(jù)小球?qū)ο筇峁┑念伾珜⑦@個圓弧線性填充。每一個小球?qū)ο笥?中顏色:光亮色、中色和暗色,這些顏色就是用來創(chuàng)建線性漸變顏色的,3d效果也是這樣做出來的。1. function drawball(context, ball, newposition, newsize)

112、   2.     var position = ball.position;  3.     var size = ball.size;  4.    5.     if (newposition != null)  6.         

113、;position = newposition;  7.    8.     if (newsize != null)  9.         size = newsize;  10.    11.     /main circle  12.    

114、 context.beginpath();  13.     context.fillstyle = ball.color;  14.     context.arc(position.x, position.y, size, 0, math.pi * 2, true);  15.    16.     var gra

115、dient = context.createradialgradient(  17.         position.x - size / 2, position.y - size / 2, 0, position.x,  18.         position.y, siz

116、e );  19.    20.     /bright spot  21.     gradient.addcolorstop(0, ball.color);  22.     gradient.addcolorstop(1, ball.darkcolor);  23.     context.fillstyle = 

117、;gradient;  24.     context.fill();  25.     context.closepath();  26.    27.     context.beginpath();  28.     context.arc(position.x, position.y, size * 0.85, (mat

118、h.pi / 180) * 270,   29.     (math.pi / 180) * 200, true);  30.     context.lineto(ball.x, ball.y);  31.     var gradient = context.createradialgradient( &

119、#160;32.         position.x - size * .5, position.y - size * .5,  33.         0, position.x, position.y, size);  34.    35.   

120、0; gradient.addcolorstop(0, ball.lightcolor);  36.     gradient.addcolorstop(0.5, 'transparent');  37.     context.fillstyle = gradient;  38.     context.fill();  39.  40.    41. function drawballshadow(context, ball)   42.     /main circle  43.     context.beginpath();  44.    

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論