我尝试使用不同的库在我的 Java Swing 游戏中播放视频,我决定使用 VLCj,我有一个名为 CutscenePlayer 的类,它负责播放视频,但我还有一个名为 JPanel 的类 GamePanel和另一个名为CutsceneManager的类调用CutscenePlayer,每当视频播放时我都可以听到声音,但只有黑屏,这是我的CutscenePlayer类:
import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.base.MediaPlayer;
import uk.co.caprica.vlcj.player.base.MediaPlayerEventAdapter;
public class CutscenePlayer extends MediaPlayerEventAdapter {
GamePanel gp;
public static EmbeddedMediaPlayerComponent mediaPlayerComponent;
public boolean playing;
public String video;
public CutscenePlayer(GamePanel gp) {
this.gp = gp;
}
public void setCutscene(String filePath) {
video = filePath;
}
public void playCutscene() {
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
Main.window.add(mediaPlayerComponent);
mediaPlayerComponent.mediaPlayer().events().addMediaPlayerEventListener(new MediaPlayerEventAdapter() {
@Override
public void finished(MediaPlayer mediaPlayer) {
System.out.println("Hello");
mediaPlayerComponent.release();
gp.gameState = gp.cutsceneState;
playing = false;
}
}
);
mediaPlayerComponent.mediaPlayer().media().play(video);
}
public void play() {
mediaPlayerComponent.mediaPlayer().controls().pause();
}
public void pause() {
mediaPlayerComponent.mediaPlayer().controls().pause();
}
}
这里是调用 CutscenePlayer 的 CutsceneManager 代码:
if (isCutscenePlaying == false) {
gp.csPlayer.setCutscene("test3.mp4");
gp.csPlayer.playCutscene();
isCutscenePlaying = true;
gp.gameState = gp.cutscenePlayingState;
}
else {
scenePhase++;
isCutscenePlaying = false;
}
这是具有线程并绘制所有内容的 GamePanel 代码:
@Override
public void run() {
final double drawInterval = 1000000000 / FPS;
double delta = 0.0;
long lastTime = System.nanoTime();
long currentTime;
while (gameThread != null) {
currentTime = System.nanoTime();
delta += (currentTime - lastTime) / drawInterval;
lastTime = currentTime;
while (delta >= 1.0) {
if (gameState != cutscenePlayingState) {
update();
drawToTempScreen();
drawToScreen();
}
--delta;
}
}
}
public void update() {
if (gameState == playState) {
//PLAYER
player.update();
//NPC
for (int i = 0; i < npc[1].length; i++) {
if (npc[currentMap][i] != null) {
npc[currentMap][i].update();
}
}
for (int i = 0; i < monster[1].length; i++) {
if (monster[currentMap][i] != null) {
if (monster[currentMap][i].alive == true && monster[currentMap][i].dying == false) {
monster[currentMap][i].update();
}
if (monster[currentMap][i].alive == false) {
monster[currentMap][i].checkDrop();
monster[currentMap][i] = null;
}
}
}
for (int i = 0; i < projectile[1].length; i++) {
if (projectile[currentMap][i] != null) {
if (projectile[currentMap][i].alive == true) {
projectile[currentMap][i].update();
}
if (projectile[currentMap][i].alive == false) {
projectile[currentMap][i] = null;
}
}
}
for (int i = 0; i < particleList.size(); i++) {
if (particleList.get(i) != null) {
if (particleList.get(i).alive == true) {
particleList.get(i).update();
}
if (particleList.get(i).alive == false) {
particleList.remove(i);
}
}
}
for (int i = 0; i < iTile[1].length; i++) {
if (iTile[currentMap][i] != null) {
iTile[currentMap][i].update();
}
}
eManager.update();
}
if (gameState == pauseState) {
//nothing
}
}
public void drawToTempScreen() {
//DEBUG
long drawStart = 0;
if (keyH.debugOn == true) {
drawStart = System.nanoTime();
}
//TITLE SCREEN
if (gameState == titleState) {
ui.draw(g2);
}
// //MAP SCREEN
// else if (gameState == mapState){
// map.drawFullMapScreen(g2);
// }
//OTHERS
else {
//TILE
tileM.draw(g2);
//INTERACTIVE TILE
for (int i = 0; i < iTile[1].length; i++) {
if (iTile[currentMap][i] != null) {
iTile[currentMap][i].draw(g2);
}
}
//ADD ENTITIES TO THE LIST
entityList.add(player);
for (int i = 0; i < npc[1].length; i++) {
if (npc[currentMap][i] != null ) {
entityList.add(npc[currentMap][i]);
}
}
for (int i = 0; i < obj[1].length; i++ ) {
if (obj[currentMap][i] != null) {
entityList.add(obj[currentMap][i]);
}
}
for (int i = 0; i < monster[1].length; i++ ) {
if (monster[currentMap][i] != null) {
entityList.add(monster[currentMap][i]);
}
}
for (int i = 0; i < projectile[1].length; i++ ) {
if (projectile[currentMap][i] != null) {
entityList.add(projectile[currentMap][i]);
}
}
for (int i = 0; i < particleList.size(); i++ ) {
if (particleList.get(i) != null) {
entityList.add(particleList.get(i));
}
}
//SORT
Collections.sort(entityList, new Comparator<Entity>() {
@Override
public int compare(Entity e1, Entity e2) {
int result = Integer.compare(e1.worldY, e2.worldY);
return result;
}
});
//DRAW ENTITIES
for (int i = 0; i < entityList.size(); i++) {
entityList.get(i).draw(g2);;
}
//EMPTY ENTITY LIST
entityList.clear();
//ENVIORNMENT
eManager.draw(g2);
// //MINIMAP
// map.drawMinimap(g2);
//CUTSCENE MANAGER
csManager.draw(g2);
//UI
ui.draw(g2);
//TIME AMULET SCREEN
if (gameState == timeAmuletState){
g2.setColor(new Color(0, 0, 0, 150));
g2.fillRect(0, 0, screenWidth, screenHeight);
dClock.drawClock(g2);
}
}
//DEBUG
if (keyH.debugOn == true) {
long drawEnd = System.nanoTime();
long passed = drawEnd - drawStart;
System.out.println("Draw Time: " + passed);
g2.setFont(getFont().deriveFont(20F));
g2.setColor(Color.WHITE);
int x = 10;
int y = 400;
int lineHeight = 20;
g2.drawString("Draw Time: " + passed, x, y); y += lineHeight;
g2.drawString("Col: " + (player.worldX + player.solidArea.x)/tileSize, x, y); y += lineHeight;
g2.drawString("Row: " + (player.worldY + player.solidArea.y)/tileSize, x, y); y += lineHeight;
g2.drawString("God Mode: "+ keyH.godModeOn, x, y); //y += lineHeight;
}
}
public void drawToScreen() {
if (gameState != cutscenePlayingState) {
Graphics g = getGraphics();
g.drawImage(tempScreen, 0, 0, screenWidth2, screenHeight2, null);
g.dispose();
}
}
最后是Main类:
public static void main(String[] args) {
window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.setTitle("Time Maze");
new Main().setIcon();
window.add(gamePanel);
gamePanel.config.loadConfig();
if (gamePanel.fullScreenOn) {
window.setUndecorated(true);
}
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
gamePanel.setUpGame();
gamePanel.startGameThread();
}
我想让它播放视频,然后恢复到 GamePanel 以便游戏可以继续,但我却得到黑屏(GamePanel 背景的颜色),并且游戏甚至无法恢复。问题是 GamePanel 显示在 mediaPlayerComponent 上。我在 mediaPlayerComponent 上尝试了 setContentPane,但视频播放完毕后,屏幕将卡在视频的最后一帧。
我用这个替换了 playCutscene() 方法:
public void playCutscene() {
mediaPlayerComponent = new EmbeddedMediaPlayerComponent();
Main.window.add(mediaPlayerComponent);
Main.gamePanel.setVisible(false);
playing = true;
mediaPlayerComponent.mediaPlayer().events().addMediaPlayerEventListener(new MediaPlayerEventAdapter() {
@Override
public void finished(MediaPlayer mediaPlayer) {
System.out.println("Hello");
Main.window.remove(mediaPlayerComponent);
Main.gamePanel.setVisible(true);
//Main.gamePanel.setFocusable(true);
gp.gameState = gp.cutsceneState;
playing = false;
mediaPlayerComponent.release();
}
}
);
mediaPlayerComponent.mediaPlayer().media().play(video);
}
它的工作原理是将 mediaPlayerComponent 添加到窗口,然后将 GamePanel 设置为不可见。在视频结束时,它将恢复正常并释放资源。