This is a sub-page of Sonic the Hedgehog 2 (DoJa, J2ME, BREW)/Low-End Versions.
Included in the Chinese low-end version of Sonic 2: Crash! for the Motorola E680 are two source code files in the STH2P2_S40P1 directory: Device.java~1~ and the rather massive Engine.java~1~. Brace yourself.
Device.java~1~#
package STH2P2_S40P1;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.GameCanvas;
/**
* Base Device: Series 40 Version 1
*
* Also compatible with: [OTHER DEVICES THIS BUILD RUNS ON]
*
* - This is only a reference implementation, and is not guaranteed to run on a particular device
*
*/
public class Device
extends GameCanvas
implements DeviceConstants
{
// --------------------------------------------------------------------------------------------
// Device Settings
// --------------------------------------------------------------------------------------------
public final static int DEVICE_ID = DeviceList.NOKIA_S40_V1;
/** True = use multiple record stores, False = use one store, multiple slots */
public final static boolean
USE_ALTERNATE_RMS_METHOD = false,
/** Use commands for softkeys (if phone does not return a softkey value) */
USE_COMMANDS = false,
/** Is sound supported on this device? */
SUPPORTS_SOUND = true,
/** Is vibration supported on this device */
SUPPORTS_VIBRATION = true;
/** Priority for main thread */
public final static int THREAD_PRIORITY = Thread.NORM_PRIORITY;
/** Delay between game ticks/refreshes */
public static final short REFRESH_DELAY = 60;
/** Compile System.gc() calls? */
public final static boolean AGGRESSIVE_GC = true;
/** True if service repaints doesn't work correctly */
public final static boolean FAKE_SERVICE_REPAINTS = false;
/** Minimum sleep time (force device to sleep for this amount per tick no matter what) */
public final static int MINIMUM_SLEEP = 15;
// --------------------------------------------------------------------------------------------
// Resource handling
// --------------------------------------------------------------------------------------------
/** ResourceMaster: Cache resources in memory */
public final static boolean CACHE_RESOURCES = false;
// --------------------------------------------------------------------------------------------
// Speed tweaks
// --------------------------------------------------------------------------------------------
public static final boolean SYSTEM_GC_IN_PAINT_THREAD = false;
public static final boolean CACHE_METATILES = false;
public static final int BACKGROUND_TYPE = BACKGROUND_FILLRECT;
// hud
public static final boolean CACHE_HUD_BACKGROUND = false;
public static final boolean ALWAYS_PAINT_HUD = true;
// --------------------------------------------------------------------------------------------
// Font Settings
//
// E.g: Engine.drawString("hello", 0, 0, Graphics.TOP | Graphics.LEFT) is used
//
// - The topmost pixel of the font should be at y position 0
// - If it isn't, adjust the FONT_OFFSET so that alignment is correct
// --------------------------------------------------------------------------------------------
public static final Font FONT = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL);
public static final Font FONT_NB = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
public static final int FONT_HEIGHT = FONT_NB.getHeight();
public static final int FONT_OFFSET = 0;
public static final int FONT_SPACING = FONT_HEIGHT+4;
// --------------------------------------------------------------------------------------------
// Font Settings
// --------------------------------------------------------------------------------------------
/**
* On low-end builds, where we don't include bitmap fonts, change this to a FINAL boolean
* so that the unused code is compiled out and remove the reference in deviceFunction.
*
* e.g. public final static boolean USE_BITMAP_FONTS = false;
*
*
* On high-end builds this should be left as follows:
*
* e.g. public static boolean USE_BITMAP_FONTS;
*
* and the following block should be present in deviceFunction
*
* case DEVICE_INIT_FONT:
* USE_BITMAP_FONTS = param.equals("1");
* break;
*/
public static final boolean USE_BITMAP_FONTS = false;
/** The type of font (bitmap or MIDP) to use for each of the logical game fonts */
public static int FONT_TYPE[] =
{
FontMgr.FONT_TYPE_MIDP, // Device specific font mapped to Constants.FONT_1
FontMgr.FONT_TYPE_MIDP, // Device specific font mapped to Constants.FONT_2
};
// --------------------------------------------------------------------------------------------
// MIDP fonts. These are used in place of each of the bitmap fonts when they are disabled.
// --------------------------------------------------------------------------------------------
private static final int MIDP_FONT_FACE_SMALL = 0;
private static final int MIDP_FONT_FACE_MEDIUM = 1;
public final static Font[] MIDP_FONT_FACES =
{
Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_SMALL), // MIDP_FONT_FACE_SMALL
Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL), // MIDP_FONT_FACE_MEDIUM//modify 2009-2-18 by qihaidong
};
/**
* COORDINATE TWEAKS FOR MIDP FONTS - one element for each of the faces
*
* Run the following tool on the device to accurately extract these values:
* \\koi\tools\midpFontTester
*
* Format :
* Baseline for Font, (Reported by tool as bline)
* Total Space Below Baseline, (Reported by tool as below bline)
* Space to font height from descender base, (Move font until bottom pixel touches bottom red line)
* Space above ascender to start of font space, (Move font until top pixel touches top red line)
*
* These are just values I got from the MIDP toolkit here and don't relate to a real device.
*/
public final static int[] MIDP_FONT_PROPS =
{
9, 3, 2, 0, // Properties for MIDP_FONT_FACES[0] / MIDP_FONT_FACE_SMALL
15, 3, 2, 0, // Properties for MIDP_FONT_FACES[1] / MIDP_FONT_FACE_MEDIUM//modify 2009-2-19 by qihaidong
};
/**
* - Face and colour to use for each of the replacement MIDP Game Fonts [FONT, COLOUR]
* - Use BitmapFont.NO_COLOUR to not set a colour to the font. If you do this you can
* colour the font manually.
*
* MIDP fonts are only used if bitmap font not specified in FONT_TYPE array.
*/
public static final int[] MIDP_FONT_COMPOSITIONS =
{
MIDP_FONT_FACE_MEDIUM, COL_WHITE, // Constants.FONT_1
MIDP_FONT_FACE_MEDIUM, FontMgr.NO_COLOUR, // Constants.FONT_2
};
// --------------------------------------------------------------------------------------------
// Bitmap fonts. A list of the bitmap fonts enabled in FONT_TYPE.
//
// NOT USED IN SONIC LOWEND PART 1!
// --------------------------------------------------------------------------------------------
private static final int BMP_FONT_FACE_BLOCK = 0;
/** for each of these .bft and .png should exist */
public static final int[] BMP_FONT_FACES =
{
// Resources.FONT_PNG, Resources.FONT_BFT, // BMP_FONT_FACE_BLOCK
};
/**
* - Face and palette to use for each of the Bitmap fonts [FONT, PALETTE]
* - Use BitmapFont.NO_PALETTE to not set a palette to the font.
* - Use Resources.PLTE_FILE if the font uses a palette
*/
public static final int[] BMP_FONT_COMPOSITIONS =
{
// BMP_FONT_FACE_BLOCK (no palette swapping) BMP_FONT_FACES[0]
BMP_FONT_FACE_BLOCK, FontMgr.NO_PALETTE,
};
/**
* Set this value, if the device:
* - does not call either hideNotify or showNotify on an event / incoming call
* - manually suspends the app itself
* - BUT: fails to resume sounds
*
* It should be set to a positive value, which indicates the number of milliseconds delay
* between game ticks (when a call will be occuring) before resuming sounds.
*
* Therefore, if you set it to '5000', it will check for a 5 second delay between game ticks
* and if this occurs an attempt to resume sound will occur
*/
public final static int HANDLE_EVENT_DELAY = 0;
/**
* Event behaviour. Depends on how the device behaves as to which of these you use.
* It can be used in conjunction with HANDLE_EVENT_DELAY above
*
* See the list in Engine.java for all possible events that can be used
*/
public final static int EVENT = Engine.EVENT_SHOW_PAUSE_SCREEN;
// --------------------------------------------------------------------------------------------
// Key Mappings
// --------------------------------------------------------------------------------------------
/** Mapped keys */
private final static int
KEY_UP_MAPPING = KEY_NUM2,
KEY_DOWN_MAPPING = KEY_NUM8,
KEY_LEFT_MAPPING = KEY_NUM4,
KEY_RIGHT_MAPPING = KEY_NUM6,
KEY_UL_MAPPING = KEY_NUM1,
KEY_UR_MAPPING = KEY_NUM3,
KEY_DL_MAPPING = KEY_NUM7,
KEY_DR_MAPPING = KEY_NUM9,
KEY_FIRE_MAPPING = KEY_NUM5,
KEY_FIRE2_MAPPING = KEY_NUM0,
KEY_STAR_MAPPING = KEY_STAR,
KEY_HASH_MAPPING = KEY_POUND;
// private static final int VENDOR_UKY = -1;
// private static final int VENDOR_DKY = -6;
// private static final int VENDOR_LKY = -2;
// private static final int VENDOR_RKY = -5;
// private static final int VENDOR_FKY = -20;
private static final int VENDOR_UKY = -1;
private static final int VENDOR_DKY = -2;
private static final int VENDOR_LKY = -3;
private static final int VENDOR_RKY = -4;
private static final int VENDOR_FKY = -5;
/** Softkey codes for device (check out vice for details) */
public final static int
KEY_SOFTLEFT = -6,
KEY_SOFTRIGHT = -7;
// KEY_SOFTLEFT = -21,
// KEY_SOFTRIGHT = -22;
/** Keys assigned to 8 way control (up, down, left, right, diagonals) */
public final static String[] STRING_8WAY = {"2", "8", "4", "6", "1", "3", "7", "9"};
// --------------------------------------------------------------------------------------------
public Device()
{
// ... MIDP2 START
super(false);
setFullScreenMode(true);
// ... MIDP2 END
// Add commands for softkey labels (used when phones do not return a value)
if (USE_COMMANDS)
{
Engine.commandSoft1 = new Command(" ", Command.OK, 1);
Engine.commandSoft2 = new Command(" ", Command.BACK, 1);
}
}
public static int soundFunction(int function_id)
{
return soundFunction(function_id, 0);
}
public static void deviceTick()
{
}
public static int deviceFunction(int function_id, String param) throws Exception
{
switch (function_id)
{
// For MIDP 1 devices, just remove the platformRequest line as it isn't supported
case DEVICE_PLATFORM_REQUEST:
// Engine.parent.platformRequest(param);
break;
// // For low-end devices without bitmap font support, just remove the following block
// // Called after language file has initialized in Engine.text[Text.USE_BITMAP_FONT]
// case DEVICE_INIT_FONT:
// USE_BITMAP_FONTS = param.equals("1");
// break;
}
return 0;
}
public static int soundFunction(int function_id, int param)
{
if (Device.SUPPORTS_SOUND)
{
switch (function_id)
{
case Engine.SOUND_INIT:
DeviceSound.init();
break;
case Engine.SOUND_PLAY:
DeviceSound.play(param);
break;
case Engine.SOUND_STOP:
DeviceSound.stop();
break;
//#if HI_ADD
//# case Engine.SOUND_RESUME:
//# DeviceSound.resume();
//# break;
//#endif
// case Engine.SOUND_UNLOAD:
// DeviceSound.unloadSounds();
// break;
}
}
return 0;
}
//public static boolean isCurrentSoundActive()
//{
//return DeviceSound.isCurrentSoundActive();
//}
/*
public static int getSoundState()
{
return DeviceSound.getSoundState();
}
public static boolean isplaying()
{
return DeviceSound.isPlaying();
}
*/
public static void vibrate(int time)
{
if (SUPPORTS_VIBRATION && Engine.vibrateOn)
{
Engine.display.vibrate(time);
Thread.yield();
}
}
public void setBackLight(boolean switch_on)
{
// ...
// Insert device specific code to turn backlight on
// ...
//#ifdef NOKIAUI
//DeviceControl.setLights(0, switch_on ? 100 : 0);
//#endif
}
public void hideNotify()
{
if(GameWorld.loading || GameWorld.gameState == GameWorld.GS_ZONE_SCREEN || GameWorld.gameState == GameWorld.GS_START_GAME || (GameWorld.gameState == GameWorld.GS_LEVEL_COMPLETE && GameWorld.whileLoading == true))
Engine.loadingInterrupted = true;
else
Engine.loadingInterrupted = false;
// Handle incoming calls / other events that mimimise the app
DeviceSound.stop();
if (Engine.state!=Engine.GS_LOADING)
{
// DeviceSound.sounds=null;
}
Engine.handleEvent = true;
Engine.hideNotify = true;
}
public void showNotify()
{
Engine.hideNotify = false;
serviceRepaints();
Thread.yield();
}
public int getKeyMap(int key)
{
if (key == KEY_FIRE_MAPPING || key == VENDOR_FKY || key == -VENDOR_FKY) return K_FIRE;
if (key == KEY_SOFTLEFT||key == -KEY_SOFTLEFT) return Engine.reverseTooltips ? K_SOFT_BACK : K_SOFT_SELECT;
if (key == KEY_SOFTRIGHT||key == -KEY_SOFTRIGHT) return Engine.reverseTooltips ? K_SOFT_SELECT : K_SOFT_BACK;
if (key == KEY_UP_MAPPING || key == VENDOR_UKY ||key == -VENDOR_UKY ) return K_UP;
if (key == KEY_DOWN_MAPPING || key == VENDOR_DKY || key == -VENDOR_DKY) return K_DOWN;
if (key == KEY_LEFT_MAPPING || key == VENDOR_LKY || key == -VENDOR_LKY) return K_LEFT;
if (key == KEY_RIGHT_MAPPING || key == VENDOR_RKY || key == -VENDOR_RKY) return K_RIGHT;
if (key == KEY_UL_MAPPING) return K_UL;
if (key == KEY_UR_MAPPING) return K_UR;
if (key == KEY_DL_MAPPING) return K_DL;
if (key == KEY_DR_MAPPING) return K_DR;
// requested by QA for playability
if (Engine.state == Engine.GS_INGAME && key == KEY_STAR_MAPPING) return K_UP;
if (Engine.state == Engine.GS_INGAME && key == KEY_HASH_MAPPING) return K_UP;
// switch ( getGameAction(key) )
// {
// case Canvas.UP: return K_UP;
// case Canvas.DOWN: return K_DOWN;
// case Canvas.LEFT: return K_LEFT;
// case Canvas.RIGHT: return K_RIGHT;
// case Canvas.FIRE: return K_FIRE;
// }
return K_OTHER;
}
public void paint(Graphics g)
{
//#if DETECT_PAUSE_WITH_TIMER
//# try {
//# long diff;
//# if((diff=System.currentTimeMillis() - Device.pauseDetectTime) > Device.PAUSE_TIME_VALUE){
//# hideNotify();
//# showNotify();
//# Engine.gameSuspendedTimeMillis-=diff;
//# }
//# pauseDetectTime = System.currentTimeMillis();
//# }catch(Exception e){}
//#endif
}
}
Engine.java~1~#
package STH2P2_S40P1;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.Sprite;
import java.util.*;
import java.io.*;
import javax.microedition.rms.*;
import Animation.Animation;
import FlashComponent.FlashUnitManager;
import PlatformStandard.Standard;
/**
*
* GLU TEMPLATE
* @version 0.25
* @author Chris White (chris.white@glu.com)
*
* Features:
*
* + Font Manager
* + Brand Rotation
* + Language Selection
* + Enable sound at startup
* + Upsell
* + Demo Mode Logic
* + Basic menus and forms
* + Example online high score code
* + Example event handling code
* + Example sound code
* + Example RMS code
* + Device debugging (output debug information to screen)
*
* Note
*
* + This isn't intended to be a definite library of functions, just a basis on which to
* build portable MIDP apps.
*
*
* Updates
*
* + See docs/CHANGELOG.txt
*
* Docs
*
* + See docs/ directory
*/
public class Engine extends Device implements Debug, Runnable, CommandListener
{
// --------------------------------------------------------------------------------------------
// Event Handling
// --------------------------------------------------------------------------------------------
/** Set to true when when the sound should be forcibly resumed each tick */
private static boolean resumeSound;
/** True when an event (e.g. incoming call) needs to be handled */
public static boolean handleEvent;
/** Is Thread Running? */
public static boolean running;
/** True when the Canvas is hidden */
public static boolean hideNotify;
public static boolean returnFromPause = false;
public static boolean loadingInterrupted = false;
/** Used to measure the length of time between game ticks for sound resuming on dodgy devuces */
public static long lastTick;
/** Used in conjunction with Device.EVENT */
public final static int
EVENT_NONE = 0, // Do nothing (phone auto-resumes sound, or doesn't trigger any events)
EVENT_FORCE_SOUND = 1, // Force sound to restart after incoming call
EVENT_SHOW_PAUSE_SCREEN = 2; // Show pause screen on event. Wait for keypress before resuming sound
// --------------------------------------------------------------------------------------------
// Sound
// --------------------------------------------------------------------------------------------
/** Last sound that was played (for restarting after calls) */
public static int lastSound = -1;
/** Vibration switched on */
public static boolean vibrateOn = SUPPORTS_VIBRATION;
/** Sound switched on */
public static int soundOn = Engine.SOUND_HALF;
// --------------------------------------------------------------------------------------------
// General References
// --------------------------------------------------------------------------------------------
private GameWorld gameWorld;
public static Display display;
public static STH2P2_S40P1 parent;
public static Engine instance;
// public static int curViewportX;
// public static int curViewportY;
// public static int curViewportWidth;
// public static int curViewportHeight;
// --------------------------------------------------------------------------------------------
// Logic
// --------------------------------------------------------------------------------------------
/** Random Number Generator */
public static Random random = new Random();
/** Engine tick index */
public static int tick;
/** Generic reusable counter for anything */
private int logicCounter;
// --------------------------------------------------------------------------------------------
// Global Images (These never get unloaded)
// --------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------
// Phone UI
// --------------------------------------------------------------------------------------------
/** Softkey commands */
public static Command commandSoft1, commandSoft2;
// ---------------------------------------------------------------------------------------------
// Game States
// ---------------------------------------------------------------------------------------------
public final static int
GS_UNUSED = -1, // Initialization of constructor
GS_INIT_APP = 0, // Initialise app
GS_LANGUAGE = 1, // Language selection screen
GS_SPLASH = 2, // Paint Splash Screen
GS_LOADING = 3, // Loading splash screen
GS_PAUSE = 4, // Paused after incoming call
GS_BRAND = 5, // Brand rotation
GS_DEMO_OVER = 6, // Demo over screen
GS_MENU = 10, // Draw menu
GS_COMMUNICATING = 11, // Communicating with server
GS_INPUT = 20, // Input string test
GS_AUDIO = 50, // Audio on/off startup screen
GS_INGAME = 100, // In game
GS_CONGRATZ = 150,
GS_EXIT=1000,//modify 2009-2-18 by qihaidong
GS_FLASH=1001 , GS_PRESS_START = 1002 , GS_MENU_COME_OUT = 1003,GS_SEGA_LOGO = 1004;//modify 2009-2-18 by qihaidong
/** Current Engine state */
public static int state = GS_UNUSED;
/** State to return to after pause state (set using EVENT_SHOW_PAUSE_SCREEN) */
public static int pauseState;
/** Used when Device.FAKE_SERVICE_REPAINTS is true */
private static boolean isPainting;
// --------------------------------------------------------------------------------------------
/*
*
* LOGIC - BRANDING
*
*/
private static final int[][] TEXT_BRANDS = {
{Text.BRAND_SEGA},
{Text.BRAND_GLU},
{Text.BRAND_SONICTEAM,Text.BRAND_PRESENTS}
};
private static final int NUM_BRANDS = TEXT_BRANDS.length;
//
protected void pointerPressed(int x, int y) {
if (x>0&&x<60&&y<DeviceConstants.SCREEN_HEIGHT&&y>DeviceConstants.SCREEN_HEIGHT-30)
{
keyPressed(Device.KEY_SOFTLEFT);
}else
if (x<DeviceConstants.SCREEN_WIDTH&&x>DeviceConstants.SCREEN_WIDTH-60&&y>DeviceConstants.SCREEN_HEIGHT-30&&y<DeviceConstants.SCREEN_HEIGHT)
{
keyPressed(Device.KEY_SOFTRIGHT);
}
}
protected void pointerReleased(int x, int y) {
if (x<0&&x<60&&y<this.getHeight()&&y>this.getHeight()-30)
{
keyReleased(Device.KEY_SOFTLEFT);
}else
if (x<this.getWidth()&&x>this.getWidth()-60&&y>this.getHeight()-30&&y<this.getHeight())
{
keyReleased(Device.KEY_SOFTRIGHT);
}
}
// public Standard _Standard;//modify 2009-2-18 by qihaidong
public Engine(STH2P2_S40P1 theMidlet)
{
super();
// _Standard=new Standard(SCREEN_WIDTH,SCREEN_HEIGHT);//modify 2009-2-18 by qihaidong
// GameWorld.engine = this;
parent = theMidlet;
instance = this;
if (USE_COMMANDS)
{
if (commandSoft1 != null) addCommand(commandSoft1);
if (commandSoft2 != null) addCommand(commandSoft2);
setCommandListener(this);
}
display = Display.getDisplay(theMidlet);
display.setCurrent(this); // note some devices auto refresh here (GX10)
Thread t = new Thread(this);
// Set thread priority as specified in Device class
if (THREAD_PRIORITY != Thread.NORM_PRIORITY)
t.setPriority(THREAD_PRIORITY);
t.start();
}
/*
* --------------------------------------------------------------------------------------------
* Main Thread Loop
* --------------------------------------------------------------------------------------------
*/
/** Length of tick in milliseconds */
private int debugTick;
/** Length of paint in milliseconds */
private int debugPaint;
/** Time thread was started */
private long debugStartFPSTime;
/** Frame counter */
private int debugFramesRendered;
/** Store FPS Count */
private int debugAvgFPS;
/** Recalculate FPS every FPS_RECALC seconds */
private final static int FPS_RECALC = 6;
public void run()
{
//
// Fix to roll hi score upload code
//
running = true;
state = GS_INIT_APP;
// DEBUG :: Reset FPS Counter
if (DEBUG_TIMING)
{
debugFramesRendered = 0;
debugAvgFPS = 0;
}
//#if HI_ADD
//# hiAdd.loadOption();
//# hiAdd.loadRanking();
//# hiAdd.loadGame();
//#endif
while (running)
{
long tickStartTime = System.currentTimeMillis();
// DEBUG :: Reset FPS
if (DEBUG_TIMING)
{
if (debugFramesRendered == 0)
{
debugStartFPSTime = tickStartTime;
}
}
try
{
// Handle a phone related event (incoming call / system button etc.)
if (handleEvent)
{
if(state==GS_LANGUAGE)//modify 2009-03-13 by qihaidong
Standard.pause();
handleEvent();
}
if (!hideNotify)
{
long timer;
if (DEBUG_TIMING)
timer = System.currentTimeMillis();
Device.deviceTick();
tick();
if (DEBUG_TIMING)
{
debugTick = (int) (System.currentTimeMillis() - timer);
timer = System.currentTimeMillis();
}
doRepaint();
if (DEBUG_TIMING)
debugPaint = (int) (System.currentTimeMillis() - timer);
if (DEBUG_STEP_BY_STEP)
{
if (debugStepByStep_stopOnNextFrame)
{
debugStepByStep_stopOnNextFrame = false;
debugStepByStep_stopped = true;
}
while (debugStepByStep_stopped)
{
Thread.yield();
}
}
}
// Throttle
long frameTime = System.currentTimeMillis() - tickStartTime;
//#ifdef USE_YIELD_IN_RUN
//# Thread.yield();
//#endif
if (frameTime < REFRESH_DELAY - MINIMUM_SLEEP)
{
Thread.sleep(REFRESH_DELAY - frameTime);
}
else if (MINIMUM_SLEEP != 0)
{
Thread.sleep(MINIMUM_SLEEP);
}
// if (garbageCollectCounter-- == 0)
// {
// System.gc();
// garbageCollectCounter = 30;
// }
}
catch (Exception e)
{
if (DEBUG)
e.printStackTrace();
}
// DEBUG :: Recalculate FPS
if (DEBUG_TIMING)
{
debugFramesRendered++;
if (System.currentTimeMillis() - debugStartFPSTime > (FPS_RECALC * 1000))
{
debugAvgFPS = debugFramesRendered / FPS_RECALC;
debugFramesRendered = 0; // Reset frames rendered
}
}
}
// ...
// Code to execute when app exits below
// ...
soundFunction(SOUND_STOP);
parent.destroyApp(true);
parent.notifyDestroyed();
}
private static int garbageCollectCounter;
private static boolean debugStepByStep_stopped;
private static boolean debugStepByStep_stopOnNextFrame;
private void tick()
{
if (DEBUG) trace = "tick Start";
try
{
// Handle event after delay on devices without hide/show notify (see Device class for details)
if (HANDLE_EVENT_DELAY > 0)
{
long diff;
long time = System.currentTimeMillis();
boolean eventOccured = ((diff=time - lastTick) > HANDLE_EVENT_DELAY);
// always clear the key buffers anyway to stop the menus being locked in scrolling even if not showing pause screen
if (!handleEvent && eventOccured)// && state != GS_LOADING && state != GS_PAUSE)
{
resetKeyBuffers();
keysPressed = 0;
}
// show the pause screen if ingame
if (!handleEvent && state == GS_INGAME && !GameWorld.loading && loadingInterrupted == false)
{
if(eventOccured)
GameWorld.plTimeStartedMillis+=diff;
handleEvent = eventOccured;
}
lastTick = time;
if (handleEvent)
{
}
}
// Handle event after delay on devices without hide/show notify (see Device class for details)
// if (HANDLE_EVENT_DELAY > 0)
// {
// long time = System.currentTimeMillis();
// if (!handleEvent && state != GS_LOADING && state != GS_PAUSE)
// handleEvent = ((time - lastTick) > HANDLE_EVENT_DELAY);
// lastTick = time;
// }
//#ifndef DISABLE_AUDIO
// Continually attempt to resume sound until successful
//if (resumeSound)
//{
//resumeSound = soundFunction(SOUND_RESUME) == 0;
//}
DeviceSound.update();
//#endif
drawCursolLogic();
// Global Debug Key
if (DEBUG_TIMING)
{
if (key(K_STAR))
displayDebugInfo = !displayDebugInfo;
}
switch (state)
{
case GS_FLASH:
if(FlashUnitManager.over()){
langSelected = 0;
initLanguage(language_file[0]);
initSettingsMenu(); // Rebuild settings menu
resetKeyBuffers();
closeBrand();
state = GS_PRESS_START;
setMenu(menuMain);
}
break;
case GS_INGAME:
GameWorld.tick();
break;
case GS_BRAND:
//#if HI_ADD
//# hiAdd.tickBrand();
//#else
tickBrand(false);
//#endif
break;
case GS_CONGRATZ:
{
//#if HI_ADD
//# hiAdd.tickCongratz();
//#else
tickCongratz();
//#endif
ingamemenu = false;
break;
}
case GS_MENU:
//#if HI_ADD
//# hiAdd.tickMenu();
//#else
tickMenu();
//#endif
break;
case GS_AUDIO:
if ( SUPPORTS_SOUND ) {
tickAudioSelect();
}
break;
case GS_LANGUAGE:
//#if !SINGLE_LANGUAGE
// tickLanguageSelect();
//modify 2009-2-18 by qihaidong
if(key(K_FIRE)||key(K_SOFT_SELECT))
Standard.pressConfirm();
else if(key(K_SOFT_BACK))
Standard.pressCancel();
int langstate = Standard.execSplash();
if (langstate == Standard.R_SPLASH_END) {
if (HAS_OPENING) {
FlashUnitManager.init("/anires/open_with_shade.mfls");
FlashUnitManager.setLength(100);
state = GS_FLASH;
}else{
langSelected = 0;
initLanguage(language_file[0]);
initSettingsMenu(); // Rebuild settings menu
resetKeyBuffers();
closeBrand();
state = GS_PRESS_START;
// setMenu(menuMain);
}
} else if (langstate == Standard.R_SPLASH_SOUND_ENABLE) {
if (soundOn == Engine.SOUND_OFF)
soundOn = Engine.SOUND_HALF;
} else if (langstate == Standard.R_SPLASH_SOUND_DISABLE) {
soundOn = Engine.SOUND_OFF;
}
//#endif
break;
case GS_EXIT://modify 2009-2-18 by qihaidong
if(key(K_FIRE)||key(K_SOFT_SELECT))
Standard.pressConfirm();
else if(key(K_SOFT_BACK))
Standard.pressCancel();
int exitestate=Standard.execMoreGame(true);
if(exitestate==Standard.R_MOREGAME_EXIT)
exit();
break;
case GS_INIT_APP:
initApp();
break;
//#if !HI_ADD
case GS_SPLASH:
tickSplash();
break;
//#endif
case GS_DEMO_OVER:
//if (DEMO_MODE) tickDemoOver();
//#ifdef GLU_STANDARDS
tickDemoOver();
if (GluGMGDemo.mDemo == 1) {
tickMenu(false);
}
//#endif
break;
case GS_PAUSE:
//#if HI_ADD
//# state = pauseState;
//# if (state == GS_INGAME)
//# {
//# // long suspendedTime = System.currentTimeMillis() - gameSuspendedTimeMillis;
//# // GameWorld.resume(suspendedTime);
//# state = GS_MENU;
//# returnFromGameWorld(true, false);
//# }
//#else
if (hasAnyKeyPressed())
{
state = pauseState;
Engine.debugWrite("setting state to " + state);
// if (lastSound != -1)
// soundFunction(SOUND_PLAY, lastSound);
//#ifdef BASE_7210
//#else
soundFunction(SOUND_INIT);
//#endif
if (state == GS_INGAME)
{
returnFromPause = true;
//#ifdef SLOW_LOAD_SOUND
//# if(DeviceSound.curSoundIndex != -1)
//# DeviceSound.play(DeviceSound.curSoundIndex);
//#endif
debugWrite("resuming gameworld" + (System.currentTimeMillis()/1000));
long suspendedTime = System.currentTimeMillis() - gameSuspendedTimeMillis;
GameWorld.resume(suspendedTime);
if(Engine.loadingInterrupted == false)
{
returnFromPause = false;
}
}
else if (state==GS_MENU&&!(menuCurrent == menuInGameHowToPlay||menuCurrent == menuIngame||menuCurrent == menuInGameSettings||menuCurrent == menuBackToMenuConfirmation))//modify 2009-03-04 by qihaidong
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
//else if (state == GS_MENU && menuCurrent != menuIngame)
//{
//debugWrite("resuming menu " + (System.currentTimeMillis()/1000));
//soundFunction(SOUND_PLAY, BGM_MAINTITLE);
//}
}
//#endif
break;
case GS_COMMUNICATING:
break;
}
tick++;
}
catch (Exception e)
{
if (DEBUG)
{
e.printStackTrace();
debugWrite("Ex in tick trace2=\"" + trace2 + "\" state=" + state+ " ex=" +e.toString(), true);
}
}
if (DEBUG) trace = "tick End";
}
private static final int STARS_MAX = 16;
private static final int STARS_DATA_FRAME = 0;
private static final int STARS_DATA_X = 1;
private static final int STARS_DATA_Y = 2;
private static final int STARS_DATA_SIZE = 3;
private final int[] starsData = new int[STARS_MAX*STARS_DATA_SIZE];
public void paint( Graphics g )
{
//#if DETECT_PAUSE_WITH_TIMER
//# try {
//# long diff;
//# if((diff=System.currentTimeMillis() - Device.pauseDetectTime) > Device.PAUSE_TIME_VALUE){
//# hideNotify();
//# showNotify();
//# gameSuspendedTimeMillis-=diff;
//# }
//# Device.pauseDetectTime = System.currentTimeMillis();
//# }catch(Exception e){}
//#endif
//#if DETECT_CALL_WITH_TIMER
//# try {
//# long diff;
//# if((diff=System.currentTimeMillis() - Device.pauseDetectTime) > Device.PAUSE_TIME_VALUE){
//# Device.pauseDetectTime = System.currentTimeMillis();
//# return;
//# }
//# Device.pauseDetectTime = System.currentTimeMillis();
//# }catch(Exception e){}
//#endif
if (DEBUG)
trace = "paint Start";
//dg 15/11 Engine.resetClip(g);
// System.out.println("painting state " + state);
try
{
// debugWrite("" + state);
//#if HI_ADD
//# if(state > GS_SPLASH)
//# hiAdd.renderSoftkeys(g);
//#endif
switch (state)
{
case GS_FLASH:
FlashUnitManager.draw(g);
break;
case GS_INGAME:
GameWorld.paint(g);
break;
case GS_BRAND:
//#if HI_ADD
//# hiAdd.paintBrand(g);
//#else
paintBrand(g);
//#endif
break;
case GS_CONGRATZ:
//#if HI_ADD
//# hiAdd.paintCongratz(g);
//#else
cls(g, COLOR_TITLE);
drawNewBg(g);
//#ifndef NO_TITLE
int y = VIEWPORT_HEIGHT - FontMgr.lineHeight[FONT_1] - img_title.height >> 1;
img_title.drawImageNoClipping(g, VIEWPORT_WIDTH - img_title.width >> 1, TITLE_HEIGHT);
//#endif
y += img_title.height + ((3*GameWorld.TILE_SIZE) / 2);
// paintBorderedString(g, text[Text.CONGRATULATIONS], VIEWPORT_WIDTH >> 1, y, Graphics.BASELINE | Graphics.HCENTER);
{
Font fontTmp = g.getFont();
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE));
paintBorderedString(g,text[Text.CONGRATULATIONS],(VIEWPORT_WIDTH >> 1), y,
Graphics.TOP | Graphics.HCENTER,0xFFFF00,0x000000);
drawCursol(g , y + (g.getFont().getHeight() + 1) / 2 , BAR_WIDTH);
g.setFont(fontTmp);
}
for (int i = 0; i < STARS_MAX; i++)
{
if (starsData[i*STARS_DATA_SIZE + STARS_DATA_FRAME] == 4 || starsData[i*STARS_DATA_SIZE+STARS_DATA_Y] == 0)
{
starsData[i*STARS_DATA_SIZE + STARS_DATA_FRAME] = rndPositive(4);//0;
starsData[i*STARS_DATA_SIZE + STARS_DATA_X] = rndPositive(SCREEN_WIDTH);
starsData[i*STARS_DATA_SIZE + STARS_DATA_Y] = y - rnd(GameWorld.TILE_SIZE);
}
else
{
starsData[i*STARS_DATA_SIZE + STARS_DATA_FRAME]++;
}
final int frame = 3 - Math.abs(starsData[i*STARS_DATA_SIZE + STARS_DATA_FRAME] - 2);
drawStar(g, starsData[i*STARS_DATA_SIZE + STARS_DATA_X], starsData[i*STARS_DATA_SIZE + STARS_DATA_Y], frame);
}
paintBorderedString(g, Text.PRESS_ANY_KEY, SCREEN_WIDTH >> 1, SCREEN_HEIGHT - HUD_INSET, Graphics.BOTTOM | Graphics.HCENTER);
//#endif
break;
case GS_MENU:
//#if HI_ADD
//# hiAdd.paintMenu(g);
//#else
paintMenu(g);
//#endif
break;
case GS_AUDIO:
if ( SUPPORTS_SOUND ) {
paintAudioSelect(g);
}
break;
case GS_LANGUAGE:
//#if !SINGLE_LANGUAGE
// paintLanguageSelect(g);
Standard.drawSplash(g, SCREEN_WIDTH, SCREEN_HEIGHT);
//#endif
break;
//#if !HI_ADD
case GS_SPLASH:
paintSplash(g);
break;
//#endif
case GS_DEMO_OVER:
//#ifdef GLU_STANDARDS
cls(g, COLOR_TITLE);
fillStatusArea(g, 0, 0, SCREEN_WIDTH, HUD_HEIGHT);
fillStatusArea(g, 0, SCREEN_HEIGHT - HUD_HEIGHT, SCREEN_WIDTH, HUD_HEIGHT);
paintTooltips(g, (GluGMGDemo.mDemo == 2 ? TOOLTIP_GETIT : 0) | (GluGMGDemo.demoQuit ? TOOLTIP_EXIT : TOOLTIP_MENU) );
if (GluGMGDemo.mDemo == 1) {
paintMenu(g, false);
} else {
GluGMGDemo.paintDemoOver(g);
}
//#endif
break;
//#if !HI_ADD
case GS_INPUT:
Engine.cls(g, Engine.COL_BLACK);
InputString.paintInputString(g, 2, (SCREEN_HEIGHT - FontMgr.lineHeight[FONT_2]) >> 1);
break;
//#endif
case GS_LOADING:
cls(g, COL_BLACK);
//#if !SINGLE_LANGUAGE
//#if HI_ADD
//# hiAdd.drawLoading(g);
//#else
FontMgr.drawString(FONT_1, g, _mloading[langSelected], SCREEN_WIDTH >> 1, (SCREEN_HEIGHT - FontMgr.lineHeight[FONT_1]) >> 1, Graphics.TOP | Graphics.HCENTER);
//#endif
//#else
//# FontMgr.drawString(FONT_1, g, text == null ? _mloading : text[Text.LOADING], SCREEN_WIDTH >> 1, (SCREEN_HEIGHT - FontMgr.lineHeight[FONT_1]) >> 1, Graphics.TOP | Graphics.HCENTER);
//#endif
//#if DETECT_PAUSE_WITH_TIMER || DETECT_CALL_WITH_TIMER
//# pauseDetectTime = System.currentTimeMillis();
//#endif
break;
// case GS_COMMUNICATING:
// cls(g, COL_BLACK);
// FontMgr.drawString(FONT_1, g, text[Text.COMMUNICATING], WIDTH >> 1, (HEIGHT - FontMgr.lineHeight[FONT_1]) >> 1, Graphics.TOP | Graphics.HCENTER);
// break;
case GS_PAUSE:
//#if HI_ADD
//#else
cls(g, COL_BLACK);
FontMgr.drawString(FONT_1, g, text[Text.PRESS_ANY_KEY], SCREEN_WIDTH >> 1, (SCREEN_HEIGHT - FontMgr.lineHeight[FONT_1]) >> 1, Graphics.TOP | Graphics.HCENTER);
//#endif
break;
case GS_EXIT://modify 2009-2-18 by qihaidong
Standard.drawMoreGame(g, SCREEN_WIDTH, SCREEN_HEIGHT);
break;
case GS_INIT_APP:
if (DEBUG) cls(g, 0);
break;
}
}
catch (Exception e)
{
if (DEBUG)
{
e.printStackTrace();
}
}
if (DEBUG_TIMING && displayDebugInfo)
{
paintDebugPanel(g);
}
if (DEBUG)
{
paintDebug(g);
}
/*
// for setting up tick-based sound linkage
g.setClip(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
g.setColor(0);
g.fillRect(0, 0, VIEWPORT_WIDTH, 30);
g.setColor(0xffffff);
// g.drawString(""+DeviceSound.timer, 0, 0, Graphics.TOP|Graphics.LEFT);
g.drawString("s:"+state+", i:"+(ingamemenu?1:0)+", h:"+(hideNotify?1:0)+", c:"+DeviceSound.curSoundIndex+", a:"+(DeviceSound.sound_current!=null?1:0), 0, 0, 0);
*/
if (DEBUG)
trace = "paint End";
// Paint has concluded
if (Device.FAKE_SERVICE_REPAINTS)
isPainting = false;
if (SYSTEM_GC_IN_PAINT_THREAD)
System.gc();
}
private void drawStar(Graphics g, int x, int y, int size)
{
final int COLOUR_STAR_DARK = 0x4040a0;
final int COLOUR_STAR_MEDIUM = 0x8080e0;
final int COLOUR_STAR_LIGHT = 0xe0e0e0;
if (size >= 3)
{
g.setColor(COLOUR_STAR_DARK);
g.drawLine(x-2, y, x+2, y);
g.drawLine(x, y-2, x, y+2);
}
if (size >= 2)
{
g.setColor(COLOUR_STAR_MEDIUM);
g.drawLine(x-1, y, x+1, y);
g.drawLine(x, y-1, x, y+1);
}
if (size >= 1)
{
g.setColor(COLOUR_STAR_LIGHT);
g.drawLine(x, y, x, y);
}
}
/* --------------------------------------------------------------------------------------------
Initialize App
* --------------------------------------------------------------------------------------------*/
static String trace2;
private void initApp() throws Exception
{
// Load main font
//trace2="fonts";
FontMgr.realise(FONT_1);
FontMgr.realise(FONT_2);
// Draw loading screen
//trace2="loadScn";
//#if !HI_ADD
// paintLoading();modify 2009-03-05 by qihaidong
// Load global images (those which never get unloaded)
//trace2="tips";
loadMenuResources();
//#endif
//#ifndef DISABLE_AUDIO
// Initialise sounds
//trace2="snd";
soundFunction(SOUND_INIT);
//#endif
// Check JAD parameter to determine whether we want to swap the softkeys over
//trace2="jadPrm";
String s = getJadValue( "ms-skPos" );
if (s != null) reverseTooltips = s.equals("1");
/* OLD DEMO CODE
// Check JAD parameter for demo mode
if (DEMO_MODE)
{
s = getJadValue( "ms-demoMode" );
if (s != null) demoMode = Integer.valueOf(s).intValue();
}
*/
//#ifdef GLU_STANDARDS
/* GLU DEMO & GMG SETTINGS */
GluGMGDemo.init();
//#endif
// Load Settings
//trace2="rms";
//#if !HI_ADD
//if (SUPPORTS_VIBRATION)
//{
loadRMS(RMS_SETTINGS);
//}
//#endif
// Increment number of times app is run
runCount++;
// Language selection screen (if code is compiled in)
//#if BASE_7210
//# //trace2="lang";
//# initLanguage(language_file);
//# setSoundEnable();
//#else
setLanguageSelect();
//#endif
}
/* --------------------------------------------------------------------------------------------
Initialize GameWorld
* --------------------------------------------------------------------------------------------*/
public void initGameWorld(int zone, int act)
{
soundFunction(SOUND_STOP);
paintLoading();
// ...
// unload whatever is necessary here
// ...
//#if !HI_ADD
unloadMenuResources();
//imgFlags = null;
//#if !BASE_7210
imgBrand = null;
//#endif
//#endif
if (Device.AGGRESSIVE_GC)
System.gc(); // Probably a good idea
try
{
GameWorld.abandonCurrentGame();
//#if HI_ADD
//# GameWorld.currentActState=act;
//#endif
GameWorld.loadLevel(zone, act, GameWorld.levelLoadState);
GameWorld.tick();
}
catch (Exception e)
{
if (DEBUG) e.printStackTrace();
debugWrite("ex in loadLevel: " + e.toString(), false);
}
resetKeyBuffers();
state = GS_INGAME;
}
//#if !HI_ADD
private void loadMenuResources()
{
try
{
//#ifndef NO_TITLE
img_title = new DeviceImage(Resources.AM_TITLE_PNG, "title");
//#endif
// never released
if (img_backicon == null)
img_backicon = new DeviceImage(Resources.AO_BACKICON_PNG, "backicon");
img_uiArrows = loadSprite(Resources.AN_UI_ARROWS_SPRITE, Resources.AO_UI_ARROWS_FRAMES,
Resources.AP_UI_ARROWS_SPR_PNG, -1);
// 添加新的资源
try {
newBg = Image.createImage("/new_bg.png");
// aniSonic = new Animation("/anires/sonic_s");
// aniTails = new Animation("/anires/tails_s");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
catch (Exception e)
{
Engine.debugWrite("Engine.returnFromGameWorld: " + e.toString(), false);
e.printStackTrace();
}
}
private void unloadMenuResources()
{
if (!CACHE_RESOURCES)
{
//#ifndef NO_TITLE
img_title = null;
//#endif
// img_uiArrows = null;
newBg = null;
}
}
//#endif
public static boolean ingamemenu = false;
public void returnFromGameWorld(boolean ingame, boolean toCongratzScreen)
{
// gameSuspendedTimeMillis = System.currentTimeMillis();
resetKeyBuffers();
if (ingame)
{
//#if HI_ADD
//# hiAdd.setPause();
//# state = GS_MENU;
//#else
setMenu(menuIngame);
//#endif
ingamemenu = true;
}
else
{
GameWorld.unloadResources(GameWorld.UNLOAD_FULL);
//#if !HI_ADD
loadMenuResources();
//#endif
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo>0) {
//setMenu(createForm(GluGMGDemo.getText(GluGMGDemo.STRING_TRIAL_OVER), GluGMGDemo.STRING_DEMO_OVER_MSG[0], null, menuMain));
setDemoOver();
} else
//#endif
{
if (toCongratzScreen)
{
state = GS_CONGRATZ;
}
else
{
//#if HI_ADD
//# hiAdd.menusubstate=hiAdd.GSM_PRESS_KEY;
//# state = GS_MENU;
//# Device.soundFunction(SOUND_PLAY, BGM_MAINTITLE);
//#else
setMenu(menuMain);
//#endif
}
ingamemenu = false;
}
}
//#if !HI_ADD
menuCursor = menuCurrent.cursor = 0;
menuStageSelect.cursor = 0;
//#endif
soundFunction(SOUND_STOP);
if (!ingame && !ingamemenu && state != GS_DEMO_OVER)
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
}
//#if !HI_ADD
private void returnToGameWorld()
{
soundFunction(SOUND_STOP);//modify 2009-03-06 by qihaidong
unloadMenuResources();
//#ifdef SLOW_LOAD_SOUND
//# returnFromPause = true;
//# state = GS_LOADING;
//# doRepaint();
//# GameWorld.setZoneMusic();
//# Device.soundFunction(SOUND_PLAY, DeviceSound.ZONE_MAP[GameWorld.currentZone]);
//# returnFromPause = false;
//#endif
Engine.resetKeyBuffers();
Engine.keysPressed = 0;
long suspendedTime = System.currentTimeMillis() - gameSuspendedTimeMillis;
GameWorld.resume(suspendedTime);
GameWorld.repaintHud();
state = GS_INGAME;
//#ifndef SLOW_LOAD_SOUND
GameWorld.setZoneMusic();
//#endif
ingamemenu = false;
}
/* --------------------------------------------------------------------------------------------
Brand Rotation
Add your brand files to 'res_0', named brand0.png, brand1.png etc.
* --------------------------------------------------------------------------------------------*/
//#if !BASE_7210
/** Vector of brand images */
private DeviceImage imgBrand;
//#endif
/** Delay in ms before changing brand image */
private final static int BRAND_DELAY = 2000;
private void setBrand()
{
menuCursor = 0; // Use to indicate current image
resetKeyBuffers();
state = GS_BRAND;
tickBrand(true);
}
private void closeBrand()
{
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
//#if !BASE_7210
imgBrand = null;
//#endif
}
private void tickBrand(boolean force_next)
{
boolean close_brand = false;
if (DEBUG && key(K_SOFT_SELECT))
close_brand = true;
// if (!force_next && key(K_SOFT_SELECT))
// {
// close_brand = true;
// }
// else
{
// Time to change to next image
if (((int) System.currentTimeMillis() - logicCounter) > BRAND_DELAY || force_next)
{
try
{
//#if !BASE_7210
imgBrand = null;
String _brandlist [] = {
"/sega_splash.png",
"/rockpool_splash.png",
""
};
byte imagedata[] = ResourceMaster.getResourceFromJar(_brandlist[menuCursor]);
if (imagedata != null) imgBrand = new DeviceImage(imagedata, "brand");
//if (imgBrand == null) close_brand = true;
//#endif
if (++menuCursor == NUM_BRANDS + 1)
close_brand = true;
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDevCreditDisable && menuCursor==2) {
if (++menuCursor == NUM_BRANDS + 1)
close_brand = true;
}
//#endif
logicCounter = (int) System.currentTimeMillis();
}
catch (Exception e)
{
close_brand = true;
}
}
}
if (close_brand)
{
resetKeyBuffers();
closeBrand();
// setSplash();
setMenu(menuMain);
}
}
private void tickCongratz()
{
if (hasAnyKeyPressed())
{
// setBrand();
resetKeyBuffers();//modify 2009-2-25 by qihaidong
closeBrand();
setMenu(menuMain);
}
}
private static boolean baseResourcesSectionLoaded;
private void paintBrand(Graphics g)
{
int brandIndex = menuCursor - 1;
// Draw brand image
cls(g, COL_BLACK);
g.setColor(COLORS_BRAND_BG[brandIndex]);
g.fillRect(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
//System.out.println("brandIndex "+brandIndex);
//#if !BASE_7210
/*if (brandIndex!=2) {
if (imgBrand != null)
imgBrand.drawImageClipStack(g, (SCREEN_WIDTH - imgBrand.width) >> 1, (SCREEN_HEIGHT - imgBrand.height) >> 1);
} else*/
//#endif
{
int[] brandText = TEXT_BRANDS[brandIndex];
int numLines = brandText.length;
int textY = (SCREEN_HEIGHT >> 1) -((FONT_HEIGHT+((numLines-1)*FONT_SPACING))>>1);
for (int i=0,y=textY ; i<numLines ; i++,y+=FONT_SPACING)
paintBorderedString(g,text[brandText[i]], SCREEN_WIDTH >> 1, y, Graphics.TOP | Graphics.HCENTER,
COLORS_BRAND_TEXT[brandIndex],COLORS_BRAND_BORDER[brandIndex]);
}
// paintTooltips(g, TOOLTIP_PRESS);
}
//#endif
public static void cls(Graphics g, int colour)
{
//dg 15/11 Engine.resetClip(g);
// g.setClip(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g.setColor(colour);
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
/* --------------------------------------------------------------------------------------------
DEMO OVER SCREEN
Summary:
- Code to show a 'demo over' screen.
- Firstly, make sure Constants.DEMO_MODE = true, if you want to enable demo functionality.
- Decide whether you want to show a form, or a graphic when the demo is over. If you want
to include a graphic, name it 'demo.png' and place in 'res_0'. If the image is detected
it will be given priority over the form.
- If you have a specific URL to direct the user to, in order to obtain the full version of
the game, add it to a JAD parameter entitled <ms-demoUrl>. Otherwise, do not include this
parameter.
- If the phone supports launching a particular URL, set <ms-demoMode> to '2'. You will
probably need to test this for yourself.
- If it doesn't support this, or you don't have a URL, set <ms-demoMode> to '1'. The URL
will be displayed, but no attempt will be made to redirect the user there.
Here is a list detailing all possible combinations of demo screen:
[1] - Text display with link (no browser)
+ Set JAD parameter <ms-demoMode> to '1'.
+ Set JAD parameter <ms-demoUrl> with correct URL.
+ DEMO_TEXT entry in language file will be displayed
[2] - Text display with link and browser launch
+ Set JAD parameter <ms-demoMode> to '2'.
+ Set JAD parameter <ms-demoUrl> with correct URL.
+ DEMO_TEXT entry in language file will be displayed
[3] - Text display (no link, no browser)
+ Set JAD parameter <ms-demoMode> to '1'.
+ Remove JAD parameter <ms-demoUrl> from build.
+ DEMO_TEXT_NO_PUSH entry in language file will be displayed
[4] - Image display (no browser)
+ Set JAD parameter <ms-demoMode> to '1'.
+ Add 'demo.png' to 'res_0.pak'.
+ Include URL in Image if desired.
[5] - Image display with browser launch
+ Set JAD parameter <ms-demoMode> to '2'.
+ Set JAD parameter <ms-demoUrl> with correct URL.
+ Add 'demo.png' to 'res_0.pak'.
+ Include URL in Image if desired.
[6] - Turn demo mode off completely
+ Remove JAD parameter <ms-demoMode>
* --------------------------------------------------------------------------------------------*/
/*
private int demoMode;
private final static int
DEMO_OFF = 0, // Demo mode OFF
DEMO_ON = 1, // Demo mode ON
DEMO_BROWSER = 2; // Demo mode ON (with browser launch)
// Demo Mode: Push URL
private String demoUrl;
*/
// Demo Mode: Download Menu/
//private Menu menuDemoDownload;
//#ifdef GLU_STANDARDS
private void setDemoOver()
{
if (GluGMGDemo.mDemo==1) {
setMenu(createForm( Engine.text[Text.TRIAL_OVER], Engine.text[Text.DEMO_OVER_MSG], null, menuMain));
}
menuCursor = 0;
state = GS_DEMO_OVER;
resetKeyBuffers();
//setMenu(menuDemoDownload);
}
private void tickDemoOver()
{
if (key(K_SOFT_SELECT) && GluGMGDemo.mDemo==2 ) {
GluGMGDemo.platRequest(GluGMGDemo.mDemoURL);
exit();
}
if ((keyLatch & K_SOFT_BACK) != 0) {
if (GluGMGDemo.demoQuit) {
exit();
} else {
setMenu(menuMain);
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
}
}
}
//#endif
/* --------------------------------------------------------------------------------------------
Sound enable menu
* --------------------------------------------------------------------------------------------*/
private void setSoundEnable()
{
if (SUPPORTS_SOUND/* && runCount == 1*/)
{
// setMenu(menuSound);
state = GS_AUDIO;
}
else
//#if HI_ADD
//# state = GS_BRAND;
//#else
setBrand();
//#endif
}
/* --------------------------------------------------------------------------------------------
Splash Screen
* --------------------------------------------------------------------------------------------*/
//#if !HI_ADD
private void setSplash()
{
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
resetKeyBuffers();
state = GS_SPLASH;
}
private void tickSplash()
{
if (hasAnyKeyPressed())
{
closeSplash();
setMenu(menuMain);
}
}
private void paintSplash(Graphics g)
{
g.setColor(COL_BLACK);
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
FontMgr.drawString(FONT_1, g, "PUT SPLASH HERE", SCREEN_WIDTH >> 1, 0, Graphics.TOP | Graphics.HCENTER);
if ((Engine.tick & 4) != 0)
{
FontMgr.drawString(FONT_1, g, text[Text.PRESS_ANY_KEY], SCREEN_WIDTH >> 1, SCREEN_HEIGHT - (FontMgr.lineHeight[FONT_1] << 1), Graphics.TOP | Graphics.HCENTER);
}
}
private void closeSplash()
{
// Unload images here
}
//#endif
/* --------------------------------------------------------------------------------------------
Language selection menu
ms-multiLang: 1 Display language selection menu
ms-multiLang: file.dat Autoload this language file, don't display menu
If the parameter is missing, the default language file will be loaded
Note this could be done with the menu system, but it's kind of nicer to have the flags
I think...
This code can be compiled out if LANGAUGE_SELECT is set to false
* --------------------------------------------------------------------------------------------*/
public int menuCursor;
private int arrowHighlight;
//private DeviceImage[] imgArrows, imgFlags;
private final static int
FRAME_ARROW_L = 0,
FRAME_ARROW_R = 2;
private final static int
FLAG_ENGLISH = 0,
FLAG_FRENCH = 1,
FLAG_GERMAN = 2,
FLAG_ITALIAN = 3,
FLAG_SPANISH = 4,
FLAG_PT =5;
private final static int NUMBER_OF_LANGUAGES = FLAG_PT+1;
/*private final static String[] LANGUAGE_FILESx =
{
"lang.dat", // default
"fr.dat",
"de.dat",
"it.dat",
"es.dat",
"pt.dat",
};*/
/** Default language */
private static int langSelected;
private void setLanguageSelect()
{
//#if BASE_7210
//# initLanguage(language_file);
//# setSoundEnable();
//#else
//#if HI_ADD
//# menuCursor = hiAdd.savedLang();
//#else
// paintLoading();modify 2009-03-05 by qihaidong
menuCursor = 0;
//#endif
state = GS_LANGUAGE;
//#endif
/* old code - commented out by Naseer 30/11/2007
// Retrieve JAD parameter controlling language selection
String lang = getJadValue( "ms-multiLang" );
if (lang != null)
{
// DISPLAY LANGUAGE SELECTION SCREEN
if (lang.equals("1"))
{
paintLoading();
menuCursor = 0;
state = GS_LANGUAGE;
}
// LOAD LANGUAGE SPECIFIED
else
{
initLanguage(lang);
setSoundEnable();
}
}
// LOAD DEFAULT LANGUAGE FILE
else
{
initLanguage(LANGUAGE_FILES[0]);
setSoundEnable();
}
*/
}
//private void closeLanguageSelect()
//{
// imgFlags = null;
//}
private void paintAudioSelect(Graphics g) {
final String _mEnableAudio[] = {"Enable Audio?","Activer l'Audio?","Attivare Audio?","Erlauben Sie Ton?","\u00bfPermitir Sonido?","Activar som?"};
final String _mYes[] = {"Yes","Oui","S\u00EC","Ja","S\u00ED","Sim"};
final String _mNo[] = {"No","Non","No","Nein","No","N\u00e3o"};
Font _smallFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
int fh = _smallFont.getHeight();
g.setColor(0xFFFFFF);
g.fillRect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
int x = (SCREEN_WIDTH>>1) - 32;
int y = (SCREEN_HEIGHT>>1) - 48;
g.setColor(0x505050);
g.fillRoundRect(x-1,y-1, 66,66, 16,16 );
g.setColor(0xffffff);
g.fillRoundRect(x,y, 64,64, 16,16 );
g.setColor(0x0058B4);
g.fillRoundRect(x+2,y+2, 60,60, 16,16 );
g.setColor(0x505050);
y+=2;
g.fillArc(x+12,y+36, 16,16, 0,360);
g.fillArc(x+36,y+32, 16,16, 0,360);
g.fillRect(x+24, y+12, 4, 34); //|
g.fillRect(x+24, y+12, 24, 4); //-
g.fillRect(x+48, y+12, 4, 26); //|
g.setColor(0xffffff);
x-=2;
y-=2;
g.fillArc(x+12,y+36, 16,16, 0,360);
g.fillArc(x+36,y+32, 16,16, 0,360);
g.drawLine(x+18,y+44, x+26, y+44);
g.drawLine(x+40, y+40, x+52, y+40);
g.fillRect(x+24, y+12, 4, 34); //|
g.fillRect(x+24, y+12, 24, 4); //-
g.fillRect(x+48, y+12, 4, 26); //|
y+=72;
g.setFont(_smallFont);
g.setColor(0x000000);
int sw = g.getFont().stringWidth(_mEnableAudio[langSelected]);
g.drawString(_mEnableAudio[langSelected], (SCREEN_WIDTH - sw) >> 1, y, 0);
y = SCREEN_HEIGHT - fh - 3;
g.setColor(0x000000);
//paintTooltips(g, TOOLTIP_YES | TOOLTIP_NO);
g.drawString(_mYes[langSelected], 4, y, 0);
g.drawString(_mNo[langSelected],SCREEN_WIDTH - g.getFont().stringWidth(_mNo[langSelected])-4,y,0);
//#endif
}
private void paintLanguageSelect(Graphics g)
{
final String _mLanguage[] = {"ENGLISH","FRAN\u00c7AIS","ITALIANO","DEUTSCH","ESPA\u00d1OL","PORTUGU\u00caS"};
final String _mSelect[] = {"Select","S\u00e9lect.","Seleziona","W\u00e4hlen","Selec.","Selec."};
final String _mExit[] = {"Exit","Quitter","Esci","Ende","Salir","Sair"};
Font _smallFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
int fh = _smallFont.getHeight();
// //#if DEVICE=="902sh"||DEVICE=="903sh"||DEVICE=="703sh"
////# fh+=4;
// //#endif
g.setColor(COL_WHITE);
g.fillRect(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
int x = 8;
int xx = SCREEN_WIDTH - (x+x);
int y = (SCREEN_HEIGHT>>1) - 40;
int yy = y;
int i;
g.setFont(_smallFont);
int minLocale = 0;
int maxLocale = 5;
for(i=minLocale;i<=maxLocale;i++ )
{
String lang = _mLanguage[i];
int sw = g.getFont().stringWidth(lang);
if( menuCursor == i )
{
g.setColor(0x000000);
yy = y - 3;
g.setColor(0x505050);
g.fillRoundRect(x,yy, xx,fh+6, 16,16 );
g.setColor(0xffffff);
g.fillRoundRect(x+1,yy+1, xx-2,fh+4, 16,16 );
g.setColor(0x0058B4);
g.fillRoundRect(x+2,yy+2, xx-4,fh+2, 16,16 );
g.setColor(0xFFFF00);
}
else
{
g.setColor(0x000000);
}
g.drawString(lang, (SCREEN_WIDTH - sw) >> 1, y, 0);
y+=(fh+4);
}
y = SCREEN_HEIGHT - fh - 3;
g.setColor(0x000000);
g.drawString(_mSelect[menuCursor], 4, y, 0);
g.drawString(_mExit[menuCursor],SCREEN_WIDTH - g.getFont().stringWidth(_mExit[menuCursor])-4,y,0);
//g.drawString(ADVAMD_MENU_STRINGS[SOFTKEY_SELECT], 8, y, Graphics.TOP | Graphics.LEFT);
//g.drawString(ADVAMD_MENU_STRINGS[SOFTKEY_EXIT], cCanvas.getGameWidth() - 8, y, Graphics.TOP | Graphics.RIGHT);
/*
// ----------------------------------------------------------------------------------------
// Moved the following array into the method
// As final static Strings don't get compiled out (Proguard 3.5)
// ----------------------------------------------------------------------------------------
String LANGUAGE_STRINGS[] = new String[]
{
"ENGLISH",
"FRAN\u833fIS",
"DEUTSCH",
"ITALIANO",
"ESPA\u88bfL",
"PORTUGU\u851b",
};
// Paint Background
cls(g, COL_BLACK);
int flag_x = (SCREEN_WIDTH - imgFlags[menuCursor].width) >> 1;
int flag_y = (SCREEN_HEIGHT - imgFlags[menuCursor].height) >> 1;
int fill_y = flag_y - 20;
int fill_height = 40 + imgFlags[menuCursor].height + FontMgr.lineHeight[FONT_2];
// Paint Background Bar
g.setColor(0x1B3535);
g.fillRect(0, fill_y, SCREEN_WIDTH, fill_height);
// Paint Lines at top and bottom of the bar
g.setColor(COL_WHITE);
g.fillRect(0, fill_y, SCREEN_WIDTH, 1);
g.fillRect(0, fill_y + fill_height - 1, SCREEN_WIDTH, 1);
FontMgr.drawString(FONT_2, g, LANGUAGE_STRINGS[menuCursor], SCREEN_WIDTH >> 1, flag_y + imgFlags[menuCursor].height + 1, Graphics.TOP | Graphics.HCENTER);
imgFlags[menuCursor].drawImageClipStack(g, flag_x, flag_y);
// Paint arrows either side of
int arrow_y = (SCREEN_HEIGHT - imgArrows[0].height) >> 1;
imgArrows[arrowHighlight > 0 ? FRAME_ARROW_L+1 : FRAME_ARROW_L].drawImageClipStack(g, flag_x - imgArrows[0].width - 10, arrow_y); // lhs
imgArrows[arrowHighlight < 0 ? FRAME_ARROW_R+1 : FRAME_ARROW_R].drawImageClipStack(g, flag_x + imgFlags[menuCursor].width + 10, arrow_y); // rhs
paintTooltips(g, TOOLTIP_OK);*/
}
private void tickAudioSelect() {
if ( key(K_FIRE) || key(K_SOFT_SELECT) ) {
if (soundOn == Engine.SOUND_OFF)
{
soundOn = Engine.SOUND_HALF;
}
//#if HI_ADD
//# hiAdd.setSound(soundOn);
//# state = GS_BRAND;
//#else
initSettingsMenu(); // Rebuild settings menu
setBrand();
//#endif
} else if ( key(K_SOFT_BACK ) ) {
soundOn = Engine.SOUND_OFF;
//#if HI_ADD
//# hiAdd.setSound(soundOn);
//# state = GS_BRAND;
//#else
initSettingsMenu(); // Rebuild settings menu
setBrand();
//#endif
}
}
//#if !SINGLE_LANGUAGE
private void tickLanguageSelect()
{
if (arrowHighlight > 0) arrowHighlight--;
else if (arrowHighlight < 0) arrowHighlight++;
if (key(K_UP))
{
if (--menuCursor < 0)
{
menuCursor = NUMBER_OF_LANGUAGES - 1;
}
arrowHighlight = 2;
}
else if (key(K_DOWN))
{
if (++menuCursor > NUMBER_OF_LANGUAGES - 1)
{
menuCursor = 0;
}
arrowHighlight = -2;
} else if (key(K_SOFT_BACK)) {
exit();
}
else if (key(K_FIRE) || key(K_SOFT_SELECT))
{
langSelected = menuCursor;
//closeLanguageSelect();
//#if BASE_7210
//# initLanguage(language_file);
//#else
//System.out.println("langSelected "+langSelected);
//#if HI_ADD
//# hiAdd.initLanguage(menuCursor);
//#else
initLanguage(language_file[menuCursor]);
//#endif
//#endif
setSoundEnable();
}
}
//#endif
//#if !HI_ADD
private void initLanguage(String language)
{
paintLoading();
// Recreate menus based on new language setting
trace2="initlang_txt";
initText("/"+language);
// // Initialize bitmap font if supported on this device
// try
// {
// deviceFunction(DEVICE_INIT_FONT, text[Text.USE_BITMAP_FONT]);
// }
// catch (Exception e)
// {}
// Initialize high score tables with default language names
trace2="initlang_hs";
// initHighScores();
// Once language file is loaded, we can initialise the menus
trace2="initlang_menus";
initMenus();
}
/* --------------------------------------------------------------------------------------------
Paint Tooltips
* --------------------------------------------------------------------------------------------*/
//#endif
/** Reverse tooltips if specified in JAD file */
public static boolean reverseTooltips;
//#if !HI_ADD
private final static int
TOOLTIP_BACK = 0x01,
TOOLTIP_OK = 0x02,
TOOLTIP_EXIT = 0x04,
TOOLTIP_YES = 0x08,
TOOLTIP_NO = 0x10,
TOOLTIP_START = 0x20,
TOOLTIP_GETIT = 0x40,
TOOLTIP_MENU = 0x80;
//TOOLTIP_YESNO = TOOLTIP_YES | TOOLTIP_NO,
//TOOLTIP_BOTH = TOOLTIP_BACK | TOOLTIP_OK,
//TOOLTIP_DEMO = TOOLTIP_BACK | TOOLTIP_START;
private final static int
IMG_OK = 0,
IMG_BACK = 1,
IMG_ARROW_DOWN = 2,
IMG_ARROW_UP = 3,
IMG_PRESS = 6,
IMG_DELETE = 7,
IMG_TRASH = 8;
private void paintTooltips(Graphics g, int mask)
{
int x1 = HUD_INSET;
int x2 = SCREEN_WIDTH - HUD_INSET;
int y = SCREEN_HEIGHT - HUD_INSET;
if (reverseTooltips)
{
if ((mask & TOOLTIP_BACK) != 0)
paintBorderedString(g, Text.BACK, x1, y, Graphics.BOTTOM | Graphics.LEFT);
if ((mask & TOOLTIP_EXIT) != 0)
paintBorderedString(g, Text.EXIT, x1, y, Graphics.BOTTOM | Graphics.LEFT);
if ((mask & TOOLTIP_OK) != 0)
paintBorderedString(g, Text.OK, x2, y, Graphics.BOTTOM | Graphics.RIGHT);
if ( (mask & TOOLTIP_YES) != 0 ) {
paintBorderedString(g, Text.YES, x2, y, Graphics.BOTTOM | Graphics.RIGHT);
}
if ( (mask & TOOLTIP_NO) != 0 ) {
paintBorderedString(g, Text.NO, x1, y, Graphics.BOTTOM | Graphics.LEFT);
}
//#ifdef GLU_STANDARDS
if ((mask & TOOLTIP_START) != 0)
paintBorderedString(g, Engine.text[Text.START], x2, y, Graphics.BOTTOM | Graphics.RIGHT);
if ((mask & TOOLTIP_GETIT) != 0)
paintBorderedString(g, Engine.text[Text.GET_IT], x2, y, Graphics.BOTTOM | Graphics.RIGHT);
if ((mask & TOOLTIP_MENU) != 0)
paintBorderedString(g, Engine.text[Text.MENU], x1, y, Graphics.BOTTOM | Graphics.LEFT);
//#endif
}
else
{
if ((mask & TOOLTIP_BACK) != 0)
paintBorderedString(g, Text.BACK, x2, y, Graphics.BOTTOM | Graphics.RIGHT);
if ((mask & TOOLTIP_EXIT) != 0)
paintBorderedString(g, Text.EXIT, x2, y, Graphics.BOTTOM | Graphics.RIGHT);
if ((mask & TOOLTIP_OK) != 0)
paintBorderedString(g, Text.OK, x1, y, Graphics.BOTTOM | Graphics.LEFT);
if ( (mask & TOOLTIP_YES) != 0 ) {
paintBorderedString(g, Text.YES, x1, y, Graphics.BOTTOM | Graphics.LEFT);
}
if ( (mask & TOOLTIP_NO) != 0 ) {
paintBorderedString(g, Text.NO, x2, y, Graphics.BOTTOM | Graphics.RIGHT);
}
//#ifdef GLU_STANDARDS
if ((mask & TOOLTIP_START) != 0)
paintBorderedString(g, Engine.text[Text.START], x1, y, Graphics.BOTTOM | Graphics.LEFT);
if ((mask & TOOLTIP_GETIT) != 0)
paintBorderedString(g, Engine.text[Text.GET_IT], x1, y, Graphics.BOTTOM | Graphics.LEFT);
if ((mask & TOOLTIP_MENU) != 0)
paintBorderedString(g, Engine.text[Text.MENU], x2, y, Graphics.BOTTOM | Graphics.RIGHT);
//#endif
}
}
//#endif
/* --------------------------------------------------------------------------------------------
Force loading repaint
* --------------------------------------------------------------------------------------------*/
private void paintLoading()
{
int old_state = state;
state = GS_LOADING;
doRepaint();
//state = old_state;
}
//#if !HI_ADD
/* --------------------------------------------------------------------------------------------
Menu Drawing and Handling
* --------------------------------------------------------------------------------------------*/
private static int menuItemHeight;
//#ifndef NO_TITLE
private static DeviceImage img_title;
//#endif
private static DeviceImage[][] img_uiArrows;
public static DeviceImage img_backicon;
/** Reference current menu in use */
private static Menu menuCurrent;
private static Menu menuMain, menuIngame, menuInGameSettings, menuSettings, menuExit, menuScores, menuBackToMenuConfirmation;
private Menu menuStageSelect;static Menu menuMoreGame;
private Menu menuHowToPlay;
private int menuId;
/** Options to display in currently selected menu */
private int menuOptions;
/** Height of current menu */
private int menuHeight;
/** Start and End points for rendering menu */
private int menuDrawStart, menuDrawEnd;
private void initMenus()
{
menuItemHeight = FontMgr.lineHeight[FONT_2];
String[] ms_yesno =
new String[] {
text[Text.YES],
text[Text.NO]};
String[] ms_noyes =
new String[] {
text[Text.NO],
text[Text.YES]};
// String[] ms_soundyesno =
// new String[] {
// text[Text.SOUND_ON],
// text[Text.SOUND_OFF]};
String[] ms_main;
{
if (SUPPORTS_SOUND)
{
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0 || GluGMGDemo.mUpsell>0) {
ms_main = GluGMGDemo.getMainMenu();
} else
//#endif
{
ms_main =
new String[] {
text[Text.STAGE_SELECT],
text[Text.HOW_TO_PLAY],
text[Text.SETTINGS],
text[Text.ABOUT],
};
}
}
else
{
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0 || GluGMGDemo.mUpsell>0) {
ms_main = GluGMGDemo.getMainMenuNoSound();
} else
//#endif
{
ms_main =
new String[] {
text[Text.STAGE_SELECT],
text[Text.HOW_TO_PLAY],
text[Text.ABOUT],
};
}
}
}
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo>0) {
GluGMGDemo.setExitDemoText();
}
//#endif
String[] ms_ingame;
if (SUPPORTS_SOUND && SUPPORTS_VIBRATION)
{
ms_ingame = new String[] {
text[Text.RESUME],
text[Text.HOW_TO_PLAY],//2010-05-25 by qihaidong
text[Text.SETTINGS],
text[Text.BACK_TO_TITLE],
};
}
else if (SUPPORTS_SOUND)
{
ms_ingame = new String[] {
text[Text.RESUME],
text[Text.HOW_TO_PLAY],//2010-05-25 by qihaidong
text[Text.SOUND_OFF + Engine.soundOn],
text[Text.BACK_TO_TITLE],
};
}
else
{
ms_ingame = new String[] {
text[Text.RESUME],
text[Text.HOW_TO_PLAY],//2010-05-25 by qihaidong
text[Text.BACK_TO_TITLE],
};
}
menuMain = new Menu(null, ms_main, Menu.MENU_ROOT);
menuExit = new Menu(text[Text.EXITQ], ms_noyes, Menu.MENU_SUB);
// menuSound = new Menu(text[Text.ENABLE_SOUND], ms_soundyesno, Menu.MENU_SUB);
if(menuMoreGame == null)menuMoreGame = new Menu("开启网页?", ms_noyes, Menu.MENU_SUB);
menuStageSelect = new Menu(text[Text.STAGE_SELECT], null, Menu.MENU_STAGE_SELECT);
menuIngame = new Menu(null, ms_ingame, Menu.MENU_SUB);
menuBackToMenuConfirmation = new Menu(text[Text.BACK_TO_TITLEQ], ms_noyes, Menu.MENU_SUB);
menuHowToPlay = createForm(text[Text.HOW_TO_PLAY], text[Text.INSTRUCTIONS], menuMain, null);
menuInGameHowToPlay=createForm(text[Text.HOW_TO_PLAY], text[Text.INSTRUCTIONS], menuIngame, null);//2010-05-25 by qihaidong
initSettingsMenu();
}
private Menu menuInGameHowToPlay;//2010-05-25 by qihaidong
private void initSettingsMenu()
{
String[] ms_settings = null;
if (SUPPORTS_SOUND && SUPPORTS_VIBRATION)
{
ms_settings = new String[] {
text[Text.SOUND_OFF + Engine.soundOn],
text[vibrateOn ? Text.VIBRATE_ON : Text.VIBRATE_OFF] };
}
else if (SUPPORTS_SOUND)
{
ms_settings = new String[] {
text[Text.SOUND_OFF + Engine.soundOn] };
}
else
return;
menuSettings = new Menu(text[Text.SETTINGS], ms_settings, Menu.MENU_SUB);
menuInGameSettings = new Menu(text[Text.SETTINGS], ms_settings, Menu.MENU_SUB);
}
/** Maximum number of simultaneous options to display in game menus */
public final static int MENU_MAX_OPTIONS = 1;
private void setMenu(Menu new_menu)
{
if (new_menu == null)
{
if (DEBUG)
System.out.println("setMenu() :: new_menu is set to null, aborting!");
return;
}
// If the menu is not a root level menu, make sure we can return to previous menu
if (new_menu.type != Menu.MENU_ROOT && menuCurrent != null && new_menu != menuCurrent.previous)// && new_menu.previous == null)
{
new_menu.previous = menuCurrent;
}
if (new_menu == menuSettings || new_menu == menuIngame || new_menu == menuInGameSettings)
{
if (SUPPORTS_SOUND && SUPPORTS_VIBRATION)
{
if(new_menu == menuSettings || new_menu == menuInGameSettings)
{
new_menu.text[0] = text[Text.SOUND_OFF + Engine.soundOn];
new_menu.text[1] = text[vibrateOn ? Text.VIBRATE_ON : Text.VIBRATE_OFF];
}
}
else if (SUPPORTS_SOUND)
{
if(new_menu == menuSettings || new_menu == menuInGameSettings)
{
new_menu.text[0] = text[Text.SOUND_OFF + Engine.soundOn];
}
else
{
new_menu.text[1] = text[Text.SOUND_OFF + Engine.soundOn];
}
}
}
menuCurrent = new_menu;
if (new_menu.type == Menu.MENU_FORM || new_menu.type == Menu.MENU_SUB)
{
menuOptions = Math.min(menuCurrent.length(), FORM_MAX_LINES);
// -1 to leave space for title
int title = menuCurrent.title == null ? 0 : 1;
menuHeight = ((menuOptions-title) * (FontMgr.lineHeight[FONT_2] + MENU_SPACING)) - MENU_SPACING;
}
else
{
menuOptions = Math.min(menuCurrent.length(), MENU_MAX_OPTIONS);
menuHeight = (menuOptions * (menuItemHeight + MENU_SPACING)) - MENU_SPACING;
}
menuCursor = menuCurrent.cursor;
updateMenuDrawPoints();
Engine.resetKeyBuffers();
state = GS_MENU;
}
private void paintMenu(Graphics g)
{
paintMenu(g, true);
}
private int menuCursorToZone() {
int _tozone[] = {
0,0,
1,1,1,
2,
};
return (_tozone[menuCurrent.cursor]);
}
private int menuCursorToAct() {
int _toact[] = {
0,1,
0,1,2,
0,
};
return (_toact[menuCurrent.cursor]);
}
private void paintMenu(Graphics g, boolean painttooltips)
{
if (painttooltips) {
cls(g, COLOR_TITLE);
Engine.fillStatusArea(g, 0, 0, SCREEN_WIDTH, HUD_HEIGHT);
Engine.fillStatusArea(g, 0, SCREEN_HEIGHT - HUD_HEIGHT, SCREEN_WIDTH, HUD_HEIGHT);
// Mask on relevant tooltips
int tooltip_mask = 0;
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0 && menuCurrent == menuStageSelect) {
paintTooltips(g, TOOLTIP_BACK | TOOLTIP_START);
} else
//#endif
{
if (menuCurrent.previous != null)
tooltip_mask |= TOOLTIP_BACK;
if (menuCurrent.next != null || /*menuCurrent.action ||*/ menuCurrent.type != Menu.MENU_FORM )
tooltip_mask |= TOOLTIP_OK;
if (menuCurrent == menuMain) {
tooltip_mask |= TOOLTIP_EXIT;
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0) {
paintBorderedString(g, Engine.text[Text.FREE_TRIAL], VIEWPORT_WIDTH>>1, 2, Graphics.TOP | Graphics.HCENTER);
}
//#endif
}
paintTooltips(g, tooltip_mask);
}
}
//
g.translate(VIEWPORT_X, VIEWPORT_Y);
g.setClip(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
//dg 15/11 Engine.setClip(g, 0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
if (menuCurrent.type == Menu.MENU_ROOT)
{
drawNewBg(g);
//#ifndef NO_TITLE
img_title.drawImageNoClipping(g, VIEWPORT_WIDTH - img_title.width >> 1, TITLE_HEIGHT - VIEWPORT_Y);
//#endif
int textLine = VIEWPORT_HEIGHT - FontMgr.lineHeight[FONT_1];
//#ifdef GLU_STANDARDS
if (menuCurrent.text[menuCurrent.cursor] == Engine.text[Text.GMG]) {
paintBorderedString(g, menuCurrent.text[menuCurrent.cursor], VIEWPORT_WIDTH >> 1, textLine - (FONT_HEIGHT >> 2), Graphics.TOP | Graphics.HCENTER, 0xFF9C6B,COLOR_TEXT_BORDER);
} else
//#endif
{
paintBorderedString(g, menuCurrent.text[menuCurrent.cursor], VIEWPORT_WIDTH >> 1, textLine - (FONT_HEIGHT >> 2), Graphics.TOP | Graphics.HCENTER);
}
drawCursol(g , textLine - (FONT_HEIGHT >> 2) + (FONT_HEIGHT >> 1 ), BAR_WIDTH);
img_uiArrows[UI_ARROW_LEFT][0].drawImageClipStack(g, GAMEOVER_MARGIN - 7, textLine - 1);
img_uiArrows[UI_ARROW_RIGHT][0].drawImageClipStack(g, VIEWPORT_WIDTH - GAMEOVER_MARGIN - img_uiArrows[UI_ARROW_RIGHT][0].width + 7, textLine - 1);
}
else if (menuCurrent.type == Menu.MENU_STAGE_SELECT)
{
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0) {
GluGMGDemo.paintDemoStart(g);
} else
//#endif
{
//paintZoneScreen(g, menuCurrent.cursor / 2, ((menuCurrent.cursor % 2)+1), true);
paintZoneScreen(g, menuCursorToZone(), menuCursorToAct() + 1, true);
}
}
else if (menuCurrent.type == Menu.MENU_SUB || menuCurrent.type == Menu.MENU_FORM)
{
g.setColor(0);
g.fillRect(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
if (menuCurrent.title != null)
paintDropString(g, menuCurrent.title, VIEWPORT_WIDTH >> 1, TITLE_Y, Graphics.TOP | Graphics.HCENTER, COLOR_TEXT, COLOR_DROP);
// Establish correct start and end drawing positions for menu
int draw_y = (VIEWPORT_HEIGHT - menuHeight) >> 1;
if (menuDrawStart > 0)
img_uiArrows[UI_ARROW_UP][0].drawImageAndRestoreClip(g, VIEWPORT_WIDTH >> 1, draw_y - MENU_PADDING+4 - img_uiArrows[UI_ARROW_UP][0].height);
// if (menuDrawStart > 0)
// img_uiArrows[UI_ARROW_UP][0].drawImageAndRestoreClip(g, VIEWPORT_WIDTH >> 1, TITLE_Y + menuItemHeight + MENU_SPACING);
for (int i = menuDrawStart; i < menuDrawEnd; i++)
{
// Unselected Menu Item / Form Drawing
if (menuCurrent.type == Menu.MENU_FORM) {
g.setColor(COL_WHITE);
} else if (i != menuCurrent.cursor) {
g.setColor(0x5A5A5A);
} else {
g.setColor(COL_WHITE);
}
FontMgr.drawString(Constants.FONT_2, g, menuCurrent.text[i], SCREEN_WIDTH >> 1, draw_y, Graphics.TOP | Graphics.HCENTER);
if (menuCurrent.type != Menu.MENU_FORM && i == menuCurrent.cursor)
drawCursol(g , (draw_y) + (FONT_HEIGHT >> 1) , FONT.stringWidth(menuCurrent.text[i]) + 20);
draw_y += menuItemHeight + MENU_SPACING;
}
if (menuDrawEnd < menuCurrent.length())
img_uiArrows[UI_ARROW_DOWN][0].drawImageAndRestoreClip(g, VIEWPORT_WIDTH >> 1, draw_y+10);
// if (menuDrawEnd < menuCurrent.length())
// img_uiArrows[UI_ARROW_DOWN][0].drawImageAndRestoreClip(g, VIEWPORT_WIDTH >> 1, VIEWPORT_HEIGHT - MENU_PADDING - img_uiArrows[UI_ARROW_DOWN][0].height);
}
//dg 15/11 Engine.popClip(g);
g.translate(-VIEWPORT_X, -VIEWPORT_Y);
// Engine.curViewportWidth = SCREEN_WIDTH;
// Engine.curViewportHeight = SCREEN_HEIGHT;
}
public static void paintZoneScreen(Graphics g, int zone, int act, boolean paintArrows)
{
if (paintArrows)
{
g.setColor(0);
g.fillRect(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
}
else
{
g.setColor(0);
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
int textLine = VIEWPORT_HEIGHT >> 1;
int margin;
if (paintArrows)
margin = GAMEOVER_MARGIN + img_uiArrows[UI_ARROW_LEFT][0].width + GAMEOVER_MARGIN;
else
margin = GAMEOVER_MARGIN << 1;
// Zone
paintDropString(g, text[Text.ZONE_NAME + zone],
margin, textLine - (FONT_HEIGHT << 1),
Graphics.TOP | Graphics.LEFT, COLOR_TEXT, COLOR_DROP);
// "Zone"
paintDropString(g, text[Text.ZONE],
VIEWPORT_WIDTH >> 1, textLine,
Graphics.TOP | Graphics.HCENTER, COLOR_TEXT, COLOR_DROP);
if (paintArrows)
{
img_uiArrows[UI_ARROW_LEFT][0].drawImageClipStack(g, GAMEOVER_MARGIN, textLine);
img_uiArrows[UI_ARROW_RIGHT][0].drawImageClipStack(g, VIEWPORT_WIDTH - GAMEOVER_MARGIN - img_uiArrows[UI_ARROW_RIGHT][0].width, textLine);
}
//dg 15/11 realiseClip(g);
//textLine += (160 * img_uiArrows[0].height) / 100;
textLine += FONT_HEIGHT << 1;
// g.setClip(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
if (zone!=GameWorld.ZONE_ID_DEATH_EGG) {
// Act
paintDropString(g, text[Text.ACT] + " " + act,
VIEWPORT_WIDTH - margin, textLine,
Graphics.TOP | Graphics.RIGHT, COLOR_TEXT, COLOR_DROP);
}
clearKey();
}
public static void fillStatusArea(Graphics g,int x,int y,int width,int height)
{
//System.out.println("fillStatusArea("+x+","+y+","+width+","+height+")");
for (int oy=height,c=0 ; --oy>=0 ; c=1-c)
{
g.setColor(COLOR_STATUSBAR[c]);
g.fillRect(x,y+oy,width,1);
}
}
private void tickMenu() {
tickMenu(true);
}
public static void clearKey()
{
keyLatch=0;
keysPressed=0;
}
private void tickMenu(boolean enablesk)
{
boolean option_changed = false;
boolean back = false;
boolean forward = false;
//#ifdef GLU_STANDARDS
if (menuCurrent.type == Menu.MENU_ROOT || (menuCurrent.type == Menu.MENU_STAGE_SELECT && GluGMGDemo.mDemo==0) )
//#else
//# if (menuCurrent.type == Menu.MENU_ROOT || menuCurrent.type == Menu.MENU_STAGE_SELECT )
//#endif
{
if (key(K_LEFT))
back = true;
}
else if (menuCurrent.type == Menu.MENU_SUB)
{
if (key(K_UP))
back = true;
}
else if (menuCurrent.type == Menu.MENU_FORM)
{
if (isPressed(K_UP))
back = true;
}
//#ifdef GLU_STANDARDS
if (menuCurrent.type == Menu.MENU_ROOT || (menuCurrent.type == Menu.MENU_STAGE_SELECT && GluGMGDemo.mDemo==0) )
//#else
//# if (menuCurrent.type == Menu.MENU_ROOT || menuCurrent.type == Menu.MENU_STAGE_SELECT )
//#endif
{
if (key(K_RIGHT))
forward = true;
}
else if (menuCurrent.type == Menu.MENU_SUB)
{
if (key(K_DOWN))
forward = true;
}
else if (menuCurrent.type == Menu.MENU_FORM)
{
if (isPressed(K_DOWN))
forward = true;
}
if (back)
{
if (--menuCurrent.cursor < 0)
{
if (menuCurrent.type == Menu.MENU_FORM)
menuCurrent.cursor = 0;
else
{
Engine.releaseKey(K_UP);
menuCurrent.cursor = menuCurrent.length() - 1;
option_changed = true;
}
}
else
{
option_changed = true;
}
}
if (forward)
{
int max = menuCurrent.length();
if (menuCurrent.type == Menu.MENU_FORM)
{
max -= (FORM_MAX_LINES - 1);
if (++menuCurrent.cursor >= max)
menuCurrent.cursor = max - 1;
else
option_changed = true;
}
else
{
Engine.releaseKey(K_DOWN);
if (++menuCurrent.cursor >= max)
menuCurrent.cursor = 0;
option_changed = true;
}
}
// Select
else if ( (key(K_FIRE) || key(K_SOFT_SELECT)) && enablesk)
{
if (menuCurrent.next != null)
{
menuCurrent.next.cursor = 0;
setMenu(menuCurrent.next);
}
else
doMenuAction(menuCurrent, menuCurrent.cursor);
}
// Back
else if ( key(K_SOFT_BACK) && enablesk)
{
if (menuCurrent == menuMain)
{
setMenu(menuExit);
return;
}
// Return to game
if (menuCurrent == menuIngame)
{
returnToGameWorld();
return;
}
if (menuCurrent.previous != null)
{
menuCurrent.cursor = 0;
setMenu(menuCurrent.previous);
}
}
// If the menu option has been successfully changed
if (option_changed)
{
updateMenuDrawPoints();
}
}
private void updateMenuDrawPoints()
{
if (menuCurrent.type == Menu.MENU_FORM)
{
menuDrawStart = menuCurrent.cursor;
menuDrawEnd = Math.min(menuDrawStart + FORM_MAX_LINES, menuCurrent.length());
}
else
{
menuDrawStart = Math.max(0, menuCurrent.cursor - (menuOptions >> 1));
menuDrawEnd = menuDrawStart + menuOptions;
if (menuDrawEnd >= menuCurrent.length())
{
menuDrawEnd = menuCurrent.length();
menuDrawStart = Math.max(0, menuDrawEnd - menuOptions);
}
}
}
/**
* Perform a menu action
*
* @param menu Menu from which action originates
* @param cursor Position of item in menu
*/
private void doMenuAction(Menu menu, int cursor)
{
// Reference to item
String item = null;
if (menu.type != Menu.MENU_STAGE_SELECT)
item = menu.text[cursor];
// ----------------------------------------------------------------------------------------
// Main menu actions
// ----------------------------------------------------------------------------------------
if (menu == menuMain)
{
if (item == text[Text.STAGE_SELECT])
setMenu(menuStageSelect);
//#ifdef GLU_STANDARDS
else if (item == Engine.text[Text.START_TRIAL] )
setMenu(menuStageSelect);
else if (item == Engine.text[Text.GET_THE_GAME] ) {
//if (GluGMGDemo.mDemo==2) {
GluGMGDemo.platRequest(GluGMGDemo.mDemoURL);
exit();
//} else {
//setMenu(createForm(GluGMGDemo.getText(GluGMGDemo.STRING_GET_THE_GAME), GluGMGDemo.STRING_GMG_NOBROWSE_MSG[0], menuCurrent, null));
//}
}
else if (item == Engine.text[Text.GMG] ) {
if (GluGMGDemo.mUpsell==2) {
// Standard.menuMoreGameSelected();//modify 2009-2-16 by qihaidong
// exit();
// GluGMGDemo.platRequest(GluGMGDemo.mUpsellURL);
// exit();
setMenu(menuMoreGame);
} else {
setMenu(createForm( Engine.text[Text.GMG], Engine.text[Text.GMG_NOBROWSE_MSG], menuCurrent, null));
}
}
//#endif
else if (item == text[Text.HOW_TO_PLAY])
setMenu(menuHowToPlay);
else if (item == text[Text.SETTINGS])
setMenu(menuSettings);
else if (item == text[Text.ABOUT])
{
// Extract Midlet version number and insert in About Text
String version = getJadValue( "MIDlet-Version" );
if (version == null) version = "?";
String midletName = getJadValue("MIDlet-Name");
if (midletName == null) midletName = "?";
setMenu(createForm(text[Text.ABOUT], getText(Text.ABOUT_TEXT, new String[]{midletName, version}), menu, null));
}
// else if (item == text[Text.EXIT])
// setMenu(menuExit);
// else if (item == text[Text.MAIN_MENU_2])
// {
// setDemoOver();
// }
// // Test the InputString class
// else if (item == text[Text.MAIN_MENU_3])
// {
// InputString.initInputString(null);
// state = GS_INPUT;
// }
//
// else if (item == text[Text.MAIN_MENU_4])
// {
// // If score uploading enabled, display scores menu
// if (ONLINE_SCORES && uploadEnabled)
// {
// setMenu(menuScores);
// }
// // Otherwise just display local score table
// else
// {
// // code to display local score table
// }
//
// }
//
// else if (item == text[Text.MAIN_MENU_5])
// {
// setMenu(menuSettings);
// }
// else if (item == text[Text.MAIN_MENU_7])
// {
// setMenu(menuExit);
// }
//
// if (UPSELL)
// {
// if (item == text[Text.UPSELL_MENU_ITEM])
// {
// setMenu(menuUpsell);
// }
// }
}
else if (menu == menuStageSelect)
{
int menuCursor = menuCurrent.cursor;
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0) {
menuCursor = 0;
GluGMGDemo.demoQuit = false;
}
//#endif
switch (menuCursor) {
case 0:
case 1:
initGameWorld(0, menuCursor);
break;
case 2:
case 3:
case 4:
initGameWorld(1, menuCursor - 2);
break;
case 5:
initGameWorld(2, 0);
break;
};
//initGameWorld(menuCursor / ACTS_PER_ZONE, menuCursor % ACTS_PER_ZONE);
}
// ----------------------------------------------------------------------------------------
// Settings menu actions
// ----------------------------------------------------------------------------------------
else if (menu == menuSettings || menu == menuIngame || menu == menuInGameSettings)
{
if ( item == text[Text.SOUND_OFF + Engine.soundOn] )
{
if ( ++soundOn > SOUND_LOUD ) {
soundOn = SOUND_OFF;
//#if BASE_7210
//# if (menu != menuInGameSettings)
//# {
soundFunction(Engine.SOUND_STOP);
//# }
//#endif
}
else
{
// if (menu != menuInGameSettings)
// {
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
// }
}
//#if BASE_7210
//#else
DeviceSound.volumeChanged();
//#endif
menu.updateItem(text[Text.SOUND_OFF + Engine.soundOn]);
}
// Switch Vibration on
else if (item == text[Text.VIBRATE_OFF])
{
vibrateOn = true;
menu.updateItem(text[Text.VIBRATE_ON]);
// if (menu != menuInGameSettings)
// {
vibrate(250);
// }
}
// Switch Vibration off
else if (item == text[Text.VIBRATE_ON])
{
vibrateOn = false;
menu.updateItem(text[Text.VIBRATE_OFF]);
}
else if (item == text[Text.BACK_TO_TITLE])
{
setMenu(menuBackToMenuConfirmation);
menuCurrent.cursor = menuCursor = 0;
}
else if (item == text[Text.SETTINGS])
{
setMenu(menuInGameSettings); // in game settings menu
}
else if (item == text[Text.HOW_TO_PLAY])
{
setMenu(menuInGameHowToPlay);//2010-05-25 by qihaidong
}
else if (item == text[Text.RESUME])
{
returnToGameWorld();
return;
}
}
else if (menu == menuBackToMenuConfirmation)
{
if (item == text[Text.YES])
{
//#ifdef SLOW_LOAD_SOUND
//# state = GS_LOADING;
//# doRepaint();
//#endif
GameWorld.abandonCurrentGame();
GameWorld.unloadResources(GameWorld.UNLOAD_FULL);
loadMenuResources();
//#ifdef GLU_STANDARDS
if (GluGMGDemo.mDemo > 0) {
GluGMGDemo.demoQuit = true;
text[Text.EXIT] = Engine.text[Text.EXIT2];
setDemoOver();
} else
//#endif
{
setMenu(menuMain);
soundFunction(SOUND_PLAY, BGM_MAINTITLE);
}
ingamemenu = false;
}
else
{
setMenu(menuIngame);
}
}
// ----------------------------------------------------------------------------------------
// Online score menu actions
// ----------------------------------------------------------------------------------------
/*else if (ONLINE_SCORES && menu == menuScores)
{
if (item == text[Text.LOCAL_SCORES])
{
}
else if (item == text[Text.ONLINE_SCORES])
{
if (scoresDownloaded)
{
setMenu(createForm(text[Text.ONLINE_SCORES], onlineNames, menuScores, null));
}
else
{
initScoreConnector(REQUEST_RETURN_TOP_N_SCORES, GAME_NAME, PORTAL_NAME, "", "");
}
}
else if (item == text[Text.UPLOAD_SCORES])
{
if (!scoreUploaded)
{
int score = 12345; // replace with real score
initScoreConnector(REQUEST_UPLOAD_RETURN_TOP_N_SCORES, GAME_NAME, PORTAL_NAME,
uploadName, Integer.toString(score));
}
else
{
setMenu(createForm(text[Text.ONLINE_SCORES], text[Text.SCORE_ALREADY_UPLOADED], menuScores, null));
}
}
}*/
// ----------------------------------------------------------------------------------------
// Exit menu confirmation actions
// ----------------------------------------------------------------------------------------
else if (menu == menuExit)
{
if (item == text[Text.YES])
{
soundFunction(SOUND_STOP);
state = GS_EXIT;//modify 2009-2-18 by qihaidong
}
else if (item == text[Text.NO])
{
setMenu(menuMain);
}
}
else if(menu == menuMoreGame){
if (item == text[Text.YES])
{
Standard.menuMoreGameSelected();
exit();
}
else if (item == text[Text.NO])
{
setMenu(menuMain);
}
}
// ----------------------------------------------------------------------------------------
// Sound enable confirmation actions
// ----------------------------------------------------------------------------------------
// else if (menu == menuSound)
// {
// if (item == text[Text.SOUND_ON])
// {
// soundOn = true;
//
// initSettingsMenu(); // Rebuild settings menu
//
// setBrand();
// }
// else if (item == text[Text.SOUND_OFF])
// {
// soundOn = false;
// initSettingsMenu(); // Rebuild settings menu
//
// setBrand();
// }
// }
}
/* --------------------------------------------------------------------------------------------
Form Handling (basically a wrapper for menu)
[1] just use setMenu(createForm(....));
[2] Or you can do
Menu form = createForm(....)
and then handle like a menu, catching in doMenuAction()
* --------------------------------------------------------------------------------------------*/
private static Menu createForm(String title, String text, Menu prevMenu, Menu nextMenu)
{
Menu form = new Menu(title, getStrings(text, SCREEN_WIDTH - MENU_PADDING, FONT_2), Menu.MENU_FORM);
form.previous = prevMenu;
form.next = nextMenu;
return form;
}
//#endif
/* --------------------------------------------------------------------------------------------
Command Handling
* --------------------------------------------------------------------------------------------*/
public void commandAction(Command c, Displayable s)
{
if (USE_COMMANDS)
{
if (c == commandSoft1)
{
keyLatch |= reverseTooltips ? K_SOFT_BACK : K_SOFT_SELECT;
}
else if (c == commandSoft2)
{
keyLatch |= reverseTooltips ? K_SOFT_SELECT : K_SOFT_BACK;
}
}
}
/* --------------------------------------------------------------------------------------------
RMS
* --------------------------------------------------------------------------------------------*/
/** Count how many times game has been run */
private static int runCount;
//#if !HI_ADD
/** Name of record store to create */
public final static String RMS_NAME = "SONIC";
/** Slots to create in RMS */
public final static int RMS_SETTINGS = 0;
public void loadRMS(int slot)
{
String rms_name = RMS_NAME;
int slot_id = slot;
// use multiple record stores
if (USE_ALTERNATE_RMS_METHOD)
{
rms_name += slot;
slot = 0;
}
try
{
RecordStore config_store = RecordStore.openRecordStore(rms_name, true); // creates if necessary
// Check RMS exists
if (config_store.getNumRecords() > slot)
{
byte[] inBytes = config_store.getRecord(slot + 1);
ByteArrayInputStream in = new ByteArrayInputStream(inBytes);
DataInputStream inData = new DataInputStream(in);
// ---- Read Settings -----------------------------------
if (slot_id == RMS_SETTINGS)
{
runCount = inData.readInt();
soundOn = inData.readInt();
vibrateOn = inData.readBoolean();
}
// ------------------------------------------------------
inData.close();
in.close();
}
config_store.closeRecordStore();
}
catch (Exception e)
{
if (DEBUG) System.out.println("loadRMS("+slot+") :: "+e);
}
}
public static boolean saveRMS(int slot)
{
String rms_name = RMS_NAME;
int slot_id = slot;
// use multiple record stores
if (USE_ALTERNATE_RMS_METHOD)
{
rms_name += slot;
slot = 0;
deleteRMS(rms_name);
}
try
{
RecordStore config_store = RecordStore.openRecordStore(rms_name, true);
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream outData = new DataOutputStream(out);
// ---- Write Settings ----------------------------------
if (slot_id == RMS_SETTINGS)
{
outData.writeInt(runCount);
outData.writeInt(soundOn);
outData.writeBoolean(vibrateOn);
}
// ------------------------------------------------------
byte[] toStorage = out.toByteArray();
outData.close();
out.close();
if (config_store.getNumRecords() <= slot)
config_store.addRecord(toStorage, 0, toStorage.length);
else
config_store.setRecord(slot + 1, toStorage, 0, toStorage.length);
config_store.closeRecordStore();
}
catch (Exception e)
{
if (DEBUG) System.out.println("saveRMS("+slot+") :: "+e);
return false;
}
return true;
}
private static void deleteRMS(String rms_name)
{
try
{
RecordStore.deleteRecordStore(rms_name);
}
catch (Exception e)
{
if (DEBUG)
System.out.println("deleteRMS("+rms_name+") :: "+e);
}
}
/*
* --------------------------------------------------------------------------------------------
* Localised String Handling
* --------------------------------------------------------------------------------------------
*/
/** Holds localised text strings for game */
public static String text[];
//#ifdef _en_
//# private static final String _mloading = "LOADING...";
//#elifdef _fr_
//# private static final String _mloading = "CHARGEMENT...";
//#elifdef _de_
//# private static final String _mloading = "L DT...";
//#elifdef _it_
//# private static final String _mloading = "CARICAMENTO...";
//#elifdef _es_
//# private static final String _mloading = "CARGANDO...";
//#else
//EN, FR, IT, DE, ES
final String[] _mloading = {
"读取中...",
"Chargement...",
"Caricamento...",
"Ladevorgang...",
"Cargando...",
"A carregar..."
};
//#endif
public static void initText(String resourceName)
{
try
{
InputStream is = null;
DataInputStream dis = null;
is = instance.getClass().getResourceAsStream(resourceName);
dis = new DataInputStream(is);
text = new String[dis.readInt()];
for (int i = 0; i < text.length; i++)
text[i] = dis.readUTF();
}
catch (Exception e)
{
trace2="initText["+resourceName+" : " + e.toString()+"]";
debugWrite(trace2,false);
if (DEBUG)
System.out.println("initText(" + resourceName + ") :: " + e);
}
}
public static String getText(int textId)
{
if (textId < text.length)
return text[textId];
else
return ("No text: " + textId);
}
public static String getText(int textId, String[] values)
{
String str = new String(getText(textId));
if (values.length == 1)
str = replaceText(str, "%U", values[0]);
else
for (int i = 0; i < values.length; i++)
str = replaceText(str, "%U", values[i]);
return str;
}
public static String replaceText(String source, String replace, String by)
{
String returnString = "";
int place = 0;
place = source.indexOf(replace);
if (place != -1)
returnString = source.substring(0, place) + by + source.substring(place + replace.length());
else
returnString = source;
return returnString;
}
/* --------------------------------------------------------------------------------------------
String splitting
* --------------------------------------------------------------------------------------------*/
public static String[] getStrings(String textString, int lineLength, int fontIndex)
{
Vector strings = new Vector();
int curWordIndex = 0;
int curLineLength = 0;
int textEndIndex = textString.length();
String stringToDraw = null, prevString;
while (true)
{
int newWordIndex = curWordIndex;
//int newLineIndex = textString.indexOf('\n', newWordIndex);
int newLineIndex = textString.indexOf('|', newWordIndex); // XXX Jens: new end line character
int prevWordIndex;
while (true)
{
prevWordIndex = newWordIndex;
prevString = stringToDraw;
// get the next word index
newWordIndex = getWordIndex(textString, newWordIndex);
if (newLineIndex > -1 && newLineIndex < newWordIndex)
newWordIndex = newLineIndex;
stringToDraw = textString.substring(curWordIndex, newWordIndex).trim();
if (FontMgr.stringWidth(fontIndex, stringToDraw) > lineLength)
{
if (prevWordIndex == curWordIndex)
{
// first word of the line is longer than the line length
// make the text wrap here
for (int i = stringToDraw.length() - 1; i > 0; i--)
{
String newString = stringToDraw.substring(0, i);
if (FontMgr.stringWidth(fontIndex, newString) <= lineLength)
{
// the newString fits the line length
newWordIndex = prevWordIndex + i;
stringToDraw = newString;
break;
}
}
}
else
{
newWordIndex = prevWordIndex;
stringToDraw = prevString;
}
break;
}
else if (newWordIndex == newLineIndex)
{
newWordIndex++;
break;
}
else if (newWordIndex >= textEndIndex)
break;
}
strings.addElement(stringToDraw);
curWordIndex = newWordIndex;
if (curWordIndex >= textEndIndex)
break;
}
String[] stringsToDraw = new String[strings.size()];
strings.copyInto(stringsToDraw);
return stringsToDraw;
}
private static int getWordIndex(String srcString, int fromIndex)
{
int curChar = srcString.charAt(fromIndex);
// if the first character is a word, return it
if (charIsWord(curChar))
return fromIndex + 1;
int toIndex = 0;
// get rid of the spaces in the front
while (true)
{
int spaceIndex = srcString.indexOf(' ', fromIndex);
if (spaceIndex == 0)
fromIndex++;
else
{
toIndex = spaceIndex;
break;
}
}
if (toIndex == -1)
toIndex = srcString.length();
else
toIndex++;
for (int i = fromIndex + 1; i < toIndex; i++)
{
if (charIsWord(srcString.charAt(i)))
return i;
}
// else a word is right up to the space character
return toIndex;
}
private static boolean charIsWord(int theChar)
{
return ((theChar >= 0x002E80 && theChar < 0x00AC00)
|| (theChar >= 0x00F900 && theChar < 0x00FB00)
|| (theChar >= 0x00FF00 && theChar < 0x00FFE0));
}
//#endif
/* --------------------------------------------------------------------------------------------
Get Value of a JAD Parameter
* --------------------------------------------------------------------------------------------*/
public static String getJadValue(String param)
{
String s = parent.getAppProperty( param );
return s != null ? s.trim() : null;
}
/* --------------------------------------------------------------------------------------------
Random Number Generation
* --------------------------------------------------------------------------------------------*/
/**
* Generate a random integer.
*
* @param range Generate random numbers from 0 to range.
* A range of 4 would generate numbers between -3 and 3.
*
* @return Random Positive Integer within range.
*/
public static int rnd(int range)
{
return random.nextInt() % range;
}
/**
* Generate a random positive integer.
*
* @param range Generate random numbers from 0 to range.
* A range of 4 would generate numbers between 0 and 3.
*
* @return Random Positive Integer within range.
*/
public static int rndPositive(int range)
{
return Math.abs(random.nextInt() % range);
}
/* --------------------------------------------------------------------------------------------
Debugging
To use the debugging facilities, enable the 'DEBUG' boolean.
Then call debugWrite to paint a message to the screen.
You can also ammend Engine.trace to store the section of code you are in. For example:
public void someMethod()
{
Engine.trace = "someMethod Start";
// Insert method code here
Engine.trace = "someMethod End";
}
This code is compiled out if DEBUG is set to false
* --------------------------------------------------------------------------------------------*/
public static void paintString(String s, Graphics g, int x, int y, int col)
{
if (DEBUG)
{
paintString(s, g, x, y, col, Graphics.TOP | Graphics.LEFT);
}
}
public static void paintString(String s, Graphics g, int x, int y, int col, int anchor)
{
if (DEBUG)
{
g.setColor(col);
//int clipX = g.getClipX(), clipY = g.getClipY(), clipW = g.getClipWidth(), clipH = g.getClipHeight();
//g.setClip(0, 0, WIDTH, HEIGHT);
g.drawString(s, x, y, anchor);
//g.setClip(clipX, clipY, clipW, clipH);
}
}
/*
*
* TEXT HANDLING
*
*/
public static void paintString(Graphics g,String s, int x, int y, int align,int color, boolean setfont)
{
if (setfont) {
g.setFont(FONT);
y += FONT_OFFSET;
}
g.setColor(color);
g.drawString(s,x,y,align);
}
public static void paintString(Graphics g,String s, int x, int y, int align,int color)
{
paintString(g,s,x,y,align,color,true);
}
//#if !HI_ADD
public static void paintBorderedString(Graphics g,int stringIndex, int x, int y, int align)
{
//System.out.println("paintBorderedString("+stringIndex+","+x+","+y+","+align+")");
paintBorderedString(g,text[stringIndex],x,y,align,COLOR_TEXT,COLOR_TEXT_BORDER);
}
/*public static void paintBorderedString(Graphics g,int stringIndex, int x, int y, int align,int color,int colorBorder)
{
//System.out.println("paintBorderedString("+stringIndex+","+x+","+y+","+align+","+color+","+colorBorder+")");
String s = text[stringIndex];
paintString(g,s,x-1,y,align,colorBorder);
paintString(g,s,x+1,y,align,colorBorder);
paintString(g,s,x,y-1,align,colorBorder);
paintString(g,s,x,y+1,align,colorBorder);
paintString(g,s,x,y,align,color);
}
*/
public static void paintBorderedString(Graphics g,String string, int x, int y, int align)
{
//System.out.println("paintBorderedString("+stringIndex+","+x+","+y+","+align+")");
paintBorderedString(g,string,x,y,align,COLOR_TEXT,COLOR_TEXT_BORDER);
}
public static void paintBorderedString(Graphics g,String s, int x, int y, int align,int color,int colorBorder)
{
//System.out.println("paintBorderedString("+stringIndex+","+x+","+y+","+align+","+color+","+colorBorder+")");
paintString(g,s,x-1,y,align,colorBorder);
paintString(g,s,x+1,y,align,colorBorder);
paintString(g,s,x,y-1,align,colorBorder);
paintString(g,s,x,y+1,align,colorBorder);
paintString(g,s,x,y,align,color);
}
//#if BASE_7210
//#else
public static void paintDropString(Font fnt, Graphics g,String s, int x, int y, int align,int color,int colorDrop)
{
g.setFont(fnt);
paintString(g,s,x+2,y+2,align,colorDrop,false);
paintString(g,s,x+1,y+1,align,COLOR_BACKGROUND,false);
paintString(g,s,x,y,align,color,false);
g.setFont(FONT);
}
//#endif
public static void paintDropString(Graphics g,String s, int x, int y, int align,int color,int colorDrop)
{
//#if BASE_7210
//#else
if (langSelected==4 && menuCurrent==menuBackToMenuConfirmation) {
g.setFont(FONT_NB);
paintString(g,s,x+2,y+2,align,colorDrop,false);
paintString(g,s,x+1,y+1,align,COLOR_BACKGROUND,false);
paintString(g,s,x,y,align,color,false);
g.setFont(FONT);
} else
//#endif
{
paintString(g,s,x+2,y+2,align,colorDrop);
paintString(g,s,x+1,y+1,align,COLOR_BACKGROUND);
paintString(g,s,x,y,align,color);
}
}
//#endif
/** Display debug panel information */
private boolean displayDebugInfo;
/** Stores current debugging information */
public static String trace;
private static int debugMsgTop;
private static String[] debugMsgs;
/**
* Paint debug written with calls to debugWrite(string, boolean)
*/
public static void paintDebug(Graphics g)
{
if (DEBUG)
{
if (debugMsgs == null)
return;
Font prevFont = g.getFont();
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
g.setFont(font);
g.setClip(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
int y = 5;
int p = debugMsgTop;
for (int i = 0; i < debugMsgs.length; ++i)
{
String s = debugMsgs[p];
if (s != null)
{
// g.setColor(COL_WHITE);
// g.fillRect(2, y - 1, font.stringWidth(s) + 2, font.getHeight() + 2);
g.setColor(COL_WHITE);
g.drawString(s, 5, y, Graphics.TOP | Graphics.LEFT);
y += g.getFont().getHeight();
}
if (++p == debugMsgs.length)
p = 0;
}
g.setFont(prevFont);
}
}
/**
* Paint a debug message to the screen
*
* @param forceRepaint set to true if we should force a repaint at this moment
* (normally would be false if in the paint thread)
*/
public static void debugWrite(String msg, boolean forceRepaint)
{
if (DEBUG)
{
if (msg == null) msg = "(null)";
System.out.println("DEBUG> " + msg);
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
if (debugMsgs == null)
debugMsgs = new String[SCREEN_HEIGHT / (font.getHeight() + 2)];
while (msg.length() > 0)
{
// Get the max length string that will fit on the screen
int endPos = 0;
while (endPos < msg.length() && font.stringWidth(msg.substring(0, endPos + 1)) < (SCREEN_WIDTH - 4)) // note: comparisons must be in this order
++endPos;
debugMsgs[debugMsgTop] = msg.substring(0, endPos);
debugMsgTop = (debugMsgTop + 1) % debugMsgs.length;
// Remove this section from the remaining msg to be painted
msg = msg.substring(endPos);
}
// Repaint with debug info only
if (forceRepaint)
doRepaint();
}
}
public static void debugWrite(String s)
{
if (DEBUG)
{
debugWrite(s, false);
}
}
public static void clearDebug()
{
if (DEBUG)
{
debugMsgTop = 0;
debugMsgs = null;
}
}
/**
* Paint timing and memory information to screen. Must also set DEBUG_TIMING
* and press *
*
* @param g
*/
private void paintDebugPanel(Graphics g)
{
int lines = 4;
int y = 0;
int fontHeight = FontMgr.lineHeight[FONT_2];
g.setClip(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
g.setColor(0xd4d0c8);
g.fillRect(0, 0, SCREEN_WIDTH, lines * fontHeight);
g.setColor(COL_BLACK);
FontMgr.drawString(Constants.FONT_2, g, "AVG FPS: "+debugAvgFPS, 0, y, Graphics.TOP | Graphics.LEFT);
y += fontHeight;
FontMgr.drawString(Constants.FONT_2, g, "TICK: "+debugTick, 0, y, Graphics.TOP | Graphics.LEFT);
y += fontHeight;
FontMgr.drawString(Constants.FONT_2, g, "PAINT: "+debugPaint, 0, y, Graphics.TOP | Graphics.LEFT);
y += fontHeight;
FontMgr.drawString(Constants.FONT_2, g, "MEM: "+getFreeMemory(), 0, y, Graphics.TOP | Graphics.LEFT);
}
/** Return the amount of free memory on the device in K */
public static String getFreeMemory()
{
System.gc();
return (Runtime.getRuntime().freeMemory()>>10)+" K";
}
/** Return the total amount of memory that the device has */
public static String getTotalMemory()
{
return (Runtime.getRuntime().totalMemory()>>10)+" K";
}
/* --------------------------------------------------------------------------------------------
* clipping
* --------------------------------------------------------------------------------------------*/
// private static final int MAX_NESTED_CLIPS = 10;
//
// /** x, y, width, height */
// private static int[] clip_stack = new int[MAX_NESTED_CLIPS << 2];
// private static int clip_top = 0;
//
// public static void setClip(Graphics g, int x, int y, int width, int height)
// {
// clip_stack[clip_top] = x;
// clip_stack[clip_top + 1] = y;
// clip_stack[clip_top + 2] = width;
// clip_stack[clip_top + 3] = height;
// clip_top += 4;
//
//// System.out.println("x=" + x + ", y=" + y + ", width=" + width + ", height=" + height);
// g.setClip(x, y, width, height);
// }
//
public static void clipRect(Graphics g, int x, int y, int width, int height)
{
// get the previous clip region
int clipX = g.getClipX(), clipY = g.getClipY(), clipWidth = g.getClipWidth(), clipHeight = g.getClipHeight();
//g.clipRect( drawX, drawY, width, height );
int newClipX = Math.max(x, clipX);
int newClipY = Math.max(y, clipY);
g.setClip( newClipX, newClipY, Math.min(x+width, clipX+clipWidth)-newClipX,
Math.min(y+height, clipY+clipHeight)-newClipY );
}
// int clip_current = clip_top-4;
// int curr_x = clip_stack[clip_current];
// int curr_y = clip_stack[clip_current + 1];
// int curr_width = clip_stack[clip_current + 2];
// int curr_height = clip_stack[clip_current + 3];
//
// int new_x = x;
// if (new_x < curr_x)
// new_x = curr_x;
//
// int new_y = y;
// if (new_y < curr_y)
// new_y = curr_y;
//
// int old_right = curr_x + curr_width;
// int new_right = x + width;
// if (new_right > old_right)
// new_right = old_right;
// width = new_right - new_x;
//
// int old_bottom = curr_y + curr_height;
// int new_bottom = y + height;
// if (new_bottom > old_bottom)
// new_bottom = old_bottom;
// height = new_bottom - new_y;
//
//// if (width < 0)
//// width = 0;
//// if (height < 0)
//// height = 0;
//
// // inline call to setClip()
// clip_stack[clip_top] = new_x;
// clip_stack[clip_top + 1] = new_y;
// clip_stack[clip_top + 2] = width;
// clip_stack[clip_top + 3] = height;
// clip_top += 4;
//
//// System.out.println("new_x=" + new_x + ", new_y=" + new_y + ", width=" + width + ", height=" + height);
// g.setClip(new_x, new_y, width, height);
// }
//
// public static void popClip(Graphics g)
// {
// if (clip_top > 4)
// {
// clip_top -= 8;
// g.setClip(clip_stack[clip_top],
// clip_stack[clip_top + 1],
// clip_stack[clip_top + 2],
// clip_stack[clip_top + 3]);
// clip_top += 4;
// }
// else
// {
//// System.out.println("full");
// g.setClip(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
// clip_top = 0;
// }
// }
//
// public static void popClip()
// {
// if (clip_top > 4)
// clip_top -= 4;
// else
// clip_top = 0;
// }
//
// public static void realiseClip(Graphics g)
// {
// int clip_current = clip_top-4;
// int curr_x = clip_stack[clip_current];
// int curr_y = clip_stack[clip_current + 1];
// int curr_width = clip_stack[clip_current + 2];
// int curr_height = clip_stack[clip_current + 3];
//
//// System.out.println("curr_x=" + curr_x + ", curr_y=" + curr_y + ", curr_width=" + curr_width + ", curr_height=" + curr_height);
// g.setClip(curr_x, curr_y, curr_width, curr_height);
// }
//
// public static void resetClip(Graphics g)
// {
// clip_top = 0;
// setClip(g, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
//// System.out.println("reset");
// }
/* --------------------------------------------------------------------------------------------
Key press handling and control
isPressed(KEY_DOWN) - Down key is currently held
key(KEY_DOWN) - Down key has been pressed (may not still be pressed)
Using the second option is clearly the way to go for fire buttons, so that the key press
is always dealt with
* --------------------------------------------------------------------------------------------*/
/** Keys Currently Pressed */
private static int keysPressed;
/** Keys that have been pressed (stored until buffer is cleared) */
public static int keyLatch;
/** Unmapped last key */
public static int keyUnmapped;
public static boolean isPressed(int key)
{
return ((keysPressed & key) != 0);
}
public static boolean key(int key)
{
if ((keyLatch & key) != 0)
{
keyLatch = 0;
return true;
}
return false;
}
public static void releaseKey(int key)
{
keyLatch = keyLatch & ~key;
}
public static boolean hasAnyKeyPressed()
{
if (keyLatch != 0)
{
keyLatch = 0;
return true;
}
return false;
}
/** Clear all stored key presses */
public static void resetKeyBuffers()
{
keyUnmapped = 0;
keyLatch = 0;
}
public synchronized void keyPressed(int key)
{
// Engine.debugWrite("key " + key);
try
{
if ( DEBUG_STEP_BY_STEP )
{
if ( key == KEY_STAR )
{
debugStepByStep_stopped = false;
debugStepByStep_stopOnNextFrame = true;
return;
}
if ( key == KEY_POUND )
{
debugStepByStep_stopped = false;
return;
}
}
int mapping = getKeyMap(key);
keysPressed |= mapping;
keyLatch |= mapping;
keyUnmapped = key;
}
catch (Exception e)
{
if (DEBUG)
{
e.printStackTrace();
debugWrite("Ex in keyPressed: " +e.toString(), true);
}
}
}
public synchronized void keyReleased(int key)
{
try
{
int mapping = getKeyMap(key);
keysPressed &=~ mapping;
}
catch (Exception e)
{
if (DEBUG)
{
e.printStackTrace();
}
}
clearKey();
}
public static void doRepaint()
{
if (!Device.FAKE_SERVICE_REPAINTS)
{
instance.repaint();
instance.serviceRepaints();
}
else
{
// isPainting set false at end of paint method
isPainting = true;
instance.repaint();
instance.serviceRepaints();
// Wait for the repaint() to conclude before continuning execution
while (isPainting)
{
Thread.yield();
}
}
}
public static long gameSuspendedTimeMillis;
public static void handleEvent()
{
handleEvent = false;
// if (state == GS_COMMUNICATING) return;
// Reset key presses
resetKeyBuffers();
keysPressed = 0;
// ...
// if (!ingamemenu)
// gameSuspendedTimeMillis = System.currentTimeMillis();
// Stick in any other generic code that should happen across devices when
// receiving a call here
if (EVENT != EVENT_NONE)
{
if (EVENT == EVENT_SHOW_PAUSE_SCREEN)
{
if (state != GS_PAUSE)
{
soundFunction(SOUND_STOP);
// Language text must be initialized before we can do this
//#if !HI_ADD
if (text != null)
//#endif
{
pauseState = state;
state = GS_PAUSE;
}
}
}
if (EVENT == EVENT_FORCE_SOUND)
{
soundFunction(SOUND_STOP);
//resumeSound = true;
}
}
}
/**
* Insert a new palette into a PNG file.
* Use the ExtractPLTE tool to extract the chunk.
* The chunk must contain the checksum and length information.
*
* @param pngData PNG bytes
* @param plte PLTE Chunk
*
* @return New PNG file
*
* @author chris.white@glu.com
* @version 1.0
*/
public static byte[] insertPLTE(byte[] pngData, byte[] plte)
{
// Default Index of PLTE Palette Data
int plteIndex = 37;
// Search for PLTE Header in original file
for (int i = 0; i < pngData.length-4; i++)
{
if (pngData[i] == 'P' &&
pngData[i+1] == 'L' &&
pngData[i+2] == 'T' &&
pngData[i+3] == 'E')
{
plteIndex = i;
break;
}
}
int lengthIndex = plteIndex - 4;
// Find PLTE length in original file
int oldPltLength =
(((pngData[lengthIndex] & 0xFF) << 24)
| ((pngData[lengthIndex + 1] & 0xFF) << 16)
| ((pngData[lengthIndex + 2] & 0xFF) << 8)
| (pngData[lengthIndex + 3] & 0xFF))
& 0xFFFFFFFF;
oldPltLength += 12; // include PLTE header, length info and CRC info
// So dataIndex is our start point and dataIndex + pltLength is end point
byte[] pngNew = new byte[pngData.length - oldPltLength + plte.length];
// Copy start of original PNG file across
System.arraycopy(pngData, 0, pngNew, 0, lengthIndex);
// Copy new PLTE Chunk across
System.arraycopy(plte, 0, pngNew, lengthIndex, plte.length);
// Copy end of original PNG file across
System.arraycopy(pngData, (lengthIndex + oldPltLength), // end of first palette
pngNew, (lengthIndex + plte.length), pngData.length - (lengthIndex + oldPltLength));
return pngNew;
}
// /**
// * loads a sprite file
// *
// * @return DeviceImage[] the individual frame of images defined in the sprite definition file
// */
// public static DeviceImage[] loadSprite(int spriteId, int unsplitImgId, int firstSplitImgId) throws Exception
// {
// // load the sprite property file
// byte[] spriteData = ResourceMaster.getResourceAsBytes(spriteId);
//
//// for (int i = 0; i < spriteData.length; i++)
//// {
//// byte b = spriteData[i];
//// System.out.println("b = " + (b&0xff));
//// }
//
// int ptr = 0;
// int numFrames = spriteData[ptr++] & 0xff;
//
// int frameWidth = spriteData[ptr++];
// int frameHeight = spriteData[ptr++];
//
// DeviceImage[] spriteImages = new DeviceImage[numFrames];
//
// if (unsplitImgId != -1)
// {
// // all frames are in one image file
//
// DeviceImage sheetImage = new DeviceImage(unsplitImgId, "unsplit image for SpriteID " + spriteId);
//
// int frameIndex = 0;
// for (int i = 0; i < numFrames; ++i)
// {
// int x = spriteData[ptr++] & 0xff;
// int y = spriteData[ptr++] & 0xff;
// int w = spriteData[ptr++] & 0xff;
// int h = spriteData[ptr++] & 0xff;
// byte offset_x = spriteData[ptr++];
// byte offset_y = spriteData[ptr++];
// //byte manipulation = spriteData[ptr++];
//
// DeviceImage frame = new DeviceImage(sheetImage, x, y, w, h, true);//, manipulation);
//
// frame.offset_x = offset_x;
// frame.offset_y = offset_y;
//
// spriteImages[frameIndex++] = frame;
//
//// System.out.println("x=" + x + ", y=" + y + ", w=" + w + ", h=" + h + ", offset_x=" + offset_x + ", offset_y=" + offset_y);// + ", manipulation=" + manipulation);
// }
// }
// else
// {
// // each frame image is in its own file
//
// int frameIndex = 0;
// for (int i = 0; i < numFrames; ++i)
// {
// ptr += 2; // skip x, y
// int w = spriteData[ptr++] & 0xff;
// int h = spriteData[ptr++] & 0xff;
// byte offset_x = spriteData[ptr++];
// byte offset_y = spriteData[ptr++];
//// byte manipulation = spriteData[ptr++];
//
// DeviceImage frame = new DeviceImage(firstSplitImgId + i, "split image " + i + " for SpriteID " + spriteId);//, manipulation);
//
// frame.offset_x = offset_x;
// frame.offset_y = offset_y;
//
// spriteImages[frameIndex++] = frame;
// }
// }
//
// return spriteImages;
// }
//
// public static byte[][] loadAnimationSet(int resourceId, DeviceImage[] spriteImages)
// {
// try
// {
// byte[] animationData = ResourceMaster.getResourceAsBytes(resourceId);
// int ptr = 0;
//
// int animationCount = animationData[ptr++];
////System.out.println("animationCount = " + animationCount);
// byte[][] animations = new byte[animationCount][];
//
// for (int animIx = 0; animIx < animationCount; ++animIx)
// {
// int animationId = animationData[ptr++];
// int frameCount = animationData[ptr++];
//
// animations[animationId] = new byte[frameCount];
// for (int frameIx = 0; frameIx < frameCount; ++frameIx)
// {
//// System.out.println("animIx=" + animIx + ", frameIx=" + frameIx + ", animationId=" + animationId + ", frameCount=" + frameCount);
//
// byte frameIndex = animationData[ptr++];
// byte manipulation = animationData[ptr++];
//
// animations[animationId][frameIx] = frameIndex;
//
//// if (frameIndex < spriteImages.length)
//// spriteImages[frameIndex].manipulation = manipulation;
//// else
//// System.out.println("couldn't set manipulation for sprite
//
// //System.out.println("animations["+animationId+"]["+frameIx+"] = " + animations[animationId][frameIx]);
// }
// }
// return animations;
// }
// catch (Exception e)
// {
// System.out.println("loadAnimationSet("+resourceId+")");
// e.printStackTrace();
// }
// return null;
// }
/**
* returns an array of images, used for example for loading a tileset without any animations
*/
public static DeviceImage[] loadNonAnimatedSprite(int spriteFileId, int framesFileId,
int unsplitImgId, int firstSplitImgId) throws Exception
{
return (DeviceImage[]) loadSprite(spriteFileId, framesFileId, unsplitImgId, firstSplitImgId, false);
}
/**
* returns an array of images, used for example for loading a tileset without any animations
*/
public static DeviceImage[] loadNonAnimatedSprite(int spriteFileId, int framesFileId,
int unsplitImgId, int firstSplitImgId, int paletteId) throws Exception
{
return (DeviceImage[]) loadSprite(spriteFileId, framesFileId, unsplitImgId, firstSplitImgId, paletteId, false);
}
/**
* returns a 2D array of images, used for example for loading Sonic's animation frames
*/
public static DeviceImage[][] loadSprite(int spriteFileId, int framesFileId,
int unsplitImgId, int firstSplitImgId) throws Exception
{
return (DeviceImage[][]) loadSprite(spriteFileId, framesFileId, unsplitImgId, firstSplitImgId, true);
}
/**
* returns either a 1D array of images or a 2D array of images. If framesFileId only contains single-frame animation
* data, multipleFrames may be set to false and a 1D array will be returned. Otherwise it's 2D.
*/
public static Object loadSprite(int spriteFileId, int framesFileId,
int unsplitImgId, int firstSplitImgId, boolean multipleFrames) throws Exception
{
return loadSprite( spriteFileId, framesFileId, unsplitImgId, firstSplitImgId, -1, multipleFrames );
}
/**
* returns either a 1D array of images or a 2D array of images. If framesFileId only contains single-frame animation
* data, multipleFrames may be set to false and a 1D array will be returned. Otherwise it's 2D.
*/
public static Object loadSprite(int spriteFileId, int framesFileId,
int unsplitImgId, int firstSplitImgId, int paletteId, boolean multipleFrames) throws Exception
{
//System.out.println("xxloadSprite("+(spriteFileId&0xffff)+", "+(framesFileId&0xffff)+")");
Object animationImagesObject = null;
try
{
//
// Read in the images
//
// load the sprite property file
byte[] spriteData = ResourceMaster.getResourceAsBytes(spriteFileId);
byte[] animationData = ResourceMaster.getResourceAsBytes(framesFileId);
int ptr = 0;
int numFrames = spriteData[ptr++] & 0xff;
//#if TILES==32
int frameWidth = spriteData[ptr++]<<1;
int frameHeight = spriteData[ptr++]<<1;
//#else
//# int frameWidth = spriteData[ptr++];
//# int frameHeight = spriteData[ptr++];
//#endif
DeviceImage[] spriteImages = new DeviceImage[numFrames];
if (unsplitImgId != -1)
{
// all frames are in one image file
DeviceImage sheetImage = new DeviceImage(unsplitImgId, paletteId, "unsplit image for SpriteID " + spriteFileId);
int frameIndex = 0;
for (int i = 0; i < numFrames; ++i)
{
//#if TILES==32
int x = (spriteData[ptr++] & 0xff)<<1;
int y = (spriteData[ptr++] & 0xff)<<1;
int w = (spriteData[ptr++] & 0xff)<<1;
int h = (spriteData[ptr++] & 0xff)<<1;
int offset_xi = spriteData[ptr++]<<1;
int offset_yi = spriteData[ptr++]<<1;
byte offset_x = (byte) offset_xi;
byte offset_y = (byte) offset_yi;
//#else
//# int x = spriteData[ptr++] & 0xff;
//# int y = spriteData[ptr++] & 0xff;
//# int w = spriteData[ptr++] & 0xff;
//# int h = spriteData[ptr++] & 0xff;
//# byte offset_x = spriteData[ptr++];
//# byte offset_y = spriteData[ptr++];
//#endif
DeviceImage frame = new DeviceImage(sheetImage, x, y, w, h, true);//, manipulation);
frame.offset_x = offset_x;
frame.offset_y = offset_y;
frame.frameWidth = (byte) frameWidth;
frame.frameHeight = (byte) frameHeight;
spriteImages[frameIndex++] = frame;
//System.out.println("x=" + x + ", y=" + y + ", w=" + w + ", h=" + h + ", offset_x=" + offset_x + ", offset_y=" + offset_y);// + ", manipulation=" + manipulation);
}
}
else
{
// each frame image is in its own file
int frameIndex = 0;
for (int i = 0; i < numFrames; ++i)
{
ptr += 4; // skip x, y, w, h
byte offset_x = spriteData[ptr++];
byte offset_y = spriteData[ptr++];
DeviceImage frame = new DeviceImage(firstSplitImgId + i, paletteId, "split image " + i + " for SpriteID " + spriteFileId);//, manipulation);
frame.offset_x = offset_x;
frame.offset_y = offset_y;
frame.frameWidth = (byte) frameWidth;
frame.frameHeight = (byte) frameHeight;
spriteImages[frameIndex++] = frame;
}
}
//
// Read in the animationFrames and frames
//
ptr = 0;
int animationCount = animationData[ptr++];
//System.out.println("reading animationFrames animationCount = " + animationCount);
byte[][] animationFrames = new byte[animationCount][];
for (int animIx = 0; animIx < animationCount; ++animIx)
{
int animationId = animationData[ptr++];
int frameCount = animationData[ptr++];
if (frameCount != 1 && !multipleFrames)
{
throw new Exception("\"frameCount != 1 && !multipleFrames\" in Engine.loadSprite frames file ("+framesFileId+")");
}
animationFrames[animationId] = new byte[frameCount << 1]; // frame, manipulation
for (int frameIx = 0; frameIx < frameCount; ++frameIx)
{
//System.out.println("animIx=" + animIx + ", frameIx=" + frameIx + ", animationId=" + animationId + ", frameCount=" + frameCount);
byte frameIndex = animationData[ptr++];
byte manipulation = animationData[ptr++];
animationFrames[animationId][frameIx << 1] = frameIndex;
animationFrames[animationId][(frameIx << 1) + 1] = manipulation;
//System.out.println("animationFrames["+animationId+"]["+frameIx+"] = " + animationFrames[animationId][frameIx]);
}
}
if (multipleFrames)
{
//
// Create an array that looks like this: images[fish|crab etc][frameIx]
//
DeviceImage[][] animationImages = new DeviceImage[animationCount][];
for (int animationIx = 0; animationIx < animationCount; ++animationIx)
{
//System.out.println("creating DeviceImage array animationIx="+animationIx);
int frameCount = animationFrames[animationIx].length >> 1; // frame,manipulation so half
animationImages[animationIx] = new DeviceImage[frameCount];
int pos = 0;
for (int frameIx = 0; frameIx < frameCount; ++frameIx)
{
//System.out.println("assigning device image " + frameIx);
int spriteImagePtr = animationFrames[animationIx][pos++];
int manipulation = animationFrames[animationIx][pos++];
if (manipulation == 0)
animationImages[animationIx][frameIx] = spriteImages[spriteImagePtr];
else
animationImages[animationIx][frameIx] = new DeviceImage(spriteImages[spriteImagePtr], manipulation);
}
}
animationImagesObject = animationImages;
}
else
{
//
// Create an array that looks like this: images[tile 1|tile 2 etc]
//
DeviceImage[] animationImages = new DeviceImage[animationCount];
for (int animationIx = 0; animationIx < animationCount; ++animationIx)
{
int pos = 0;
int spriteImagePtr = animationFrames[animationIx][pos++];
int manipulation = animationFrames[animationIx][pos++];
if (manipulation == 0)
{
animationImages[animationIx] = spriteImages[spriteImagePtr];
}
else
{
animationImages[animationIx] = new DeviceImage(spriteImages[spriteImagePtr], manipulation);
}
}
animationImagesObject = animationImages;
}
}
catch (Exception e)
{
System.out.println("Exception in loadSprite(spriteFileId="+(spriteFileId&0xffff)+", framesFileId="+(framesFileId&0xffff)+
", unSplitImgId="+(unsplitImgId&0xffff)+", firstSplitImgId="+(firstSplitImgId&0xffff)+")");
e.printStackTrace();
}
return animationImagesObject;
}
/**
* Exit Engine
*/
public void exit()
{
running = false;
}
//添加菜单条
private static final int BAR_WIDTH = 140;
private static final boolean HAS_OPENING = true;
public static final int BAR_HEIGHT = FONT_HEIGHT+5;
private static final int COLOUR_BANNER_TOP_HIGH = 0x7de466;
private static final int COLOUR_BANNER_TOP_HALF_HIGH = 0x2d8818;
private static final int COLOUR_BANNER_BOTTOM_HALF_HIGH = 0x006700;
private static final int COLOUR_BANNER_BOTTOM_1_HIGH = 0x2d8818;
private static final int COLOUR_BANNER_BOTTOM_2_HIGH = 0x006700;
private static final int COLOUR_BANNER_CENTRE_HIGH = 0x003a04;
private static final int COLOUR_BANNER_SHADOW_HIGH = 0x040604;
private static final int COLOUR_BANNER_TOP_LOW = 0x197502;
private static final int COLOUR_BANNER_TOP_HALF_LOW = 0x155600;
private static final int COLOUR_BANNER_BOTTOM_HALF_LOW = 0x143519;
private static final int COLOUR_BANNER_BOTTOM_1_LOW = 0x155600;
private static final int COLOUR_BANNER_BOTTOM_2_LOW = 0x143519;
private static final int COLOUR_BANNER_CENTRE_LOW = 0x0c250c;
private static final int COLOUR_BANNER_SHADOW_LOW = 0x040604;
private static final int COLOUR_BANNER_CENTRE_HIGH_GMG = 0x637F51;
private static final int COLOUR_BANNER_CENTRE_LOW_GMG = 0x3E442C;
private static final int[][] BANNER_COLOURS =
{
{
COLOUR_BANNER_TOP_HIGH,
COLOUR_BANNER_TOP_HALF_HIGH,
COLOUR_BANNER_BOTTOM_HALF_HIGH,
COLOUR_BANNER_BOTTOM_1_HIGH,
COLOUR_BANNER_BOTTOM_2_HIGH,
COLOUR_BANNER_CENTRE_HIGH,
COLOUR_BANNER_SHADOW_HIGH
,COLOUR_BANNER_CENTRE_HIGH_GMG
},
{
COLOUR_BANNER_TOP_LOW,
COLOUR_BANNER_TOP_HALF_LOW,
COLOUR_BANNER_BOTTOM_HALF_LOW,
COLOUR_BANNER_BOTTOM_1_LOW,
COLOUR_BANNER_BOTTOM_2_LOW,
COLOUR_BANNER_CENTRE_LOW,
COLOUR_BANNER_SHADOW_LOW
,COLOUR_BANNER_CENTRE_LOW_GMG
}
};
private static final int BANNER_TOP = 0;
private static final int BANNER_TOP_HALF = 1;
private static final int BANNER_BOTTOM_HALF = 2;
private static final int BANNER_BOTTOM_1 = 3;
private static final int BANNER_BOTTOM_2 = 4;
private static final int BANNER_CENTRE = 5;
private static final int BANNER_SHADOW = 6;
private static final int BANNER_CENTRE_GMG = 7;
private static void drawBar(Graphics g, int y, int width, boolean highlighted, String text, int scrollPos)
{
int x = (SCREEN_WIDTH - width) / 2;
drawBar(g, x, y, width, highlighted, text, scrollPos);
}
private static final void drawBar(Graphics g, int x, int y, int width, boolean highlighted, String text, int scrollPos)
{
y -= g.getTranslateY();
int paddedFontHeight = FONT_HEIGHT;
if (FONT_HEIGHT % 2 == 0)
{
paddedFontHeight += 2;
}
else
{
paddedFontHeight += 3;
}
int halfPaddedFontHeight = paddedFontHeight / 2;
int index = highlighted ? 0 : 1;
g.setColor(BANNER_COLOURS[index][BANNER_TOP]);
g.fillRect(x + 7, y, width - 13, 1);
int red = ((BANNER_COLOURS[index][BANNER_TOP_HALF])&0xff0000) >> 16;
int green = ((BANNER_COLOURS[index][BANNER_TOP_HALF])&0x00ff00) >> 8;
int blue = ((BANNER_COLOURS[index][BANNER_TOP_HALF])&0x0000ff);
int step = halfPaddedFontHeight / 2;
int biggestColor = ((red > green?red:green)>blue)?(red > green?red:green):blue;
int colorStep = ((highlighted?290:150) - biggestColor)/step;
for(int i = 0 ; i < halfPaddedFontHeight ; i+=2){
int tmpRed = red + colorStep*(i/2);
int tmpGreen = green + colorStep*(i/2);
int tmpBlue = blue + colorStep*(i/2);
g.setColor(tmpRed>255?255:tmpRed, tmpGreen>255?255:tmpGreen, tmpBlue>255?255:tmpBlue);
g.fillRect(x, y + i, width, 2);
}
for(int i = halfPaddedFontHeight ; i <= paddedFontHeight ; i+=2){
int i2 = paddedFontHeight - i;
// g.setColor(red + colorStep*(i2/2), green + colorStep*(i2/2), blue + colorStep*(i2/2));
int tmpRed = red + colorStep*(i2/2);
int tmpGreen = green + colorStep*(i2/2);
int tmpBlue = blue + colorStep*(i2/2);
g.setColor(tmpRed>255?255:tmpRed, tmpGreen>255?255:tmpGreen, tmpBlue>255?255:tmpBlue);
g.fillRect(x, y + i, width, 2);
}
// g.setColor(BANNER_COLOURS[index][BANNER_TOP_HALF]);
// g.fillRect(x, y + 1, width, halfPaddedFontHeight);
// g.setColor(BANNER_COLOURS[index][BANNER_BOTTOM_HALF]);
// g.fillRect(x, y + 1 + halfPaddedFontHeight, width, halfPaddedFontHeight);
g.setColor(BANNER_COLOURS[index][BANNER_BOTTOM_1]);
g.fillRect(x, y + paddedFontHeight + 1, width, 1);
g.setColor(BANNER_COLOURS[index][BANNER_BOTTOM_2]);
g.fillRect(x, y + paddedFontHeight + 2, width, 1);
g.setColor(BANNER_COLOURS[index][BANNER_SHADOW]);
g.fillRect(x + 6, y + 2, width - 12, 1);
g.fillRect(x + 6, y + 2, 1, paddedFontHeight - 2);
if (text == Engine.text[Text.GMG]) {
g.setColor(BANNER_COLOURS[index][BANNER_CENTRE_GMG]);
} else {
g.setColor(BANNER_COLOURS[index][BANNER_CENTRE]);
}
g.fillRect(x + 7, y + 3, width - 13, paddedFontHeight - 3);
if (text != null)
{
int clipX = g.getClipX();
int clipY = g.getClipY();
int clipW = g.getClipWidth();
int clipH = g.getClipHeight();
g.setClip(x + 8, y, width - 16, paddedFontHeight);
if(text == Engine.text[Text.GMG])//modify 2009-03-16 by qihaidong
paintBorderedString(g, text, x + (width >> 1) + scrollPos, y + 2,
Graphics.TOP | Graphics.HCENTER,0xff0000, 0);
else
paintBorderedString(g, text, x + (width >> 1) + scrollPos, y + 2,
Graphics.TOP | Graphics.HCENTER, highlighted?0xffffff:0xc0c0c0, 0);
g.setClip(clipX, clipY, clipW, clipH);
}
}
private Image newBg;
private Animation aniSonic , aniTails;
private int newBgOffsetX[] = new int[7];
//7层水的移动速度
private final int NEW_BG_VX[] = {
-27,
-32,
-38,
-48,
-64,
-96,
-192,
};
//7层水在图片中的截取坐标
private final int NEW_BG_PARAM[][] = {
{0,138,240,3},
{0,141,240,4},
{0,145,240,4},
{0,149,240,6},
{0,155,240,10},
{0,165,240,20},
{0,185,240,41},
};
private void backgroundMoveLogic(){
for(int i = 0 ; i < newBgOffsetX.length ; i ++){
newBgOffsetX[i] += NEW_BG_VX[i];
if(newBgOffsetX[i] < -(240 * 16)){
newBgOffsetX[i] += 240 * 16;
}
}
}
private final int TITLE_HEIGHT = 36 + 20;
private final int WATER_HEIGHT = 74 + 20;
private void drawNewBg(Graphics g){
int yOffset = g.getTranslateY();
// 在此添加背景
g.setColor(0, 10, 247);
g.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
backgroundMoveLogic();
g.drawImage(newBg, 0, WATER_HEIGHT - yOffset, Graphics.LEFT|Graphics.TOP);
for(int i = 0 ; i < 7 ; i ++){
g.drawRegion(newBg, NEW_BG_PARAM[i][0], NEW_BG_PARAM[i][1],
NEW_BG_PARAM[i][2], NEW_BG_PARAM[i][3], Sprite.TRANS_NONE,
newBgOffsetX[i] >> 4, NEW_BG_PARAM[i][1] + WATER_HEIGHT - yOffset, Graphics.LEFT|Graphics.TOP);
g.drawRegion(newBg, NEW_BG_PARAM[i][0], NEW_BG_PARAM[i][1],
NEW_BG_PARAM[i][2], NEW_BG_PARAM[i][3], Sprite.TRANS_NONE,
(newBgOffsetX[i] >> 4) + 240, NEW_BG_PARAM[i][1] + WATER_HEIGHT - yOffset, Graphics.LEFT|Graphics.TOP);
}
}
private static int CURSOL_PARAM[][] = {
{0, 0, 16, 16, Sprite.TRANS_NONE},
{0, 16, 16, 16, Sprite.TRANS_NONE},
{0, 32, 16, 16, Sprite.TRANS_NONE},
{0, 16, 16, 16, Sprite.TRANS_MIRROR},
};
private static Image imgCursol = null;
private static int cursolClock = 0;
public static void drawCursolLogic(){
cursolClock ++;
if(cursolClock == Integer.MAX_VALUE){
cursolClock = 0;
}
}
public static void drawCursol(Graphics g ,int y , int width){
if(imgCursol == null){
try {
imgCursol = Image.createImage("/ring.png");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(imgCursol != null){
int id = (int)((cursolClock/2)%4);
int[] tmp = CURSOL_PARAM[id];
g.drawRegion(imgCursol, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4],
(SCREEN_WIDTH - width)/2, y, Graphics.HCENTER|Graphics.VCENTER);
g.drawRegion(imgCursol, tmp[0], tmp[1], tmp[2], tmp[3], tmp[4],
(SCREEN_WIDTH + width)/2, y, Graphics.HCENTER|Graphics.VCENTER);
}
}
//索尼克和塔尔斯的纵坐标都是常量
private final int SONIC_Y = (BAR_HEIGHT) + 18;
private final int TAILS_Y = (BAR_HEIGHT) * 3 - 0;
private int sonic_x = -35, tails_x = (276 + 18);
private final int MOVE_VX = 30;
private final int barVelocity = 25;
private final int barAcc = 20;
private int barOffsetX[] = {
-143,
-143 + (-barVelocity)*6,
382,
382 + (barVelocity)*6,
};
private int barOffsetVX[] = {
barVelocity,
barVelocity,
-barVelocity,
-barVelocity,
};
private int barOffsetAX[] = {
-barAcc,
-barAcc,
barAcc,
barAcc,
};
private byte barState[] = {
0,
0,
0,
0,
};
}
(Source: TwoSpacesSG (discovery))