分享
 
 
 

基于MIDP1.0实现动画效果

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

在SUN的技术文章里面有一篇文章讲述了如何基于MIDP1.0实现动画,个人觉得很不错。在MIDP1.0中并为直接对动画提供支持,如果我们明白动画的原理,熟悉Timer和TimerTask的话实现动画并非很困难的事情。

动画实际上就是一系列连续的帧,当他们变换的足够快的时候,我们人的眼睛就会觉得他是运动的。所以如果我们能够周期性的切换画面,从第一帧到第二帧到第三帧 ......那么我们就可以制作出动画的效果了。Timer和TimerTask正好可以很好的帮我们完成这一功能,如果你还不熟悉这两个类可以参考使用Java中的Timer和TimerTask。我们首先扩展TimerTask实现AnimatedImage类,它的功能就是在特定位置画图

import java.util.*;

import javax.microedition.lcdui.*;

// Defines an animated image, which is just a set

// of images of equal size which are drawn in turn

// to simulate movement.

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();

}

}

// Draw the current image in the animation. If

// no clip list, just a simple 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);

}

}

我们需要预先在jar文件里面存储几个大小一样,形态有序的图片,在MIDlet启动的时候把它装载在一个Image数组,并把它作为参数传递给AnimatedImage。

private Image[] loadFrames( String name, int frames )

throws IOException {

Image[] images = new Image[frames];

for( int i = 0; i < frames; ++i ){

images[i] = Image.createImage( name + i +

".png" );

}

return images;

}

Image[] frames = loadFrames( "/images/bird", 7 );

AnimatedImage ai = new AnimatedImage( frames );

ai.move( 20, 20 ); // set top-left to 20,20

下面是两个测试效果的AnimatedCanvas和AnimationTest类的源代码,在这里你可以得到全部的源文件和图片资源。仔细读读这几个类是很有好处的。有一点值得一提的是,在绘制图片的时候应该判断设备是否支持双缓冲,如果不支持要使用双缓冲技术避免画面闪烁。而且我们也不适宜把动画图片作的过大,这样会增大jar文件的大小,同时会给设备造成很大的负担。

protected void paint(Graphics g)

{

Graphics saved = g;

if (offscreen != null)

{

g = offscreen.getGraphics();

}

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);

}

}

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[i] = 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[i] = Image.createImage(name + i + ".png");

}

return images;

}

protected void pauseApp()

{

}

protected void startApp() throws MIDletStateChangeException

{

if (display == null)

{

display = Display.getDisplay(this);

initMIDlet();

}

}

}

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();

}

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);

}

}

}

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有