讓你不再僅僅只有玩遊戲的癮,更有玩自己開發的遊戲的“癮”。

此次,小編在學習了多執行緒開發之後,就想著去玩弄一個自己開發的小遊戲,當然,著實本人能力有限,就弄了個簡易版的飛機大戰遊戲。接下來,小編就來講講在開發過程中一些想法和思路。

先來“秀一秀”我的遊戲啦啦啦啦啦啦啦啦

java學習之多執行緒遊戲開發--飛機大戰

這就是我設計的小遊戲,接下來我就按照我在設計中的思路,來分析如何開發這類遊戲。

場景分析:

首先,在開發遊戲的時候,可以想想,遊戲裡面有哪些物件(當然,在最開始的時候,記得不要把事情想得太複雜,還是要循序漸進滴)

在我開發的飛機大戰遊戲中,小編認為主要有三類:敵機,玩家,子彈

但是,如果分別來對這些進行處理的話,會不會感覺太困難了,所以,我們還得簡化

既然如此,那我們就先來不考慮玩家和子彈,只考慮敵機,因為從某種程度上來講,子彈和玩家都是特殊的”敵機“

敵機分析:

首先先來想想敵機有哪些動作

1。隨機生成並在對應位置畫出來 2。 自己移動 3。與玩家碰撞 4。 發射小敵機(子彈)

所以,現在就想想如何來實現這些動作

現在我們在java中藥設計敵機這個類,本人在這裡就說出建立ball類

1。隨機生成並在對應位置畫出來:

怎麼做到隨機生成呢?

https://

zhuanlan。zhihu。com/p/40

400970

這是之前小編在寫多執行緒方面的理解

我們知道在main主方法中,我們如果用一個while迴圈來實現ball在介面上隨機生成的話,那麼在while迴圈之後的程式碼,就無法執行了,所以,在這裡,我們需要建立一個執行緒類來控制小球的生成,小編就設計了public class BallAI extends Thread{}這個方法來實現ball隨機生成。在run()方法中,小編就用了一個while()迴圈來實現ball不斷地生成,即不斷地建立

ball物件

接下來就來思考如何畫出這麼多個ball物件了。

首先是如何儲存在BallAI中生成的ball物件,這裡我就用了佇列ArrayList list來把生成的ball存到一起,之後就是逐個把小球畫出來了

這裡可以在ball類裡面設計一個public void drawball(){}的方法,在獲取窗體的畫布之後,就可以來用Graphics的相關方法來畫出你想要的圖形。

2。自己移動:

首先想到的就是要給ball類speedx,speedy這兩個屬性,這樣ball才能在介面上移動,x+=speedx;y+=speedy;之後,在對應的(x,y)座標上呼叫drawball(){}方法不就行了?

但是這裡會有個問題,ball在移動前已經畫過一次了,現在又畫一次,則會與之前的重複,最後之後導致整個窗體介面全是ball的影象。。。。

當然可以在移動之後,先刪除原來ball物件的影象,再來畫出移動後的影象

那麼,我們應該在哪寫所有ball物件移動的程式碼呢?

main主方法嗎?我們想要ball物件在窗體介面上一直移動,即需要while迴圈來執行,這樣就會出現之前隨機生成小球的問題,所以這裡也需要一個執行緒類

小編就設計了public class Ballmove extends Thread{}這個執行緒類來控制小球的移動。在其中,應該如何來寫while迴圈裡面的程式碼呢?

如上面所說,while迴圈中,遍歷list佇列,先刪去之前的影象,然後再畫出移動後的影象

這樣確實可以,不過如果加上可背景圖片後,如何刪去之前的影象(我們知道,所謂刪去就是拿另一張圖片覆蓋)?

所以小編在這裡就介紹另一種方法:用次畫布的方法

即先在背景圖片上獲取與窗體介面同等大小的次畫布

在while迴圈中,在畫ball物件移動後的影象時,先用次畫布畫出背景圖片,然後遍歷list佇列,畫出移動後的影象,最後,把次畫布畫在窗體介面原來的畫布,這樣就解決了刪去原影象的問題了(也就是用背景圖片覆蓋了原來所有ball物件的圖片的意思)

3。與玩家碰撞

在敵機移動的過程中,必定會發生與另一個ball物件“碰撞”的問題,當然,在小編設計的飛機大戰遊戲中,沒有考慮敵機與敵機之間的碰撞,只考慮了與玩家之間的碰撞。

但不論怎樣,都會發生“碰撞”(其實就是兩者之間的距離小於一定範圍)

所以我們如何來實現“碰撞”?

可以想到的是,在ball物件中,設計一個方法public void crash(){}:遍歷list佇列,將自己與list佇列中其他的ball物件進行距離比較,如若滿足碰撞條件,則發生碰撞;否則跳過。

現在應該在哪裡呼叫crash()這個方法呢?

由於要一直判斷是否發生碰撞,所以應該在ball移動之前,對每一個ball物件呼叫crash()這個方法,所以應該在Ballmove這個執行緒類中,移動方法之前呼叫。

4。隨機發射小敵機(子彈)

現在來考慮如何發射子彈吧

可以這樣認為,子彈就是一個小敵機,故我們可以建立一個bullet類來繼承ball類,這樣之前ball類的方法我們就可以使用了,即之前所說的3個動作都可以實現

小編在ball類中建立了public void attack(){}這個方法,即隨機的建立bullet物件,並將其加入到list佇列中。與前面所講的相同,為了不時地生成bullet,所以在Ballmove執行緒類中,在移動小球之前,呼叫這個attack()方法。

但是這裡會有個問題:crash()這個方法中,不僅敵機會發射子彈,玩家也會發射子彈,如果不對這些子彈進行一定的標記,那麼就會出現自己發射的子彈還沒發射出去,先把自己打死了……

所以,這裡就得進行子彈的標記:1。子彈的發射者 2。子彈的攻擊者

小編在bullet類中,建立了ball這個屬性,用於儲存子彈發射者,這樣子彈就不會傷到自己了

其二,由於在list這個佇列是以ball類來建立的,所以,還得在ball類中設計一個flag標誌,用以標記這個ball物件是敵機,子彈還是玩家

在設計好這些標記以後,就可以在crash()方法中加上對應的if條件,來限制

這裡小編就來說說我設計的遊戲中有幾種碰撞:

(1)敵機與玩家碰撞(可在玩家這個類中寫這種碰撞)

(2)敵機發射的子彈與玩家碰撞(可在玩家這個類中寫這種碰撞)

(3)玩家發射的子彈和敵機碰撞(可在ball類中寫這類碰撞)

在此,小編就來總結一下:

1。設計ball類,其中,會有drawball(), moveball(),crash(),attack()這四個方法,當然還有構造方法,小編的程式碼如下:

public class Ball {

protected int x;

protected int y;

protected int speedx;

protected int speedy;

protected int r;

protected mainframe frame;

// 血量,攻擊力

int blood, attack;

// 用於是否為小球的判斷,0為小球,1為子彈,3為玩家

int balljudge;

public Ball(int x, int y, int speedx, int speedy, int r, mainframe frame, int blood, int attack,int balljudge) {

this。x = x;

this。y = y;

this。speedx = speedx;

this。speedy = speedy;

this。r = r;

this。frame = frame;

this。blood = blood;

this。attack = attack;

this。balljudge = balljudge;

}

//後期可以選擇不同型別的子彈,ball用不同的圖片來做

public void drawball(Graphics g) {

ImageIcon ma = new ImageIcon( “C:\\java圖片\\飛機大戰圖片資源\\戰機。png”);

Image im= ma。getImage();

int r =(int)Math。sqrt(ma。getIconWidth()/2*ma。getIconWidth()/2)*3/4;

this。r = r;

g。drawImage(im, x-ma。getIconWidth()/2, y-ma。getIconHeight()/2, null);

}

public void moveball(ArrayList list) {

if (x <= 0 || x >= frame。getWidth())

speedx *= -1;

if ( y >= frame。getHeight()+r)

list。remove(this);

y += speedy;

}

public void crash(ArrayList list) {

if(this。balljudge == 0){

for (int i = 0; i < list。size(); i++) {

Ball ball = list。get(i);

//小球被玩家的子彈攻擊

if (ball!=null && ball。balljudge == 1 ) {

bullet bullet1 = (bullet) ball;

if(bullet1。ball != this && bullet1。ball。balljudge==3){

double R = Math。abs(r + ball。r);

double l = Math。sqrt((x - ball。x) * (x - ball。x) + (y - ball。y) * (y - ball。y));

if (l < R) {

//System。out。println(“小球被玩家的子彈攻擊”);

blood ——;

list。remove(ball);

if (blood <= 0)

list。remove(this);

}

}

}

}

}

}

public void attack(ArrayList list) {

Random rand = new Random();

int i = rand。nextInt(100);

if (i == 1) {

int tspeedx = 0;//rand。nextInt(10) - 5;

int tspeedy = rand。nextInt(5) +5;;

int tattack = rand。nextInt(5) + 1;

Ball ball = new bullet(x, y, tspeedx, tspeedy, 5, frame, 1, tattack, this, list,color。red );

list。add(ball);

}

}

}

2。設計BallAI執行緒類,控制ball物件的生成

public class BallAI extends Thread{

private ArrayList list;

private mainframe frame;

private Graphics g;

private Random rand;

public BallAI(ArrayList list,mainframe frame,Graphics g){

this。list = list;

this。frame = frame;

this。g = g;

rand = new Random();

}

public void run(){

int i = 0;

while(true){

int x = rand。nextInt(frame。getWidth());

int y = 0;

int r = 20;

int attack = 10;

int blood = 40;

int speedx = 0;

int speedy = rand。nextInt(4)+1;

int sleepTime = rand。nextInt(1000)+1000;

Ball ball = new Ball(x,y,speedx,speedy,r,frame,blood,attack,0); list。add(ball);

try {

Thread。sleep(sleepTime);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e。printStackTrace();

}

i++;

}

}

}

2。設計Ballmove執行緒類,控制ball物件的移動

public class Ballmove extends Thread{

private mainframe frame;

private Graphics g ;

private ArrayList list;

public Ballmove(mainframe frame,Graphics g ,ArrayList list){

this。frame = frame;

this。g = g;

this。list = list;

}

public void run(){

//建立次畫布

ImageIcon ma = new ImageIcon( “C:\\java圖片\\飛機大戰圖片資源\\背景3。jpg”);

Image im= ma。getImage();

Image img = frame。createImage(frame。getWidth(),frame。getHeight());

Graphics ig = img。getGraphics();

while(true){

ig。drawImage(im, 0, 0, frame。getWidth(), frame。getHeight(), 0, 0, ma。getIconWidth(), ma。getIconHeight(), null);

for( int i=0; i < list。size();i++){

Ball ball = list。get(i);

//System。out。println(“i=”+i);

ball。drawball(ig);

ball。attack(list);

//ball。eat(list);

ball。crash(list);

ball。moveball(list);

}

try {

Thread。sleep(10);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e。printStackTrace();

}

//把之前在次畫布上畫好的球畫在窗體畫布

g。drawImage(img, 0, 0, frame);

}

}

}

玩家分析:

分析分析,原本只 分析敵機,沒想到就把子彈也分析了。那麼接下來就來分析玩家吧。

之前,小編說過,從某種程度上來講,玩家就是特殊的敵機,所以,可以像bullet一樣,建立一個Ballgamer這個類繼承Ball類,但是其中得重寫一些方法

玩家的幾個動作:

1。在對應位置畫出來 2。與敵機及其發射的子彈碰撞 3。鍵盤來控制他的移動 3。 鍵盤控制其發射子彈

1這個動作可以直接就用ball類的drawball(){}方法,而2這個動作,在之前分析敵機的時候就已經談過了,就不再闡述,而3和4都是透過鍵盤來控制,所以在這裡就得加上一個監聽器

public class BallListener implements KeyListener{},其中在BallListener中重寫public void keyTyped(KeyEvent e){} , public void keyPressed(KeyEvent e){}, public void keyReleased(KeyEvent e){)這三個方法,用相關的字母來呼叫移動和發射子彈者兩種方法,所以在Ballgamer類中重寫attack()和moveball()這兩個方法,在其中加上一個標誌,這樣在Ballmove執行緒中呼叫相關方法市,就不會呼叫Ballgamer的方法,從而達到鍵盤來控制

在此,小編就來總結一下:

1。設計bullet類,重寫相關方法

public class bullet extends Ball {

Ball ball;

ArrayList list;

Color color;

public bullet(int x, int y, int speedx, int speedy, int r, mainframe frame, int blood, int attack, Ball ball,ArrayList list,Color color) {

super(x, y, speedx, speedy, 5, frame, 1, attack,1);

this。ball = ball;

this。list = list;

this。color = color;

}

public void drawball(Graphics g) {

ImageIcon ma;

if(this。ball。balljudge == 3)

ma = new ImageIcon( “C:\\java圖片\\飛機大戰圖片資源\\bullet1。png”);

else ma= new ImageIcon( “C:\\java圖片\\飛機大戰圖片資源\\bullet2。png”);

Image im= ma。getImage();

int r =(int)Math。sqrt(ma。getIconWidth()/2*ma。getIconWidth()/2)*3/4;

this。r = r;

if(this。ball。balljudge == 3)

g。drawImage(im, x-ma。getIconWidth()/3,y-ma。getIconHeight()/3,x+ma。getIconWidth()/3, y+ma。getIconHeight()/3, 0,0,ma。getIconWidth(),ma。getIconHeight(),null);

else

g。drawImage(im, x-ma。getIconWidth()/17,y-ma。getIconHeight()/17,x+ma。getIconWidth()/17, y+ma。getIconHeight()/17, 0,0,ma。getIconWidth(),ma。getIconHeight(),null);

}

public void attack(ArrayList list) {

}

public void moveball(ArrayList list) {

if (x < 0 || x > frame。getWidth())

list。remove(this);

if (y < 0 || y > frame。getHeight())

list。remove(this);

x += speedx;

y += speedy;

// t+=1;

}

}

1。設計ballgamer類,重寫相關方法

public class Ballgamer extends Ball {

//一個標誌:這樣在Ballmove執行緒中呼叫相關方法市,就不會呼叫Ballgamer的方法,從而達到鍵盤來控制

public boolean flag = false;

static ImageIcon ma = new ImageIcon( “C:\\java圖片\\飛機大戰圖片資源\\飛機1。png”);

Image im= ma。getImage();

static int r =(int)Math。sqrt(ma。getIconWidth()/2*ma。getIconWidth()/2)*3/4;

public Ballgamer(mainframe frame, int speedx, int speedy) {

super(frame。getWidth()/2-30, frame。getHeight()-30, speedx, speedy, r , frame, 100, 200, 3);

}

public void drawball(Graphics g) {

g。drawImage(im, x-ma。getIconWidth()/2, y-ma。getIconHeight()/2, null);

g。setColor(Color。red);

g。fillRect(x - r, y - r - 5, blood, 5);

g。fillRect(0, 70, blood*5, 20);

}

public void moveball(ArrayList list) {

if (x <= 0 ) x=0;

if( x >= frame。getWidth()) x =frame。getWidth();

if (y <= 0 ) y=0;

if( y >= frame。getHeight()) y = frame。getHeight();

}

public void crash(ArrayList list){

for (int i = 0; i < list。size(); i++) {

Ball ball = list。get(i);

//小球與遊戲玩家的撞擊

if(ball!=null && ball。balljudge ==0){

double R = Math。abs(r + ball。r);

double l = Math。sqrt((x - ball。x) * (x - ball。x) + (y - ball。y) * (y - ball。y));

if (l < R) {

System。out。println(“小球與遊戲玩家的撞擊”);

blood ——;

list。remove(ball);

if (blood <= 0)

list。remove(this);

}

}

//玩家被小球的子彈攻擊

if (ball!=null && ball。balljudge == 1 ) {

bullet bullet1 = (bullet) ball;

if(bullet1。ball != this && bullet1。ball。balljudge==0){

double R = Math。abs(r + ball。r);

double l = Math。sqrt((x - ball。x) * (x - ball。x) + (y - ball。y) * (y - ball。y));

if (l < R) {

//System。out。println(“玩家被小球的子彈攻擊”);

blood ——;

list。remove(ball);

if (blood <= 0)

list。remove(this);

}

}

}

}

}

public void attack(ArrayList list) {

if (flag == true && attack >0) {

Ball ball = new bullet(x, y, 0, -2, 5, frame, 1, 2, this, list, Color。blue);

list。add(ball);

flag = false;

}

}

}

3。設計監聽器,在此小編就不展示自己的程式碼了

窗體:

在設計好這幾個類之後,我們好像忘了一個最最最最最基本的東西——窗體了。。。。。

所以在寫上面的幾個類之前,大家一定要先建立一個窗體類:

1。在窗體類中顯示介面,並建立Ballgamer物件,將其加入list佇列

2。例項化BallAI執行緒類,用於隨機生成敵機

3。例項化Ballmove執行緒類,用於實現移動,碰撞,發射子彈這些動作

程式碼如下:

public class mainframe extends JFrame {

private ArrayList list = new ArrayList();

public Graphics g;

Random rand = new Random();

public void showui(){

this。setSize(1500,1000);

this。setTitle(“飛機大戰”);

this。setDefaultCloseOperation(3);

this。setLocationRelativeTo(null);

String path = “C:\\java圖片\\飛機大戰圖片資源\\背景3。jpg”;

ImageIcon background = new ImageIcon(path);

JLabel label = new JLabel(background);

label。setBounds(0, 0, this。getWidth(),this。getHeight());

JPanel imagePanel = (JPanel) this。getContentPane();

imagePanel。setOpaque(false);

this。getLayeredPane()。add(label, new Integer(Integer。MIN_VALUE));

this。setVisible(true);

g = this。getGraphics();

Ballgamer ballgamer = new Ballgamer(this,0,0);

list。add(ballgamer);

BallListener l = new BallListener(ballgamer,this。list);

this。addKeyListener(l);

//用於生成小球的執行緒

BallAI ballai = new BallAI(this。list, this, this。g);

ballai。start();

//用於小球移動的執行緒

Ballmove ballmove = new Ballmove(this, this。g, this。list);

ballmove。start();

}

public static void main(String[] arg) throws FileNotFoundException,

IOException{

mainframe frame = new mainframe();

frame。showui();

}

}

當然,可能大家會看的很雲裡霧裡的。小編主要先從ball 類入手,先分析ball類中會用到哪些方法,然後從ball類展開來講繼承ball類的bullet類和Ballgamer類,其中講了這兩個類中要重寫的方法,最後再總體來介紹窗體中啟動哪些執行緒。

其實,最最最最最最重要的就是自己去寫一遍吧,當你把這些都寫下來,你就會明白其中的關係。本人只涉及了飛機大戰這個遊戲,你也可以設計小球碰撞等遊戲,還可以更加完善,比如增加闖關功能,登入功能等,小編就不一一闡述了,一切只看你發揮了!