j2me学习七_翻译教程-牧羊犬游戏3

八.音效实现

SoundEffects class

利用MIDP2.0 的mediaAPI创建犬吠,绵羊叫,还有游戏结束音

1创建SoundEffects类

2.引入类

import javax.microedition.media.*;

import java.io.*;

3.创建参数

class SoundEffects
{
 private static SoundEffects instance;
 private Player sheepSoundPlayer;
 private Player dogSoundPlayer;

4.初始化

 private SoundEffects()
 {
 sheepSoundPlayer = createPlayer("/sheep.wav", "audio/x-wav");
 dogSoundPlayer = createPlayer("/dog.wav", "audio/x-wav");
 }
 
 static SoundEffects getInstance()
 {
 if (instance == null)
 {
 instance = new SoundEffects();
 }
 return instance;
}
5.创建声音播放方法
 void startSheepSound()
 {
 startPlayer(sheepSoundPlayer);
 }
 
void startDogSound()
 {
 startPlayer(dogSoundPlayer);
 }
 
 void startGameOverSound()
 {
 startPlayer(createPlayer("/gameover.mid", "audio/midi"));
 }
 
void startHighScoreSound()
 {
 startPlayer(createPlayer("/highscore.mid", "audio/midi"));
 }
 
6.创建音效控制方法
private void startPlayer(Player p)
 {
 if (p != null)
 {
 try
 {
 p.stop();
 p.setMediaTime(0L);
 p.start();
 }
 catch (MediaException me)
 {
 // ignore
 }
 }
}
7.创建createPlayer方法
private Player createPlayer(String filename, String format)
 {
 Player p = null;
 try
 {
 InputStream is = getClass().getResourceAsStream(filename);
 p = Manager.createPlayer(is, format);
 p.prefetch();
 }
 catch (IOException ioe)
 {
 // ignore
 }
 catch (MediaException me)
 {
 // ignore
 }
 return p;
 }
}
 

九.实现游戏功能

SheepdogCanvas class

1. 创建类

2. 引入类

import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
import javax.microedition.media.*;
import java.io.*;

3. SheepdogCanvas类继承GameCanvas类和Runable接口,GameCanvas是Canvas的一个子类,它提供了一些方便的游戏接口,还有一些特殊的游戏特性,例如帧缓冲,按键侦听。

class SheepdogCanvas
 extends GameCanvas
 implements Runnable

{

4. 定义和初始化参数

static final int NONE = -1;

static final int UP = 0;

static final int LEFT = 1;

static final int DOWN = 2;

static final int RIGHT = 3;

private static final int MILLIS_PER_TICK = 50;

private static final int NUM_SHEEP = 5;

private final SheepdogMIDlet midlet;

private final Field field;

private final Sheepdog sheepdog;

private final Vector sheep = new Vector();

private final LayerManager layerManager;

private final Graphics graphics;

private long gameDuration;

private long startTime;

private volatile Thread animationThread = null;

5.创建SheepdogCanvas对象,getGraphic方法用于获得Graphics对象来渲染GameCanvas,LayerManager类用于管理一系列的图层

SheepdogCanvas(SheepdogMIDlet midlet)

{

super(true); // suppress key events for game keys

this.midlet = midlet;

setFullScreenMode(true);

graphics = getGraphics();

layerManager = new LayerManager();

field = new Field();

sheepdog = new Sheepdog(this);

layerManager.append(sheepdog);

for (int i = 0; i < NUM_SHEEP; ++i)

{

Sheep newSheep = new Sheep(this);

layerManager.append(newSheep);

sheep.addElement(newSheep);

}

layerManager.append(field); // last layer, behind sprites

init();

}

6.创建用于按键侦听的方法,如果按了一个负数按键码的按键了,则跳出菜单

public void keyPressed(int keyCode)

{

// The constructor suppresses key events for game keys, so we'll

// only get key events for non-game keys. The number keys, * & #

// have positive keyCodes, so negative keyCodes mean non-game

// special keys like soft-keys. We'll use key-presses on special

// keys to take us to the menu.

if (keyCode < 0)

{

stop();

midlet.sheepdogCanvasMenu();

}

}

7.初见初始化函数,getWidth和getHeight方法用于获得当前画布的宽和高,setPosition方法用于设定层得位置(左上角为基准点)

void init()

{

sheepdog.setPosition(field.getSheepdogStartX(),

field.getSheepdogStartY());

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

{

Sheep sh = (Sheep)(sheep.elementAt(i));

// find a valid position for the sheep

do

{

int x = midlet.random(field.getWidth() - Sheep.WIDTH);

int y = midlet.random(field.getHeight() - Sheep.HEIGHT);

sh.setPosition(x, y);

} while (field.containsImpassableArea(sh.getX(),

sh.getY(),

sh.getWidth(),

sh.getHeight()) ||

overlapsSheepdog(sh) ||

overlapsSheep(sh, i) ||

field.inFold(sh));

}

}

8.创建用于开始和终止游戏的方法

public synchronized void start()

{

animationThread = new Thread(this);

animationThread.start();

startTime = System.currentTimeMillis() - gameDuration;

}

public synchronized void stop()

{

gameDuration = System.currentTimeMillis() - startTime;

animationThread = null;

}

9.创建run方法,FlushGraphics方法用于将缓冲区的图像在屏幕上显示

public void run()

{

Thread currentThread = Thread.currentThread();

try

{

// This ends when animationThread is set to null, or when

// it is subsequently set to a new thread; either way, the

// current thread should terminate

while (currentThread == animationThread)

{

long startTime = System.currentTimeMillis();

// Don't advance game or draw if canvas is covered by

// a system screen.

if (isShown())

{

tick();

draw();

flushGraphics();

}

long timeTaken = System.currentTimeMillis() - startTime;

if (timeTaken < MILLIS_PER_TICK)

{

synchronized (this)

{

wait(MILLIS_PER_TICK - timeTaken);

}

}

else

{

currentThread.yield();

}

}

}

catch (InterruptedException e)

{

// won't be thrown

}

}

10.创建用于监视多按键同时按下的情况,用到了getKeyStates方法来获得当前按键情况

private void tick()

{

// If player presses two or more direction buttons, we ignore them

// all. But pressing fire is independent. The code below also ignores

// direction buttons if GAME_A..GAME_D are pressed.

int keyStates = getKeyStates();

boolean bark = (keyStates & FIRE_PRESSED) != 0;

keyStates &= ~FIRE_PRESSED;

int direction = (keyStates == UP_PRESSED) ? UP :

(keyStates == LEFT_PRESSED) ? LEFT:

(keyStates == DOWN_PRESSED) ? DOWN :

(keyStates == RIGHT_PRESSED) ? RIGHT : NONE;

sheepdog.tick(direction, bark);

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

{

Sheep sh = (Sheep)(sheep.elementAt(i));

sh.tick();

}

field.tick();

}

11.创建多个方法用于提取对象和控制犬吠

Field getField()

{

return field;

}

Sheepdog getSheepdog()

{

return sheepdog;

}

Vector getSheep()

{

return sheep;

}

void handleDogBark()

{

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

{

Sheep sh = (Sheep)(sheep.elementAt(i));

sh.handleDogBark();

}

}

12.创建精灵的碰撞控制方法,一个精灵是一个基本的视觉对象,它储存在一个图像中,并能变化;不同的帧能够显示精灵的运动,一些变换,如旋转,缩放也能应用到精灵上,用于进一步改变他们的显示。collidesWith方法用于检测精灵碰撞。

boolean overlapsSheepdog(Sprite sprite)

{

return sprite.collidesWith(sheepdog, false); // false -> not pixelLevel

}

boolean overlapsSheep(Sprite sprite)

{

return overlapsSheep(sprite, sheep.size());

}

// whether the sprite overlaps the first 'count' sheep

boolean overlapsSheep(Sprite sprite, int count)

{

for (int i = 0; i < count; ++i)

{

Sheep sh = (Sheep)(sheep.elementAt(i));

if (sprite.collidesWith(sh, false)) // false -> not pixelLevel

{

return true;

}

}

return false;

}

boolean overlapsOtherSheep(Sprite sprite)

{

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

{

Object obj = sheep.elementAt(i);

if (obj != sprite)

{

Sheep sh = (Sheep)obj;

if (sprite.collidesWith(sh, false)) // false -> not pixelLevel

{

return true;

}

}

}

return false;

}

void vibrate(int millis)

{

midlet.vibrate(millis);

}

13.创建方法用于画出游戏中可视的对象。getX方法获取x值,getY获取y之。

// draw game

private void draw()

{

int width = getWidth();

int height = getHeight();

// clear screen to grey

graphics.setColor(0x00888888);

graphics.fillRect(0, 0, width, height);

// clip and translate to centre

int dx = origin(sheepdog.getX() + sheepdog.getWidth() / 2,

field.getWidth(),

width);

int dy = origin(sheepdog.getY() + sheepdog.getHeight() / 2,

field.getHeight(),

height);

graphics.setClip(dx, dy, field.getWidth(), field.getHeight());

graphics.translate(dx, dy);

The paint method paints this Layer if it is visible.

For more information, see paint in the MIDP 2.0 API specification.

// draw background and sprites

layerManager.paint(g, 0, 0);

// undo clip & translate

graphics.translate(-dx, -dy);

graphics.setClip(0, 0, width, height);

// display time & score

long time = (System.currentTimeMillis() - startTime) / 1000;

int score = numSheepInFold();

graphics.setColor(0x00FFFFFF); // white

graphics.drawString(Integer.toString(score),

1,

1,

Graphics.TOP | Graphics.LEFT);

graphics.drawString(Long.toString(time),

width - 2,

1,

Graphics.TOP | Graphics.RIGHT);

if (score == sheep.size())

{

midlet.sheepdogCanvasGameOver(time);

}

}

14.创建用于计算场景大小的方法

// If the screen is bigger than the field, we center the field

// in the screen. Otherwise we center the screen on the focus, except

// that we don't scroll beyond the edges of the field.

private int origin(int focus, int fieldLength, int screenLength)

{

int origin;

if (screenLength >= fieldLength)

{

origin = (screenLength - fieldLength) / 2;

}

else if (focus <= screenLength / 2)

{

origin = 0;

}

else if (focus >= (fieldLength - screenLength / 2))

{

origin = screenLength - fieldLength;

}

else

{

origin = screenLength / 2 - focus;

}

return origin;

}

15.创建用于计算羊的数目的方法

int numSheepInFold()

{

int count = 0;

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

{

Sheep sh = (Sheep)(sheep.elementAt(i));

if (field.inFold(sh))

{

count++;

}

}

return count;

}

}

你可能感兴趣的:(j2me)