java基础 --- 简单的动画

java基础 --- 简单的动画

这篇主要是写在Swing程序中如何制作动画的效果。我们都知道游戏动画主要是一些连续的图片通过快速播放,由于这些连续的图片变化不是很大,因此使我们的眼睛产生影象的残留,这样就能造成动画的效果。一般以每秒24帧的速度播放图片,那么我们就感觉不出图片的停顿。
在GUI的程序中,我们可以通过线程来控制播放的速度,通过绘制不同的图片来产生动画的效果。比如:

while(播放==true)
   {
          绘制当前图像;
      暂停时间;
      if(当前图像==最后一张图像)
                       当前图像 = 第一张图像;
         else
                       当前图像 = 下一张图像
  }

这种方法有时候并不是最好的解决方法,因为需要很多张的图片,加载的时候就会很耗内存。特别是在游戏中,速度应该是是首先考虑的因素。那么我们还有另外一种方式,只需要1张图片,而这张图片将一些连续的动作绘制在里一起。我们仅需要不停的改变这张图片的某个位置就可以达到动画的效果。比如下面这张图片:

 

Graphics类中有个重载过的drawImage()方法,里面有很多的参数:
public abstract boolean drawImage(Image img,
                                  int dx1,
                                  int dy1,
                                  int dx2,
                                  int dy2,
                                  int sx1,
                                  int sy1,
                                  int sx2,
                                  int sy2,
                                  ImageObserver observer)
首尾两个参数和其他的drawImage方法一样,这里就不再做介绍。主要是中间这8个参数。
dx1,dy1,dx2,dy2表示需要绘制到窗口的某个区域,其中dx1,dy1表示该区域的左上角坐标。dx2,dy2表示该区域的右下角坐标。
sx1,sy1,sx2,sy2表示需要绘制图片上哪个区域到窗口上,其中sx1,sy1表示该区域的左上角坐标。sx2,sy2表示该区域的右下角坐标。
下面我们就可以使用这个方法来让上面这张图片动起来。

public   class  EyesNext  extends  JFrame {

 
private  Image image  =   new  ImageIcon( " Images/SERIAL.gif " ).getImage();
 
private   int  index;

 
public  EyesNext() {
  init();
 }

 
void  init() {
  
this .setUndecorated( true );
  setSize(
250 250 );
  createContent();
  setVisible(
true );
 }

 
private   void  createContent() {
  MediaTracker tracker 
=   new  MediaTracker( this );
  tracker.addImage(image, 
0 );
  
try
  {
   tracker.waitForID(
0 );
  }
  
catch  (InterruptedException e1)
  {
   e1.printStackTrace();
  }
  JPanel jpanelForm 
=   new  JPanel() {
   
protected   void  paintComponent(Graphics g) {
    g.drawImage(image, 
0 0 250 250 , index,  0 , index  +   250 250 ,
      
this );
   }
  };

  
this .getContentPane().add(jpanelForm);
 }

 
public   static   void  main(String [] args) {

  
final  EyesNext eyes  =   new  EyesNext();
  Thread thread 
=   new  Thread() {

   
public   void  run() {

    
while  ( true )
    {

     
try
     {
      Thread.sleep(
100 );
     }
     
catch  (InterruptedException e)
     {
      e.printStackTrace();
     }
     eyes.index 
=  eyes.index  +   250 ;
     
if  (eyes.index  >=   2000 )
     {
      eyes.index 
=   0 ;
      eyes.repaint();
     }
     
else
     {
      eyes.repaint();

     }
    }
   }
  };
  thread.start();

 }

}

不过这种方法也只适合绘制一些简单点的图片。比如象上面那张,只有8个图象,并且是单行的。但是如果是多行的图象,那么有时候控制起来就不是那么容易了,比如象下面这张图片:

那么我们就需要使用图片分割方法来对这张图片进行分割,然后保存在数组里面,这样我们仅需要控制数组的下标就方便多了。
java基础类库提供了这样的方法,我们需要使用到三个类ImageProduce,CropImageFilter,FilteredImageSource。我们可以通过下面的操作步骤来完成图象的分割:
Image serial = getImage(URL);//获取联系图片
  //剪切连续图片
 ImageProducer src = serial .getSource();
//设置剪切区域,一维状态,改变y值构成二维
ImageFilter cut = new CropImageFilter( i*250,0,250,250);
 FilteredImageSource fs = new FilteredImageSource( src , cut );
 Image[ i] ani = createImage(fs);

下面我们通过一段代码来将上面的图片播放出来

public   class  TestCutImage  extends  JFrame  implements  Runnable{

 Insets insets;
 Image images [][] 
=   new  Image[ 5 ][ 5 ];
 
int  row;
 
int  colum;
 TestCutImage(){
  
// 获得图片的Image对象
  Image image  =  Toolkit.getDefaultToolkit().getImage( " Images/Cg0430.jpg " );
  
// 获取需要剪切的图片资源
  ImageProducer porducer  =  image.getSource();
  
// 下面通过两个循环分割图片,保存在一个Image类型的二维数组里
   for  ( int  i  =   0 ; i  <  images.length; i ++ )
  {
   
for  ( int  j  =   0 ; j  <  images[i].length; j ++ )
   {
    
// CropImageFilter构造函数中的第一个参数是分割图片的左上角x坐标
    
// 第二个参数是分割图片的左上角y坐标
    
// 第三个参数是分割图片的宽
    
// 第四个参数是分割图片的高
    FilteredImageSource source  =   new  FilteredImageSource(porducer, new  CropImageFilter(j * 128 ,i * 96 , 128 , 96 ));
    images[i][j] 
=  createImage(source);
    
   }
  }
  MediaTracker tracker 
=   new  MediaTracker( this );
  
for  ( int  i  =   0 ; i  <  images.length; i ++ )
  {
   
for  ( int  j  =   0 ; j  <  images[i].length; j ++ )
   {
    tracker.addImage(images[i][j], 
0 );
   }
  }
  
try
  {
   tracker.waitForID(
0 );
  }
  
catch  (InterruptedException e)
  {
   e.printStackTrace();
  }
  JPanel panel 
=   new  JPanel(){
   
protected   void  paintComponent(Graphics g) {
    g.drawImage(images[row][colum], 
0 0 , 340 , 240 this );
   
   }
  };
  
this .getContentPane().add(panel);
  setUndecorated(
true );
  setSize(
340 , 240 );
  setVisible(
true );
  Thread thread 
=   new  Thread( this );
  thread.start();
 }
 
 
public   static   void  main(String [] args) {
  
  
new  TestCutImage();
 }
 
public   void  run() {

  
while ( true )
  {
   
for  ( int  i  =   0 ; i  <  images.length; i ++ )
   {
    row 
=  i;
    
for  ( int  j  =   0 ; j  <  images[i].length; j ++ )
    {
     colum 
=  j;
     
try
     {
      Thread.sleep(
50 );
     }
     
catch  (InterruptedException e)
     {
      e.printStackTrace();
     }
     repaint();
    }
   }
   
  }
 }
 
protected   void  processWindowEvent(WindowEvent e) {
  
if (e.getID()  ==  WindowEvent.WINDOW_CLOSING)
  {
   System.exit(
0 );
  }
 }
}

分割图片后,只需要对Image数组进行操作,就比操作图片里的坐标方便多了,也更准确!

 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值