📄 ufocanvas.java.bak
字号:
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*; //引入创建乐音及乐音序列要用的包
import javax.microedition.media.control.*; //和接口
import java.util.*;
import java.io.*;
//GameCanvas对双缓冲图形支持,适合于动画应用
public class UFOCanvas extends GameCanvas implements Runnable
{
private Display display;//存储MIDlet的主要显示,并将画布设置为主屏幕的时候必须用到它
private boolean sleeping;//确定MIDlet动画循环是否开始,true暂停一个动画
private long frameDelay;//控制循环周期的频率
private Random rand;
private Player tonePlayer; //声明一个乐音播放器
private Sprite ufoSprite;
private int ufoXSpeed,ufoYSpeed;
private Sprite[] roidSprite=new Sprite[3];//UFO2中有3个行星精灵
public UFOCanvas(Display d)
{
super(true);
display=d;
//设置祯速率(30祯每秒,控制动画的祯频率,控制循环周期的频率,以毫秒为单位设置循环在两次重复之间等待多长的时间),
//可以用1除以这个数值(以秒为单位),很容易将其转换为祯速率。如果frameDelay为40(ms),也就是0.04秒,用1除以它可得
//25祯每秒
//同样反向转换,1/30祯每秒=0.0333 s=33 ms,33由此而来
frameDelay=33;
}
public void start()
{
//设置画布为当前屏幕
display.setCurrent(this);
//初始化随机数生成器
rand=new Random();
//初始化UFO精灵和小行星精灵
ufoXSpeed=ufoYSpeed=3;
try
{
ufoSprite=new Sprite(Image.createImage("/images/ufo.png"));
//以下代码使用画布的宽度和高度以及精灵的宽度和高度,经过精确计算使精灵位于屏幕中央
ufoSprite.setPosition((getWidth()-ufoSprite.getWidth())/2,(getHeight()-ufoSprite.getHeight())/2);//飞碟出现的初始位置在屏幕中央
roidSprite[0]=new Sprite(Image.createImage("/images/xx1.png"),80,70);
//roidSprite[0].setPosition(0,0);
roidSprite[1]=new Sprite(Image.createImage("/images/xx2.png"),120,70);
//roidSprite[1].setPosition(getWidth(),getHeight()/2);
roidSprite[2]=new Sprite(Image.createImage("/images/xx3.png"),90,96);
//roidSprite[3].setPosition(0,-getHeight());
}
catch(IOException e)
{
System.err.println("Failed loading images!");
}
//初始化乐音序列
initTune();
//启动动画线程
sleeping=false;
Thread t=new Thread(this);//分配新的 Thread 对象,UFOCanvas有Runnable接口,这里this表示UFOCanvas
t.start();
}
public void stop()
{
//停止动画
sleeping=true;
}
public void run()
{
Graphics g=getGraphics();
//主游戏循环
while(!sleeping)
{
update();
draw(g);
try
{
Thread.sleep(frameDelay);
}
catch(InterruptedException ie){}
}
}
//初始化乐音序列
private void initTune()
{
//确定速度和音符长度
byte tempo=30;//120bpm
byte d4=16;//1/4音符
byte d2=32;//1/2音符
//根据中央C定义一系列的音符,包括一个表示静默的rest乐音
//这里搞的不是很懂,加强乐音的学习
byte C4 = ToneControl.C4;
byte A6 = (byte)(C4+21);
byte B6 = (byte)(C4+23);
byte G5 = (byte)(C4+19);
byte G4 = (byte)(C4+7);
byte D5 = (byte)(C4+14);
byte rest = ToneControl.SILENCE;
//乐音序列存储为一个byte数组,只需要使用ToneControl接口中定义的几个变量就可以了
/*
VERSION: 乐音序列的版本(通常对于新的序列,设置为1)
TEMPO: 乐音序列的速度(播放多快)
BLOCK_START: 一段乐音的开始(一个子序列)
BLOCK_END: 一段乐音的结束(一个子序列)
PLAY_BLOCK:
*/
byte[] encountersSequence = {
ToneControl.VERSION,1,
ToneControl.TEMPO,tempo,
ToneControl.BLOCK_START,0,
A6,d4, B6,d4, G5,d4, G4,d4, D5,d2, rest,d2,
ToneControl.BLOCK_END,0,
ToneControl.PLAY_BLOCK,0,
ToneControl.PLAY_BLOCK,0,
};
try
{
//创建一个乐音播放器,TONE_DEVICE_LOCATOR常量表示你需要为播放乐音而创建一个播放器
tonePlayer = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
//用安全的资源实现播放器,以便能播放乐音
tonePlayer.realize();
//创建乐音控制,调用getcontrol()方法
ToneControl toneControl=(ToneControl)tonePlayer.getControl("ToneControl");
//设置乐音序列
toneControl.setSequence(encountersSequence);
}
catch(IOException ioe){}
catch(MediaException me){}
}
private void playTune()
{
try
{
//播放乐音序列
tonePlayer.start();
}
catch(MediaException me){}
}
//在什么时候关闭乐音呢?
private void cleanupTune()
{
//关闭乐音播放器
tonePlayer.close();
}
private void update()
{
//随机播放"遭遇"乐音
if(rand.nextInt()%200==0)
playTune();
//处理用户输入以控制UFO速度
//G4乐音相对于中央C(C4)定义,但为什么要+7,有待于研究哈乐音方面的知识
byte G4=(byte)(ToneControl.C4+7);
int keyState=getKeyStates();
if((keyState & LEFT_PRESSED)!=0)
{
//播放一个声音表示移动
try
{
//以一半的音量播放G4乐音1/10秒
Manager.playTone(G4,100,50);
}
catch(MediaException e){}
ufoXSpeed--;
}
else if((keyState & RIGHT_PRESSED)!=0)
{
try
{
Manager.playTone(G4,100,50);
}
catch(MediaException e){}
ufoXSpeed++;
}
if((keyState & UP_PRESSED)!=0)
{
try
{
Manager.playTone(G4,100,50);
}
catch(MediaException e){}
ufoYSpeed--;
}
else if((keyState & DOWN_PRESSED)!=0)
{
try
{
Manager.playTone(G4,100,50);
}
catch(MediaException e){}
ufoYSpeed++;
}
//将速度限制在-8到8之间
ufoXSpeed=Math.min(Math.max(ufoXSpeed,-8),8);
ufoYSpeed=Math.min(Math.max(ufoYSpeed,-8),8);
//移动UFO精灵
ufoSprite.move(ufoXSpeed,ufoYSpeed);
//检查ufo精灵是否到达屏幕边界,是则返回
checkBounds(ufoSprite);
//更新小行星精灵
for(int i=0;i<3;i++)
{
//移动小行星精灵,符号(-/+表示方向)
roidSprite[i].move(i+1,1-i);
//检查小行星精灵是否到达屏幕边界
checkBounds(roidSprite[i]);
//递增小行星精灵的祯,每个小行星的索引用来确定动画祯旋转的方向
if(i==1)
roidSprite[i].prevFrame();
else
roidSprite[i].nextFrame();
//检查UFO和小行星精灵之间的冲突
//collidesWith()的第二个参数为真,冲突检测按照水平方向进行
if(ufoSprite.collidesWith(roidSprite[i],true))
{
//发出警告的声音
//AlertType.ERROR.playSound(display);
try
{
Manager.playTone(ToneControl.C4-12,500,100);
}
catch(MediaException e){}
//重置精灵的位置和速度
ufoSprite.setPosition((getWidth()-ufoSprite.getWidth())/2,(getHeight()-ufoSprite.getHeight())/2);
ufoXSpeed=ufoYSpeed=0;
for(int j=0;j<3;j++)
roidSprite[j].setPosition(0,0);
//不需要继续更新小行星的动画
break;
}
}
}
private void draw(Graphics g)//注意绘制图形的先后顺序
{
//清除显示屏
g.setColor(0x000000);
g.fillRect(0,0,getWidth(),getHeight());
//绘制UFO精灵,该方法负责在精灵的当前位置绘制精灵对象相关的图象.
ufoSprite.paint(g);
//绘制小行星精灵
for(int i=0;i<3;i++)
roidSprite[i].paint(g);
//刷新屏幕外图形缓冲区,为了让屏幕外绘制好的图象显示到实际的屏幕上,必须调用该方法(将缓冲区的内容绘制到屏幕上)
flushGraphics();
}
//使精灵返回的方法
private void checkBounds(Sprite sprite)
{
if(sprite.getX()<-sprite.getWidth())//判断左边是否到边界
sprite.setPosition(getWidth(),sprite.getY());//如果是,将精灵的位置变到右边同样的高度上
else if(sprite.getX()>getWidth())//判断右边是否到界
sprite.setPosition(-sprite.getWidth(),sprite.getY());
if(sprite.getY()<-sprite.getHeight())//判断上边是否到界
sprite.setPosition(sprite.getX(),getHeight());
else if(sprite.getY()>getHeight())//判断下边是否到界
sprite.setPosition(sprite.getX(),-sprite.getHeight());
}
}
/*
Layer类:该类是一个抽象类(你可以创建一个派生自该类的对象实例来使用它的方法),可跟踪一个可视元素的位置\宽度\高度\可见性等信息,下面是该类的一些方法
getX():获得图层左上角的X位置
getY():获得图层左上角的Y位置
getWidth():获得图层的宽度
getHeight():获得图层的高度
setPosition():设置图层左上角的XY位置
move():根据给定的XY量来移动图层
isVisible():获得图层的可见性
setVisible():设置图层的可见性
paint():在派生自Layer类的子类中重写
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -