慈溪仲嫉娱乐有限公司

java飛機(jī)大戰(zhàn)心得體會(huì)

| 小揚(yáng)21147

心得體會(huì)是指一種讀書(shū)、實(shí)踐后所寫(xiě)的感受性文字。語(yǔ)言類讀書(shū)心得同數(shù)學(xué)札記相近;體會(huì)是指將學(xué)習(xí)的東西運(yùn)用到實(shí)踐中去,通過(guò)實(shí)踐反思學(xué)習(xí)內(nèi)容并記錄下來(lái)的文字,近似于經(jīng)驗(yàn)總結(jié)。下面是小編帶來(lái)的有關(guān)java飛機(jī)大戰(zhàn)心得體會(huì),希望大家喜歡

java飛機(jī)大戰(zhàn)心得體會(huì)1

1.首先有玩家類,窗口類,主函數(shù)類和圖片文件(.jpg)

2.然后是先行知識(shí),創(chuàng)建窗口(JFrame),設(shè)置窗口屬性;窗口上不能直接添加組件(鍵盤(pán)監(jiān)聽(tīng)等),所以先在窗口上添加容器(Jpanel),將組件(KeyAdapter)添加到容器;

3.畫(huà)出玩家:重寫(xiě)窗口類中的paintComponent方法,創(chuàng)建Graphics對(duì)象,調(diào)用drawImage方法可畫(huà)圖,調(diào)用drawString方法可標(biāo)注其名字

4.移動(dòng):在窗口類中創(chuàng)建鍵盤(pán)監(jiān)聽(tīng)抽象類KeyAdapter(實(shí)現(xiàn)了接口的部分方法但無(wú)具體操作),需要重寫(xiě)該類的Keypressed方法和KeyRleased方法,賦給按鍵變量真值,隨后將該對(duì)象添加到窗口

5.隨機(jī)生成初始坐標(biāo):在開(kāi)始游戲后隨機(jī)給定玩家的x、y坐標(biāo),創(chuàng)建Random對(duì)象,調(diào)用Random.nextInt(n)方法,n代表從[0,n)區(qū)間的隨機(jī)值。

6.最后通過(guò)一個(gè)Timer.schedule(匿名內(nèi)部類對(duì)象,指定延遲后開(kāi)始,周期)方法來(lái)實(shí)現(xiàn)移動(dòng)效果。匿名內(nèi)部類【TimerTask的子類,重寫(xiě)了run方法,包括repaint方法(實(shí)則調(diào)用paintComponent)和yidong方法】來(lái)重畫(huà)、監(jiān)聽(tīng)鍵盤(pán)的指令()并作出相應(yīng)動(dòng)作

下面是源代碼(有注釋):

容器類

package a;

import javax.swing._;

import java.awt._;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.util.Random;

import java.util.Timer;

import java.util.TimerTask;

import static a.Newgame.frame;

//新建面板

public class War extends JPanel {

private Timer timer;

private boolean sUp, sDown, sRight, sLeft;//右飛機(jī)按鍵變量

private boolean sW, sD, sS, sA;//左飛機(jī)按鍵變量

private Player1 player1 = new Player1();

private Player2 player2 = new Player2();

private ImageIcon img11 = player1.img1;

private ImageIcon img22 = player2.img2;

@Override

protected void paintComponent(Graphics g) {

super.paintComponent(g);//此句調(diào)用父類方法進(jìn)行界面重繪,恢復(fù)到某個(gè)界面,下面的步驟再畫(huà)玩家;如果注釋掉會(huì)有重影

//在面板上畫(huà)出玩家

g.drawImage(img11.getImage(), player1.x, player1.y, 100, 100, this);

g.drawString("P1", player1.x, player1.y);

g.drawImage(img22.getImage(), player2.x, player2.y, 100, 100, this);

g.drawString("P2", player2.x, player2.y);

}

public void startGame() {

timer = new Timer();

timer.schedule(new TimerTask() {//匿名內(nèi)部類(TimerTask的子類)

@Override

public void run() {//重寫(xiě)run()函數(shù)

repaint();//調(diào)用重寫(xiě)的paintComponent來(lái)畫(huà)兩飛機(jī)

yidong();//并每次判斷按下哪個(gè)鍵,然后移動(dòng)

}

}, 0, 50);//安排指定的任務(wù)從指定的延遲后開(kāi)始進(jìn)行重復(fù)的固定延遲執(zhí)行。50毫秒執(zhí)行一次

}

public void yidong() {

//因?yàn)槊看蛴∫淮慰赡苡脩舭聪乱粋€(gè)飛機(jī)的幾個(gè)鍵或者兩個(gè)飛機(jī)的幾個(gè)鍵,這些是都要檢測(cè)到的,改成else if后只能檢測(cè)到一個(gè)鍵,無(wú)法實(shí)現(xiàn)兩架飛機(jī)同時(shí)多方向移動(dòng)

if (sW && player1.y > 0) {

player1.y -= player1.speed;

}

if (sA && player1.x > 0) {

player1.x -= player1.speed;

}

if (sS && player1.y < 700) {

player1.y += player1.speed;

}

if (sD && player1.x < 900) {

player1.x += player1.speed;

}

if (sUp && player2.y > 0) {

player2.y -= player2.speed;

}

if (sDown && player2.y < 700) {

player2.y += player2.speed;

}

if (sLeft && player2.x > 0) {

player2.x -= player2.speed;

}

if (sRight && player2.x < 900) {

player2.x += player2.speed;

}

}

public void act() {

//隨機(jī)生成兩飛機(jī)的初始坐標(biāo)

Random rd = new Random();

player1.x = rd.nextInt(900);

player1.y = rd.nextInt(700);

player2.x = rd.nextInt(900);

player2.y = rd.nextInt(700);

//開(kāi)始游戲后獲得計(jì)時(shí)器開(kāi)始監(jiān)聽(tīng)并重畫(huà)

startGame();

//KeyAdapter是KeyListener的實(shí)現(xiàn)類,重寫(xiě)了所有方法但沒(méi)有具體操作

KeyAdapter keyAdapter = new KeyAdapter() {

@Override

public void keyPressed(KeyEvent e) {

super.keyPressed(e);

int key = e.getKeyCode();

switch (key) {

case KeyEvent.VK_W:

sW = true;

break;

case KeyEvent.VK_A:

sA = true;

break;

case KeyEvent.VK_D:

sD = true;

break;

case KeyEvent.VK_S:

sS = true;

break;

case KeyEvent.VK_RIGHT:

sRight = true;

break;

case KeyEvent.VK_LEFT:

sLeft = true;

break;

case KeyEvent.VK_DOWN:

sDown = true;

break;

case KeyEvent.VK_UP:

sUp = true;

break;

}

}

@Override

public void keyReleased(KeyEvent e) {

int key = e.getKeyCode();

switch (key) {

case KeyEvent.VK_W:

sW = false;

break;

case KeyEvent.VK_A:

sA = false;

break;

case KeyEvent.VK_D:

sD = false;

break;

case KeyEvent.VK_S:

sS = false;

break;

case KeyEvent.VK_RIGHT:

sRight = false;

break;

case KeyEvent.VK_LEFT:

sLeft = false;

break;

case KeyEvent.VK_DOWN:

sDown = false;

break;

case KeyEvent.VK_UP:

sUp = false;

break;

}

}

};

frame.addKeyListener(keyAdapter);

}

}

主函數(shù)類:

package a;

import javax.swing._;

public class Newgame {

public static JFrame frame;

public static void main(String[] args) {

frame = new JFrame("逃出生天");

frame.setSize(1000,800);

//絕對(duì)布局組件位置和形狀不會(huì)隨窗體改變,不設(shè)置布局管理器就可以使用setBounds()來(lái)控制位置

frame.setLayout(null);

//設(shè)置窗體關(guān)閉程序自動(dòng)關(guān)閉

frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

//窗體居中顯示

frame.setLocationRelativeTo(null);

//添加主面板

War war = new War();

frame.add(war);

//設(shè)置面板大小

war.setBounds(0,0,1000,800);

//設(shè)置主面板可見(jiàn)

frame.add(war);

frame.setVisible(true);

war.act();

}

}

1234567891011121314151617181920212223242526

玩家類:

玩家1

package a;

import javax.swing._;

public class Player1 {

public int x;

public int y;

public int speed = 50;

public ImageIcon img1 = new ImageIcon("D:\\Program_Files\\Jetbrains\\workspace_idea\\src\\a\\plane.jpg");

}

12345678910

玩家2

package a;

import javax.swing._;

public class Player2 {

public int x;

public int y;

public int speed = 50;

public ImageIcon img2 = new ImageIcon("D:\\Program_Files\\Jetbrains\\workspace_idea\\src\\a\\plane2.jpg");

}

做成一個(gè)桌面小游戲:

點(diǎn)“+”號(hào)

選好主函數(shù)類后點(diǎn)ok

然后點(diǎn)Build中的Build Artificts

選擇jar包點(diǎn)Build即可

然后jar包就在你的workspace生成了,找到它發(fā)送桌面快捷方式,更改圖標(biāo)名字即可

圖片轉(zhuǎn)換成圖標(biāo)的網(wǎng)站附上

java飛機(jī)大戰(zhàn)心得體會(huì)2

用Java制作游戲之前,一定要做到方向明確,思路清晰。首先確定自己需要用到幾個(gè)類,類里的內(nèi)容大致是什么,用腦圖進(jìn)行表達(dá)展現(xiàn)。

Java語(yǔ)言是一種跨平臺(tái)、適合于分布式計(jì)算環(huán)境的面向?qū)ο缶幊陶Z(yǔ)言,具有簡(jiǎn)單性、面向?qū)ο?、分布式,多線程性等,其中面向?qū)ο笥蟹庋b,繼承,多態(tài)三大特性。

1)封裝:數(shù)據(jù)和基于數(shù)據(jù)的操作封裝

2) 繼承:一個(gè)對(duì)象直接使用另一個(gè)對(duì)象的屬性和方法,子類可以繼承父類

3) 多態(tài):一個(gè)程序中同名的多個(gè)不同方法,實(shí)現(xiàn)多態(tài)的常見(jiàn)方法 子類對(duì)父類的覆蓋,利用重載在同一個(gè)類中定義多個(gè)同名的不同方法;

Java游戲制作中必須有 public static void main(String[] args)的主方法,main()方法是程序執(zhí)行的入口。例如我的飛機(jī)大戰(zhàn)main(),便是游戲開(kāi)始執(zhí)行的入口,寫(xiě)在GameFace類中。

游戲框架的制作,其大部分的代碼都是固定形式,可以通用。使用setVisible(true)的方法,改變默認(rèn)的不可見(jiàn)狀態(tài),setLayout(null)取消默認(rèn)的管理布局,然后setLocation(),setSize(),setBound()等方法設(shè)置其大小。將按鈕添加監(jiān)聽(tīng),實(shí)現(xiàn)監(jiān)聽(tīng)。在對(duì)應(yīng)方法中編寫(xiě)代碼,,為監(jiān)聽(tīng)者創(chuàng)建對(duì)象,完成注冊(cè),即在接口名字前添加“add”。

游戲版面要繼承JPanel,其原因是JPanel帶有雙緩沖技術(shù),可以解決閃爍的問(wèn)題,需要加入到JFrame窗體中,JPanel默認(rèn)的布局管理器是FlowLayout。調(diào)用畫(huà)筆,將所要顯示的圖片畫(huà)出來(lái)。然后再根據(jù)自己的思路,在游戲版面內(nèi)添加敵機(jī),實(shí)現(xiàn)矩形碰撞,生命值判定,游戲結(jié)束對(duì)話框。要熟練掌握調(diào)用其他的類,畫(huà)出分?jǐn)?shù),畫(huà)出生命值。制作容器,裝子彈,飛機(jī),炸彈。

制作游戲思路一定要清晰,對(duì)于共有屬性,可以建立一個(gè)父類,例如在創(chuàng)建一個(gè)FlyingObject類,這樣可以避免代碼的反復(fù)編寫(xiě)。對(duì)于子類myplane 、enemies可以直接繼承父類,子類可以根據(jù)自己的需求再增加新的變量。在子類myplane中,畫(huà)出我的飛機(jī),控制飛機(jī)飛行的邊界,調(diào)用子彈容器,畫(huà)出容器中子彈,與敵機(jī)進(jìn)行碰撞檢測(cè)。飛機(jī)大戰(zhàn)還應(yīng)該實(shí)現(xiàn)鍵盤(pán)監(jiān)聽(tīng),例如Enter鍵實(shí)現(xiàn)暫停,上下左右鍵實(shí)現(xiàn)移動(dòng)等。在敵機(jī)Enemies類中,定義敵機(jī)隨機(jī)出現(xiàn)坐標(biāo),敵機(jī)圖片的相對(duì)路徑,敵機(jī)速度,敵機(jī)子彈與我的plane碰撞出現(xiàn)的結(jié)果以及敵機(jī)子彈生成的時(shí)間等。

游戲制作時(shí)需要注意的事項(xiàng):1.JLabel的位置一定要放對(duì),應(yīng)當(dāng)先添加背景JLabel,再添加其它控件。否則其它控件將被JLabel所遮擋。

2.對(duì)于多次重復(fù)編寫(xiě)的代碼,盡可能的用for循環(huán),簡(jiǎn)單方便。但是也要注意跳出語(yǔ)句的使用。

3.調(diào)用函數(shù)時(shí)要注意順序

4.類名,方法名要遵循命名規(guī)范性,盡量做到見(jiàn)名知義,也要注意大小寫(xiě)。

java飛機(jī)大戰(zhàn)心得體會(huì)3

線程:進(jìn)程(process)就是一塊包含了某些資源的內(nèi)存區(qū)域。操作系統(tǒng)利用進(jìn)程把它的工作劃分為一些功能單元。 線程:進(jìn)程中所包含的一個(gè)或多個(gè)執(zhí)行單元稱為線程(thread)。進(jìn)程還擁有一個(gè)私有的虛擬地址空間,該空間僅能被它所包含的線程訪問(wèn)。 線程和進(jìn)程的區(qū)別如下: 1)一個(gè)進(jìn)程至少有一個(gè)線程。線程的劃分尺度小于進(jìn)程,使得多線程程序的并發(fā)性高。 另外,進(jìn)程在執(zhí)行過(guò)程中擁有獨(dú)立的內(nèi)存單元,而多個(gè)線程共享內(nèi)存,從而極大地提高了程序的運(yùn)行效率。 2)線程在執(zhí)行過(guò)程中與進(jìn)程的區(qū)別在于每個(gè)獨(dú)立的線程有一個(gè)程序運(yùn)行的入口、順序執(zhí)行序列和程序的出口。但是線程不能夠獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個(gè)線程執(zhí)行控制。 3)從邏輯角度來(lái)看,多線程的意義在于一個(gè)應(yīng)用程序中,有多個(gè)執(zhí)行部分可以同時(shí)執(zhí)行。但操作系統(tǒng)并沒(méi)有將多個(gè)線程看做多個(gè)獨(dú)立的應(yīng)用來(lái)實(shí)現(xiàn)進(jìn)程的調(diào)度和管理以及資源分配。

2 簡(jiǎn)述線程的狀態(tài)及其轉(zhuǎn)換 1)New,創(chuàng)建一個(gè)線程,但是線程并沒(méi)有進(jìn)行任何的操作。 2)Runnable,新線程從New狀態(tài),調(diào)用start方法轉(zhuǎn)換到Runnable狀態(tài)。線程調(diào)用start方法向線程調(diào)度程序(JVM或者是操作系統(tǒng))注冊(cè)一個(gè)線程,這個(gè)時(shí)候一切就緒只等CPU的時(shí)間。 3)Running,從Runnable狀態(tài)到Running狀態(tài),線程調(diào)度根據(jù)調(diào)度策略的不同調(diào)度不同的線程,被調(diào)度執(zhí)行的線程進(jìn)入Running狀態(tài),執(zhí)行run方法。 4)Dead狀態(tài),從Running狀態(tài)到Runnable,run方法運(yùn)行完畢后,線程就會(huì)被拋棄,線程就進(jìn)入Dead狀態(tài)。 5)Block狀態(tài),從Running狀態(tài)到Block狀態(tài),如果線程在運(yùn)行的狀態(tài)中因?yàn)镮/O阻塞、調(diào)用了線程的sleep方法以及調(diào)用對(duì)象的wait方法則線程將進(jìn)入阻塞狀態(tài),直到這些阻塞原因被結(jié)束,線程進(jìn)入到Runnable狀態(tài)。

3 簡(jiǎn)述線程的兩種創(chuàng)建方式以及它們的區(qū)別 創(chuàng)建線程的兩種方式: 1)使用Thread創(chuàng)建線程。Thread類是線程類,其每一個(gè)實(shí)例表示一個(gè)可以并發(fā)運(yùn)行的線程。我們可以通過(guò)繼承該類并重寫(xiě)run方法來(lái)定義一個(gè)具體的線程。其中重寫(xiě)run方法的目的是定義該線程要執(zhí)行的邏輯。啟動(dòng)線程時(shí)調(diào)用線程的start()方法而非直接調(diào)用run()方法。start()方法會(huì)將當(dāng)前線程納入線程調(diào)度,使當(dāng)前線程可以開(kāi)始并發(fā)運(yùn)行。當(dāng)線程獲取時(shí)間片段后會(huì)自動(dòng)開(kāi)始執(zhí)行run方法中的邏輯。 2)使用Runnable創(chuàng)建線程。實(shí)現(xiàn)Runnable接口并重寫(xiě)run方法來(lái)定義線程體,然后在創(chuàng)建線程的時(shí)候?qū)unnable的實(shí)例傳入并啟動(dòng)線程。 兩種創(chuàng)建線程方式的區(qū)別: 使用Thread創(chuàng)建線程,編寫(xiě)簡(jiǎn)單,可以直接操縱線程,無(wú)需使用Thread.currentThread(),但是不能夠再繼承其他類。 使用Runnable創(chuàng)建線程可以將線程與線程要執(zhí)行的任務(wù)分離開(kāi)減少耦合,同時(shí)Java是單繼承的,定義一個(gè)類實(shí)現(xiàn)Runnable接口,這樣該類還可以繼承自其他類。

多線程實(shí)現(xiàn)方法

使用Thread創(chuàng)建線并啟動(dòng)線程

java.lang.Thread類是線程類,其每一個(gè)實(shí)例表示一個(gè)可以并發(fā)運(yùn)行的線程。我們可以通過(guò)繼承該類并重寫(xiě)run方法來(lái)定義一個(gè)具體的線程。其中 重寫(xiě)run方法的目的是定義該線程要執(zhí)行的邏輯。啟動(dòng)線程時(shí)調(diào)用線程的start()方法而非直接調(diào)用run()方法。start()方法會(huì)將當(dāng)前線程納入線程調(diào) 度,使當(dāng)前線程可以開(kāi)始并發(fā)運(yùn)行。當(dāng)線程獲取時(shí)間片段后會(huì)自動(dòng)開(kāi)始執(zhí)行run方法中的邏輯。

public class TestThread extends Thread{

@Override

public void run() {

for(int i=0;i<100;i++){

System.out.println("我是線程");

}

}

}

創(chuàng)建預(yù)啟動(dòng)線程

Thread thread = new TestThread();//實(shí)例化線程

thread.start();//啟動(dòng)線程

使用Runnable創(chuàng)建并啟動(dòng)線程

實(shí)現(xiàn)Runnable接口并重寫(xiě)run方法來(lái)定義線程體,然后在創(chuàng)建線程的時(shí)候?qū)unnable的實(shí)例傳入并啟動(dòng)線程。 這樣做的好處在于可以將線程與線程要執(zhí)行的任務(wù)分離開(kāi)減少耦合,同時(shí)java是單繼承的,定義一個(gè)類實(shí)現(xiàn)Runnable接口這樣的做法可以更好的 去實(shí)現(xiàn)其他父類或接口。因?yàn)榻涌谑嵌嗬^承關(guān)系。

public class TestRunnable implements Runnable{

@Override

public void run() {

for(int i=0;i<100;i++){

System.out.println("我是線程");

}

}

}

啟動(dòng)線程的方法:

Runnable runnable = new TestRunnable();

Thread thread = new Thread(runnable);//實(shí)例化線程并傳入線程體

thread.start();//啟動(dòng)線程

使用內(nèi)部類創(chuàng)建線程

通常我們可以通過(guò)匿名內(nèi)部類的方式創(chuàng)建線程,使用該方式可以簡(jiǎn)化編寫(xiě)代碼的復(fù)雜度,當(dāng)一個(gè)線程僅需要一個(gè)實(shí)例時(shí)我們通常使用這種方式來(lái) 創(chuàng)建。 例如: 繼承Thread方式:

Thread thread = new Thread(){ //匿名類方式創(chuàng)建線程

public void run(){

//線程體

}

};

thread.start();//啟動(dòng)線程

Runnable方式:

Runnable runnable = new Runnable(){ //匿名類方式創(chuàng)建線程

public void run(){

}

};

Thread thread = new Thread(runnable);

thread.start();//啟動(dòng)線程

線程的方法

currentThread:方法可以用于獲取運(yùn)行當(dāng)前代碼片段的線程

Thread current = Thread.currentThread();

獲取線程信息 Thread提供了 獲取線程信息的相關(guān)方法: long getId():返回該線程的標(biāo)識(shí)符 String getName():返回該線程的名稱 int getPriority():返回線程的優(yōu)先級(jí) Thread.state getState():獲取線程的狀態(tài) boolean isAlive():測(cè)試線程是否處于活動(dòng)狀態(tài) boolean isDaemon():測(cè)試線程是否為守護(hù)線程 boolean isInterrupted():測(cè)試線程是否已經(jīng)中斷

線程優(yōu)先級(jí)

線程的切換是由線程調(diào)度控制的,我們無(wú)法通過(guò)代碼來(lái)干涉,但是我們可以通過(guò)提高線程的優(yōu)先級(jí)來(lái)最大程度的改善線程獲取時(shí)間片的幾率。 線程的優(yōu)先級(jí)被劃分為10級(jí),值分別為1-10,其中1最低,10最高。線程提供了3個(gè)常量來(lái)表示最低,最高,以及默認(rèn)優(yōu)先級(jí): Thread.MIN_PRIORITY, Thread.MAX_PRIORITY, Thread.NORM_PRIORITY 設(shè)置優(yōu)先級(jí)的方法為:

void setPriority(int priority)

守護(hù)線程

守護(hù)線程與普通線程在表現(xiàn)上沒(méi)有什么區(qū)別,我們只需要通過(guò)Thread提供的方法來(lái)設(shè)定即可: __void setDaemon(boolean )__ 當(dāng)參數(shù)為true時(shí)該線程為守護(hù)線程。 守護(hù)線程的特點(diǎn)是,當(dāng)進(jìn)程中只剩下守護(hù)線程時(shí),所有守護(hù)線程強(qiáng)制終止。 GC就是運(yùn)行在一個(gè)守護(hù)線程上的。 需要注意的是,設(shè)置線程為后臺(tái)線程要在該線程啟動(dòng)前設(shè)置。

Thread daemonThread = new Thread();

daemonThread.setDaemon(true);

daemonThread.start();

sleep方法

Thread的靜態(tài)方法sleep用于使當(dāng)前線程進(jìn)入阻塞狀態(tài): __static void sleep(long ms)__ 該方法會(huì)使當(dāng)前線程進(jìn)入阻塞狀態(tài)指定毫秒,當(dāng)指定毫秒阻塞后,當(dāng)前線程會(huì)重新進(jìn)入Runnable狀態(tài),等待分配時(shí)間片。 該方法聲明拋出一個(gè)InterruptException。所以在使用該方法時(shí)需要捕獲這個(gè)異常 改程序可能會(huì)出現(xiàn)"跳秒"現(xiàn)象,因?yàn)樽枞幻牒缶€程并非是立刻回到running狀態(tài),而是出于runnable狀態(tài),等待獲取時(shí)間片。那么這段等待 時(shí)間就是"誤差"。所以以上程序并非嚴(yán)格意義上的每隔一秒鐘執(zhí)行一次輸出。

yield方法:

Thread的靜態(tài)方法yield: __static void yield()__ 該方法用于使當(dāng)前線程主動(dòng)讓出當(dāng)次CPU時(shí)間片回到Runnable狀態(tài),等待分配時(shí)間片。

join方法

__void join()__ 該方法用于等待當(dāng)前線程結(jié)束。此方法是一個(gè)阻塞方法。 該方法聲明拋出InterruptException。

線程同步

synchronized關(guān)鍵字 多個(gè)線程并發(fā)讀寫(xiě)同一個(gè)臨界資源時(shí)候會(huì)發(fā)生"線程并發(fā)安全問(wèn)題“ 常見(jiàn)的臨界資源: 多線程共享實(shí)例變量 多線程共享靜態(tài)公共變量 若想解決線程安全問(wèn)題,需要將異步的操作變?yōu)橥讲僮鳌?所謂異步操作是指多線程并發(fā)的操作,相當(dāng)于各干各的。 所謂同步操作是指有先后順序的操作,相當(dāng)于你干完我再干。

同步代碼塊(synchronized 關(guān)鍵字 ),同步代碼塊包含兩部分:一個(gè)作為鎖的對(duì)象的引用,一個(gè)作為由這個(gè)鎖保護(hù)的代碼塊 這個(gè)比較難理解故寫(xiě)了下面代碼幫助理解

/__

_ 多線程并發(fā)安全問(wèn)題

_ 當(dāng)多個(gè)線程同時(shí)操作同一資源時(shí),由于

_ 線程切換時(shí)機(jī)不確定,導(dǎo)致出現(xiàn)邏輯混亂。

_ 嚴(yán)重時(shí)可能導(dǎo)致系統(tǒng)崩潰。

_ @author ylg

_

_/

public class SyncDemo1 {

public static void main(String[] args) {

/_

_ 當(dāng)一個(gè)方法中的局部?jī)?nèi)部類想引用該方法

_ 的其他局部變量時(shí),這個(gè)變量必須被聲明

_ 為final的

_/

final Table table = new Table();

Thread t1 = new Thread(){

public void run(){

while(true){

int bean = table.getBean();

Thread.yield();//模擬線程切換

System.out.println(

getName()+":"+bean

);

}

}

};

Thread t2 = new Thread(){

public void run(){

while(true){

int bean = table.getBean();

Thread.yield();//模擬線程切換

System.out.println(

getName()+":"+bean

);

}

}

};

t1.start();

t2.start();

}

}

class Table{

//20個(gè)豆子

private int beans = 20;

/__

_ 當(dāng)一個(gè)方法被synchronized修飾后,該方法

_ 成為"同步方法"。多個(gè)線程不能同時(shí)進(jìn)入到

_ 方法內(nèi)部。

_ @return

_/

public synchronized int getBean(){

if(beans==0){

throw new RuntimeException("沒(méi)有豆子了!");

}

Thread.yield();//模擬線程切換

return beans--;

}

}

/__

_ 有效的縮小同步范圍可以保證在

_ 安全的前提下提高了并發(fā)的效率

_ @author ylg

_

_/

public class SyncDemo2 {

public static void main(String[] args) {

final Shop shop = new Shop();

Thread t1 = new Thread(){

public void run(){

shop.buy();

}

};

Thread t2 = new Thread(){

public void run(){

shop.buy();

}

};

t1.start();

t2.start();

}

}

class Shop{

/_

_ 在方法上使用synchroinzed,同步監(jiān)視器對(duì)象即當(dāng)前方法所屬對(duì)象:this

_/

// public synchronized void buy(){

public void buy(){

try{

Thread t = Thread.currentThread();

System.out.println(t+"正在挑選衣服..");

Thread.sleep(5000);

/_

_ 同步塊可以縮小同步范圍。

_ 但是必須保證"同步監(jiān)視器"即:"上鎖對(duì)象"是同一個(gè)才可以。

_ 通常,在一個(gè)方法中使用this所謂同步監(jiān)視器對(duì)象即可。

_/

synchronized (this) {

System.out.println(t+"正在試衣服..");

Thread.sleep(5000);

}

System.out.println(t+"結(jié)賬離開(kāi)");

}catch(Exception e){

}

}

}

/__

_ synchronized也成為"互斥鎖"

_ 當(dāng)synchronzed修飾的是兩段代碼,但是"鎖對(duì)象"相同時(shí),這兩段代碼就是互斥的。

_ @author ylg

_

_/

public class SyncDemo4 {

public static void main(String[] args) {

final Boo b = new Boo();

Thread t1 = new Thread(){

public void run(){

b.methodA();

}

};

Thread t2 = new Thread(){

public void run(){

b.methodB();

}

};

t1.start();

t2.start();

}

}

class Boo{

public synchronized void methodA(){

Thread t = Thread.currentThread();

System.out.println(t+"正在調(diào)用方法A");

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

}

System.out.println(t+"調(diào)用方法A完畢");

}

public synchronized void methodB(){

Thread t = Thread.currentThread();

System.out.println(t+"正在調(diào)用方法B");

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

}

System.out.println(t+"調(diào)用方法B完畢");

java飛機(jī)大戰(zhàn)心得體會(huì)4

開(kāi)發(fā)登錄界面、設(shè)計(jì)地圖加載、子彈飛機(jī)的加載、主控制程序的開(kāi)發(fā)登錄界面的開(kāi)發(fā),通常是在界面上顯示游戲菜單選項(xiàng),用戶可根據(jù)菜單項(xiàng)選擇需要的操作。菜單項(xiàng)是和游戲的功能緊密相關(guān)的。手機(jī)游戲的開(kāi)發(fā)往往在界面和操作方式上有較高的要求,Java ME提供了低級(jí)界面開(kāi)發(fā)的API,可用于游戲開(kāi)發(fā)。低級(jí)界面畫(huà)布類主要有Canvas和GameCanvas,其中Canvas是屬于MIDP 1.0,GameCanvas則是屬于MIDP 2.0。低級(jí)用戶界面技術(shù)為用戶提供了靈活的開(kāi)發(fā)方法,可以進(jìn)行一些較為底層的操作,例如:按鍵的處理事件更為豐富,組件位置的設(shè)置更為靈活。手機(jī)上的屏幕坐標(biāo)系和我們常規(guī)數(shù)學(xué)的坐標(biāo)系不相同。對(duì)于坐標(biāo)(x,y),若x值越大,則越向右,y值越大,則越向下。對(duì)于飛機(jī)射擊游戲,飛機(jī)在飛行過(guò)程中經(jīng)過(guò)不同的地理環(huán)境,例如大海、小島、石礁等作為地圖的背景。地圖的寬度通常要求能夠自動(dòng)匹配不同類型的手機(jī)寬度,高度則是以一個(gè)關(guān)卡所需的時(shí)間為依據(jù)進(jìn)行設(shè)計(jì)。在此我們采用簡(jiǎn)化操作方法,給地圖寬度和高度設(shè)置一個(gè)具體值。子彈的射擊應(yīng)該支持不同的方向,例如我方飛機(jī)自下而上發(fā)射子彈,敵方飛機(jī)自上而下發(fā)射子彈。當(dāng)子彈與飛機(jī)碰撞之后,飛機(jī)的血量相應(yīng)地要減少,如果飛機(jī)的血量為0,則產(chǎn)生爆炸效果,子彈和飛機(jī)都消失。飛機(jī)主角在開(kāi)始游戲時(shí)出現(xiàn)在屏幕最底部的中間處,玩家可以通過(guò)上、下、左、右鍵控制其飛行方向,按下確認(rèn)鍵后可以發(fā)射子彈。敵機(jī)在游戲開(kāi)始后從背景上部出現(xiàn),飛行,并發(fā)射子彈。在本任務(wù)中需要考慮敵機(jī)出現(xiàn)的位置,出現(xiàn)的數(shù)量和頻率,飛行的速度和子彈的發(fā)射方向。

為了更好地控制游戲的主體邏輯,可以統(tǒng)一對(duì)游戲地圖進(jìn)行設(shè)置,對(duì)主角飛機(jī)、敵方飛機(jī)初始化,并在多線程中實(shí)現(xiàn)游戲的邏輯控制。

游戲主框架的首要模塊的安排:

1.游戲的初始化。主要是完成游戲資源的加載,各種游戲?qū)ο蟆⒆兞咳≈档某跏蓟?,游戲運(yùn)行環(huán)境的獲取和設(shè)置,歷史記錄的讀取等。

2.游戲的主循環(huán)。執(zhí)行游戲處理的主要代碼,直到滿足退出要求才停止循環(huán),例如:玩家選擇退出游戲,玩家游戲失敗,玩家最終完成游戲等。主要實(shí)現(xiàn)分為三步:(1)獲得游戲的輸入信息;(2)處理游戲的邏輯;(3)更新游戲的畫(huà)面

3.退出游戲

Canvas為抽象類,負(fù)責(zé)圖形圖像的繪制和用戶交互。進(jìn)行低級(jí)玩家界面的開(kāi)發(fā)通常需要繼承Canvas類,主要方法如下:

1.getHeight():獲取Canvas繪圖區(qū)域的高度。

2.getWidth():獲取Canvas繪圖區(qū)域的寬度。

3.paint(Graphics g):渲染畫(huà)布,向屏幕畫(huà)圖,通常將畫(huà)圖的操作放在該方法中實(shí)現(xiàn)。當(dāng)屏幕需要重新繪制時(shí),Java ME主線程會(huì)自動(dòng)調(diào)用paint方法,程序員不能在代碼中直接聲明調(diào)用該方法。

4.repaint():主動(dòng)向系統(tǒng)請(qǐng)求刷新界面,具體的刷新操作實(shí)際是通過(guò)調(diào)用paint方法來(lái)完成。

5.isDoubleBuffered():判斷手機(jī)設(shè)備是否匹配雙緩沖。有些手機(jī)匹配雙緩沖技術(shù),有些則不匹配。

6.getGameAction(int keyCode):將手機(jī)的鍵值切換為游戲動(dòng)作。

7.getKeyName(keyCode):得到按鍵的名字。

Graphics提供2D渲染能力,作用是在屏幕上繪制圖形,類似于一支畫(huà)筆。

Graphics繪制的圖形不能夠直接顯示,必須通過(guò)Canvas或GameCanvas才能顯示在屏幕上,因此Canvas和GameCanvas類似于可以顯示圖形的畫(huà)布

Graphics類支持繪制圖形主要包括以下3種:

(1)文本:可以設(shè)置文本的顏色、字體大小等

(2)圖像:可以直接繪制圖像文件或者從緩存中繪制

(3)2D幾何圖形:繪制點(diǎn)、直線、平面圖形等

Graphics類沒(méi)有構(gòu)造方式,獲取對(duì)象的途徑有3種:

1.Canvas類中的paint方法有一個(gè)Graphics對(duì)象參數(shù),系統(tǒng)會(huì)自動(dòng)調(diào)用paint方法,并傳進(jìn)一個(gè)Graphics對(duì)象,因此可以在paint方法中使用Graphics對(duì)象編寫(xiě)繪圖代碼。

2.在GameCanvas類中通過(guò)getGraphics方法來(lái)獲取一個(gè)Graphics對(duì)象,因此可以在要求的地方靈活地編寫(xiě)與繪圖有關(guān)的代碼。

3.Image對(duì)象的getGraphics()方法得到Graphics對(duì)象,可用于編寫(xiě)雙緩沖區(qū)代碼。

1.直接用整幅圖片作為背景,再在上面重疊一層加入物件、擺設(shè)等,優(yōu)點(diǎn)在于圖形相對(duì)豐富、漂亮,但消耗資源較多,受手機(jī)硬件條件的影響不能做太大的圖。

2.游戲地圖是用一個(gè)個(gè)圖塊重復(fù)拼接成,而在程序中就可以通過(guò)一個(gè)較小的圖像文件和一個(gè)二維數(shù)組,繪制出一幅較大的地圖。具體的做法是將圖像文件劃分為若干個(gè)相同大小的圖塊(一般每個(gè)圖塊是16像素 × 16像素或者32像素 × 32像素),每個(gè)圖塊給一個(gè)索引值,例如:1表示草地圖塊,2表示磚頭圖塊。而二維數(shù)據(jù)中記錄的數(shù)字就是圖像文件中的圖塊索引值,例如:某個(gè)數(shù)組元素的數(shù)值若為1,則表示在此處畫(huà)草地。此方法的益處在于比較節(jié)約系統(tǒng)資源,可做出來(lái)的地圖相對(duì)比較一般。

地圖編輯器能夠幫助將地圖最后轉(zhuǎn)變成程序直接使用,所以一個(gè)好的地圖編輯器能夠加速游戲的開(kāi)發(fā)周期。

業(yè)界已經(jīng)推出多款地圖編輯器,例如Mappy(MapWin)、Tiled、TILE STUDIO等,其中Mappy功能比較強(qiáng)大,可以很方便地對(duì)2D地圖進(jìn)行編輯。

下載mayppy軟件:HTTP:/ / www.tilemap.uk /mappy

假如需支持png圖片,那么還需下載兩個(gè)dll文件,這兩個(gè)文件也都放在Mappy軟件的網(wǎng)址上

zlib.dll用于文件壓縮

libpng12.dll是PNG圖像壓縮庫(kù)

將這兩個(gè)文件下載復(fù)制到Mappy可執(zhí)行文件的同一個(gè)目錄下即可,否則在導(dǎo)入PNG文件時(shí),會(huì)報(bào)圖5-23的錯(cuò)誤

制作游戲還需要用到圖像素材,因此除了Mappy軟件之外,還需要用到圖像處理軟件Photoshop來(lái)制作原始游戲素材。

J2SE中提供了多個(gè)接口和類管理集合,例如有Collection、List、Set、Map接口,實(shí)現(xiàn)接口的集合類有LinkedList、ArrayList、Vector、Hashtable、HashMap和WeakHashMap類。

在Java ME中只有java.util包提供Vector類,其功能和J2SE的Vector類似,實(shí)現(xiàn)的是一個(gè)動(dòng)態(tài)增長(zhǎng)的數(shù)組,可以在程序代碼中調(diào)整或者裁減集合的大小,能向集合插入、刪除和修改元素。

每一個(gè)集合中的元素都被分派一個(gè)整數(shù)索引號(hào),能夠直接根據(jù)索引號(hào)插入和刪除一個(gè)元素,也能夠修改和得到一個(gè)元素的值。

為了更好地控制游戲的主體邏輯,可以統(tǒng)一對(duì)游戲地圖進(jìn)行設(shè)置,對(duì)主角飛機(jī)、敵方飛機(jī)初始化,并在多線程中實(shí)現(xiàn)游戲的邏輯控制。

46890 太白县| 镇安县| 浦北县| 河北区| 鄂尔多斯市| 靖远县| 山阳县| 自治县| 衡南县| 上杭县| 浠水县| 乐平市| 临夏县| 石门县| 建昌县| 海口市| 昌平区| 阜南县| 呈贡县| 香格里拉县| 吴江市| 莒南县| 揭阳市| 平乡县| 广安市| 大埔县| 嵊州市| 灵璧县| 丰镇市| 固原市| 墨竹工卡县| 尚义县| 且末县| 泌阳县| 富锦市| 镇远县| 龙南县| 手游| 湖南省| 琼海市| 鹤山市|