Java編程經(jīng)典小游戲設(shè)計(jì)-打磚塊小游戲源碼
[程序中使用的數(shù)據(jù)結(jié)構(gòu)和符號(hào)說(shuō)明]
HitBrick類
GreenBallThread控制小球路線
xUp,yUp,bouncing定義變量存儲(chǔ)16位數(shù)值形式
x,y小球坐標(biāo)
xDx,yDy坐標(biāo)增量
MAX_X,MAX_Y坐標(biāo)最大值
renew初始化
label標(biāo)簽
Rx,Ry橫板坐標(biāo)
Brick[]磚塊
ball小球
HitBrick()定義小球橫板及磚塊位置坐標(biāo)
keyPressd(keyEent)定義小球啟動(dòng)鍵(按空格鍵啟動(dòng))
keyReleased(keyEvent)接收鍵盤(pán)事件偵聽(tīng)器接口)
keyTyped(keyEvent)鍵入空格鍵時(shí)調(diào)用keyEvent
paint(Graphics)對(duì)磚塊填充顏色
move定義小球的運(yùn)動(dòng)軌跡和磚塊的消失
main主函數(shù)
BallThread類
通過(guò)繼承Thread類使Ball類線程化,并把小球的彈跳動(dòng)作放進(jìn)Run()中執(zhí)行
Brick類
定義磚塊坐標(biāo)位置和磚塊按鈕
Ball類
定義小球坐標(biāo)位置
[程序設(shè)計(jì)流程]
程序中使用的部分方法解釋
開(kāi)始命令:空格鍵
privateJLabellabel;定義一個(gè)標(biāo)簽,label=newJLabel("按空格鍵開(kāi)始");內(nèi)容為空格鍵開(kāi)始,addKeyListener(this);定義一個(gè)鍵盤(pán)監(jiān)聽(tīng)器,
if (e.getKeyCode() ==e.VK_SPACE) { if(renew){ greenBallThread=new BallThread(this); bouncing = true; greenBallThread.start(); label.setVisible(false); } renew=false; }
重置并開(kāi)始游戲
移動(dòng)命令:方向鍵左鍵和右鍵
if(e.getKeyCode()==e.VK_LEFT){ Rx=Rx-20; if(bouncing){ if(Rx<0){ Rx=0; } } else{ if(Rx<0){ Rx=0; } else{ x=x-20; ball.ball_x=x; } } repaint(); }
同開(kāi)始命令原理,如果鍵入左鍵,橫版向左移動(dòng)20個(gè)單位(Rx為橫板坐標(biāo)),如果小球還在運(yùn)動(dòng),當(dāng)橫板移到最左側(cè)(Rx=0),不能再向左移動(dòng),則橫板靠在最左側(cè)(Rx=0),
if(e.getKeyCode()==e.VK_RIGHT){ Rx=Rx+20; if(bouncing){ if(Rx+80>300){ Rx=220; } } else{ if(Rx+80>300){ Rx=220; } else{ x=x+20; ball.ball_x=x; } } repaint(); } }
向右移動(dòng)同向左移動(dòng)原理,因?yàn)槎x界面橫坐標(biāo)最大值為300,橫板長(zhǎng)度80,故Rx=220時(shí)碰最右側(cè)
磚塊設(shè)定:
brick[0]=new Brick(0,60,50,20); brick[1]=new Brick(50,60,50,20); brick[2]=new Brick(100,60,50,20); …… brick[16]=new Brick(200,160,50,20); brick[17]=new Brick(250,160,50,20); ball=new Ball(150,450,10,10);
public void paint(Graphics g){ super.paint(g); ball.rect.setLocation(x,y); if(bouncing){ for(int i=0;i<=17;i++){ if(brick[i].visible==true){ switch(i){ case 0 :g.setColor(Color.blue); break; case 1 :g.setColor(Color.cyan); break; case 2 :g.setColor(Color.gray); break; …… case 17 :g.setColor(Color.yellow); break; } g.fill3DRect(brick[i].brick_x,brick[i].brick_y,brick[i].brick_width,brick[i].brick_height,true); } } g.setColor(Color.red); g.fillOval(x, y, 10, 10); g.setColor(Color.blue); g.fillRect(Rx,Ry,80,20);
brick[0]=newBrick(0,60,50,20);設(shè)置磚塊坐標(biāo),ball=newBall(150,450,10,10);和小球的坐標(biāo)
if(brick[i].visible==true)判斷磚塊存在,用switch語(yǔ)句,逐個(gè)對(duì)磚塊填充顏色,最后四行代碼是分別對(duì)小球和橫板顏色坐標(biāo)的定義
小球的移動(dòng):
try{ Thread.currentThread().sleep(25); } catch(InterruptedException exception){ System.err.println(exception.toString()); }
定義小球的速度,若發(fā)生錯(cuò)誤,則執(zhí)行catch語(yǔ)句,打印錯(cuò)誤
for(int i=0;i<=17;i++){ if(ball.rect.intersects(brick[i].rect)&&brick[i].visible){ brick[i].visible=false; yUp=!yUp;/ } }
當(dāng)小球接觸到磚塊時(shí),磚塊不可見(jiàn)(消失)
if(x+5>Rx&&x+5<Rx+80&&y+10>=Ry){ yUp=false; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); }
判斷小球坐標(biāo)和橫板坐標(biāo),當(dāng)小球落在橫板坐標(biāo)之內(nèi),小球反彈,小球橫坐標(biāo)和縱坐標(biāo)都以一個(gè)隨機(jī)值改變后運(yùn)動(dòng)
if(xUp==true){ x+=xDx; } else{ x-=xDx; } if(yUp==true){ y+=yDy; } else{ y-=yDy; }
判斷小球橫坐標(biāo)如果在增加,小球橫坐標(biāo)=小球原橫坐標(biāo)+小球橫坐標(biāo)增量,否則小球橫坐標(biāo)=小球原橫坐標(biāo)-小球橫坐標(biāo)增量;縱坐標(biāo)同理
if(y<=0){ y=0; ball.ball_y=y; yUp=true; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); } else if(y>=MAX_Y-15){ yDy=(int)(Math.random()*5+2); //yUp=false; break; }
判斷小球到畫(huà)面頂部(定義頂部的縱坐標(biāo)為0),小球向下反彈,原理同小球和橫板接觸的反彈規(guī)則,否則,判斷小球縱坐標(biāo)是否大于MAX_Y-15(縱坐標(biāo)最大值-15),反彈規(guī)則改變?yōu)闄M坐標(biāo)不變,縱坐標(biāo)隨機(jī)改變
if(x<=0){ x=0; ball.ball_x=x; xUp=true; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); } else if(x>=MAX_X-10){ x=MAX_X-10; ball.ball_x=x; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); xUp=false; }
判斷小球到畫(huà)面最左側(cè)(定義最左側(cè)橫坐標(biāo)為0),向右側(cè)反彈,反彈規(guī)則同小球和橫板接觸的反彈規(guī)則,或者小球到畫(huà)面最右側(cè),向左反彈,反彈規(guī)則同上,(if(x>=MAX_X-10)判斷小球是否到右邊側(cè),小球的直徑為10)
int i; for(i=0;i<=17&&brick[i].visible==false;i++){ } if(i==18){ break; }
如果所有磚塊都不可見(jiàn),則重新玩
renew=true; //初始化 bouncing=false; for(int i=0;i<=17;i++){ brick[i].visible=true; } xUp=true; yUp=false; xDx=1; yDy=1; x=150; y=450; Rx=120; Ry=460; //
重新開(kāi)始,初始化,小球靜止,所有磚塊可見(jiàn),小球在橫坐標(biāo)方向,可隨橫板移動(dòng)而移動(dòng),縱坐標(biāo)在未開(kāi)時(shí)游戲前不能改變,定義小球橫坐標(biāo)和縱坐標(biāo)增量都為1,小球初始位置坐標(biāo)(150,450)橫板初始位置坐標(biāo)(120,460)
[源程序]
import java.awt.*; import javax.swing.*; import java.awt.event.*; import javax.swing.event.*; public class HitBrick extends JFrame implements KeyListener{ private BallThread greenBallThread; //控制小球的線程 private Boolean xUp,yUp,bouncing; private int x,y,xDx,yDy; //小球坐標(biāo),增量 private final int MAX_X=300,MAX_Y=500; private Boolean renew; private JLabel label; private int Rx,Ry; //橫板坐標(biāo) private Brick brick[]=new Brick[18]; //磚塊 private Ball ball; //小球 public HitBrick(){ super("打磚塊"); Container pane=getContentPane(); //設(shè)置空白面板容器 label=new JLabel("按空格鍵開(kāi)始"); //標(biāo)簽 label.setHorizontalAlignment(JLabel.CENTER); //水平 label.setVerticalAlignment(JLabel.BOTTOM); //垂直 pane.add(label); //向面板里添加標(biāo)簽 xUp=true; //橫坐標(biāo)可以移動(dòng) yUp=false; //縱坐標(biāo)不可以移動(dòng) xDx=1; yDy=1; x=150; //小球坐標(biāo) y=450; Rx=120; //橫板坐標(biāo) Ry=460; renew=true; bouncing=false; addKeyListener(this); //鍵盤(pán)監(jiān)聽(tīng)器 brick[0]=new Brick(0,60,50,20); //磚塊坐標(biāo) brick[1]=new Brick(50,60,50,20); brick[2]=new Brick(100,60,50,20); brick[3]=new Brick(150,60,50,20); brick[4]=new Brick(200,60,50,20); brick[5]=new Brick(250,60,50,20); brick[6]=new Brick(0,90,50,20); brick[7]=new Brick(50,110,50,20); brick[8]=new Brick(100,130,50,20); brick[9]=new Brick(150,130,50,20); brick[10]=new Brick(200,110,50,20); brick[11]=new Brick(250,90,50,20); brick[12]=new Brick(0,160,50,20); brick[13]=new Brick(50,160,50,20); brick[14]=new Brick(100,160,50,20); brick[15]=new Brick(150,160,50,20); brick[16]=new Brick(200,160,50,20); brick[17]=new Brick(250,160,50,20); ball=new Ball(150,450,10,10); //球的坐標(biāo) setSize(MAX_X,MAX_Y); //窗口大小 setResizable(false); setVisible( true ); //可視化 } public void keyPressed(KeyEvent e) { if (e.getKeyCode() ==e.VK_SPACE) { if(renew){ greenBallThread=new BallThread(this); bouncing = true; greenBallThread.start(); label.setVisible(false); } renew=false; } if(e.getKeyCode()==e.VK_LEFT){ Rx=Rx-20; if(bouncing){ if(Rx<0){ Rx=0; } } else{ if(Rx<0){ Rx=0; } else{ x=x-20; ball.ball_x=x; } } repaint(); } if(e.getKeyCode()==e.VK_RIGHT){ Rx=Rx+20; if(bouncing){ if(Rx+80>300){ Rx=220; } } else{ if(Rx+80>300){ Rx=220; } else{ x=x+20; ball.ball_x=x; } } repaint(); } } public void keyReleased (KeyEvent e) { } public void keyTyped (KeyEvent e){ } public void paint(Graphics g){ super.paint(g); ball.rect.setLocation(x,y); if(bouncing){ for (int i=0;i<=17;i++){ if(brick[i].visible==true){ switch(i){ case 0 :g.setColor(Color.blue); break; case 1 :g.setColor(Color.cyan); break; case 2 :g.setColor(Color.gray); break; case 3 :g.setColor(Color.green); break; case 4 :g.setColor(Color.magenta); break; case 5 :g.setColor(Color.yellow); break; case 6 :g.setColor(Color.white); break; case 7 :g.setColor(Color.black); break; case 8 :g.setColor(Color.orange); break; case 9 :g.setColor(Color.pink); break; case 10 :g.setColor(Color.darkGray); break; case 11 :g.setColor(Color.red); break; case 12 :g.setColor(Color.blue); break; case 13 :g.setColor(Color.cyan); break; case 14 :g.setColor(Color.gray); break; case 15 :g.setColor(Color.green); break; case 16 :g.setColor(Color.magenta); break; case 17 :g.setColor(Color.yellow); break; } g.fill3DRect(brick[i].brick_x,brick[i].brick_y,brick[i].brick_width,brick[i].brick_height,true); } } g.setColor(Color.red); g.fillOval(x, y, 10, 10); g.setColor(Color.blue); g.fillRect(Rx,Ry,80,20); } else{ for (int i=0;i<=17;i++){ switch(i){ case 0 :g.setColor(Color.blue); break; case 1 :g.setColor(Color.cyan); break; case 2 :g.setColor(Color.gray); break; case 3 :g.setColor(Color.green); break; case 4 :g.setColor(Color.magenta); break; case 5 :g.setColor(Color.yellow); break; case 6 :g.setColor(Color.white); break; case 7 :g.setColor(Color.black); break; case 8 :g.setColor(Color.orange); break; case 9 :g.setColor(Color.pink); break; case 10 :g.setColor(Color.darkGray); break; case 11 :g.setColor(Color.red); break; case 12 :g.setColor(Color.blue); break; case 13 :g.setColor(Color.cyan); break; case 14 :g.setColor(Color.gray); break; case 15 :g.setColor(Color.green); break; case 16 :g.setColor(Color.magenta); break; case 17 :g.setColor(Color.yellow); break; } g.fill3DRect(brick[i].brick_x,brick[i].brick_y,brick[i].brick_width,brick[i].brick_height,true); } g.setColor(Color.red); g.fillOval(x, y, 10, 10); g.setColor(Color.blue); g.fillRect(Rx, Ry, 80, 20); } } public void move(){ while(true){ try{ Thread.currentThread().sleep(25); } catch(InterruptedException exception){ System.err.println(exception.toString()); } for (int i=0;i<=17;i++){ if(ball.rect.intersects(brick[i].rect)&&brick[i].visible){ brick[i].visible=false; yUp=!yUp; //打到球不可見(jiàn) } } if(x+5>Rx&&x+5<Rx+80&&y+10>=Ry){ yUp=false; xDx=(int)(Math.random()*5+2); //小球坐標(biāo)增量 yDy=(int)(Math.random()*5+2); } if(xUp==true){ x+=xDx; //小球左右移動(dòng)坐標(biāo)改變 } else{ x-=xDx; } if(yUp==true){ y+=yDy; } else{ y-=yDy; } if(y<=0){ y=0; ball.ball_y=y; yUp=true; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); } else if(y>=MAX_Y-15){ yDy=(int)(Math.random()*5+2); //yUp=false; break; } if(x<=0){ x=0; ball.ball_x=x; xUp=true; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); } else if(x>=MAX_X-10){ x=MAX_X-10; ball.ball_x=x; xDx=(int)(Math.random()*5+2); yDy=(int)(Math.random()*5+2); xUp=false; } ball.rect.setLocation(ball.ball_x,ball.ball_y); repaint(); int i; //如果所有磚塊都不可見(jiàn) for (i=0;i<=17&&brick[i].visible==false;i++){ //則重新玩 } if(i==18){ break; } // } renew=true; //初始化 bouncing=false; for (int i=0;i<=17;i++){ brick[i].visible=true; } xUp=true; yUp=false; xDx=1; yDy=1; x=150; y=450; Rx=120; Ry=460; // repaint(); repaint(); label.setVisible(true); } public static void main(String[] args) { HitBrick mar=new HitBrick(); } } class BallThread extends Thread{ private HitBrick m; BallThread(HitBrick a){ //super(); m=a; } public void run(){ m.move(); m.repaint(); } } class Brick{ Rectangle rect=null; //長(zhǎng)方形對(duì)象,磚塊按鈕的位置和寬高 int brick_x,brick_y; //按扭的左上角坐標(biāo) int brick_width,brick_height; //按扭的寬和高 Boolean visible; public Brick(int x,int y,int w,int h) { brick_x=x; brick_y=y; brick_width=w; brick_height=h; visible=true; rect=new Rectangle(x,y,w,h); //創(chuàng)建長(zhǎng)方形對(duì)象---磚塊按鈕的位置和寬高。 } } class Ball{ Rectangle rect=null; int ball_x,ball_y; int ball_width,ball_height; public Ball(int x,int y,int w,int h){ ball_x=x; ball_y=y; ball_width=w; ball_height=h; rect=new Rectangle(x,y,w,h); } }
運(yùn)行結(jié)果:
空格鍵開(kāi)始,方向鍵控制左右,死亡重新開(kāi)始。
雖然系統(tǒng)的基本功能都已實(shí)現(xiàn),但還是存在系統(tǒng)不穩(wěn)定等多個(gè)bug尚待解決。在做系統(tǒng)的過(guò)程中遇到了很多問(wèn)題,有的是知識(shí)存儲(chǔ)不足,有的是考慮不夠周全,所以學(xué)習(xí)之路永無(wú)止境。作為一個(gè)程序編程人員,要保持清醒的頭腦,以現(xiàn)實(shí)為依據(jù),讓自己的每一行代碼都能實(shí)現(xiàn)自己的意義。
總結(jié)
以上就是本文關(guān)于Java編程經(jīng)典小游戲設(shè)計(jì)-打磚塊小游戲源碼的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:JavaWeb項(xiàng)目中dll文件動(dòng)態(tài)加載方法解析(詳細(xì)步驟)、python基礎(chǔ)練習(xí)之幾個(gè)簡(jiǎn)單的游戲等,有什么問(wèn)題可以隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。感謝朋友們對(duì)本站的支持!
相關(guān)文章
java中的Arrays這個(gè)工具類你真的會(huì)用嗎(一文秒懂)
這篇文章主要介紹了java中的Arrays這個(gè)工具類你真的會(huì)用嗎,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Java封裝數(shù)組實(shí)現(xiàn)包含、搜索和刪除元素操作詳解
這篇文章主要介紹了Java封裝數(shù)組實(shí)現(xiàn)包含、搜索和刪除元素操作,結(jié)合實(shí)例形式分析了java針對(duì)數(shù)組元素的查找、刪除、判斷等相關(guān)操作封裝與使用技巧,需要的朋友可以參考下2020-03-03springboot3請(qǐng)求參數(shù)種類及接口測(cè)試案例小結(jié)
這篇文章主要介紹了springboot3請(qǐng)求參數(shù)種類及接口測(cè)試案例小結(jié),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-10-10SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了SpringMVC文件上傳原理及實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Java保留兩位小數(shù)的實(shí)現(xiàn)方法
這篇文章主要介紹了 Java保留兩位小數(shù)的實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2017-06-06如何使用@Slf4j和logback-spring.xml搭建日志框架
這篇文章主要介紹了如何使用@Slf4j和logback-spring.xml搭建日志框架問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06淺談resultMap的用法及關(guān)聯(lián)結(jié)果集映射
這篇文章主要介紹了resultMap的用法及關(guān)聯(lián)結(jié)果集映射操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06