?? ufo_attack.java
字號:
//哈哈,這個好 UFO 攻擊
// Free to use and copy for any purpose.
//
// No responsability for any mis-use or problems
// due to the usage of this code on any device.
// (i.e. crashing your browser and/or your OS)
//
//引入所需的類包
import java.awt.*;
import java.applet.*;
import java.util.*;
//將類UFO_Attack轉換為線程,并實現Runnable接口
public class UFO_Attack extends Applet implements Runnable {
Image buffer = null ; // 臨時圖像緩沖
Image backdrop = null ; // 背景幕
Image bgimg = null ; // 原背景幕
Image ufostrip = null ; // UFO 序列圖
Image missile = null ; // 導彈序列圖
Image missile_explosion = null ; // 導彈爆炸序列圖
MediaTracker tracker = null ;//媒體跟蹤器,用來監測圖像的裝載
Graphics buf_g = null ; // 緩沖中的圖像對象
Graphics bkd_g = null ; // 背景幕的圖像對象
Dimension window_size = null;//窗口尺寸
Font font ;
Font font_s ; //顯示字的字體
AudioClip explosion = null ; //爆炸聲
AudioClip newufo = null ; //新的UFO出現時發出的聲音
AudioClip missile_launch = null ; //導彈發射的聲音
Thread game = null ; //程序的主線程
boolean game_over = true ; //用來判斷游戲結束與否
int mouse_x = 100 ; //鼠標的X坐標,用來控制導彈和發射架的移動
Rectangle paint_area = new Rectangle() ; //對象出現的區域
Rectangle new_area = new Rectangle() ; //對象即將出現的區域
Launcher L = null ; //定義一個導彈發射架
Missile M = null ; //定義一個導彈
Vector UV = new Vector() ; //定義UFO向量,即一個UFO集合
Vector EV = new Vector() ; //定義爆炸向量,即一個爆炸集合
int NU = 1 ; //UFO的數目
int score = 0 ; //玩家所得分數
// 相應對象的顏色設置
Color gunColor;
Color mColor;
Color ufoColor;
Color scoreColor;
Color bgColor;
//UFO_Attack類的初始化
public void init() {
System.out.println("UFO Attack: A game by Sergio Fanchiotti") ;
tracker = new MediaTracker(this) ; //媒體跟蹤器監測圖像裝載的情況
//圖片的裝載
bgimg = getImage(this.getCodeBase(),"bgimg.gif") ;
tracker.addImage(bgimg,0) ;
ufostrip = getImage(this.getCodeBase(),"ufostrip.gif") ;
tracker.addImage(ufostrip,0) ;
missile = getImage(this.getCodeBase(),"missile.gif") ;
tracker.addImage(missile,0) ;
missile_explosion = getImage(this.getCodeBase(),"explosionstrip.gif") ;
tracker.addImage(missile_explosion,0) ;
font = new Font("Helvetica", Font.BOLD, 24) ;
font_s = new Font("Helvetica", Font.BOLD, 14) ; //顯示字的字體設置
// 設置所需的顏色
bgColor = new Color(0,0,128);
gunColor = new Color(0,88,0);
mColor = new Color(255,255,255);
ufoColor = new Color(255,0,0);
scoreColor = new Color(0,0,255);
}
public void start() {
// 使用十字型光標
getFrame(this).setCursor(Frame.CROSSHAIR_CURSOR) ;
//獲取窗口的尺寸
window_size = size();
//生成緩沖區
buffer = null;
buffer = createImage(window_size.width, window_size.height);
backdrop = null;
backdrop = createImage(window_size.width, window_size.height);
//用背景色來填充緩沖區
buf_g = buffer.getGraphics();
buf_g.setColor(bgColor);
buf_g.fillRect(0, 0, window_size.width, window_size.height);
// 顯示初始化信息
set_say_font(font) ;
set_say_mode(CENTER) ;
set_say_style(SHADOW) ;
say("UFO",10,80) ;
say("ATTACK") ;
set_say_font(font_s) ;
set_say_style(NORMAL) ;
say("") ;
say("Click to start") ;
say("a game") ;
//將緩沖繪制到屏幕上
Graphics g = getGraphics() ;
g.drawImage(buffer,0,0,this) ;
// 初始化導彈發射架
mouse_x = window_size.width/2 ;
L = new Launcher(this) ;
L.set_color(gunColor) ;
// 初始化導彈
M = new Missile(this) ;
M.set_color(mColor) ;
// 加載聲音文件
if (explosion == null)
explosion = getAudioClip(getCodeBase(),"explosion.au") ;
if (newufo == null)
newufo = getAudioClip(getCodeBase(),"sonar.au") ;
if (missile_launch == null)
missile_launch = getAudioClip(getCodeBase(),"rocket.au") ;
game_over = true ;
//聲音播放
newufo.play() ;
missile_launch.play() ;
explosion.play() ;
}
//停止運行函數
public void stop() {
// 如果線程正在運行,強行令其停止
if (game != null) {
game.stop() ;
game = null ; // and eliminate the thread
}
// 重新設置光標形狀
getFrame(this).setCursor(Frame.DEFAULT_CURSOR) ;
}
// 游戲主線程的執行函數
public void run() {
// 定義本地變量和對象
UFO U ;
Explosion E ;
long count = 0 ;
long ti = 0 ;
// 等待圖片裝載完畢
Graphics g = getGraphics() ;
g.setColor(Color.red) ;
g.drawString("Starting Game...", 20,20) ;
while (tracker.checkAll(true) == false) {
if ((ti++ % 2) == 0)
g.setColor(Color.red) ;
else
g.setColor(Color.green) ;
g.drawString("*", 10,22) ;
try {Thread.sleep(50);} catch (InterruptedException e) { } ;
//裝載超時時強行退出
if (ti > 1000) break ;
}
//捕捉獲取圖片時的錯誤信息
if (tracker.isErrorAny()) {
showStatus("Error getting images") ;
return ;
}
showStatus("Loading completed") ;//裝載成功
g.dispose() ;
//繪制背景幕的緩沖區
buf_g = backdrop.getGraphics();
buf_g.drawImage(bgimg,0,0,window_size.width,window_size.height,this) ;
// 將背景幕的緩沖繪制到屏幕上
buf_g = getGraphics();
buf_g.drawImage(backdrop,0,0,this) ;
// 繪制緩沖區
buf_g = buffer.getGraphics();
buf_g.drawImage(bgimg,0,0,window_size.width,window_size.height,this) ;
//重新繪制
repaint() ;
// 顯示玩家得分數
display_score() ;
//繪制導彈發射架
L.draw() ;
showStatus("UFO ATTACK") ;
// 事件循環
for (;;) {
ti = System.currentTimeMillis() ;
// 如果有多余的UFO飛行空間的話可增加一架UFO
if ((UV.size() < NU) &&
(Math.random() > (UV.size() == 0 ? 0.90 : 0.98))) {
newufo.play() ; // 播放警報聲
U = new UFO(this) ;
U.set_color(ufoColor) ;
// 在相應條件下提高UFO的下降速度
if (score > 10 && Math.random() > 0.7) U.vy -= 1 ;
// 在UFO向量中增加一名成員
UV.addElement(U) ;
}
// 在背景幕上繪制爆炸畫面,結束后將其清除
for (int j=EV.size()-1; j>=0 ; --j) {
E = (Explosion) EV.elementAt(j) ;
if (E.active) {
// 如果爆炸出現就進行其畫面的繪制
E.draw() ;
}
else {
// 結束后從背景幕上清除,并從爆炸向量中刪除
E.erase() ;
EV.removeElementAt(j) ;
}
}
//移動導彈發射架
L.move() ;
//如果導彈存在,移動導彈
if (M.active() == true) M.move() ;
//移動每個UFO
for (int i=0; i < UV.size(); ++i) {
U = (UFO) UV.elementAt(i) ;
U.move() ;
}
//監察UFO與導彈之間的碰撞
for (int i=(UV.size()-1); i >=0 ; --i) {
U = (UFO) UV.elementAt(i) ;
if (U.active() && M.active() && U.collision(M)) {
++score ; //增加玩家的得分
explosion.stop() ;
display_score() ;
explosion.play() ;
//每擊落10架UFO后便增加UFO的最大出現數目,直到數目為5
if ((NU < 5) && (score % 10) == 1) ++NU ;
// 碰撞發生后,將導彈從背景幕上清除,并使其active屬性為false
M.active(false) ;
M.erase() ;
//將被擊中的UFO從背景幕上清除,并使其active屬性為false
U.active(false) ;
U.erase() ;
//顯示爆炸的場面
E = new Explosion(this,U.px,U.py) ;
//在爆炸向量中添加一員
EV.addElement(E) ;
}
// 如果UFO沒有被擊中,則顯示出來,否則,將其從UFO向量中刪除
if (U.active())
U.draw() ;
else
UV.removeElementAt(i) ;
//如果有一個UFO成功著陸則玩家失敗
if ((U.py - U.h/2) <=0) {
game_over = true ;
display_game_over() ;
return ;
}
}
//如果導彈發射架移動了,重畫發射架
if (L.has_moved() || ((M.py-M.h) < (L.py+L.h)) || (! M.active()) )
L.draw() ;
//如果導彈的active屬性值為true,則重畫導彈
if (M.active() == true) M.draw() ;
// 萬一CPU速度太快,要使循環維持在20ms以上
ti = System.currentTimeMillis() - ti ;
ti = 20 - ti ;
ti = ti > 0 ? 10 + ti : 10 ;
Thread.yield() ;
//處理線程sleep函數的異常
try {Thread.sleep(ti);}
catch (InterruptedException e) { } ;
// 每100次循環重新繪制一次
if ((count = ++count % 500) == 0) {
repaint() ;
}
}
}
//顯示玩家的得分
public void display_score() {
Graphics bkd_g = backdrop.getGraphics();
bkd_g.clipRect(window_size.width/2, 0, window_size.width/2, 40);
bkd_g.drawImage(bgimg,0,0,window_size.width,window_size.height,this) ;
bkd_g.setColor(Color.red) ;
bkd_g.setFont(font) ;
String aux = score > 9 ? "" : "0" ;
bkd_g.drawString(aux+score, window_size.width - 60,30) ;
bkd_g.dispose() ;
Graphics bg = buffer.getGraphics() ;
bg.clipRect(0, 0, window_size.width, 40);
bg.drawImage(backdrop,0,0,this) ;
bg.dispose() ;
Graphics g = getGraphics() ;
g.clipRect(0, 0, window_size.width, 40);
g.drawImage(buffer,0,0,this) ;
g.dispose() ;
}
//游戲結束時進行提示
public void display_game_over() {
set_say_font(font) ;
set_say_mode(CENTER) ;
set_say_style(SHADOW) ;
set_say_pos(10,80) ;
say("GAME OVER") ;
set_say_font(font_s) ;
set_say_style(NORMAL) ;
say("(click to start)") ;
repaint() ;
try {Thread.sleep(500);} catch (InterruptedException e) { } ;
}
//處理鼠標移動事件
public boolean mouseMove(Event e, int x, int y) {
// 返回鼠標所在位置的X坐標
mouse_x = x ;
return true;
}
// 處理鼠標的按下事件
public boolean mouseDown(Event e, int x, int y) {
//游戲結束時所做的相應處理
if (game_over) {
game_over = false ;
if (game != null) {
game.stop() ;
game = null ;
}
NU = 1 ;
score = 0 ;
M.active(false) ;
UV.removeAllElements() ;
EV.removeAllElements() ;
//新建一個線程
game = new Thread(this) ;
game.setPriority(Thread.MIN_PRIORITY) ;
//線程啟動
game.start() ;
buf_g.dispose() ;
return true ;
}
//如果游戲沒有結束并且導彈沒有被發射,則發射導彈
if (M != null && ! M.active()) {
missile_launch.stop() ;
missile_launch.play() ;
M.set_pos(L.px,L.py) ;
M.active(true) ;
}
return true;
}
// 將緩沖繪制到屏幕上
public void paint(Graphics g) {
if (buffer != null) g.drawImage(buffer, 0, 0, this);
}
// 使動畫更加流暢
public void update(Graphics g) {
paint(g) ;
}
//獲取這個applet的Frame對象
public Frame getFrame(Component c) {
while( c != null && !(c instanceof java.awt.Frame) )
c = c.getParent();
return (Frame) c;
}
// 文本顯示的常量
public static final int CENTER = 1 ; // 模式: 居中
public static final int LEFT = 2 ; // 居左
public static final int RIGHT = 3 ; // 居右
public static final int FREE = 0 ; // 居于所給的(x,y)位置上
public static final int NORMAL = 0 ; // 類型:正常
public static final int SHADOW = 1 ; // 帶有陰影
// 文本顯示變量
private int say_pos_y = 0 ;
private int say_pos_x = 0 ;
private int say_mode = -1 ;
private int say_style = -1 ;
private int say_margin = 10 ;
private Font say_font = null ;
// 文本顯示方法
public void say(String s, int x, int y) {
set_say_pos(x, y) ;
say(s) ;
}
//文本顯示
public void say(String s) {
//獲取字體的信息
FontMetrics fm = getFontMetrics(say_font) ;
// 計算x坐標
switch(say_mode) {
case CENTER:
say_pos_x = (window_size.width - fm.stringWidth(s))/2 ;
break ;
case RIGHT:
say_pos_x = window_size.width - fm.stringWidth(s) - say_margin ;
break ;
case LEFT:
default :
say_pos_x = say_margin ;
break ;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -