当前位置: 首页 > 工具软件 > Fire 2.0 j2me > 使用案例 >

j2me学习五_翻译教程-牧羊犬游戏1

易瀚漠
2023-12-01
 

一.游戏的实现

包含类

SheepDogMIDlet

主游戏类,负责控制和管理各个屏幕和组件还有它们之间的联系。

SplashScresn

闪屏类,在屏幕中央显示一幅图像,同时程序在后台初始化。

MenuList

出现在闪屏之后,游戏结束或是游戏被暂停。

InstructionsScreen

向用户显示游戏说明

HightScoreScreen

显示最好记录

SheepdogCanvas

主游戏类

Field

用于画草地和水

SheepDog

画牧羊犬

Sheep

画羊,并且负责动物的人工智能

GameoverScreen

游戏结束画面

SoundEffects

利用MIDP 2.0 Media API 播放四种音效

Uml图

二.主游戏类SheepDogMIDlet class

这个类会和SplashScreen有联系,通过splashScreenPainted方法和splashScreenDone方法——在显示闪屏的时候在后台初始化游戏。

readRecordStore和writeRecordStore方法用于将游戏中的最高分保存在“BESTTIME”中。

1.     新建一个SheepDogMIDlet类。

2.     引入需要的类

import javax.microedition.midlet.*;

import javax.microedition.lcdui.*;

import javax.microedition.rms.*;

import java.util.*;

import java.io.*;

3.     继承MIDlet类和Runnable接口,并给出构造函数。

public class SheepdogMIDlet

    extends MIDlet

    implements Runnable

{

    private static final String RS_NAME = "BESTTIME";

    private MenuList menuList;

    private SheepdogCanvas sheepdogCanvas;

    private boolean initDone = false;

    private static final Random random = new Random();

    private boolean hasBestTime = false;

    private long bestTime;

 

    public SheepdogMIDlet()

   {

}

4.     startApp, pauseApp 和 destroyApp方法,因为继承了Runable接口,所以要实现run方法。

public void startApp()

    {

        Displayable current = Display.getDisplay(this).getCurrent();

        if (current == null)

        {

            // first time we've been called

            Display.getDisplay(this).setCurrent(new SplashScreen(this));

        }

        else

        {

            if (current == sheepdogCanvas)

            {

                sheepdogCanvas.start();   // start its animation thread

            }

            Display.getDisplay(this).setCurrent(current);

        }

    }

 

    public void pauseApp()

    {

        Displayable current = Display.getDisplay(this).getCurrent();

        if (current == sheepdogCanvas)

        {

            sheepdogCanvas.stop();   // kill its animation thread

        }

    }

 

    public void destroyApp(boolean unconditional)

    {

        if (sheepdogCanvas != null)

        {

            sheepdogCanvas.stop();   // kill its animation thread

        }

}

5.    创建一些控制程序的方法。

private void quit()

    {

        destroyApp(false);

        notifyDestroyed();

    }

 

    public void run()

    {

        init();

    }

 

    private synchronized void init()

    {

        if (!initDone)

        {

            readRecordStore();

            SoundEffects.getInstance();

            menuList = new MenuList(this);

            sheepdogCanvas = new SheepdogCanvas(this);

            initDone = true;

        }

    }

 

    void splashScreenPainted()

    {

        new Thread(this).start();   // start background initialization

    }

 

    void splashScreenDone()

    {

        init();   // if not already done

        Display.getDisplay(this).setCurrent(menuList);

    }

 

    void menuListContinue()

    {

        Display.getDisplay(this).setCurrent(sheepdogCanvas);

        sheepdogCanvas.start();

    }

 

    void menuListNewGame()

    {

        sheepdogCanvas.init();

        Display.getDisplay(this).setCurrent(sheepdogCanvas);

        sheepdogCanvas.start();

    }

 

    void menuListInstructions()

    {

        // create and discard a new Instructions screen each time, to

        // avoid keeping heap memory for it when it's not in use

        Display.getDisplay(this).setCurrent(new InstructionsScreen(this));

    }

 

    void menuListHighScore()

    {

        // create and discard a new High Score screen each time, to

        // avoid keeping heap memory for it when it's not in use

        Display.getDisplay(this).setCurrent(new HighScoreScreen(this));

    }

  

    void menuListQuit()

    {

        quit();

    }

 

    void sheepdogCanvasMenu()

    {

        sheepdogCanvas.stop();

        menuList.setGameActive(true);

        Display.getDisplay(this).setCurrent(menuList);

    }

 

    void sheepdogCanvasGameOver(long time)

    {

        sheepdogCanvas.stop();

        menuList.setGameActive(false);

        Display.getDisplay(this).setCurrent(new GameOverScreen(this, time));

    }

 

    void gameOverDone()

    {

        Display.getDisplay(this).setCurrent(menuList);

    }

 

    void instructionsBack()

    {

        Display.getDisplay(this).setCurrent(menuList);

    }

 

    void highScoreBack()

    {

        Display.getDisplay(this).setCurrent(menuList);

    }

 

    // method needed by lots of classes, shared by putting it here

    static Image createImage(String filename)

    {

        Image image = null;

        try

        {

            image = Image.createImage(filename);

        }

        catch (java.io.IOException ex)

        {

            // just let return value be null

        }

        return image;

    }

 

    // method needed by lots of classes, shared by putting it here

    static int random(int size)

    {

        return (random.nextInt() & 0x7FFFFFFF) % size;

    }

 

    // only the MIDlet has access to the display, so put this method here

    void flashBacklight(int millis)

    {

        Display.getDisplay(this).flashBacklight(millis);

    }

 

    // only the MIDlet has access to the display, so put this method here

    void vibrate(int millis)

    {

        Display.getDisplay(this).vibrate(millis);

}

6.     创建一个记录最高分的方法

long getBestTime()

    {

        return hasBestTime ? bestTime : -1;

    }

 

    boolean checkBestTime(long time)

    {

        if (!hasBestTime || (time < bestTime))

        {

            hasBestTime = true;

            bestTime = time;

            writeRecordStore();

            return true;

        }

        else

        {

            return false;

        }

 

    private void readRecordStore()

    {

        hasBestTime = false;

        RecordStore rs = null;

        ByteArrayInputStream bais = null;

        DataInputStream dis = null;

        try

        {

            rs = RecordStore.openRecordStore(RS_NAME, false);

            byte[] data = rs.getRecord(1);

            bais = new ByteArrayInputStream(data);

            dis = new DataInputStream(bais);

            bestTime = dis.readLong();

            hasBestTime = true;

        }

        catch (IOException ex)

        {

            // hasBestTime will still be false

        }

        catch (RecordStoreException ex)

        {

            // hasBestTime will still be false

        }

        finally

        {

            if (dis != null)

            {

                try

                {

                    dis.close();

                }

                catch (IOException ex)

                {

                    // no error handling necessary here

                }

            }

            if (bais != null)

            {

                try

                {

                    bais.close();

                }

                catch (IOException ex)

                {

                    // no error handling necessary here

                }

            }

            if (rs != null)

            {

                try

                {

                    rs.closeRecordStore();

                }

                catch (RecordStoreException ex)

                {

                    // no error handling necessary here

                }

            }

        }

    }Create the method for writing a new high score.

 

    // this will only be called when we have a best time

    private void writeRecordStore()

    {

        RecordStore rs = null;

        ByteArrayOutputStream baos = null;

        DataOutputStream dos = null;

        try

        {

            rs = RecordStore.openRecordStore(RS_NAME, true);

            baos = new ByteArrayOutputStream();

            dos = new DataOutputStream(baos);

            dos.writeLong(bestTime);

            byte[] data = baos.toByteArray();

            if (rs.getNumRecords() == 0)

            {

                // new record store

                rs.addRecord(data, 0, data.length);

            }

            else

            {

                // existing record store: will have one record, id 1

                rs.setRecord(1, data, 0, data.length);

            }

        }

        catch (IOException ex)

        {

            // just leave the best time unrecorded

        }

        catch (RecordStoreException ex)

        {

            // just leave the best time unrecorded

        }

        finally

        {

            if (dos != null)

            {

                try

                {

                    dos.close();

                }

                catch (IOException ex)

                {

                    // no error handling necessary here

                }

            }

            if (baos != null)

            {

                try

                {

                    baos.close();

                }

                catch (IOException ex)

                {

                    // no error handling necessary here

                }

            }

            if (rs != null)

            {

                try

                {

                    rs.closeRecordStore();

                }

                catch (RecordStoreException ex)

                {

                    // no error handling necessary here

                }

            }

        }

    }

}

二. SplashScreen

说明:在屏幕中显示图像,并画一个相框,当图像显示完之后,返回主程序类,经过3s或者按下按键,再次叫回主程序,主程序在闪屏出现的时候进行初始化。

1.  创建SplashScreen类,继承Canvas类和Runable接口;

2.  导入类

import javax.microedition.lcdui.*;

    3.继承Canvas类和Runable接口

    class SplashScreen

    extends Canvas

    implements Runnable

{

    private final SheepdogMIDlet midlet;

    private Image splashImage;

    private volatile boolean dismissed = false;

3.  构造函数

    SplashScreen(SheepdogMIDlet midlet)

    {

        this.midlet = midlet;

        setFullScreenMode(true);

        splashImage = SheepdogMIDlet.createImage("/splash.png");

        new Thread(this).start();

}

4.  创建run方法

public void run()

    {

        synchronized(this)

        {

            try

            {

                wait(3000L);   // 3 seconds

            }

            catch (InterruptedException e)

            {

                // can't happen in MIDP: no Thread.interrupt method

            }

            dismiss();

        }

}

5.  创建paint方法绘制屏幕

  public void paint(Graphics g)

    {

        int width = getWidth();

        int height = getHeight();

        g.setColor(0x00FFFFFF);  // white

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

        g.setColor(0x00FF0000);  // red

        g.drawRect(1, 1, width-3, height-3);  // red border one pixel from edge

        if (splashImage != null)

        {

            g.drawImage(splashImage,

                        width/2,

                        height/2,

                        Graphics.VCENTER | Graphics.HCENTER);

            splashImage = null;

            midlet.splashScreenPainted();

        }

}

6.  创建监视按键的方法和使闪屏消失的方法

  public synchronized void keyPressed(int keyCode)

    {

        dismiss();

    }

 

    private void dismiss()

    {

        if (!dismissed)

        {

            dismissed = true;

            midlet.splashScreenDone();

        }

    }

}

三.MenuList类

说明:在闪屏过后,或是游戏结束后显示,如果是暂停,列表最上方还会加入Continue项

1.  创建类

2.  导入类

import javax.microedition.lcdui.*;

3.  继承List类和CommandListener接口

class MenuList

    extends List

    implements CommandListener

{

    private SheepdogMIDlet midlet;

    private Command exitCommand;

    private boolean gameActive = false;Create the menu listing for the game.

 

    MenuList(SheepdogMIDlet midlet)

    {

        super("Sheepdog", List.IMPLICIT);

        this.midlet = midlet;

        append("New game", null);

        append("High score", null);

        append("Instructions", null);

        exitCommand = new Command("Exit", Command.EXIT, 1);

        addCommand(exitCommand);

       

        setCommandListener(this);

}

4.  创建激活游戏方法

void setGameActive(boolean active)

    {

        if (active && !gameActive)

        {

            gameActive = true;

            insert(0, "Continue", null);

        }

        else if (!active && gameActive)

        {

            gameActive = false;

            delete(0);

        }

}

5.  创建监视菜单命令的方法

    public void commandAction(Command c, Displayable d)

    {

        if (c == List.SELECT_COMMAND)

        {

            int index = getSelectedIndex();

            if (index != -1)  // should never be -1

            {

                if (!gameActive)

                {

                    index++;

                }

                switch (index)

                {

                case 0:   // Continue

                    midlet.menuListContinue();

                    break;

                case 1:   // New game

                    midlet.menuListNewGame();

                    break;

                case 2:   // High score

                    midlet.menuListHighScore();

                    break;

                case 3:

                    midlet.menuListInstructions();

                    break;

                default:

                    // can't happen

                    break;

                }

            }

        }

        else if (c == exitCommand)

        {

            midlet.menuListQuit();

        }

    }

}

 下面是菜单中的几个选项

说明类

import javax.microedition.lcdui.*;

class InstructionsScreen

    extends Form

    implements CommandListener

{

    private final SheepdogMIDlet midlet;

    private final Command backCommand;

 

    private static final String instructions =

        "Herd the sheep into the fold as quickly as you can.\n" +

        "Sheep won't leave the fold once they've entered it.\n" +

        "If they're not behaving, bark using the Fire key!";

InstructionsScreen(SheepdogMIDlet midlet)

    {

        super("Instructions");

        this.midlet = midlet;

        append(new StringItem(null, instructions));

        backCommand = new Command("Back", Command.BACK, 1);

        addCommand(backCommand);

        setCommandListener(this);

}

  public void commandAction(Command c, Displayable d)

    {

        midlet.instructionsBack();

    }

}

最高分类

import javax.microedition.lcdui.*;

class HighScoreScreen

    extends Form

    implements CommandListener

{

    private final SheepdogMIDlet midlet;

    private final Command backCommand;Write the code that will create the high score screen.

 

    HighScoreScreen(SheepdogMIDlet midlet)

    {

        super("High score");

        this.midlet = midlet;

 

        long bestTime = midlet.getBestTime();

        String text = (bestTime == -1) ? "none yet"

                                       : (Long.toString(bestTime) + "s");

        append(new StringItem("Best time", text));

 

        backCommand = new Command("Back", Command.BACK, 1);

        addCommand(backCommand);

        setCommandListener(this);

}

public void commandAction(Command c, Displayable d)

    {

        midlet.highScoreBack();

    }

}

游戏结束类

注意文字描边效果的实现

import javax.microedition.lcdui.*;

class GameOverScreen

    extends Canvas

{

    private final SheepdogMIDlet midlet;

    private boolean wasBestTime;

    private long time;

private long bestTime;

GameOverScreen(SheepdogMIDlet midlet, long time)

    {

        super();

        this.midlet = midlet;

        this.time = time;

        setFullScreenMode(true);

 

        if (midlet.checkBestTime(time))

        {

            wasBestTime = true;

            bestTime = time;

            SoundEffects.getInstance().startHighScoreSound();

        }

        else

        {

            wasBestTime = false;

            bestTime = midlet.getBestTime();

            SoundEffects.getInstance().startGameOverSound();

        }

        midlet.flashBacklight(1000);    // 1 second

    }

 

Create the method for painting the screen.

 

    public void paint(Graphics g)

    {

        int width = getWidth();

        int height = getHeight();

 

        // clear screen to green

        g.setColor(0x0000FF00);

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

 

        // Write message. We use a trick to make outlined text: we draw it

        // offset one pixel to the top, bottom, left & right in white, then

        // centred in black.

        g.setFont(Font.getFont(Font.FACE_PROPORTIONAL,

                               Font.STYLE_BOLD,

                               Font.SIZE_LARGE));

        int centerX = width / 2;

        int centerY = height / 2;

        g.setColor(0x00FFFFFF);   // white

        drawText(g, centerX, centerY - 1);

        drawText(g, centerX, centerY + 1);

        drawText(g, centerX - 1, centerY);

        drawText(g, centerX + 1, centerY);

        g.setColor(0x00000000);   // black

        drawText(g, centerX, centerY);

    }Create a method for drawing text on the screen.

 

    private void drawText(Graphics g, int centerX, int centerY)

    {

        int fontHeight = g.getFont().getHeight();

        int textHeight = 3 * fontHeight;

        int topY = centerY - textHeight / 2;

        g.drawString("GAME OVER",

                     centerX,

                     topY,

                     Graphics.HCENTER | Graphics.TOP);

        g.drawString("Time: " + time + "s",

                     centerX,

                     topY + fontHeight,

                     Graphics.HCENTER | Graphics.TOP);

        g.drawString(wasBestTime ? "New best time!" :

                                   ("Best time: " + bestTime + "s"),

                     centerX,

                     topY + 2 * fontHeight,

                     Graphics.HCENTER | Graphics.TOP);

    }

   

    public void keyPressed(int keyCode)

    {

        midlet.gameOverDone();

    }

}

 

 类似资料: