J2ME在移动设备上实现动画

关于J2me手游fillrect和drawImage效率问题 <br />前一阵子两个同事,做游戏中按钮的时候,一个说用矩形去画按钮,另一位说让美术出图,效果一样,最有就讨论起这两者的效率问题,说画矩形并填充颜色也很耗内存和资源。因为是一个一个点打出来的,今天做了下测试,用一张纯黑的图,重复画N次,2用fillrect画黑矩形<br />程序如下:<br /> <br /> import java.io.IOException; import javax.microedition.amms.control.imageeffect.WhiteBalanceCont 阅读详情

使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。MIDP 1.0 没有直接提供对动画的支持(MIDP 2.0支持),但真要是自己去实现,其实也并非是一件很难的事。
  任何动画的最基本的前提,是要在足够快的时间内显示和更换一张张的图片,让人的眼睛看到动的画面效果。图片必须按照顺序画出来。从一张图片到下一张图片之间的变化越小,效果会越好。

  首先要做的,是使用你的图片处理软件(比如ps或者firework)创建一系列相同大小的图片来组成动画。每张图片代表动画一帧。你需要制作一定数量的祯--越多的帧会让你的动画看上去越平滑。制作好的图片一定要保存成PNG(Portable Network Graphics)格式,MIDP唯一支持的图片格式。

  有两个办法让你刚做好的图片在MIDlet上变成动画。第一,把图片都放到一个web服务器上,让MIDlet下载他们,MIDP内置的HTTP支持。第二个办法更简单,把图片用MIDlet打包成jar文件。如果你使用的是J2ME开发工具,把PNG文件放你的项目文件里面就可以了。

  动画的过程其实更像帐本记录:显示当前帧,然后适当地更换到下一帧。那么使用一个类来完成这个工作应该是很恰当的,那好,我们就先定义一个AnimatedImage类:

import java.util.*;
import javax.microedition.lcdui.*;
// 定义了一个动画,该动画其实只是一系列相同大小的图片
// 轮流显示,然后模拟出的动画
public class AnimatedImage extends TimerTask {;
private Canvas canvas;
private Image[] images;
private int[][] clipList;
private int current;
private int x;
private int y;
private int w;
private int h;

// Construct an animation with no canvas.

public AnimatedImage( Image[] images ){;
 this( null, images, null );
};

// Construct an animation with a null clip list.

public AnimatedImage( Canvas canvas, Image[] images )
{;
 this( canvas, images, null );
};

// Construct an animation. The canvas can be null,
// but if not null then a repaint will be triggered
// on it each time the image changes due to a timer
// event. If a clip list is specified, the image is
// drawn multiple times, each time with a different
// clip rectangle, to simulate transparent parts.

public AnimatedImage( Canvas canvas, Image[] images, int[][] clipList ){;
 this.canvas = canvas;
 this.images = images;
 this.clipList = clipList;

 if( images != null && clipList != null ){;
  if( clipList.length < images.length ){;
   throw new IllegalArgumentException();
  };
 };

 if( images != null && images.length > 0 ){;
  w = images[0].getWidth();
  h = images[0].getHeight();
 };
};

// Move to the next frame, wrapping if necessary.

public void advance( boolean repaint ){;
 if( current >= images.length ){;
  current = 0;
 };

 if( repaint && canvas != null && canvas.isShown() ){;
  canvas.repaint( x, y, w, h );
  canvas.serviceRepaints();
 };
};

copy, otherwise
// set the clipping rectangle accordingly and
// draw the image multiple times.

public void draw( Graphics g ){;
 if( w == 0 || h == 0 ) return;
 int which = current;
 if( clipList == null || clipList[which] == null ){;
  g.drawImage( images[which], x, y,
  g.TOP | g.LEFT );
 }; else {;
  int cx = g.getClipX();
  int cy = g.getClipY();
  int cw = g.getClipWidth();
  int ch = g.getClipHeight();

  int[] list = clipList[which];

  for( int i = 0; i 3 <= list.length; i =4 ){;
   g.setClip( x list[0], y list[1], list[2], list[3] );
   g.drawImage( images[which], x, y,
   g.TOP | g.LEFT );
  };

  g.setClip( cx, cy, cw, ch );
 };
};

// Moves the animation′s top left corner.

public void move( int x, int y ){;
 this.x = x;
 this.y = y;
};

// Invoked by the timer. Advances to the next frame
软件开发网

// and causes a repaint if a canvas is specified.

 public void run(){;
  if( w == 0 || h == 0 ) return;
 
  advance( true );
 };
};
  你实例化一个AnimatedImage对象的时候你必须给AnimatedImage类的构造方法传一个Image对象数组,该数组代表动画的每一帧。使用的所有图片必须具有相同的高度和宽度。

  用Image.createImage()方法从jar文件里面加载图片:

private Image[] loadFrames( String name, int frames )
throws IOException {;
 Image[] images = new Image[frames];
 for( int i = 0; i < frames; i ){;
  images = Image.createImage( name i ".png" );
 };
 return images;
};
  你也可以传递一个Canvas对象(可选),和一个剪辑列表(clip list)。如果你指定了一个canvas和使用一个timer来自动更换到动画的下一帧,就如下面的例子代码中一样,canvas在动画向前滚动以后自动被重画(repaint)。不过这样的实现办法是可选的,你可以这样做,也可以让程序选择合适的时候重画canvas。

  因为MIDP 1.0不支持透明的图片,AnimatedImage 类使用一个剪辑列表来模拟透明的效果,剪辑列表是图片被剪成的方块区域的系列。图片被画出来的时候分开几次,每次画一个剪辑列表里面的剪辑区域。剪辑列表在帧的基础上被定义好,所以你需要为图片的每一帧创建一个数组。数组的大小应该是4的倍数,因为每一个剪辑面积保持了四个数值:左坐标,顶坐标,宽度以及高度。坐标的原点是整个图片的左上角。需要注意的是使用了剪辑列表会使动画慢下来。如果图片更加复杂的话,你应该使用矢量图片。

  AnimatedImage类扩展了java.util.TimerTask,允许你设定一个timer。这里有个例子说明如何使用timer做动画:

Timer timer = new Timer();
AnimatedImage ai = ..... // get the image
timer.schedule( ai, 200, 200 );
  每隔大约200毫秒,timer调用AnimatedImage.run()方法一次,这个方法使得动画翻滚到下一个帧。现在我们需要的是让MIDlet来试试显示动画!我们定义一个简单的Canvas类的子类,好让我们把动画“粘贴上去”。

import java.util.*;
import javax.microedition.lcdui.*;

// A canvas to which you can attach one or more
// animated images. When the canvas is painted,
it cycles through the animated images and asks
// them to paint their current image.

public class AnimatedCanvas extends Canvas {;
 private Display display;
 private Image offscreen;
 private Vector images = new Vector();

 public AnimatedCanvas( Display display ){;
  this.display = display;

  // If the canvas is not double buffered by the
  // system, do it ourselves...

  if( !isDoubleBuffered() ){;
   offscreen = Image.createImage( getWidth(),
   getHeight() );
  };
 };

 // Add an animated image to the list.

 public void add( AnimatedImage image ){;
  images.addElement( image );
 };

 // Paint the canvas by erasing the screen and then
 // painting each animated image in turn. Double
 // buffering is used to reduce flicker.

 protected void paint( Graphics g ){;
  Graphics saved = g;

  if( offscreen != null ){;
   g = offscreen.getGraphics();
http://www.mscto.com
  };

  g.setColor( 255, 255, 255 );
  g.fillRect( 0, 0, getWidth(), getHeight() );

  int n = images.size();
  for( int i = 0; i < n; i ){;
   AnimatedImage img = (AnimatedImage)
   images.elementAt( i );
   img.draw( g );
  };

  if( g != saved ){;
   saved.drawImage( offscreen, 0, 0,
   Graphics.LEFT | Graphics.TOP );
  };
 };
};

  AnimatedCanvas 类的代码相当简单,由一个动画导入方法和一个paint方法。canvas画布每次被画,背景都会被擦除然后循环每个导入的AnimatedImage对象,直接画到自己身上来(自己扩展了canvas类)。

import java.io.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

// MIDlet that displays some simple animations.
// Displays a series of birds on the screen and
// animates them at different (random) rates.

public class AnimationTest extends MIDlet
implements CommandListener {;

 private static final int BIRD_FRAMES = 7; 软件开发网
 private static final int NUM_BIRDS = 5;

 private Display display;
 private Timer timer = new Timer();
 private AnimatedImage[] birds;
 private Random random = new Random();

 public static final Command exitCommand = new Command( "Exit",Command.EXIT, 1 );
 public AnimationTest(){; };

 public void commandAction( Command c,Displayable d ){;
  if( c == exitCommand ){;
   exitMIDlet();
  };
 };

 protected void destroyApp( boolean unconditional )
  throws MIDletStateChangeException {;
   exitMIDlet();
  };

 public void exitMIDlet(){;
  timer.cancel(); // turn it off...
  notifyDestroyed();
 };

 // Generate a non-negative random number...

 private int genRandom( int upper ){;
  return( Math.abs( random.nextInt() ) % upper );
 };

 public Display getDisplay(){; return display; };

 // Initialize things by creating the canvas and then
// creating a series of birds that are moved to
 // random locations on the canvas and attached to
 // a timer for scheduling.

 protected void initMIDlet(){;
  try {;
   AnimatedCanvas c = new
   AnimatedCanvas( getDisplay() );
   Image[] images =loadFrames( "/images/bird", BIRD_FRAMES );

   int w = c.getWidth();
   int h = c.getHeight();

   birds = new AnimatedImage[ NUM_BIRDS ];
   for( int i = 0; i < NUM_BIRDS; i ){;
    AnimatedImage b = new
    AnimatedImage( c, images );
    birds = b;
    b.move( genRandom( w ), genRandom( h ) );
    c.add( b );
    timer.schedule( b, genRandom( 1000 ),genRandom( 400 ) );
   };

   c.addCommand( exitCommand );
   c.setCommandListener( this );

   getDisplay().setCurrent( c );
  };
  catch( IOException e ){;
   System.out.println( "Could not load images" );
   exitMIDlet();


  };
 };

 // Load the bird animation, which is stored as a
 // series of PNG files in the MIDlet suite.

 private Image[] loadFrames( String name, int frames )
 throws IOException {;
  Image[] images = new Image[frames];
  for( int i = 0; i < frames; i ){;
   images = Image.createImage( name i ".png" );
  };

  return images;
 };

 protected void pauseApp(){; };

 protected void startApp()
 throws MIDletStateChangeException {;
  if( display == null ){;
   display = Display.getDisplay( this );
   initMIDlet();
  };
 };
};
  七帧图片的动画,你可以看到一个拍着翅膀的小鸟。MIDlet显示了5只小鸟,小鸟的位置和刷新速度是随机的。你可以用一些其他的办法来改进这个程序,但这个程序也应该足够能让你上手了。

一个简单的J2ME动画代码 用midp1.0实现一个龙喷火的动画,是手机游戏初学者很好的借鉴范例,代码也很好理解。 立即下载

相关推荐

别再怕非观测区了!手把手教你用移相法搞定PMSM单电阻FOC的电流重构难题

本文详细解析了永磁同步电机(PMSM)单电阻FOC系统中非观测区的电流重构难题,重点介绍了移相法的工程实践。通过STM32平台的具体实现和调试指南,帮助工程师有效解决相电流检测中的采样窗口不足问题,提升系统稳定性和性能。

weixin_27252001的博客 433

用J2ME在移动设备上实现动画

用J2ME在移动设备上实现动画使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。MIDP 1.0 没有直接提供对动画的支持(MIDP 2.0支持),但真要是自己去实现,其实也并非是一件很难的事。   任何动画的最基本的前提,是要在足够快的时间内显示和更换一张张的图片,让人的眼睛看到动的画面效

vgame的专栏 651

CMake接口库实战:如何用add_library的INTERFACE选项管理跨项目依赖

本文深入探讨了CMake中add_library的INTERFACE选项在管理跨项目依赖时的实战应用。通过创建不包含源代码的接口库,开发者可以集中管理头文件路径、编译定义、链接库等公共配置,并将其声明式地传递给依赖目标。文章以构建模块化跨平台网络应用为例,详细展示了如何利用接口库实现配置的集中化、依赖关系的显式化,从而提升大型项目的可维护性和可移植性。

water的专栏 1040

android 图片动态移动,使用动画移动视图  |  Android 开发者  |  Android Developers

屏幕上的对象通常需要重新定位。这种情况可能是由于用户互动或幕后进行某些处理而导致的。您应使用动画将对象从起始位置移动到结束位置,而不应立即更新对象位置,立即更新对象位置会使对象从一个区域闪跳到另一个区域。Android 提供了一些可让您在屏幕上重新定位视图对象的方法,例如 ObjectAnimator。您可以提供希望对象停留的结束位置,以及动画的持续时间。您可以将此方法与时间插值器结合使用,以控制...

weixin_34493203的博客 451

【技术解析】LUT-Fuse:如何通过可学习查找表与蒸馏技术,为边缘设备解锁实时图像融合

本文解析了ICCV 2025提出的LUT-Fuse技术,它通过可学习查找表与知识蒸馏,解决了边缘设备上图像融合的质量、速度与功耗“不可能三角”。该方法将复杂计算预编译为高速查找表,在Jetson等设备上实现100+ FPS的实时红外-可见光图像融合,为无人机、安防等应用提供了高效解决方案。

code8的博客 495

Matlab编码转换实战:从GBK到UTF-8的完整解决方案

本文提供Matlab编码转换的完整实战方案,重点解决GBK与UTF-8编码冲突导致的中文乱码问题。通过修改系统配置文件、批量转换项目文件及设置默认保存编码,实现从GBK到UTF-8的彻底迁移,并分享常见避坑指南与自动化脚本技巧,确保代码跨平台协作的稳定性。

weixin_29031057的博客 325

使用J2ME技术实现简单的动画(附代码实现)

在J2ME程序开发过程中经常需要实现游戏动画,例如简单的文字闪动,复杂的游戏界面变化等等,下面简单的介绍一下动画的原理,并附实现代码。        动画原理就是利用人的视觉暂留的生理特性,实现出来的一种假象。下面的代码就是不断的变化绘制的内容,实现文字的闪动。       程序的逻辑:每隔0.2秒变换一次绘制的内容,如果屏幕上没有绘制文字,则绘制,否则绘制文字。       实现代码如下:pac

Scent of Mobile Application 1614

Python航空航天设计神器!从入门到实操,小白也能搞定飞机优化

AeroSandbox的核心价值的是:​降低航空工程优化的门槛,用Python实现高效、简洁的工程设计​。无论是科研、学习还是实际项目,它都能帮你节省大量时间,不用再手动推导导数、编写复杂的优化逻辑。对于新手来说,建议先从案例1(Rosenbrock函数)入手,熟悉优化流程,再尝试案例2(翼型优化),逐步掌握核心用法;对于有航空相关需求的小伙伴,可以深入研究内置的物理模型,结合自己的项目进行定制化开发。最后,互动时间到!👉 你是用AeroSandbox做科研、练手还是实际项目?

源代码杀手的博客 124

用J2ME在移动设备上实现动画(3)

用J2ME在移动设备上实现动画(3)[@more@]AnimatedCanvas 类的代码相当简单,由一个动画导入方法和一个paint方法。canvas画布每次被画,背景都会被擦除,然后循环每个导入的AnimatedImage对...

cuilongshi8706的博客 150

uniapp - 超详细的 H5 公众号网页微信登录示例代码,提供从 0-1 公众号配置及详细注释代码(站在新手小白的角度)第三方微信授权登录的实现!!

uniapp微信浏览器H5授权微信登录,UniApp开发H5接入微信登录的全过程,uniapp的H5页面使用微信登录,uniapp H5微信授权登录,H5之微信授权登陆 (uniapp网页版微信授权登录),uni-app开发H5第三方微信授权登录的实现,uniapp如何实现微信授权登录,公众号H5页面接入微信登录流程,uni-app - 最详细 H5 网页接入微信登录功能,提供公众号配置与详细注释示例代码(移动端网页实现点击登录按钮后 调用微信公众号授权登录功能 详细讲解接入流程与详细示例代码)官方最新超级

✅ 精选推荐文章 1万+

基于 STM32 的便携式肌电信号采集与疲劳度评估系统设计与实现

本系统以 STM32 单片机为核心控制器,通过肌电电极采集人体骨骼肌表面的 sEMG 信号,经仪表放大、滤波、AD 采样后送入 MCU 进行时域 / 频域特征提取,利用 RMS(均方根)、MPF(中位频率)、MF(平均频率)等指标实时评估肌肉疲劳状态,最终通过 OLED 显示疲劳等级,并支持蓝牙上传至上位机。

weixin_42300449的博客 105

[转载]用J2ME在移动设备上实现动画

用J2ME在移动设备上实现动画使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。MIDP 1.0 没有直接提供对动画的支持(正在...

congji3817的博客 168

AXI总线详解完结篇

经过几个月的整理和发文,AXI总线详解系列正式迎来最终篇,内容基本涵盖了上一篇文章的全部内容。 所有文章的链接如下: 1、 AXI总线详解 2、AXI总线详解-总线和接口以及协议 3、AXI协议中的通道结构 4、AXI总线详解-AXI4读写操作时序及AXI4猝发地址及选择 5、AXI4交换机制 6、ZYNQ中DMA与AXI4总线-DMA简介 7、AXI总线详解-不同类型的DMA 8、AXI总线详解-DMA内部寄存器的读写方式 9、AXI总线详解-几种应用DMA的场合 10、Altera Scatter-G.

OpenFPGA的博客 5492

用J2ME在移动设备上实现动画(2)

用J2ME在移动设备上实现动画(2)[@more@]使用的所有图片必须具有相同的高度和宽度。用Image.createImage()方法从jar文件里面加载图片: private Image[] loadFrames( Stri...

cuilongshi8706的博客 123

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

用J2ME在移动设备上实现动画(转)

使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。 MIDP 1.0 没有直接提供对动画的支持(正在开发中的MIDP 2.0支持...

cuankuangzhong6373的博客 162

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

用J2ME在移动设备上实现动画(1)

用J2ME在移动设备上实现动画(1)[@more@]使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。 MIDP 1.0 没有直...

cuilongshi8706的博客 153

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

用J2ME在移动设备上实现动画(1) (2007-04-11 11:47)

使用MIDP(Mobile Information Device Profile)的开发人员经常会抱怨用些什么办法才可以在一个MIDlet上显示动画。MIDP 1.0 没有直接提供对动画的支持(MIDP 2.0支持),但真要是自己去实现,其实也并非是一件很难的事。   任何动画的最基本的前提,是要在足够快的时间内显示和更换一张张的图片,让人的眼睛看到动的画面效果。图片必须按照顺序画出来。

eric474470的专栏 374

用J2ME在移动设备上实现动画(3) (2007-04-11 11:50)

使用Sprite类实现人物动画   Game API函数里提供的另一个具体的Layer类是Sprite类。一方面,Sprite类是TileLayer类的概念化的逆转.TiledLayer类使用源图像贴片的调色板来创建一幅大场景,而Sprite类则使用一系列源图像帧来产生动画。   你创建一个Sprite类所需要的只是源图像和每个帧的尺寸。在TiledLayer类里,源图像被分为相同大小的图

eric474470的专栏 460

用J2ME在移动设备上实现动画(2) (2007-04-11 11:48)

使用图层   在一个游戏中 (或者其他的图形程序),显示区域内通常包含不同的内容(图像可能是有关联的或者是没有关联的)。比如一只蜜蜂可以在森林,陆地,水面上飞翔,但是在一个迷宫中人却不能穿越围墙。   MIDP 2.0游戏 API为此引进了图层。图层提供了控制屏幕上的对象或者上下文的方法。图层可以是TiledLayer (比如背景), Sprite (比如飞机), 或者通过继承L

eric474470的专栏 628
上一篇: 多线程的几种实现方法详解
下一篇: 利用J2ME与ASP建立数据库连接
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值