武汉理工大学爪哇大作业——玩蛇
作业内容
用Java实现贪吃蛇游戏的同时,添加用户登录(无需使用网络编程、无需密码)、用户得分存储、得分排行榜、音乐播放等功能。
开发环境
macOS 10.15 BlueJ(要是当年我知道Eclipse的windowbuilder这个插件的话就不会写的这么痛苦了)
说明
此项目仅供参考(各位看看在BlueJ里面的结构图就知道我这玩意儿耦合性有多高),直接cv只能说分还过得去,但高不了。
贪吃蛇游戏主体部分参考;
音乐播放部分参考案例代码music player;
具体实现方法就是把music player的JFrame界面设置一个监听器,监听贪吃蛇界面的位置并跟随(这是在当时只有两天作业就截止的情况下最快的方法);然后再自己实现登录功能以及文件读取以保存得分记录。
播放音乐时,需要将.mp3格式的文件放在工程同级文件夹的名为audio的文件夹中。同样记得修改保存记录以及用户信息的.txt的路径。
源代码
Main.java
import java.awt.*;
public class Main
{
public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
myFrame.init();
}
}
MyFrame.java
import java.awt.*;
import java.awt.event.*;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.JFrame;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.*;
public class MyFrame extends JFrame
{
public void init()
{
MyFrame frame = new MyFrame();
frame.setTitle("贪吃蛇");
frame.setResizable(false);
frame.setBounds(200,100,1015,810);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.makeMenuBar();
GamePanel panel = new GamePanel();
frame.add(panel);
frame.setVisible(true);
SideWindow gui = new SideWindow();
gui.makeFrame();
gui.setVisible(true);
showLogIn();
frame.addComponentListener(new ComponentAdapter()
{
public void componentMoved(ComponentEvent e)
{
Rectangle rect = frame.getBounds();
gui.setLocation(rect.x+rect.width-150, rect.y+44);
}
});
}
private void makeMenuBar()
{
final int SHORTCUT_MASK =
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
JMenuBar menubar = new JMenuBar();
setJMenuBar(menubar);
JMenu menu;
JMenuItem item;
menu = new JMenu("分数");
menubar.add(menu);
item = new JMenuItem("排行榜");
item.addActionListener(e -> showChart());
menu.add(item);
menu = new JMenu("玩家");
menubar.add(menu);
item = new JMenuItem("注册/登录");
item.addActionListener(e -> showLogIn());
menu.add(item);
}
public void showChart()
{
try
{
ArrayList<PlayerScore> results = Point.loadAllResults();
int length = results.size();
if(length > 10)
{
length = 10;
}
MyFrame frame1 = new MyFrame();
frame1.setTitle("点击查看排行榜");
frame1.setResizable(false);
frame1.setBounds(200,100,200,250);
frame1.setVisible(true);
for(int i = 0; i < length; i++)
{
JTextArea chart = new JTextArea();
chart.setFont(new Font("苹方-简",Font.BOLD,16));
chart.setBounds(0, 25 + 20 * i, 180, 20);
chart.setLineWrap(true);
chart.setEditable(false);
chart.setOpaque(false);
chart.setVisible(true);
PlayerScore result = results.get(i);
chart.setText(" " + result.getName() + " " + result.getScore());
frame1.add(chart);
}
JTextArea chart = new JTextArea();
chart.setFont(new Font("苹方-简",Font.BOLD,16));
chart.setBounds(0, 0, 180, 20);
chart.setLineWrap(true);
chart.setEditable(false);
chart.setOpaque(false);
chart.setVisible(true);
chart.setText(" 前十排行榜");
frame1.add(chart);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void showLogIn()
{
MyFrame frame2 = new MyFrame();
frame2.setTitle("注册/登录");
frame2.setResizable(false);
frame2.setBounds(300,150,300,100);
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel pCenter = new JPanel();
pCenter.setLayout(new FlowLayout());
JPanel pSouth = new JPanel();
JLabel l1 = new JLabel("用户名:");
JTextField tf1= new JTextField();
tf1.setPreferredSize(new Dimension(120,30));
pCenter.add(l1);
pCenter.add(tf1);
JButton b1 = new JButton("注册");
JButton b2 = new JButton("登录");
pSouth.add(b1);
pSouth.add(b2);
b1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String name = tf1.getText();
if(0==name.length())
{
JOptionPane.showMessageDialog(frame2, "用户名不能为空");
tf1.grabFocus();
return;
}
if(Player.isPlayer(name))
JOptionPane.showMessageDialog(frame2, "用户名已存在");
else
{
try
{
Player.createPlayer(name);
JOptionPane.showMessageDialog(frame2, "创建成功");
}
catch (IOException a)
{
a.printStackTrace();
JOptionPane.showMessageDialog(frame2, "创建失败");
}
}
}
});
b2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
String name = tf1.getText();
if(0==name.length())
{
JOptionPane.showMessageDialog(frame2, "用户名不能为空");
tf1.grabFocus();
return;
}
if(Player.isPlayer(name))
{
Player.name = name;
JOptionPane.showMessageDialog(frame2, "登录成功");
frame2.dispose();
}
else
JOptionPane.showMessageDialog(frame2, "用户名不存在");
}
});
frame2.setLayout(new BorderLayout());
frame2.add(pCenter,BorderLayout.CENTER);
frame2.add(pSouth,BorderLayout.SOUTH);
frame2.setVisible(true);
}
}
GamePanel.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
public class GamePanel extends JPanel implements KeyListener, ActionListener
{
static final int BODYSIZE = 20;
Snake snake = new Snake();
Food food = new Food();
Timer timer = new Timer(100, this);
static boolean isStart = false;
static boolean isDead = false;
public GamePanel()
{
setFocusable(true);
addKeyListener(this);
food.startTimer();
timer.start();
}
@Override
protected void paintComponent(Graphics g)
{
if(Player.name != "")
{
super.paintComponent(g);
setBackground(Color.BLACK);
g.setColor(Color.green);
for (int i = 0; i < Snake.length; i++)
g.fillRect(Snake.snakeX[i], Snake.snakeY[i], BODYSIZE, BODYSIZE);
g.setColor(Color.RED);
g.fillOval(food.normalX, food.normalY, BODYSIZE, BODYSIZE);
if (food.hasBonus)
{
g.setColor(Color.YELLOW);
g.fillOval(food.bonusX, food.bonusY, BODYSIZE, BODYSIZE);
}
g.setColor(Color.WHITE);
g.setFont(new Font("苹方-简", Font.PLAIN, 20));
g.drawString("目前得分:" + Point.point, 5, 20);
g.drawString("玩家:" + Player.name, 5, 42);
if (!isStart)
{
g.setColor(Color.ORANGE);
g.setFont(new Font("苹方-简", Font.BOLD, 40));
g.drawString("使用空格开始游戏", 250, 300);
timer.stop();
}
else if (isDead)
{
g.setColor(Color.RED);
g.setFont(new Font("苹方-简", Font.BOLD, 40));
g.drawString("GAME OVER", 250, 300);
try
{
Point.writeResult();
Point.readBestResult();
}
catch (IOException e)
{
e.printStackTrace();
}
g.setColor(Color.WHITE);
g.setFont(new Font("苹方-简", Font.PLAIN, 30));
g.drawString("最后得分:" + Point.point, 250, 350);
g.drawString("最高分:" + Point.bestScore, 250, 400);
timer.stop();
}
}
}
@Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
if (keycode == KeyEvent.VK_SPACE)
{
isStart = !isStart;
if (isStart)
{
timer.start();
}
if (isDead)
{
isStart = false;
isDead = false;
snake = new Snake();
snake.length = 3;
snake.speedX = 20;
snake.speedY = 0;
Point.point = 0;
timer.start();
}
}
else if (snake.isTmpMove)
{
snake.changeDirection(e);
}
repaint();
}
@Override
public void actionPerformed(ActionEvent e)
{
snake.move();
snake.checkEatFood(food);
food.changeFoodPosition();
snake.checkCollide();
repaint();
}
@Override
public void keyReleased(KeyEvent e)
{
}
@Override
public void keyTyped(KeyEvent e)
{
}
}
Snake.java
import java.awt.event.KeyEvent;
public class Snake
{
static String direction = "right";
static int length = 3;
static int[] snakeX = new int[1000];
static int[] snakeY = new int[1000];
static int speedX = 20;
static int speedY = 0;
boolean isTmpMove = true;
public Snake() {
snakeX[0] = 400;
snakeY[0] = 400;
snakeX[1] = 380;
snakeY[1] = 400;
snakeX[2] = 360;
snakeY[2] = 400;
}
public void move()
{
for (int i = length - 1; i > 0; i--)
{
snakeX[i] = snakeX[i - 1];
snakeY[i] = snakeY[i - 1];
}
snakeX[0] += speedX;
snakeY[0] += speedY;
isTmpMove = true;
checkBoundaries();
}
public void changeDirection(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP && !direction.equals("down"))
{
direction = "up";
speedX = 0;
speedY = -20;
}
else if (e.getKeyCode() == KeyEvent.VK_DOWN && !direction.equals("up"))
{
direction = "down";
speedX = 0;
speedY = 20;
}
else if (e.getKeyCode() == KeyEvent.VK_RIGHT && !direction.equals("left"))
{
direction = "right";
speedX = 20;
speedY = 0;
}
else if (e.getKeyCode() == KeyEvent.VK_LEFT && !direction.equals("right"))
{
direction = "left";
speedX = -20;
speedY = 0;
}
isTmpMove = false;
}
public void checkBoundaries() {
if (snakeX[0] > 840) {
snakeX[0] = 0;
} else if (snakeX[0] < 0) {
snakeX[0] = 840;
} else if (snakeY[0] > 760) {
snakeY[0] = 0;
} else if (snakeY[0] < 0) {
snakeY[0] = 760;
}
}
public void checkEatFood(Food food) {
if (snakeX[0] == food.normalX && snakeY[0] == food.normalY) {
food.isEat = true;
getLonger(food);
} else if (snakeX[0] == food.bonusX && snakeY[0] == food.bonusY && food.hasBonus) {
food.isBonusEat = true;
food.hasBonus = false;
getLonger(food);
}
}
public void getLonger(Food food) {
if (food.isEat) {
Point.getNormalFoodPoint();
snakeX[length] = snakeX[length - 1] - (snakeX[length - 2] - snakeX[length - 1]);
snakeY[length] = snakeY[length - 1] - (snakeY[length - 2] - snakeY[length - 1]);
length++;
}
else if (food.isBonusEat)
{
Point.getBonusFoodPoint();
snakeX[length] = snakeX[length - 1] - (snakeX[length - 2] - snakeX[length - 1]);
snakeY[length] = snakeY[length - 1] - (snakeY[length - 2] - snakeY[length - 1]);
length++;
food.isBonusEat = false;
}
}
public void checkCollide()
{
for (int i = 1; i < length; i++)
{
if (snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0])
{
GamePanel.isDead = true;
break;
}
}
}
}
Food.java
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class Food {
Random rd = new Random();
private int tmpX = rd.nextInt(840);
private int tmpY = rd.nextInt(780);
int normalX = tmpX - tmpX % 20;
int normalY = tmpY - tmpY % 20;
int bonusX;
int bonusY;
boolean isEat = false;
boolean hasBonus = false;
boolean isBonusEat = false;
Timer foodTimer = new Timer();
TimerTask task = new TimerTask()
{
@Override
public void run()
{
createBonus();
hasBonus = !hasBonus;
}
};
public void changeFoodPosition() {
if (isEat) {
tmpX = rd.nextInt(840);
tmpY = rd.nextInt(780);
normalX = tmpX - tmpX % 20;
normalY = tmpY - tmpY % 20;
isEat = false;
}
}
public void createBonus() {
int tmpX = rd.nextInt(840);
int tmpY = rd.nextInt(780);
bonusX = tmpX - tmpX % 20;
bonusY = tmpY - tmpY % 20;
}
public void startTimer() {
foodTimer.scheduleAtFixedRate(task, 10000, 10000);
}
}
Player.java
import java.io.*;
import java.util.ArrayList;
public class Player
{
static String name = "";
public static String getPlayer()
{
return name;
}
public static void setPlayer(String rename)
{
name = rename;
}
public static ArrayList<String> loadAllPlayers() throws IOException
{
ArrayList<String> players = new ArrayList<String>();
BufferedReader br = new BufferedReader(new FileReader("玩家.txt"));
String player;
while ((player = br.readLine()) != null)
{
players.add(player);
}
br.close();
return players;
}
public static boolean isPlayer(String aplr)
{
try
{
ArrayList<String> players = loadAllPlayers();
for(String player:players)
{
if(player.equals(aplr))
{
return true;
}
}
return false;
}
catch (IOException e)
{
e.printStackTrace();
return false;
}
}
public static void createPlayer(String aplr) throws IOException
{
BufferedWriter bw = new BufferedWriter(new FileWriter("玩家.txt", true));
bw.write(aplr);
bw.newLine();
bw.close();
}
}
PlayerScore.java
public class PlayerScore
{
private String player;
private int score;
public PlayerScore(String name, int point)
{
player = name;
score = point;
}
public String getName()
{
return player;
}
public int getScore()
{
return score;
}
}
Point.java
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Point
{
static int point = 0;
static int bestScore;
public static void getNormalFoodPoint()
{
point += 50;
}
public static void getBonusFoodPoint()
{
point += 100;
}
public static void writeResult() throws IOException
{
BufferedWriter bw = new BufferedWriter(new FileWriter("记录.txt", true));
bw.write(Player.name + "\t" + point);
bw.newLine();
bw.close();
}
public static void readBestResult() throws IOException
{
BufferedReader br = new BufferedReader(new FileReader("记录.txt"));
String line;
int score;
while ((line = br.readLine()) != null)
{
String[] tmp = line.split("\t");
score = Integer.parseInt(tmp[1]);
if (score > bestScore)
{
bestScore = score;
}
}
br.close();
}
public static ArrayList<PlayerScore> loadAllResults() throws IOException
{
BufferedReader br = new BufferedReader(new FileReader("记录.txt"));
ArrayList<PlayerScore> results = new ArrayList<PlayerScore>();
String line;
int score;
while ((line = br.readLine()) != null)
{
String[] tmp = line.split("\t");
score = Integer.parseInt(tmp[1]);
PlayerScore playerscore = new PlayerScore(tmp[0], score);
results.add(playerscore);
}
br.close();
Collections.sort(results,new SortByScore());
return results;
}
}
class SortByScore implements Comparator<PlayerScore>
{
@Override
public int compare(PlayerScore s1, PlayerScore s2)
{
if(s1.getScore() < s2.getScore())
{
return 1;
}
return -1;
}
}
SideWindow.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.*;
public class SideWindow extends JFrame
{
private static final String AUDIO_DIR = "../audio";
private JList<String> fileList;
private JSlider slider;
private JLabel infoLabel;
private MusicOrganizer organizer;
private MusicPlayer player;
private List<Track> trackList;
public SideWindow()
{
super("Music Player");
organizer = new MusicOrganizer(AUDIO_DIR);
player = new MusicPlayer();
}
private void play()
{
int index = fileList.getSelectedIndex();
if(index >= 0 && index < trackList.size()) {
//slider.setValue(0);
player.startPlaying(trackList.get(index).getFilename());
}
}
private void stop()
{
player.stop();
}
private void setListOrdering(String ordering)
{
trackList = organizer.sortByField(ordering);
String[] tracks = getTracksDisplayList(trackList);
fileList.setListData(tracks);
}
private String[] getTracksDisplayList(List<Track> trackList)
{
int numTracks = trackList.size();
String[] tracks = new String[numTracks];
for(int i = 0; i < numTracks; i++) {
String[] fields = trackList.get(i).getFields();
StringBuilder listing = new StringBuilder();
for(String field : fields) {
listing.append(field);
listing.append(" ");
}
tracks[i] = listing.toString().trim();
}
return tracks;
}
public void makeFrame()
{
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel contentPane = (JPanel) getContentPane();
contentPane.setBorder(new EmptyBorder(6, 10, 10, 10));
setUndecorated(true);
setAlwaysOnTop(true);
contentPane.setLayout(new BorderLayout(8, 8));
JPanel leftPane = new JPanel();
{
leftPane.setLayout(new BorderLayout(8, 8));
JPanel orderingPanel = new JPanel();
orderingPanel.setLayout(new BorderLayout());
orderingPanel.add(new JLabel("Order by:"), BorderLayout.NORTH);
String[] ordering = Track.FIELDS;
JComboBox<String> formatList = new JComboBox<>(ordering);
formatList.addActionListener(a -> {
int index = formatList.getSelectedIndex();
if(index >= 0) {
String selectedOrder = formatList.getItemAt(index);
setListOrdering(selectedOrder);
}
});
orderingPanel.add(formatList, BorderLayout.CENTER);
leftPane.add(orderingPanel, BorderLayout.NORTH);
fileList = new JList<>();
fileList.setForeground(new Color(140,171,226));
fileList.setBackground(new Color(0,0,0));
fileList.setSelectionBackground(new Color(87,49,134));
fileList.setSelectionForeground(new Color(140,171,226));
JScrollPane scrollPane = new JScrollPane(fileList);
scrollPane.setColumnHeaderView(new JLabel("Audio files"));
leftPane.add(scrollPane, BorderLayout.CENTER);
setListOrdering(ordering[0]);
}
contentPane.add(leftPane, BorderLayout.CENTER);
JPanel toolbar = new JPanel();
{
toolbar.setLayout(new GridLayout(0, 1));
JButton button = new JButton("Play");
button.addActionListener(a -> play());
toolbar.add(button);
button = new JButton("Stop");
button.addActionListener(a -> stop());
toolbar.add(button);
}
contentPane.add(toolbar, BorderLayout.NORTH);
pack();
setBounds(1065,79,150,766);
setVisible(true);
}
}
MusicPlayer.java
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.FactoryRegistry;
public class MusicPlayer
{
private MusicFilePlayer player;
private String filename;
public MusicPlayer()
{
player = null;
filename = "";
}
public void startPlaying(final String filename)
{
try {
setupPlayer(filename);
playFrom(0);
}
catch (JavaLayerException ex) {
reportProblem();
}
}
public void stop()
{
killPlayer();
}
public int getLength()
{
if(player != null) {
return player.getLength();
}
else {
return 0;
}
}
private void setupPlayer(String filename)
{
try {
if(player != null) {
killPlayer();
}
this.filename = filename;
player = new MusicFilePlayer(filename);
}
catch(JavaLayerException e) {
System.out.println("Problem setting up player");
e.printStackTrace();
reportProblem();
killPlayer();
}
}
private void playFrom(final int start) throws JavaLayerException
{
Thread playerThread = new Thread() {
public void run()
{
try {
player.playFrom(start);
}
catch(JavaLayerException e) {
reportProblem();
killPlayer();
}
}
};
playerThread.setPriority(Thread.MIN_PRIORITY);
playerThread.start();
}
private void killPlayer()
{
synchronized(this) {
if(player != null) {
player.stop();
player = null;
filename = "";
}
}
}
private void reportProblem()
{
System.out.println("There was a problem playing: " + filename);
}
}
Track.java
public class Track
{
private String artist;
private String title;
private String filename;
public static final String[] FIELDS = {
"Artist",
"Title",
"Filename",
};
public Track(String artist, String title, String filename)
{
setDetails(artist, title, filename);
}
public Track(String filename)
{
setDetails("unknown", "unknown", filename);
}
public String getArtist()
{
return artist;
}
public String getTitle()
{
return title;
}
public String getFilename()
{
return filename;
}
public String getField(String field)
{
if (field.equals("Artist")) {
return artist;
}
else if (field.equals("Title")) {
return title;
}
else if (field.equals("Filename")) {
return filename;
}
else {
throw new IllegalArgumentException("Unknown field name: " + field);
}
}
public String[] getFields()
{
String[] fields = new String[FIELDS.length];
for(int i = 0; i < FIELDS.length; i++) {
fields[i] = getField(FIELDS[i]);
}
return fields;
}
public String getDetails()
{
return artist + ": " + title + " (file: " + filename + ")";
}
private void setDetails(String artist, String title, String filename)
{
this.artist = artist;
this.title = title;
this.filename = filename;
}
}
MuiscOrganizer.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class MusicOrganizer
{
private ArrayList<Track> tracks;
private TrackReader reader;
public MusicOrganizer(String folderName)
{
tracks = new ArrayList<>();
reader = new TrackReader();
readLibrary(folderName);
}
public void addFile(String filename)
{
tracks.add(new Track(filename));
}
public void addTrack(Track track)
{
tracks.add(track);
}
public Track getTrack(int index)
{
if(indexValid(index)) {
return tracks.get(index);
}
else {
return null;
}
}
public int getNumberOfTracks()
{
return tracks.size();
}
public List<Track> getAllTracks()
{
return new ArrayList<>(tracks);
}
public List<Track> sortByArtist()
{
return sortByField("Artist");
}
public List<Track> sortByTitle()
{
return sortByField("Field");
}
private List<Track> sortBy(Comparator<Track> comparator)
{
List<Track> copy = getAllTracks();
Collections.sort(copy, comparator);
return copy;
}
public List<Track> sortByField(final String field)
{
return sortBy(new Comparator<Track>() {
public int compare(Track t1, Track t2)
{
return t1.getField(field).compareTo(t2.getField(field));
}
});
}
public void removeTrack(int index)
{
if(indexValid(index)) {
tracks.remove(index);
}
}
private boolean indexValid(int index)
{
boolean valid;
if(index < 0) {
System.out.println("Index cannot be negative: " + index);
valid = false;
}
else if(index >= tracks.size()) {
System.out.println("Index is too large: " + index);
valid = false;
}
else {
valid = true;
}
return valid;
}
public void readLibrary(String folderName)
{
ArrayList<Track> tempTracks = reader.readTracks(folderName, ".mp3");
for(Track track : tempTracks) {
addTrack(track);
}
}
}
MusicFilePlayer.java
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import javazoom.jl.decoder.Bitstream;
import javazoom.jl.decoder.BitstreamException;
import javazoom.jl.decoder.Decoder;
import javazoom.jl.decoder.Header;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.decoder.SampleBuffer;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.FactoryRegistry;
public class MusicFilePlayer
{
private Bitstream bitstream;
private Decoder decoder;
private AudioDevice audio;
private boolean playing = false;
private String filename;
private int frameCount;
private int frameNumber;
public MusicFilePlayer(String filename) throws JavaLayerException
{
this.filename = filename;
openAudio();
frameCount = getFrameCount(filename);
openBitstream(filename);
frameNumber = 0;
}
public void play() throws JavaLayerException
{
playFrames(0, frameCount);
}
public boolean play(int frames) throws JavaLayerException
{
return playFrames(frameNumber, frameNumber + frames);
}
public boolean play(int start, int end) throws JavaLayerException
{
return playFrames(start, start + end);
}
public int getLength()
{
return frameCount;
}
public boolean playFrom(int start) throws JavaLayerException
{
return playFrames(start, frameCount);
}
public int getFrameNumber()
{
return frameNumber;
}
private boolean playFrames(int start, int end) throws JavaLayerException
{
if(end > frameCount) {
end = frameCount;
}
synchronized(this) {
moveTo(start);
playing = true;
}
boolean ok = true;
while (frameNumber < end && playing && ok) {
ok = decodeFrame();
if(ok) {
frameNumber++;
}
}
synchronized(this) {
playing = false;
AudioDevice out = audio;
if (out != null) {
out.flush();
}
}
return ok;
}
private void moveTo(int position) throws JavaLayerException
{
if(position < frameNumber) {
synchronized(this) {
if(bitstream != null) {
try {
bitstream.close();
}
catch (BitstreamException ex) {
}
}
if(audio != null) {
audio.close();
}
openAudio();
openBitstream(filename);
frameNumber = 0;
}
}
while(frameNumber < position) {
skipFrame();
frameNumber++;
}
}
public void close()
{
synchronized(this) {
if (audio != null) {
AudioDevice out = audio;
audio = null;
out.close();
try {
bitstream.close();
}
catch (BitstreamException ex) {
}
bitstream = null;
decoder = null;
}
}
}
protected boolean decodeFrame() throws JavaLayerException
{
try
{
synchronized (this) {
if (audio == null) {
return false;
}
Header h = readFrame();
if (h == null) {
return false;
}
SampleBuffer output = (SampleBuffer) decoder.decodeFrame(h, bitstream);
if(audio != null) {
audio.write(output.getBuffer(), 0, output.getBufferLength());
}
}
bitstream.closeFrame();
}
catch (RuntimeException ex) {
ex.printStackTrace();
throw new JavaLayerException("Exception decoding audio frame", ex);
}
return true;
}
protected boolean skipFrame() throws JavaLayerException
{
Header h = readFrame();
if (h == null) {
return false;
}
frameNumber++;
bitstream.closeFrame();
return true;
}
public void stop()
{
close();
}
protected int getFrameCount(String filename) throws JavaLayerException
{
openBitstream(filename);
int count = 0;
while(skipFrame()) {
count++;
}
bitstream.close();
return count;
}
protected Header readFrame() throws JavaLayerException
{
if(audio != null) {
return bitstream.readFrame();
}
else {
return null;
}
}
protected void openAudio() throws JavaLayerException
{
audio = FactoryRegistry.systemRegistry().createAudioDevice();
decoder = new Decoder();
audio.open(decoder);
}
protected void openBitstream(String filename)
throws JavaLayerException
{
try {
bitstream = new Bitstream(new BufferedInputStream(
new FileInputStream(filename)));
}
catch(java.io.IOException ex) {
throw new JavaLayerException(ex.getMessage(), ex);
}
}
}
接下来的面向对象实验——档案管理系统我就不放上来了,有更老的老学长的博文可以搜得到。