java手机游戏开发 4 综合GameCanvas,Sprite开发UFO游戏

GameCanvas是Canvas的子类

本例程将用到Display,Sprite,GameCanvas,Runnable等

Sprite:精灵类,可以把Sprite看作游戏中的某角色(如主角),Sprite可实现角色便移动,便改变自身形象

1.于 com.sk.model 建立UFOCanvas 类,继承GameCanvas,实现Runnable接口

package com.sk.model;

 

import java.io.IOException;

import java.util.Random;

import java.util.Vector;

 

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Font;

import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.Image;

import javax.microedition.lcdui.game.GameCanvas;

import javax.microedition.lcdui.game.Sprite;

import javax.microedition.media.Manager;

import javax.microedition.media.MediaException;

import javax.microedition.media.Player;

import javax.microedition.media.control.ToneControl;

 

public class UFOCanvas extends GameCanvas implements Runnable{

 

private Display display;

private Sprite ufoSprite;

private boolean sleeping;

private int ufoXSpeed,ufoYSpeed;

private Random rand;

//帧率:一幅幅图片连续快速移动从而形成动画,1s内切换的图片数30帧,线程休眠33毫秒,25帧,休眠40毫秒

private int frameRate=33;

private boolean isCenter;

//小行星集合

private Vector roidSprite;

private Image roidImage;

//坚持的时间

private long startTime;

private long endTime;

private boolean gameOver;

//音频部分

private Player tonePlayer;

//输入延迟

private int inputDelay;

 

public UFOCanvas(Display display){

super(true);

this.display=display;

this.initTune();

}

//音频初始

private void initTune(){

byte tempo=30;

byte d4=16;

byte d2=32;

 

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[] encounterSeq={

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 {

tonePlayer = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);

tonePlayer.realize();

ToneControl tc=(ToneControl) tonePlayer.getControl("ToneControl");

tc.setSequence(encounterSeq);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (MediaException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

private void playTune(){

try {

tonePlayer.start();

} catch (MediaException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public void closeTune(){

tonePlayer.close();

}

private void stopTune(){

try {

tonePlayer.stop();

} catch (MediaException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

public void start(){

display.setCurrent(this);

ufoXSpeed=ufoYSpeed=3;

startTime=System.currentTimeMillis();

rand=new Random();

try {

ufoSprite=new Sprite(Image.createImage("/com/sk/imgs/ufo.png"));

ufoSprite.setPosition((this.getWidth()-ufoSprite.getWidth())/2, (this.getHeight()-ufoSprite.getHeight())/2);

ufoSprite.defineCollisionRectangle(2, 2, ufoSprite.getWidth()-1, ufoSprite.getHeight()-1);

//行星群

roidSprite=new Vector();

//行星图

roidImage=Image.createImage("/com/sk/imgs/roid.png");

//初始1个行星

Sprite roid=new Sprite(roidImage,roidImage.getWidth(),roidImage.getHeight());

roid.defineCollisionRectangle(2, 2, 12, 12);

roidSprite.addElement(roid);

 

} catch (IOException e) {

// TODO Auto-generated catch block

System.out.println("loading image error");

e.printStackTrace();

}

sleeping=false;

new Thread(this).start();

}

 

public void stop(){

this.sleeping=true;

}

 

private void update(){

 

if(gameOver){

int keyState=this.getKeyStates();

if((keyState & this.FIRE_PRESSED)!=0){

ufoSprite.setPosition((this.getWidth()-ufoSprite.getWidth())/2, (this.getHeight()-ufoSprite.getHeight())/2);

//清空行星

roidSprite.removeAllElements();

//重置 1颗行星

Sprite roid=new Sprite(roidImage,roidImage.getWidth(),roidImage.getHeight());

roid.defineCollisionRectangle(2, 2, 12, 12);

roidSprite.addElement(roid);

gameOver=false;

//重新计时

startTime=System.currentTimeMillis();

//音频

this.stopTune();

}

return;

}

//音频(遭遇)

if(rand.nextInt() % 500 ==0){

playTune();

}

if(++inputDelay>1){

ufoXSpeed=ufoYSpeed=0;

//按键

int keyState=this.getKeyStates();

if((keyState & this.LEFT_PRESSED)!=0){

ufoXSpeed-=2;

}else if((keyState & this.RIGHT_PRESSED)!=0){

ufoXSpeed+=2;

}

if((keyState & this.UP_PRESSED)!=0){

ufoYSpeed-=2;

}else if((keyState & this.DOWN_PRESSED)!=0){

ufoYSpeed+=2;

}

//开始 移动

if(rand.nextInt()%2==0){

ufoXSpeed=Math.min(Math.max(ufoXSpeed, -6), 6);

ufoYSpeed=Math.min(Math.max(ufoYSpeed, -6), 6);

}

}

//ufo

 

ufoSprite.move(ufoXSpeed, ufoYSpeed);

checkBounds(ufoSprite);

//roid

for(int i=0;i<roidSprite.size();i++){

Sprite roid=(Sprite)roidSprite.elementAt(i);

 

roid.move(1+i, 1-i);

 

checkBounds(roid);

//碰撞

if(ufoSprite.collidesWith(roid, true)){

//音频(冲突)

try {

Manager.playTone((byte)(ToneControl.C4-12), 500, 100);

} catch (MediaException e) {

// TODO Auto-generated catch block

System.out.println("冲突处");

}

 

//位置

ufoSprite.setPosition((this.getWidth()-ufoSprite.getWidth())/2, (this.getHeight()-ufoSprite.getHeight())/2);

roid.setPosition(0, 0);

gameOver=true;

//碰撞时间

endTime=System.currentTimeMillis();

return;

}

}

//增加难度,6秒增加一颗roid

if((System.currentTimeMillis()-startTime)/1000>6*roidSprite.size()){

Sprite roid=new Sprite(roidImage,roidImage.getWidth(),roidImage.getHeight());

roid.defineCollisionRectangle(2,2,12,12);

roidSprite.addElement(roid);

}

 

}

private void draw(Graphics g){

 

g.setColor(0xFFFFFF);

g.fillRect(0, 0, this.getWidth(), this.getHeight());

 

if(isCenter){

g.drawString("Fire", (this.getWidth()-ufoSprite.getWidth())/2, (this.getHeight()-ufoSprite.getHeight())/2, Graphics.HCENTER|Graphics.TOP);

isCenter=false;

}

//统计信息

g.setColor(0xFF0000);

if(!gameOver){

g.drawString("时间:"+(System.currentTimeMillis()-startTime)+"毫秒", 0, 0, Graphics.LEFT|Graphics.TOP);

}else{

g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_MEDIUM));

g.drawString("GAME OVER", (this.getWidth()-ufoSprite.getWidth())/2, (this.getHeight()+ufoSprite.getHeight())/2, Graphics.HCENTER|Graphics.TOP);

g.drawString("坚持了:"+(endTime-startTime)/1000+"秒", (this.getWidth()-ufoSprite.getWidth())/2,(this.getHeight()+ufoSprite.getHeight())/2+g.getFont().getHeight(), Graphics.LEFT|Graphics.TOP);

g.drawString("确认键...继续", (this.getWidth()-ufoSprite.getWidth())/2,(this.getHeight()+ufoSprite.getHeight())/2+g.getFont().getHeight()*2, Graphics.LEFT|Graphics.TOP);

 

}

g.setFont(Font.getDefaultFont());

 

//ufo

ufoSprite.paint(g);

//roid

for(int i=0;i<roidSprite.size();i++){

Sprite roid=(Sprite)roidSprite.elementAt(i);

roid.paint(g);

}

this.flushGraphics();

 

}

//出界

private void checkBounds(Sprite sprite){

if(sprite.getX()<-sprite.getWidth()){

sprite.setPosition(this.getWidth(), sprite.getY());

}else if(sprite.getX()>this.getWidth()){

sprite.setPosition(-sprite.getWidth(), sprite.getY());

}

if(sprite.getY()<-sprite.getHeight()){

sprite.setPosition(sprite.getX(),this.getHeight());

}else if(sprite.getY()>this.getHeight()){

sprite.setPosition(sprite.getX(),-sprite.getHeight());

}

 

}

public void run() {

// TODO Auto-generated method stub

Graphics g=this.getGraphics();

while(!sleeping){

this.update();

this.draw(g);

try {

Thread.sleep(frameRate);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

 

}

//com.sk.model包UFOCanvas的思路:多线程进行update(),draw(),start()控制此GameCanvas开始工作,stop()停止GameCanvas,CheckBounds()进行边界检测,start()开始工作后,开启新线程不断进行update(),draw(),从而效果便是游戏的连续运动了

2.Midlet调用 UFOCanvas

package com.sk.view;

 

import javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Displayable;

import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

 

import com.sk.model.UFOCanvas;

 

public class UFOForm extends MIDlet implements CommandListener{

private UFOCanvas canvas;

private static Command CMD_EXIT=new Command("退出",Command.EXIT,1);

protected void destroyApp(boolean arg0) throws MIDletStateChangeException {

// TODO Auto-generated method stub

 

}

 

protected void pauseApp() {

// TODO Auto-generated method stub

 

}

 

protected void startApp() throws MIDletStateChangeException {

// TODO Auto-generated method stub

canvas=new UFOCanvas(Display.getDisplay(this));

canvas.addCommand(CMD_EXIT);

canvas.setCommandListener(this);

canvas.start();

}

 

public void commandAction(Command c, Displayable d) {

// TODO Auto-generated method stub

if(c.equals(CMD_EXIT)){

try {

destroyApp(true);

notifyDestroyed();

} catch (MIDletStateChangeException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

 

}

//本代码可编译后,运行,体验过段时间后,再理解,效果会比较好

你可能感兴趣的:(java,多线程,thread,游戏,REST)