(1)使用 Java Swing 类库完成飞机大战游戏中的难度选择、音效开关界面。
(2)使用 Java Swing 类库完成得分排行榜界面,显示该难度的玩家得分排名。 并可与玩家进行交互,输入玩家姓名后可记录该局得分,并可删除任一玩家的历史得分。
(3)使用 Runnable 接口实现多线程,完善火力道具功能。
(4)继承 Thread 类实现多线程,完成游戏背景音乐、子d击中敌机、炸d爆炸、 道具生效、Boss 机出场、游戏结束时的音效控制。
用ide的自带的图形界面编程:
例如:
新建窗口
其中form是一个基于XML的文件,这么设计的目的是为了摆脱复杂的Swing代码,intelliJ编译器会透明地自动生成必要的代码来创建和布局所有的控件。
给按钮或其他什么组件添加监听器:
图例中添加的是ActionListener,用于接收 *** 作事件的侦听器接口。对处理 *** 作事件感兴趣的类可以实现此接口,而使用该类创建的对象可使用组件的 addActionListener 方法向该组件注册。在发生 *** 作事件时,调用该对象的 actionPerformed 方法。
业务逻辑:
以第一个窗口为例:
对应类:
public class AircraftWarStartFrame {
private JFrame frame;
private JPanel StartPanel;
private JButton easyButton;
private JButton hardButton;
private JButton normalButton;
private JComboBox musicComboBox;
private JLabel musicLabel;
private static Object locker = Main.locker;
private String gameDegree;
private boolean isStop = false;
public AircraftWarStartFrame() {
frame = new JFrame("AircraftWar");
frame.setSize(400,600);
frame.setLocationRelativeTo(null);
frame.setContentPane(this.StartPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
easyButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
synchronized (locker){
try{
gameDegree = "Easy";
locker.notify();
frame.dispose();
}catch (Exception e1){
e1.printStackTrace();
}
}
}
});
normalButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
synchronized (locker){
try{
gameDegree = "Normal";
locker.notify();
frame.dispose();
}catch (Exception e1){
e1.printStackTrace();
}
}
}
});
hardButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
synchronized (locker){
try{
gameDegree = "Hard";
locker.notify();
frame.dispose();
}catch (Exception e1){
e1.printStackTrace();
}
}
}
});
musicComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(musicComboBox.getSelectedItem().equals("关")){
Main.bgmMusicThread.setStop(true);
isStop = true;
}
else{
Main.bgmMusicThread.setStop(false);
isStop = false;
}
}
});
}
/**
* 选择游戏难度
* @return 游戏实例
*/
public Game startGame(){
Game game;
switch (gameDegree){
case "Easy":
game=new EasyGame();
break;
case "Normal":
game=new NormalGame();
break;
case "Hard":
game=new HardGame();
break;
default:
game=new EasyGame();
}
game.isStop=isStop;
return game;
}
}
实现背景音乐的暂停播放
播放音频线程:
public class MusicThread extends Thread {
//音频文件名
private String videos;
private AudioFormat audioFormat;
private byte[] samples;
//播放/停止标志
private boolean isStop = false;
//循环播放标志
private boolean inLoop = false;
//借宿播放标志
private boolean toEnd = false;
public MusicThread(String filename,boolean isStop,boolean inLoop) {
//初始化filename
this.videos = filename;
this.isStop = isStop;
this.inLoop = inLoop;
reverseMusic();
}
public void reverseMusic() {
try {
//定义一个AudioInputStream用于接收输入的音频数据,使用AudioSystem来获取音频的音频输入流
AudioInputStream stream = AudioSystem.getAudioInputStream(new File(videos));
//用AudioFormat来获取AudioInputStream的格式
audioFormat = stream.getFormat();
samples = getSamples(stream);
} catch (UnsupportedAudioFileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] getSamples(AudioInputStream stream) {
int size = (int) (stream.getFrameLength() * audioFormat.getFrameSize());
byte[] samples = new byte[size];
DataInputStream dataInputStream = new DataInputStream(stream);
try {
dataInputStream.readFully(samples);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return samples;
}
public void play(InputStream source) {
int size = (int) (audioFormat.getFrameSize() * audioFormat.getSampleRate());
byte[] buffer = new byte[size];
//源数据行SoureDataLine是可以写入数据的数据行
SourceDataLine dataLine = null;
//获取受数据行支持的音频格式DataLine.info
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
try {
dataLine = (SourceDataLine) AudioSystem.getLine(info);
dataLine.open(audioFormat, size);
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
dataLine.start();
try {
int numBytesRead = 0;
while (numBytesRead != -1) {
//结束
if(toEnd){
break;
}
//暂停
if(isStop){
while (isStop){
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
//从音频流读取指定的最大数量的数据字节,并将其放入缓冲区中
numBytesRead =
source.read(buffer, 0, buffer.length);
//通过此源数据行将数据写入混频器
if (numBytesRead != -1) {
dataLine.write(buffer, 0, numBytesRead);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
dataLine.drain();
dataLine.close();
}
/**
* 设置音效打开/关闭
*/
public void setStop(boolean isStop){this.isStop=isStop;}
/**
* 设置循环播放
*/
public void setInLoop(boolean inLoop){this.inLoop = inLoop;}
/**
* 结束播放
*/
public void setToEnd(boolean toEnd){this.toEnd = toEnd;}
/**
* 控制音频循环播放
*/
@Override
public void run() {
if(inLoop){
while (inLoop){
InputStream stream = new ByteArrayInputStream(samples);
play(stream);
}
}
InputStream stream = new ByteArrayInputStream(samples);
play(stream);
}
}
新建音效线程
以子d击中音效为例
new MusicThread("src/videos/bullet_hit.wav",isStop,false).start();
其他
JTable 的设置:
利用model来导入数据
/**
* 设置表格
*/
public void setTable(){
//显示难度
degreeLabel.setText("难度:"+userDao.degree);
DefaultTableModel model = new DefaultTableModel();
String[] columnName = {"排 名","名 称","分 数","达成时间"};
model.setColumnIdentifiers(columnName);
List<User> users = userDao.getAllUsers();
int index = 1;
for(User user : users){
Vector row = new Vector(4);
row.add(0,Integer.toString(index));
row.add(1,user.getUserName());
row.add(2,Integer.toString(user.getScore()));
row.add(3,user.getTime());
index++;
model.addRow(row);
}
scoreTable.setModel(model);
tableScrollPane.setViewportView(scoreTable);
}
线程相关方法总结
重点是理清业务逻辑,实际实现代码没有用到多少技术
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)