⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ufocanvas.java.bak

📁 一个碰撞检测的简单游戏
💻 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 + -