/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine is distributed in the hope that it will *
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.game;
import totalcross.ui.event.*;
import totalcross.ui.font.Font;
import totalcross.ui.gfx.Graphics;
import totalcross.ui.image.ImageException;
/**
* This abstract class represents the game API engine.
* <br>
* <pre>
* Version 1.1 of the GameEngine features:
* <ul>
* <li>Highscores management.
* <li>Versionned options management of String, Integer, Double and Boolean types.
* <li>Quick text display through text pre-rendering for game status & score display.
* <li>Sprite/animated sprite support.
* <li>Animation control.
* <li>AnimatedButton control.
* <li>Game framework extending the TotalCross MainWindow.
* </ul>
*
* You can find a complete game API sample named 'Ping' in the TotalCross samples folder.<br>
* <B>NOTE: This sample may be used as a skeleton for your own game development and the
* source reading may be much helpful to understand this framework.</B>
* You also can change the game settings at the top of the file 'Ping.java' to
* experiment the different game API behaviours.<br>
* <B>Further i recommand the reading of the TotalCross game API tutorial that gives
* many details on this framework use.</B>
*
*
* <u><B>1) GAME FRAMEWORK DESCRIPTION</B></u>
*
* Basically the game engine consists in a class that extends TotalCross's MainWindow.
* This class is named <A href="GameEngine.html"><B>GameEngine</B></A> and provides
* many game oriented services like game settings and game highscores management.
* You won't have to access the game associated settings nor the highscore databases
* directly, you will have to use <A href="HighScores.html"><B>HighScores</B></A>
* and <A href="Options.html"><B>Options</B></A> interfaces instead.
* This services are retrievable by the <i>getHisghscores()</i> and the <i>getOptions()</i> calls.<br>
*
* <u><B>2) GAME SETUP</B></u>
*
* A game using this API has to extend the <A href="GameEngine.html"><B>GameEngine</B></A> class,
* like this:
*
* <i>public class MyOwnGame extends GameEngine {
* ...
* }
* </i>
*
* to setup the game engine, you will have to provide some information.
* These information are defined through the following GameEngine member variables:
*
* -<u>gameName</u> the name of the game, this information is used to name the game associated databases.
* -<u>gameCreatorID</u> the creatorID of the game
* -<u>gameVersion</u> the game version number
* -<u>gameHighscoresSize</u> number of best scores to save in the highscores database
* -<u>gameRefreshPeriod</u> refresh period in milliseconds for action games, or NO_AUTO_REFRESH for non animated games.
* -<u>gameDoClearScreen</u> enable/disable the whole screen erasing between frames displays.
* -<u>gameHasUI</u> declare UI uses, if false the drawing is improved
*
* You see below the definition of a the sample game named "Scape":
*
* import totalcross.game.*;
* import totalcross.util.props.*;
* ...
*
* <i>public class Ping extends <U>GameEngine</U></i> {
*
* // constructor
* public Ping()
* {
* totalcross.sys.Settings.setPalmOSStyle(true);
*
* // define the game API setup attributes
*
* gameName = "Scape";
*
* // when not run on device, appCreatorId does not always return the same value.
*
* gameCreatorID = Settings.onJavaSE ? totalcross.sys.Settings.appCreatorId:"Scpe";
*
* gameVersion = 100; // v1.00
* gameHighscoresSize = 7; // store the best 7 highscores
* gameRefreshPeriod = 75; // 75 ms refresh periods
* gameIsDoubleBuffered = true; // used double buffering to prevent flashing display
* gameDoClearScreen = true; // screen is cleared before each frame display
* gameHasUI = false; // no UI elements, frame displays are optimized
* ...
* }
*
* <u><B>3) GAME FRAMEWORK DETAILS</B></u>
*
* The GameEngine class traps many TotalCross event handler functions to fulfill tasks
* behind the scenes. Thus the following TotalCross functions cannot be overloaded in your
* game's main window:
* <i>
* void initUI ();
* void onExit ();
* void onEvent (Event ev);
* </i>
* they are replaced by the following game API functions that may be overloaded :
* <i>
* void onGameInit ();
* void onGameExit ();
*
* void onKey (KeyEvent evt);
* void onPenDown (PenEvent evt);
* void onPenUp (PenEvent evt);
* void onPenDrag (PenEvent evt);
*
* void onTimer (ControlEvent evt);
* void onOtherEvent (Event evt);
* </i>
*
* The framework extends the event handlers to provide game specific events, such as:
* <i>
* void onGameStart ();
* void onGameStop ();
* </i>
* The first one is called when the game mainloop starts (when the game enters the
* <i>"run mode"</i>), the second one when the run mode is leaved.
*
* You can control (run/stop) and retrieve the current state by the game API functions and fields:
* <i>
* void start ();
* void stop ();
* boolean gameIsRunning;
* </i>
* The game API supports both arcade games that are "time driven" (a timer causes
* frequent screen refreshes to get an animation of the game elements/objects)
* and "static" games such as cards, puzzles, etc.
*
* When entering the game run mode by the <i>start()</i> call, time based games
* arm a timer that causes scheduled calls to your overloaded <i>onPaint()</i>
* to draw a new frame/image.<br>
* On static games that may be designated as "user event driven" refreshes have to
* be launched by an explicit call of <i>refresh()</i> that also causes the call
* of your overloaded <i>onPaint()</i> to draw a new frame/image. Static games
* can also use timers to signal the end of a reflection time, etc.<br>
*
* <u><B>4) GAME SPRITES</B></u>
*
* A <A href="Sprite.html"><B>Sprite</B></A> is a graphical object typicaly used in games that can be moved,
* with collision detection feature and background saving/restoring capability.
*
* To create a sprite you will have to provide an Image object, it's transparency color
* if needed (DRAW_SPRITE mode), a flag indicating if the background have to be saved
* (required if screen clearing is disabled as far as the screen is not
* erased to be redrawn completly) and the sprite valid positions area (Rect).
*
* You may also have to define the drawOp for the Sprite drawing. It's common values are:
* <li>USE_CURRENT_DRAWOP default
* <li>DRAW_SPRITE
* <li>DRAW_PAINT
*
* You can override the onPositionChange() method to manage valid positions, collisions,
* bounces or any other object position based condition.<br>
* The default implementation checks position validity by using the <i>region</i> argument
* of the sprite constructor.
* see the "Scape" source code for more details.
*
* When background saving is enabled, each sprite display with the show() method
* restores any previously saved background.<br>
* In some games, sprites may overlap... if you write such a game, you may have to
* call the sprite hide() method explicitly (which is not necessary in the common
* usage) in the reverse draw order to restore the background.
*
* <u><B>5) ANIMATIONS</B></u>
*
* This <A href="Animation.html"><B>Animation</B></A> control provides an image sequence display. You can handle the
* animation frames displays by your own, or call one of the several <i>start()</i>
* methods provided to launch a thread driven animation.
*
* The animation is composed by a collection of Image objects that can be loaded
* from indexed BMP files (one frame per image) or from a so-called multi-image
* bitmap. It is an image format that contains all the animation frames side by side.
* All the images share a same color palette and must have the same size.
*
* <u><B>6) ANIMATED BUTTONS</B></u>
*
* The <A href="AnimatedButton.html"><B>AnimatedButton</B></A> class is a button implementation that extends the
* Animation class. It uses an animation containing the different states of the
* button and their transition frames in a specific layout.
*
* </pre>
* @author Frank Diebolt
* @author Guilherme Campos Hazan
* @version 1.1
*/
public abstract class GameEngine extends GameEngineMainWindow
{
public final static int GAME_ENGINE_VERSION = 110; // version 1.1 - remodeled by guich
/**
* Name of the game. <br>
* The Highscores/Options databases are prefixed with this name.
*/
public String gameName;
/**
* Game CreatorID. <br>
* The Highscores/Options databases references are created with this ID.<br>
* This must be a String with exactly four characters.
* This has the effect to link the databases to the game software
* causing an automatic database removal when the application is
* deleted from the device.
*/
public String gameCreatorID;
/**
* Game version. <br>
* This information is written in the Options database and may be compared
* to it's old version retrievable by the getOldVersion() function of the
* Options interface.
* E.g. 100 for 1.00)
*/
public int gameVersion;
/**
* Amount of highscores entries in the highscores database. <br>
*/
public int gameHighscoresSize;
/**
* No automatic refresh. <br>
* @see #gameRefreshPeriod
*/
public final static int NO_AUTO_REFRESH=-1;
/**
* Automatic refresh period in milliseconds. <br>
* The NO_AUTO_REFRESH value prevents the engine to do time
* based refreshes. You will have to call explicitly the refresh() function
* to force a screen repainting.
* @see #refresh()
*/
public int gameRefreshPeriod = NO_AUTO_REFRESH;
/**
* True if the screen should be cleared before the onPaint() call. <br>
*/
public boolean gameDoClearScreen;
/** True if the game is running. Set by the GameEngineMainWindow. To stop or
* start the game use the methods stop or run. Setting this variable has
* no effect.
*/
protected boolean gameIsRunning;
/** Must be set to true if the game screen has any control from the totalcross.ui.
* package. Complex games should not have UI elements
*/
protected boolean gameHasUI;
/**
* Event notication called when the game is initialized. <br>
* It's the first place where API calls can take place because
* the game engine has been initialized.<br>
* You can do game initialization at this place. Typically Sprites may be
* created in the overloaded function.
*/
public abstract void onGameInit ();
/**
* Event notication called when the game exits. <br>
*/
public void onGameExit () {}
/**
* Event notication called when the game mainloop is entered. <br>
*/
public void onGameStart () {}
/**
* Event notication called when the game mainloop is leaved. <br>
* @see #stop
*/
public void onGameStop () {}
/**
* Event notication called when a control event is signaled. <br>
* @param evt control event that occurred.
*/
public void onTimer (TimerEvent evt) {}
/**
* Event notication called when a key event is signaled. <br>
* @param evt key event that occurred.
*/
public void onKey (KeyEvent evt) {}
/**
* Event notication called when a pen down event is signaled. <br>
* @param evt pen event that occurred.
*/
public void onPenDown (PenEvent evt) {}
/**
* Event notication called when a pen up event is signaled. <br>
* @param evt pen event that occurred.
*/
public void onPenUp (PenEvent evt) {}
/**
* Event notication called when a pen drag/move event is signaled. <br>
* @param evt pen event that occurred.
*/
public void onPenDrag (PenEvent evt) {}
/**
* Event notication called when any other event is signaled. <br>
* @param evt event that occurred.
*/
public void onOtherEvent (Event evt) {}
/** Called at each refresh to draw the current game state */
public void onPaint(Graphics g) {}
/**
* Get the game highscores.
* @return HighScores.
*/
public HighScores getHighScores()
{
return super.getHighScores();
}
/**
* Get a new instance of the game options.
* @return Options.
*/
public Options getOptions()
{
return super.getOptions();
}
/**
* Create a new TextRenderer.
* A TextRenderer performs a fast String display with an optional integer value.
* @param font to display with.
* @param foreColor text color, may be null.
* @param text to render.
* @param maxDigits digits to display.
* @return a new TextRenderer.
* @throws ImageException
* @see TextRenderer TextRenderer for more information
*/
public final TextRenderer createTextRenderer (Font font,int foreColor, String text,int maxDigits) throws ImageException
{
return super.createTextRenderer(font,foreColor,text,maxDigits);
}
/**
* Create a new TextRenderer. A TextRenderer performs a fast String display with an optional integer value.
*
* @param font
* to display with.
* @param foreColor
* text color, may be null.
* @param text
* to render.
* @param maxDigits
* digits to display.
* @param zeroPadding
* pad with leading zeros.
* @return a new TextRenderer.
* @throws ImageException
* @see TextRenderer TextRenderer for more information
*/
public final TextRenderer createTextRenderer(Font font, int foreColor, String text, int maxDigits,
boolean zeroPadding) throws ImageException // fdie@420_27
{
return super.createTextRenderer(font, foreColor, text, maxDigits, zeroPadding);
}
/** Must be called to start the game. */
final public void start()
{
super.start();
}
/** Must be called to make the game stop. */
final public void stop()
{
super.stop();
}
/**
* This function causes an onPaint() call to draw a new frame.<br>
* This function has to be called in non time based games to refresh
* the complete screen.
*/
final public void refresh()
{
super.refresh();
}
/** Creates a new GameEngine */
public GameEngine()
{
super.setGameEngine(this);
}
}