您的位置:首页 > 其它

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

2011-07-27 22:55 316 查看
 一.游戏的实现
包含类
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();    }}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息