// 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