我有 3 个关于我的动画项目的问题。
- 程序的结构是否正确(见下文)
- 我的第一张图像(来自数组)表现不正常。有时它会弹出然后消失,然后其余图像会正确显示。
- 如何控制音频剪辑何时开始播放。有时听起来就像一根针在撕裂唱片......?
关于该计划的结构: 以下内容的顺序是否正确:
在初始化中:
- 设置小程序大小。
- 运行具有 sleep 时间的计时器任务
- 获取声音文件。
- 从数组中获取图像。
- 初始化 MediaTracker 对象并告诉它“等待所有”图像。
- 播放声音文件。
开始(图形g) 1.绘制小程序并加载数组的第一张图片
开始时: 1.检查线程是否为空值,如果不为空,则启动它们
运行中: 1. 使用变量“iPictureNumber”按顺序迭代图像,也使用 repaint 和 Thread.sleep 方法
更新中: 1. 再次绘制小程序。
<小时/>这段代码是我拥有的另一个没有使用线程的程序的更新版本,所以我不确定这是否是正确的结构。 我的目标是对这种类型的简单程序使用最佳实践。如果需要,我可以提供 zip 文件中的图像和声音。请指教,先谢谢了。 这是代码:
//使用线程包含图像数组和 1 个声音文件的 Java 动画项目
import java.net.*;
import java.io.*;
import java.lang.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.applet.Applet;
import java.applet.AudioClip;
import java.util.*;
public class c_TrainAnimation extends Applet implements Runnable
{
Image trainAndBush[];
int totalImages = 17,
currentImage = 0, // Set current image array subscript to 0
sleepTime = 900;
Image imageCurrent; // Set to the matching image in "trainAndBush" Array
MediaTracker myImageTracker;
Timer myTimer;
Thread threadTrainAnimation = new Thread(this);
Thread threadSoundFile = new Thread(this);
AudioClip mySound;
public void init()
{
setSize(400,400);
myTimer = new Timer(true);
myTimer.schedule( new TimerTask()
{
public void run()
{ repaint();}
} // end TimerTask
,0,sleepTime);
mySound = getAudioClip(getDocumentBase(), "onpoint.au");
trainAndBush = new Image[ totalImages ];
// Load the array of images into the Applet when it begins executing
for( int i = 0; i < trainAndBush.length; i++ )
{
trainAndBush[i] = getImage(getDocumentBase(),
"Hill" + (i + 1) + ".jpg" );
myImageTracker = new MediaTracker( this );
// Give the images an ID number to pass to MediaTracker
myImageTracker.addImage(trainAndBush[i], i);
// Tell MediaTracker to wait until all images are loaded
try
{
myImageTracker.waitForAll();
}
catch(Exception e) {}
mySound.play();
} // end for loop
} // end init
// check threads for null values and then start threads
public void start()
{
if (threadTrainAnimation != null )
threadTrainAnimation.start();
if (threadSoundFile != null )
threadSoundFile.start();
}
// Draw the applet with the first image of the array
public void start(Graphics g)
{
g.drawImage(trainAndBush[0],50,50,300,300, this );
currentImage = 0;
}
// Set "imageCurrent"to appropriate "trainAndBush image" in the array and_
loop through
public void run()
{
int iPictureNumber[] = {0, 1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16};
while( true )
{
for( int i = 0; i < iPictureNumber.length; i++ )
{
imageCurrent = trainAndBush[iPictureNumber[i]];
repaint();
try
{
Thread.sleep( sleepTime );
}
catch( InterruptedException e) {}
} // end for loop
} // end while statement
} // end run
public void update(Graphics g)
{
g.drawImage( imageCurrent, 50, 50, 300, 300, this );
}
} // end of Applet
最佳答案
我不会使用Applet
,使用JApplet
,它会立即解决几十个问题;)
我可能会为 threadTrainAnimation
和 threadSoundFile
使用单独的 Runnables
,但我过去在声音方面没有太多经验。我看到的问题是你有两个线程同时访问代码部分做同样的事情。这只会把事情搞得一团糟。
您需要弄清楚如何同步声音和动画。
使用java.util.Timer
对于您想要实现的目标来说是不正确的,考虑到您正在运行threadTrainAnimation
,它也是矫枉过正的,因为它们通常都在做同样的事情。在这种情况下,我可能会摆脱它。将来,您最好使用javax.swing.Timer
,因为它为事件调度线程
提供更好的支持
我个人不会按照您的方式在 init
方法中加载我的资源。这会减慢小程序的加载速度并使用户感到不安。您最好放置一个漂亮的“加载”图像并使用Thread
来执行加载。完成后,使用 SwingUtilities.invokeLater
之类的东西来启动动画。
不要重写 update
方法,您应该重写 paint
方法。
图像的更改速度也有可能比绘制速度更快,您可能也需要考虑一下这一点 - 即 run
方法可能会在 paint
被调用
作为建议,我会通读
- Concurrency in Swing
- Performing Custom Painting
- Painting in AWT and Swing
- How to make Applets (因为他们在这里讨论动画)
如果你认真对待动画,我也会看看
Java 的动画框架有哪些
关于带有 MediaTracker、线程和计时器的 Java 动画小程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11943032/