下面來完成桌面彈球游戲中最關鍵的一個類BallService(業務處理類)。
編寫draw方法,分別將擋板、彈球、磚塊、道具在畫板中繪制出來,當游戲勝出,繪制勝出畫面,當玩家失敗,繪制失敗畫面。
?
擋板和彈球不難繪制,下面主要看下磚塊和道具的繪制。
磚塊類與控制臺五子棋中的棋盤類很相似,可以用二維數組來表示所有的磚塊,磚塊的位置是不發生變化的,也就說不會涉及元素的移動,所以使用二維數組來表示是合理的。
在繪制磚塊的時候,涉及兩個問題,一個是創建和初始化磚塊數組,另一個是繪制磚塊。
?
在創建磚塊的過程中,要掌握初始化二維數組和二重循環的知識。磚塊的創建是有技巧的,首先磚塊不是擺滿的,假設這里設成11列6行,并且空缺的磚塊是隨機產生的,畫板的寬度已設定為307,因此11列表示每塊磚的大小為28,所以根據每塊磚的大小、列號、行號就可以計算磚塊的坐標:
x = i*imageSize;
y = j*imageSize;
那么如何決定哪些坐標有磚塊,哪些坐標沒有磚塊呢?
通過隨機函數Math.random()來決定
isDisable = Math.random()>0.8?true:false;
每個磚塊還有類型,0表示普通磚塊,沒有魔法,1表示變長魔法,2表示變短魔法
那么如何決定哪些磚塊有魔法,哪些沒有呢?
當然初始化時沒有顯示出來的磚塊一定是沒有魔法,其余的磚塊還是使用隨機函數來決定是否有魔法。
?
if(isDisable){ //如果該磚塊不存在,其魔法也不存在 random = 0; } random = (int)(Math.random()*3);
還需要注意的是在設置磚塊的坐標的時候,如果該磚塊有道具,還要設置道具的坐標。同樣,在繪制磚塊時,還要注意為有道具的磚塊繪制相應的道具。
繪制磚塊和道具的時候,分別使用了兩個畫圖方法:
drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)
繪制指定圖像中已縮放到適合指定矩形內部的圖像。
drawImage(Image img, int x, int y, ImageObserver observer)
繪制指定圖像中當前可用的圖像。
?
判斷玩家是否勝出的方法,其實很簡單,就是所有的磚塊的狀態都變為了不可用時,也就是所有磚塊都被消除時,玩家就勝出了。
?
碰撞檢測問題
1.彈球是否與磚塊有碰撞
?當磚塊的中心與彈球的中心兩點之間的距離小于n+r 時,就認為磚塊與彈球碰撞上了。
2.道具或者彈球是否與擋板有碰撞:
判斷道具與擋板是否碰撞上和判斷彈球與擋板是否碰撞上的方法是一樣的,碰撞檢測的方法是這樣設計的:
public boolean isHitStick(BallComponent bc)
不管是彈球實例還是道具實例都可以使用該方法。
小球最左面的點的橫坐標最大不能超過檔板的最右面點的橫坐標(藍線標記)
并且
小球最右面的點的橫坐標最小不能小于檔板的最左面點的橫坐標(紅線標記)
并且
小球最下面的點的縱坐標大于擋板的縱坐標
?
同時滿足了以上三個條件,就認為彈球與擋板相撞了。
?
坐標變換
?
下面是時候讓擋板、彈球、道具動起來了,擋板是靠玩家鍵盤操作控制的,而小球和道具則由程序來控制,下面分別實現擋板、小球、道具的坐標變換。
1.設置擋板圖片的位置
判斷鍵盤輸入,來作出相應的處理。
2.設置道具的位置
3.實施魔法
調用magicDo(Stick stick)來實現。
4.設置彈球圖片的位置
在移動彈球之前,先要保證小球的移動是合法的,也就是要判斷彈球移動后,是否會碰到上、下、左、右邊界。其中還有彈球碰到磚塊、彈球碰到擋板這些特殊情況。
當彈球碰到左邊界時,要將彈球的運動的X軸方向變為向右;
當彈球碰到右邊界時,要將彈球的運動的X軸方向變為向左;
當彈球碰到上邊界,要將彈球的運動Y軸方向改變為向下;
當彈球碰到擋板或者磚塊時,都要改變彈球的Y軸方向為相反方向;
?
如果ball.getSpeedY()為正時,彈球向上運動,相反,如果ball.getSpeedY()為負時,向下
所以初始狀態時,
private int speedX = 10;
private int speedY = 8;
彈球會向上走,這也就是玩家一移動擋板時,小球就向上走。
?
設定彈球的坐標:
// 設置x坐標 ball.setX(ball.getX() - (int) (Math.random() * 2)- ball.getSpeedX()); // 設置y坐標 ball.setY(ball.getY() - (int) (Math.random() * 2)- ball.getSpeedY());
?
調試
?
程序寫完了,但是發現總是沒有道具出現,初步判斷創建磚塊時,沒有創建出類型為1或2的帶魔法的磚塊,發現在創建和設置磚塊createBrickArr()中,打印出random,結果發現random這個值一直是0。
于是發現是這條語句發生了錯誤:
//創建一個新的磚塊 random = (int)Math.random()*3;
應該是:
random = (int)(Math.random()*3);
?馬上檢查了程序中其它使用Math.random()的代碼,發現了并改正了:
//設置小球的坐標 ball.setX(ball.getX()-ball.getSpeedX()-(int)(Math.random()*2)); ball.setY(ball.getY()-ball.getSpeedY()-(int)(Math.random()*2));
怪不得在測試過程中總感覺小球的路徑變化不大的緣故,因為如果不加括號的話,這個值(int)Math.random()*2也總是0。改正了上面存在的問題后,發現之前的問題是解決了,但是落下來的道具竟然是磚塊!
找到LongMagic這個類,發現magicDo方法中:
double imageWidth = this.getImage().getWidth(null);
應該是:
double imageWidth = stick.getImage().getWidth(null); //當擋板沒有變長過 if (stick.getPreWidth()<=imageWidth){ //加長變為原來的兩倍 stick.setPreWidth((int)(stick.getPreWidth()*2)); // System.out.println("變長了"); }?
打包
?
打包后運行,遇到Exception in thread "main" javax.imageio.IIOException: Can't read input file!錯誤。
?
在Eclipse中開發時,使用的是以當前工作路徑為基準來尋找圖片文件的:
stick = new Stick(width,height,"img/stick.jpg");
?在創建Image圖像時,使用的如下方法:
this.image = ImageIO.read(new File(path));?
但是打包后,當前用戶路徑有可能發生變化,因此無法找到圖片,解決辦法是使用以當前類為基準的路徑指定方式。
this.image = ImageIO.read(getClass().getResource(path));
這時就可以找到圖片了。
為了確定指定的路徑是否正確,可以打印出來:
System.out.println(getClass().getResource(path).toString());
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
