简体   繁体   English

带有MediaTracker,线程和计时器的Java动画小程序

[英]Java animation applet with MediaTracker, threads and timer

I have 3 questions about my animation project. 关于动画项目,我有3个问题。

  1. Is the structure of the program correct (see below) 程序的结构是否正确(请参见下文)
  2. My first image (from an array) isn't behaving properly. 我的第一张图片(来自数组)的行为异常。 Sometimes it pops up and then disappears, and then the rest of the images display correctly. 有时它会弹出然后消失,然后其余图像可以正确显示。
  3. How do I control when the audio clip starts to play. 如何控制音频剪辑何时开始播放。 It also sometimes sounds like a needle is ripping across a record...? 有时听起来像是一根针在记录中撕裂……?

REGARDING THE PROGRAM's STRUCTURE: Are the following in the right order: 有关程序的结构:以下是按正确顺序排列的:

IN INIT: 初始化:

  1. Set applet size. 设置小程序大小。
  2. Run a timer task with a sleep time 运行带有睡眠时间的计时器任务
  3. Get the sound file. 获取声音文件。
  4. Get the images from the array. 从数组中获取图像。
  5. Initialize the MediaTracker object and tell it to "wait for all" images. 初始化MediaTracker对象,并告诉它“等待所有”图像。
  6. Play the sound file. 播放声音文件。

IN START(Graphics g) 1. Draw the applet and load the first image of the array 开始(图形g)1.绘制小程序并加载数组的第一张图像

IN START: 1. Check the threads for null values, if not null, start them 启动:1.检查线程是否为空值,如果不为空,则启动它们

IN RUN: 1. Use a variable "iPictureNumber" to iterate through the images in sequential order also using repaint and Thread.sleep methods 运行中:1.使用变量“ iPictureNumber”以顺序方式遍历图像,也使用repaint和Thread.sleep方法

IN UPDATE: 1. Draw the applet again. 更新:1.再次绘制小程序。


This code is an updated version of another program I have that didn't use threads, so I'm not sure if this is the correct structure. 这段代码是我没有使用线程的另一个程序的更新版本,所以我不确定这是否是正确的结构。 My goal is to use best practices with this type of simple program. 我的目标是在此类简单程序中使用最佳做法。 I can provide the images and sound in a zip file if needed. 如果需要,我可以在zip文件中提供图像和声音。 Please advise, thanks in advance. 请告知,在此先感谢。 HERE IS THE CODE: 代码如下:

// Java animation project with array of images and 1 sound file using threads // Java动画项目,其中包含使用线程的图像数组和1个声音文件

 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

I wouldn't use Applet , use JApplet , it will solve dozens of problems off the bat ;) 我不会使用Applet ,而不会使用JApplet ,它将立即解决许多问题;)

I probably would probably use separate Runnables for the threadTrainAnimation and threadSoundFile , but I've not had much experience with sound in the past. 我可能会为threadTrainAnimationthreadSoundFile使用单独的Runnables ,但是过去我对声音没有太多的经验。 The problem I see though is you have two threads accessing the portion of code simultaneously doing the same thing. 我看到的问题是,您有两个线程同时访问同一部分代码。 This is just making a mess of things. 这只是一团糟。

You need to figure out how to sync the sound and the animation. 您需要弄清楚如何同步声音和动画。

The use of the java.util.Timer is incorrect for what you are trying to achieve, it's also overkill given the fact that you have threadTrainAnimation running, as they are generally doing the same thing. java.util.Timer的使用对于您要实现的目标是不正确的,考虑到您正在运行threadTrainAnimation的事实(这通常与它们的作用相同),这也threadTrainAnimation了。 In this case I'd probably just get rid of it. 在这种情况下,我可能会摆脱它。 In the future, you're better of using javax.swing.Timer as it provides better support for the Event Dispatching Thread 将来,最好使用javax.swing.Timer因为它为Event Dispatching Thread提供了更好的支持。

I, personally, wouldn't load my resources in the init method the way you are. 我个人不会以您的方式在init方法中加载资源。 This is going to slow down the loading of the applet and make users upset. 这将减慢小程序的加载并使用户不高兴。 You'd be better putting up a nice "loading" image and use a Thread to perform the loading. 您最好放置一个不错的“加载”图像,并使用Thread执行加载。 Once done, using something like SwingUtilities.invokeLater to start the animation. 完成后,使用SwingUtilities.invokeLater东西开始动画。

Don't override the update method, you should override the paint method instead. 不要覆盖update方法,而应该覆盖paint方法。

It's also possible that images are been changed faster then they can be painted, you may want to give some thought to this as well - that is the run method may execute a number of times before paint is called 也可能是图像的更改速度更快,然后可以绘制它们,您可能还需要对此加以考虑-即run方法可能在调用paint之前执行了多次

As a suggestion, I'd read through 作为建议,我会通读

If you're serious about animation, I'd also check out 如果您对动画很认真,我也会帮您检查一下

Which are animation frameworks for Java 哪些是Java的动画框架

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM