java51游戏_简单实现美空军也得玩的游戏-谁能坚持超过50秒?(Java)
前天不知道又在哪里見到這么一句話“誰能堅(jiān)持超過50秒,我請他吃飯”(可以點(diǎn)擊玩一玩原版游戲),其實(shí)這個(gè)不就是之前在同學(xué)QQ空間里面轉(zhuǎn)來轉(zhuǎn)去的一個(gè)網(wǎng)頁游戲嗎?什么“據(jù)說,美國空軍的飛行員被強(qiáng)制達(dá)到2分鐘?!庇谑?#xff0c;又來了一點(diǎn)點(diǎn)興趣再玩一下下。游戲界面如下:
其實(shí)前段時(shí)間自己也嘗試用 Java 實(shí)現(xiàn)了這游戲,具體是按照自己對這游戲的簡單理解使用 Java GUI 進(jìn)行編程。電腦裝了 JRE 的朋友可以下載附件直接雙擊 .bat 文件試玩一下哦!!!(*^__^*) 嘻嘻……
我的思路是這樣子的(游戲中的方塊用 JLabel 實(shí)現(xiàn)):
1、游戲中4個(gè)自動(dòng)移動(dòng)并且會(huì)慢慢加速的方塊是碰到固定的“壁”就按照光的反射特性改變移動(dòng)的方向,這個(gè)我們可以通過條件判斷來改變方塊的具體坐標(biāo) x 和 y 來實(shí)現(xiàn);
2、自動(dòng)移動(dòng)則用 Java 線程來實(shí)現(xiàn),具體是在線程類的 run() 方法中用死循環(huán)不斷改變 x 和 y 坐標(biāo),然后不斷地擦除、重繪即可,而碰壁之后反射的算法也是包含在這里的;
3、玩家能夠通過按住鼠標(biāo)左鍵來移動(dòng)自己的方塊,這個(gè)應(yīng)該用 java.awt.event 包中的 MouseMotionAdapter 這個(gè)鼠標(biāo)事件監(jiān)聽器類,Java 文檔中的描述是“接收鼠標(biāo)移動(dòng)事件的抽象適配器類”,它包含() 和() 方法,可以監(jiān)聽鼠標(biāo)時(shí)間按,具體的可以查閱一下該類;對于玩家控制的方塊,要每時(shí)每刻都獲取鼠標(biāo)當(dāng)前在面板上的坐標(biāo) x 、y,以此為 JLabel 方塊的中心進(jìn)行不斷擦除、重繪,也就達(dá)到了跟著鼠標(biāo)移動(dòng)的效果了;
4、判斷游戲是否結(jié)束,就是遍歷4個(gè)自動(dòng)移動(dòng)的 JLabel 方塊,看它們在游戲面板中的覆蓋面是否與玩家控制的 JLabel 方塊有一點(diǎn)點(diǎn)重合,重合則說明相碰了,游戲結(jié)束;
5、關(guān)于游戲計(jì)時(shí),這個(gè)可以用到 Java 線程中的 java.util.TimerTask 類來實(shí)現(xiàn),不過這里我的游戲中沒實(shí)現(xiàn),偷懶了一下;
6、至于方塊的移動(dòng)速度,用一定的策略對 Thead.sleep() 方法中的睡眠時(shí)間進(jìn)行減少即可。
我的游戲界面:
1、游戲開始狀態(tài)
2、游戲進(jìn)行中
3、碰壁了,游戲結(jié)束
代碼實(shí)現(xiàn):
GlobalVars.java
//常量接口模式:把系統(tǒng)中相關(guān)的常量放在專門的常量接口中定義
publicinterfaceGlobalVars?{
/**
*?4個(gè)移動(dòng)方向,L、R為左、右,U、D為上、下
*/
publicstaticfinalintLD?=?-1;//往左下方
publicstaticfinalintRD?=1;//往右下方
publicstaticfinalintRU?=2;//往右上方
publicstaticfinalintLU?=?-2;//往左上方
/**
*?游戲窗口大小
*/
publicstaticfinalintFRAME_WIDTH?=500;
publicstaticfinalintFRAME_HEIGTH?=500;
/**
*?面板大小
*/
publicstaticfinalintPANEL_WIDTH?=400;
publicstaticfinalintPANEL_HEIGTH?=400;
/**
*?玩家JLabel的大小
*/
publicstaticfinalintPLAYER_WIDTH?=50;
publicstaticfinalintPLAYER_HEIGTH?=50;
}
ImpMove.java
importjavax.swing.JLabel;
/**
*?定義一個(gè)電腦方、玩家的JLabel都要實(shí)現(xiàn)的
*?移動(dòng)策略的抽象類?ImpMove?,該接口繼承自
*?JLabel,所以可以獲取?JLabel?類中常用?的方法
*?@author?haolloyin
*/
publicabstractclassImpMoveextendsJLabel{
//?移動(dòng)
protectedabstractvoidmove();
//?開始
protectedabstractvoidbegin();
}
ComputerPanel.java
/**
*?電腦控制的?JLabel?方塊,繼承自?ImpMove
*?抽象類,必須實(shí)現(xiàn)其?move()和?begin()方法,
*?它可以在游戲中存在多個(gè)具體實(shí)例,由玩家
*?確定,它使用了線程因此能夠自動(dòng)移動(dòng)
*?@author?haolloyin
*/
publicclassComputerLabelextendsImpMove{
/*?碰到壁必須反彈,這里4個(gè)常量用于
*?判斷電腦方塊碰到那一面壁
*/
privatestaticfinalintPL?=?-1;
privatestaticfinalintPR?=1;
privatestaticfinalintPU?=2;
privatestaticfinalintPD?=?-2;
privateintxx;
privateintyy;
privateintwidth;
privateintheigth;
privatePoint?p;
privateRectangle?r;
privateintdirection;//移動(dòng)方向
privateintspeed?=5;//移動(dòng)速度
privateThread?go;//驅(qū)動(dòng)其移動(dòng)的線程實(shí)例
privatebooleanisLive?=true;//游戲是否結(jié)束
publicComputerLabel(intx,inty,intw,inth,intd)?{
this.width?=?w;
this.heigth?=?h;
init(x,?y,?w,?h,?d);
}
privatevoidinit(intx,inty,intw,inth,intdirection)?{
setBounds(x,?y,?w,?h);
setOpaque(true);
setBackground(Color.green);
r?=?getBounds();
p?=?r.getLocation();
this.direction?=?direction;
}
/**
*??實(shí)現(xiàn)了Runnable接口的私有內(nèi)部類,用于驅(qū)動(dòng)move()方法
*/
privateclassMoveAbleimplementsRunnable?{
publicvoidrun()?{
while(isLive)?{
try{
Thread.sleep(speed);
}catch(InterruptedException?e)?{
e.printStackTrace();
}
//??????????????System.out.println("speed?=?"?+?speed);
move();
}
}
}
/**
*?實(shí)現(xiàn)ImpMove抽象類中的move()
*/
@Override
protectedvoidmove()?{
isPengBi();
p.x?+=?xx;
p.y?+=?yy;
setLocation(p.x,?p.y);
}
/**
*?測試是否碰到壁,若是則調(diào)
*?用changeDirection()改變移動(dòng)方向
*/
privatevoidisPengBi()?{
if(p.x?<0)?{
changeDirection(PL);
}elseif(p.x?>?GlobalVars.PANEL_WIDTH?-?width)?{
changeDirection(PR);
}elseif(p.y?<0)?{
changeDirection(PU);
}elseif(p.y?>?GlobalVars.PANEL_HEIGTH?-?heigth)?{
changeDirection(PD);
}
}
/**
*?碰到壁則反彈,即改變移動(dòng)方向
*/
privatevoidchangeDirection(intpeng)?{
if(peng?==?PL?&&?direction?==?LD)?{//?↙碰左
direction?=?RD;
xx?=1;
yy?=1;
}elseif(peng?==?PL?&&?direction?==?LU)?{//?↖碰左
direction?=?RU;
xx?=1;
yy?=?-1;
}elseif(peng?==?PR?&&?direction?==?RU)?{//?↗碰右
direction?=?LU;
xx?=?-1;
yy?=?-1;
}elseif(peng?==?PR?&&?direction?==?RD)?{//?↘碰右
direction?=?LD;
xx?=?-1;
yy?=1;
}elseif(peng?==?PU?&&?direction?==?RU)?{//?↗碰上
direction?=?RD;
xx?=1;
yy?=1;
}elseif(peng?==?PU?&&?direction?==?LU)?{//?↖碰上
direction?=?LD;
xx?=?-1;
yy?=1;
}elseif(peng?==?PD?&&?direction?==?LD)?{//?↙碰下
direction?=?LU;
xx?=?-1;
yy?=?-1;
}elseif(peng?==?PD?&&?direction?==?RD)?{//?↘碰下
direction?=?RU;
xx?=1;
yy?=?-1;
}
}
/**
*?游戲開始,啟動(dòng)線程
*/
@Override
protectedvoidbegin()?{
go?=newThread(newMoveAble());
toWhere();
go.start();
}
/**
*?確定方塊的移動(dòng)方向
*/
privatevoidtoWhere()?{
if(direction?==?LD)?{
xx?=?-1;
yy?=1;
}elseif(direction?==?LU)?{
xx?=?-1;
yy?=?-1;
}elseif(direction?==?RD)?{
xx?=1;
yy?=1;
}elseif(direction?==?RU)?{
xx?=1;
yy?=?-1;
}
}
/**
*?游戲是否結(jié)束
*/
publicvoidisDead()?{
this.isLive?=false;
}
/**
*?設(shè)置移動(dòng)速度
*/
publicvoidsetSpeed(intspeed)?{
this.speed?=?speed;
}
}
PlayerPanel.java
/**
*?供玩家控制的?JLabel?方塊,它在整個(gè)游戲
*?當(dāng)中只會(huì)存在一個(gè)實(shí)例對象,繼承自?ImpMove
*?抽象類,必須實(shí)現(xiàn)其?move()?和?begin()?方法
*?@author?haolloyin
*/
publicclassPlayerLabelextendsImpMove{
privateRectangle?r;//方塊的大小、位置
privatePoint?now;//方塊的坐標(biāo)x、y
privateintx;//原來的坐標(biāo)?x
privateinty;//原來的坐標(biāo)?y
privateintmax_x?=?PANEL_WIDTH?-?PLAYER_WIDTH;
privateintmax_y?=?PANEL_HEIGTH?-?PLAYER_HEIGTH;
publicPlayerLabel()?{
begin();
}
/**
*?重寫begin()方法,玩家鼠標(biāo)一單擊中間的
*?JLabel?方塊,則游戲開始
*/
@Override
protectedvoidbegin()?{
setText("點(diǎn)擊吧");
setForeground(Color.black);
setSize(PLAYER_WIDTH,?PLAYER_HEIGTH);
setLocation(150,150);
setOpaque(true);
setBackground(Color.green);
r?=this.getBounds();
now?=newPoint();
/**
*?為當(dāng)前JLabel對象添加接收鼠標(biāo)移動(dòng)事件的抽象適配器類,
*?用于當(dāng)按下鼠標(biāo)時(shí)獲取當(dāng)前坐標(biāo)并開始游戲
*/
addMouseMotionListener(newMouseMotionAdapter()?{
publicvoidmouseDragged(MouseEvent?e)?{
x?=?e.getX();
y?=?e.getY();
move();
}
});
/**
*?添加可以變換鼠標(biāo)指針樣式的事件監(jiān)聽器
*/
addMouseListener(newMouseAdapter()?{
publicvoidmouseEntered(MouseEvent?e)?{
//?變成手型鼠標(biāo)
setBackground(Color.yellow);
setCursor(newCursor(Cursor.HAND_CURSOR));
}
publicvoidmouseExited(MouseEvent?e)?{
//?變成默認(rèn)鼠標(biāo)
setBackground(Color.green);
setCursor(newCursor(Cursor.DEFAULT_CURSOR));
}
});
}
/**
*?游戲的主要算法:實(shí)現(xiàn)ImpMove抽象類中的move()
*/
@Override
protectedvoidmove()?{
now?=?MouseInfo.getPointerInfo().getLocation();
if(now.x?%10>4)
now.x?=?now.x?/10+1;
else
now.x?/=10;
if(now.y?%10>4)
now.y?=?now.y?/10+1;
else
now.y?/=10;
r.x?+=?(x?-?now.x);
r.y?+=?(y?-?now.y);
/*
*?如果玩家JLabel方塊碰壁了,則保證其
*?始終緊靠著壁,而不是結(jié)束游戲
*/
if(r.x?<=0)
r.x?=0;
if(r.y?<=0)
r.y?=0;
if(r.x?>?max_x)
r.x?=?max_x;
if(r.y?>?max_y)
r.y?=?max_y;
now.x?=?x;
now.y?=?y;
setBackground(Color.cyan);
setLocation(r.x,?r.y);
}
/**
*?測試
*/
publicstaticvoidmain(String[]?args)?{
JFrame?jf?=newJFrame();
PlayerLabel?p1?=newPlayerLabel();
jf.setLayout(null);//布局設(shè)置為null
jf.add(p1);
jf.setLocation(400,50);
jf.setSize(500,500);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
GamePanel.java
/**
*??游戲的面板,所有JLabel對象都被添加
*??到該面板,由其來具體控制游戲的運(yùn)行,
*??類似于中介者模式中的?Mediator
*?@author?haolloyin
*/
publicclassGamePanelextendsJPanel{
//?保存自動(dòng)移動(dòng)的JLabel對象,即電腦控制的方塊
privateLinkedList?labels;
//?游戲是否結(jié)束
privatebooleanisLive?=true;
//?玩家JLabel
privatePlayerLabel?player;
//游戲進(jìn)行中判斷是否相碰的線程
privateThread?go;
publicGamePanel()?{
setBounds(50,30,?PANEL_WIDTH,?PANEL_HEIGTH);
setBackground(Color.yellow);
setLayout(null);
init();
}
privatevoidinit()?{
labels?=newLinkedList();
player?=newPlayerLabel();
this.add(player);
player.addMouseListener(newMouseAdapter()?{
publicvoidmousePressed(MouseEvent?me)?{
player.setText("我閃...");
startGame();
}
});
}
privatevoidstartGame()?{
intnum?=?labels.size();
for(inti?=0;?i?
labels.get(i).begin();
}
if(this.go?==null)?{
go?=newThread(newCheckGameIsOver());
go.start();
}
}
privatevoidisOver()?{
Rectangle?r_player?=?player.getBounds();
intnum?=?labels.size();
for(inti?=0;?i?
if(labels.get(i).getBounds().intersects(r_player))?{
System.out.println("Game?Over?...");
System.out.println("你碰到第-->?"+?i?+"?
gameOver();
try{
Thread.sleep(2000);
}catch(InterruptedException?e)?{
e.printStackTrace();
}
System.exit(0);
}
}
}
privatevoidgameOver()?{
intnum?=?labels.size();
for(inti?=0;?i?
ComputerLabel?l?=?(ComputerLabel)labels.get(i);
l.isDead();
}
}
privateclassCheckGameIsOverimplementsRunnable?{
publicvoidrun()?{
while(isLive)?{
isOver();
}
}
}
publicvoidaddLabel(ImpMove?label)?{
this.labels.add(label);
this.add(label);
}
}
Game.java
/**
*?最終游戲測試類,其實(shí)就是初始化所有
*?JLabel?對象并啟動(dòng)游戲
*?@author?haolloyin
*/
publicclassGameextendsJFrame?{
publicGame()?{
setTitle("躲避?游戲");
setLayout(null);
setBounds(300,100,?FRAME_WIDTH,?FRAME_HEIGTH);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/*
*?測試
*/
publicstaticvoidmain(String[]?args)?{
GamePanel?gamePanel?=newGamePanel();
ComputerLabel?p1?=newComputerLabel(340,320,35,59,?RU);
ComputerLabel?p2?=newComputerLabel(13,30,40,20,?LU);
ComputerLabel?p3?=newComputerLabel(20,200,60,40,?RD);
ComputerLabel?p4?=newComputerLabel(350,60,70,60,?LD);
ComputerLabel?p5?=newComputerLabel(200,20,10,15,?LD);
p1.setBackground(Color.black);
p2.setBackground(Color.DARK_GRAY);
p3.setBackground(Color.magenta);
p4.setBackground(Color.red);
p5.setBackground(Color.red);
p1.setSpeed(4);
p2.setSpeed(5);
p3.setSpeed(6);
p4.setSpeed(3);
p5.setSpeed(2);
gamePanel.addLabel(p1);
gamePanel.addLabel(p2);
gamePanel.addLabel(p3);
gamePanel.addLabel(p4);
gamePanel.addLabel(p5);
Game?game?=newGame();
game.add(gamePanel);
}
}
小結(jié):
1、各個(gè)類的設(shè)計(jì)、結(jié)構(gòu)感覺很亂;
2、上面的一點(diǎn)還體現(xiàn)在關(guān)于游戲?qū)嶓w(即 JLabel 方塊)所選取的數(shù)據(jù)結(jié)構(gòu)很亂;
3、重要方法如 move() 的代碼過多且雜,本來這是整個(gè)游戲的重點(diǎn)算法實(shí)現(xiàn),卻這樣子糟糕,+_+;
4、代碼中沒有注釋,所以剛才在理解自己的代碼時(shí)花了點(diǎn)時(shí)間,%>_<%…嗯,以后這要注意了。
總結(jié)
以上是生活随笔為你收集整理的java51游戏_简单实现美空军也得玩的游戏-谁能坚持超过50秒?(Java)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鼠标移动小球 Java_js实现跟随鼠标
- 下一篇: mongodb java 学习_Mong