- Added ads support for Android

- basic "message" system between JGE and java through jni 
- Fixed pause/resume on android/sdl
This commit is contained in:
wagic.the.homebrew
2011-09-04 02:45:18 +00:00
parent 269934fe1e
commit 33691d1f13
21 changed files with 396 additions and 114 deletions
@@ -24,10 +24,12 @@ extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass c
/* Run the application code! */ /* Run the application code! */
int status; int status;
char *argv[2]; char *argv[4];
argv[0] = strdup("SDL_app"); argv[0] = strdup("SDL_app");
argv[1] = NULL; argv[1] = (char *)env;
status = SDL_main(1, argv); argv[2] = (char *)&cls;
argv[3] = NULL;
status = SDL_main(3, argv);
/* We exit here for consistency with other platforms. */ /* We exit here for consistency with other platforms. */
exit(status); exit(status);
+20
View File
@@ -55,6 +55,10 @@ typedef u32 LocalKeySym;
#endif #endif
#if defined(ANDROID)
#include <jni.h>
#endif
bool JGEGetButtonState(const JButton button); bool JGEGetButtonState(const JButton button);
bool JGEGetButtonClick(const JButton button); bool JGEGetButtonClick(const JButton button);
void JGECreateDefaultBindings(); void JGECreateDefaultBindings();
@@ -121,6 +125,12 @@ class JGE
private: private:
#endif #endif
#if defined (ANDROID)
JNIEnv * mJNIEnv;
jclass mJNIClass;
jmethodID midSendCommand;
#endif
bool mDone; bool mDone;
float mDeltaTime; float mDeltaTime;
bool mDebug; bool mDebug;
@@ -356,6 +366,16 @@ class JGE
void Assert(const char *filename, long lineNumber); void Assert(const char *filename, long lineNumber);
/// Sends a message through JGE
/// Currently used only to communicate with the JNI Layer in Android
void SendCommand(std::string command);
#if defined (ANDROID)
/// Access to JNI Environment
void SetJNIEnv(JNIEnv * env, jclass cls);
void sendJNICommand(std::string command);
#endif
protected: protected:
JGE(); JGE();
~JGE(); ~JGE();
+29
View File
@@ -315,6 +315,11 @@ JGE::JGE()
strcpy(mDebuggingMsg, ""); strcpy(mDebuggingMsg, "");
mCurrentMusic = NULL; mCurrentMusic = NULL;
#endif #endif
#if defined (ANDROID)
mJNIEnv = NULL;
#endif
Init(); Init();
} }
@@ -567,5 +572,29 @@ void JGE::Scroll(int inXVelocity, int inYVelocity)
} }
} }
void JGE::SendCommand(string command)
{
#if defined (ANDROID)
sendJNICommand(command);
#endif
}
#if defined (ANDROID)
/// Access to JNI Environment
void JGE::SetJNIEnv(JNIEnv * env, jclass cls)
{
mJNIEnv = env;
mJNIClass = cls;
midSendCommand = mJNIEnv->GetStaticMethodID(mJNIClass,"jgeSendCommand","(Ljava/lang/String;)V");
}
void JGE::sendJNICommand(string command)
{
if (midSendCommand) {
mJNIEnv->CallStaticVoidMethod(mJNIClass, midSendCommand, mJNIEnv->NewStringUTF(command.c_str()));
}
}
#endif
std::queue< pair< pair<LocalKeySym, JButton>, bool> > JGE::keyBuffer; std::queue< pair< pair<LocalKeySym, JButton>, bool> > JGE::keyBuffer;
std::multimap<LocalKeySym, JButton> JGE::keyBinds; std::multimap<LocalKeySym, JButton> JGE::keyBinds;
+49
View File
@@ -50,12 +50,39 @@ uint64_t lastTickCount;
JGE* g_engine = NULL; JGE* g_engine = NULL;
JApp* g_app = NULL; JApp* g_app = NULL;
JGameLauncher* g_launcher = NULL; JGameLauncher* g_launcher = NULL;
#ifdef ANDROID
JNIEnv * mJNIEnv = NULL;
jclass * mJNIClass = NULL;
#endif
class SdlApp; class SdlApp;
SdlApp *g_SdlApp = NULL; SdlApp *g_SdlApp = NULL;
#ifdef ANDROID
// Pause
extern "C" void Java_org_libsdl_app_SDLActivity_nativePause(
JNIEnv* env, jclass cls)
{
DebugTrace("Attempt pause");
if (!g_engine)
return;
g_engine->Pause();
DebugTrace("Pause done");
}
// Resume
extern "C" void Java_org_libsdl_app_SDLActivity_nativeResume(
JNIEnv* env, jclass cls)
{
if (!g_engine)
return;
g_engine->Resume();
}
#endif
class SdlApp class SdlApp
{ {
public: /* For easy interfacing with JGE static functions */ public: /* For easy interfacing with JGE static functions */
@@ -88,6 +115,8 @@ public:
SDL_Event Event; SDL_Event Event;
while(Running) while(Running)
{
if (g_engine && !g_engine->IsPaused())
{ {
while(SDL_WaitEventTimeout(&Event, 0)) while(SDL_WaitEventTimeout(&Event, 0))
{ {
@@ -95,6 +124,7 @@ public:
} }
OnUpdate(); OnUpdate();
} }
}
OnCleanup(); OnCleanup();
@@ -348,6 +378,16 @@ bool InitGame(void)
g_app = g_launcher->GetGameApp(); g_app = g_launcher->GetGameApp();
g_app->Create(); g_app->Create();
g_engine->SetApp(g_app); g_engine->SetApp(g_app);
#ifdef ANDROID
DebugTrace("Can I Set JNI Params ?");
if (mJNIEnv)
DebugTrace("mJNIEnv is ok");
if (mJNIEnv && mJNIClass)
{
DebugTrace("Setting JNI Params");
g_engine->SetJNIEnv(mJNIEnv, *mJNIClass);
}
#endif
JRenderer::GetInstance()->Enable2D(); JRenderer::GetInstance()->Enable2D();
lastTickCount = JGEGetTime(); lastTickCount = JGEGetTime();
@@ -686,6 +726,15 @@ int SDL_main(int argc, char * argv[])
int main(int argc, char* argv[]) int main(int argc, char* argv[])
#endif //ANDROID #endif //ANDROID
{ {
#if (defined ANDROID)
if (argc > 2)
{
mJNIEnv = (JNIEnv * )argv[1];
mJNIClass = (jclass * )argv[2];
}
#endif
DebugTrace("I R in da native"); DebugTrace("I R in da native");
g_launcher = new JGameLauncher(); g_launcher = new JGameLauncher();
+8 -2
View File
@@ -3,7 +3,10 @@
package="org.libsdl.app" package="org.libsdl.app"
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> android:versionName="1.0">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true" android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> <application android:label="@string/app_name" android:icon="@drawable/icon" android:debuggable="true" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<activity android:name="SDLActivity" <activity android:name="SDLActivity"
android:configChanges="orientation" android:configChanges="orientation"
@@ -13,6 +16,9 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.google.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation"/>
</application> </application>
<uses-sdk android:minSdkVersion="4" /> <uses-sdk android:minSdkVersion="8" />
</manifest> </manifest>
+1 -1
View File
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project name="Wagic" default="help"> <project name="Wagic">
<!-- The local.properties file is created and updated by the 'android' tool. <!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked in in Version It contains the path to the SDK. It should *NOT* be checked in in Version
+2 -1
View File
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:orientation="vertical"
android:id="@+id/mainLayout"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
> >
<TextView <TextView
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello World, Wagic" android:text="Wagic"
/> />
</LinearLayout> </LinearLayout>
@@ -21,12 +21,18 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.util.Log; import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.VelocityTracker; import android.view.VelocityTracker;
import android.view.View; import android.view.View;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import com.google.ads.*;
/** /**
@@ -35,6 +41,7 @@ import android.view.View;
public class SDLActivity extends Activity { public class SDLActivity extends Activity {
// Main components // Main components
private static AdView mAdView;
private static SDLActivity mSingleton; private static SDLActivity mSingleton;
private static SDLSurface mSurface; private static SDLSurface mSurface;
@@ -52,6 +59,7 @@ public class SDLActivity extends Activity {
} }
// Setup // Setup
@Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
//Log.v("SDL", "onCreate()"); //Log.v("SDL", "onCreate()");
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@@ -59,26 +67,86 @@ public class SDLActivity extends Activity {
// So we can call stuff from static callbacks // So we can call stuff from static callbacks
mSingleton = this; mSingleton = this;
FrameLayout _videoLayout = new FrameLayout(this);
//mGLView = new DemoGLSurfaceView(this);
// Set up the surface // Set up the surface
mSurface = new SDLSurface(getApplication()); mSurface = new SDLSurface(getApplication());
setContentView(mSurface);
//setContentView(mSurface);
SurfaceHolder holder = mSurface.getHolder(); SurfaceHolder holder = mSurface.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU); holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
// Create the adView
mAdView = new AdView(this, AdSize.BANNER, "a14dc0ab7b27413");
_videoLayout.addView(mSurface, new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
_videoLayout.addView(mAdView, new LayoutParams(LayoutParams.WRAP_CONTENT
, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM + Gravity.CENTER_HORIZONTAL) );
// mGLView.setFocusableInTouchMode(true);
// mGLView.setFocusable(true);
// adView.requestFreshAd();
setContentView(_videoLayout,
new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
mSurface.requestFocus();
AdRequest request = new AdRequest();
request.addTestDevice(AdRequest.TEST_EMULATOR);
request.addTestDevice("1DA1E070BC7D4ABE8BA77EB73C2CB0AA"); //wololo's phone
// Initiate a generic request to load it with an ad
mAdView.loadAd(request);
} }
// Events // Events
@Override
protected void onPause() { protected void onPause() {
//Log.v("SDL", "onPause()"); //Log.v("SDL", "onPause()");
super.onPause(); super.onPause();
SDLActivity.nativePause();
} }
@Override
protected void onResume() { protected void onResume() {
//Log.v("SDL", "onResume()"); Log.v("SDL", "onResume()");
super.onResume(); super.onResume();
SDLActivity.nativeResume();
}
@Override
public void onDestroy() {
Log.v("SDL", "onDestroy()");
super.onDestroy();
mSurface.onDestroy();
}
// Handler for Messages coming from JGE
// Suggested syntax for JGE messages is a string separated by the ":" symbol
protected void processJGEMsg (String command)
{
if (null == command) {
return;
}
if ((command.compareTo("entergamestate:menu") == 0)
|| (command.compareTo("enterduelphase:end") == 0)) {
mAdView.setVisibility(View.VISIBLE);
} else if (command.compareTo("leavegamestate:menu") == 0) {
mAdView.setVisibility(View.INVISIBLE);
}
} }
// Messages from the SDLMain thread // Messages from the SDLMain thread
static int COMMAND_CHANGE_TITLE = 1; static int COMMAND_CHANGE_TITLE = 1;
static int COMMAND_JGE_MSG = 2;
// Handler for the messages // Handler for the messages
Handler commandHandler = new Handler() { Handler commandHandler = new Handler() {
@@ -86,6 +154,9 @@ public class SDLActivity extends Activity {
if (msg.arg1 == COMMAND_CHANGE_TITLE) { if (msg.arg1 == COMMAND_CHANGE_TITLE) {
setTitle((String)msg.obj); setTitle((String)msg.obj);
} }
if (msg.arg1 == COMMAND_JGE_MSG) {
processJGEMsg((String)msg.obj);
}
} }
}; };
@@ -100,6 +171,8 @@ public class SDLActivity extends Activity {
// C functions we call // C functions we call
public static native void nativeInit(); public static native void nativeInit();
public static native void nativeQuit(); public static native void nativeQuit();
public static native void nativePause();
public static native void nativeResume();
public static native void onNativeResize(int x, int y, int format); public static native void onNativeResize(int x, int y, int format);
public static native void onNativeKeyDown(int keycode); public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode); public static native void onNativeKeyUp(int keycode);
@@ -111,6 +184,10 @@ public class SDLActivity extends Activity {
// Java functions called from C // Java functions called from C
// Receive a message from the SDLMain thread
public static void jgeSendCommand(String command) {
mSingleton.sendCommand(COMMAND_JGE_MSG, command);
}
public static boolean createGLContext(int majorVersion, int minorVersion) { public static boolean createGLContext(int majorVersion, int minorVersion) {
return mSurface.initEGL(majorVersion, minorVersion); return mSurface.initEGL(majorVersion, minorVersion);
@@ -223,19 +300,6 @@ public class SDLActivity extends Activity {
} }
} }
/**
Simple nativeInit() runnable
*/
class SDLMain implements Runnable {
public void run() {
// Runs SDL_main()
SDLActivity.nativeInit();
//Log.v("SDL", "SDL thread terminated");
}
}
/** /**
SDLSurface. This is what we draw on, so we need to know when it's created SDLSurface. This is what we draw on, so we need to know when it's created
in order to do anything useful. in order to do anything useful.
@@ -252,15 +316,46 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
private EGLContext mEGLContext; private EGLContext mEGLContext;
private EGLSurface mEGLSurface; private EGLSurface mEGLSurface;
private EGLDisplay mEGLDisplay; private EGLDisplay mEGLDisplay;
private EGLConfig mEGLConfig;
// Sensors // Sensors
private static SensorManager mSensorManager; private static SensorManager mSensorManager;
private static VelocityTracker mVelocityTracker; private static VelocityTracker mVelocityTracker;
final private Object mSemSurface;
private Boolean mSurfaceValid;
void startSDLThread() {
if (mSDLThread == null) {
mSDLThread = new Thread(new SDLMain(), "SDLThread");
mSDLThread.start();
}
}
/**
Simple nativeInit() runnable
*/
class SDLMain implements Runnable {
public void run() {
// Runs SDL_main()
SDLActivity.nativeInit();
SDLActivity.nativeQuit();
Log.v("SDL", "SDL thread terminated");
// On exit, tear everything down for a fresh restart next time.
System.exit(0);
}
}
// Startup // Startup
public SDLSurface(Context context) { public SDLSurface(Context context) {
super(context); super(context);
mSemSurface = new Object();
mSurfaceValid = false;
getHolder().addCallback(this); getHolder().addCallback(this);
setFocusable(true); setFocusable(true);
@@ -274,16 +369,15 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Called when we have a valid drawing surface // Called when we have a valid drawing surface
public void surfaceCreated(SurfaceHolder holder) { public void surfaceCreated(SurfaceHolder holder) {
//Log.v("SDL", "surfaceCreated()"); Log.v("SDL", "surfaceCreated()");
enableSensor(Sensor.TYPE_ACCELEROMETER, true); enableSensor(Sensor.TYPE_ACCELEROMETER, true);
} }
// Called when we lose the surface public void onDestroy() {
public void surfaceDestroyed(SurfaceHolder holder) {
//Log.v("SDL", "surfaceDestroyed()");
// Send a quit message to the application // Send a quit message to the application
//should that be in SDLActivity "onDestroy" instead ?
SDLActivity.nativeQuit(); SDLActivity.nativeQuit();
// Now wait for the SDL thread to quit // Now wait for the SDL thread to quit
@@ -297,14 +391,22 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
//Log.v("SDL", "Finished waiting for SDL thread"); //Log.v("SDL", "Finished waiting for SDL thread");
} }
}
// Called when we lose the surface
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL", "surfaceDestroyed()");
synchronized(mSemSurface) {
mSurfaceValid = false;
mSemSurface.notifyAll();
}
enableSensor(Sensor.TYPE_ACCELEROMETER, false); enableSensor(Sensor.TYPE_ACCELEROMETER, false);
} }
// Called when the surface is resized // Called when the surface is resized
public void surfaceChanged(SurfaceHolder holder, public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) { int format, int width, int height) {
//Log.v("SDL", "surfaceChanged()"); Log.v("SDL", "surfaceChanged()");
int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default int sdlFormat = 0x85151002; // SDL_PIXELFORMAT_RGB565 by default
switch (format) { switch (format) {
@@ -353,10 +455,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
SDLActivity.onNativeResize(width, height, sdlFormat); SDLActivity.onNativeResize(width, height, sdlFormat);
// Now start up the C app thread // Now start up the C app thread
if (mSDLThread == null) { startSDLThread();
mSDLThread = new Thread(new SDLMain(), "SDLThread");
mSDLThread.start();
}
} }
// unused // unused
@@ -368,6 +467,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion); Log.v("SDL", "Starting up OpenGL ES " + majorVersion + "." + minorVersion);
try { try {
EGL10 egl = (EGL10)EGLContext.getEGL(); EGL10 egl = (EGL10)EGLContext.getEGL();
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
@@ -394,28 +494,20 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
Log.e("SDL", "No EGL config available"); Log.e("SDL", "No EGL config available");
return false; return false;
} }
EGLConfig config = configs[0]; mEGLConfig = configs[0];
EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null); EGLContext ctx = egl.eglCreateContext(dpy, mEGLConfig, EGL10.EGL_NO_CONTEXT, null);
if (ctx == EGL10.EGL_NO_CONTEXT) { if (ctx == EGL10.EGL_NO_CONTEXT) {
Log.e("SDL", "Couldn't create context"); Log.e("SDL", "Couldn't create context");
return false; return false;
} }
EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null);
if (surface == EGL10.EGL_NO_SURFACE) {
Log.e("SDL", "Couldn't create surface");
return false;
}
if (!egl.eglMakeCurrent(dpy, surface, surface, ctx)) {
Log.e("SDL", "Couldn't make context current");
return false;
}
mEGLContext = ctx; mEGLContext = ctx;
mEGLDisplay = dpy; mEGLDisplay = dpy;
mEGLSurface = surface;
if (!createSurface(this.getHolder())) {
return false;
}
} catch(Exception e) { } catch(Exception e) {
Log.v("SDL", e + ""); Log.v("SDL", e + "");
@@ -427,8 +519,55 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
return true; return true;
} }
public Boolean createSurface(SurfaceHolder holder) {
/*
* The window size has changed, so we need to create a new
* surface.
*/
EGL10 egl = (EGL10)EGLContext.getEGL();
if (mEGLSurface != null) {
/*
* Unbind and destroy the old EGL surface, if
* there is one.
*/
egl.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
egl.eglDestroySurface(mEGLDisplay, mEGLSurface);
}
/*
* Create an EGL surface we can render into.
*/
mEGLSurface = egl.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, holder, null);
if (mEGLSurface == EGL10.EGL_NO_SURFACE) {
Log.e("SDL", "Couldn't create surface");
return false;
}
/*
* Before we can issue GL commands, we need to make sure
* the context is current and bound to a surface.
*/
if (!egl.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
Log.e("SDL", "Couldn't make context current");
return false;
}
mSurfaceValid = true;
return true;
}
// EGL buffer flip // EGL buffer flip
public void flipEGL() { public void flipEGL() {
if (!mSurfaceValid)
{
createSurface(this.getHolder());
}
try { try {
EGL10 egl = (EGL10)EGLContext.getEGL(); EGL10 egl = (EGL10)EGLContext.getEGL();
@@ -447,6 +586,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
Log.v("SDL", s.toString()); Log.v("SDL", s.toString());
} }
} }
} }
// Key events // Key events
+1
View File
@@ -93,6 +93,7 @@ public:
void LoadGameStates(); void LoadGameStates();
void SetNextState(int state); void SetNextState(int state);
void SetCurrentState(GameState * state);
void DoTransition(int trans, int tostate, float dur = -1, bool animonly = false); void DoTransition(int trans, int tostate, float dur = -1, bool animonly = false);
void DoAnimation(int trans, float dur = -1); void DoAnimation(int trans, float dur = -1);
static hgeParticleSystem * Particles[6]; static hgeParticleSystem * Particles[6];
+4 -1
View File
@@ -44,9 +44,10 @@ class GameState
protected: protected:
GameApp* mParent; GameApp* mParent;
JGE* mEngine; JGE* mEngine;
string mStringID;
public: public:
GameState(GameApp* parent); GameState(GameApp* parent, string id);
virtual ~GameState(){} virtual ~GameState(){}
virtual void Create(){} virtual void Create(){}
@@ -62,6 +63,8 @@ public:
virtual void Update(float dt) = 0; virtual void Update(float dt) = 0;
virtual void Render() = 0; virtual void Render() = 0;
string getStringID() {return mStringID;};
// deck manipulation methods // deck manipulation methods
// 2010/09/15: // 2010/09/15:
// this was originally one method to do everything. That has been split up into two distinct // this was originally one method to do everything. That has been split up into two distinct
+1
View File
@@ -45,6 +45,7 @@ private:
void loadPlayer(int playerId, int decknb = 0, bool isAI = false, bool isNetwork = false); void loadPlayer(int playerId, int decknb = 0, bool isAI = false, bool isNetwork = false);
void ConstructOpponentMenu(); //loads the opponentMenu if it doesn't exist void ConstructOpponentMenu(); //loads the opponentMenu if it doesn't exist
void initScroller(); void initScroller();
void setGamePhase(int newGamePhase);
public: public:
GameStateDuel(GameApp* parent); GameStateDuel(GameApp* parent);
+20 -6
View File
@@ -40,8 +40,8 @@ string GameApp::systemError = "";
JQuadPtr manaIcons[7]; JQuadPtr manaIcons[7];
GameState::GameState(GameApp* parent) : GameState::GameState(GameApp* parent, string id) :
mParent(parent) mParent(parent), mStringID(id)
{ {
mEngine = JGE::GetInstance(); mEngine = JGE::GetInstance();
} }
@@ -341,13 +341,13 @@ void GameApp::Update()
mTrans->End(); mTrans->End();
if (mTrans->to != NULL && !mTrans->bAnimationOnly) if (mTrans->to != NULL && !mTrans->bAnimationOnly)
{ {
mCurrentState = mTrans->to; SetCurrentState(mTrans->to);
SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]); SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]);
mCurrentState->Start(); mCurrentState->Start();
} }
else else
{ {
mCurrentState = mTrans->from; SetCurrentState(mTrans->from);
SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]); SAFE_DELETE(mGameStates[GAME_STATE_TRANSITION]);
} }
} }
@@ -356,7 +356,7 @@ void GameApp::Update()
if (mCurrentState != NULL) if (mCurrentState != NULL)
mCurrentState->End(); mCurrentState->End();
mCurrentState = mNextState; SetCurrentState(mNextState);
#if defined (PSP) #if defined (PSP)
/* /*
@@ -423,6 +423,20 @@ void GameApp::SetNextState(int state)
mNextState = mGameStates[state]; mNextState = mGameStates[state];
} }
void GameApp::SetCurrentState(GameState * state)
{
if (mCurrentState == state)
return;
if (mCurrentState)
JGE::GetInstance()->SendCommand("leavegamestate:" + mCurrentState->getStringID());
mCurrentState = state;
if (mCurrentState)
JGE::GetInstance()->SendCommand("entergamestate:" + mCurrentState->getStringID());
}
void GameApp::Pause() void GameApp::Pause()
{ {
stopMusic(); stopMusic();
@@ -471,7 +485,7 @@ void GameApp::DoTransition(int trans, int tostate, float dur, bool animonly)
tb->bAnimationOnly = animonly; tb->bAnimationOnly = animonly;
mGameStates[GAME_STATE_TRANSITION] = tb; mGameStates[GAME_STATE_TRANSITION] = tb;
mGameStates[GAME_STATE_TRANSITION]->Start(); mGameStates[GAME_STATE_TRANSITION]->Start();
mCurrentState = tb; //The old current state is ended inside our transition. SetCurrentState(tb); //The old current state is ended inside our transition.
} }
else if (toState) else if (toState)
{ //Somehow failed, just do standard SetNextState behavior { //Somehow failed, just do standard SetNextState behavior
+1 -1
View File
@@ -23,7 +23,7 @@ namespace
} }
GameStateAwards::GameStateAwards(GameApp* parent) : GameStateAwards::GameStateAwards(GameApp* parent) :
GameState(parent) GameState(parent, "trophies")
{ {
} }
+1 -1
View File
@@ -39,7 +39,7 @@ void StringExplode(string str, string separator, vector<string>* results)
} }
GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) : GameStateDeckViewer::GameStateDeckViewer(GameApp* parent) :
GameState(parent) GameState(parent, "deckeditor")
{ {
bgMusic = NULL; bgMusic = NULL;
useFilter = 0; useFilter = 0;
+51 -35
View File
@@ -32,6 +32,7 @@ const float MENU_FONT_SCALE = 1.0f;
enum ENUM_DUEL_STATE enum ENUM_DUEL_STATE
{ {
DUEL_STATE_UNSET = 0,
DUEL_STATE_START, DUEL_STATE_START,
DUEL_STATE_END, DUEL_STATE_END,
DUEL_STATE_CHOOSE_DECK1, DUEL_STATE_CHOOSE_DECK1,
@@ -45,12 +46,13 @@ enum ENUM_DUEL_STATE
DUEL_STATE_PLAY, DUEL_STATE_PLAY,
DUEL_STATE_BACK_TO_MAIN_MENU, DUEL_STATE_BACK_TO_MAIN_MENU,
DUEL_STATE_MENU, DUEL_STATE_MENU,
#ifdef NETWORK_SUPPORT DUEL_STATE_OPPONENT_WAIT, // used For Network only
DUEL_STATE_OPPONENT_WAIT,
#endif //NETWORK_SUPPORT
DUEL_STATE_ERROR DUEL_STATE_ERROR
}; };
const char * stateStrings[] = { "unset", "start", "end", "choose_deck1", "deck1_detailed_info", "deck2_detailed_info", "choose_deck1_to_2", "choose_deck2", "choose_deck2_to_play",
"error_no_deck", "cancel", "play", "back_to_main_menu", "menu", "oponent_wait", "error" };
enum ENUM_DUEL_MENUS enum ENUM_DUEL_MENUS
{ {
DUEL_MENU_GAME_MENU, DUEL_MENU_GAME_MENU,
@@ -64,7 +66,7 @@ int GameStateDuel::selectedPlayerDeckId = 0;
int GameStateDuel::selectedAIDeckId = 0; int GameStateDuel::selectedAIDeckId = 0;
GameStateDuel::GameStateDuel(GameApp* parent) : GameStateDuel::GameStateDuel(GameApp* parent) :
GameState(parent) GameState(parent, "duel")
{ {
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
@@ -76,6 +78,7 @@ GameState(parent)
opponentMenu = NULL; opponentMenu = NULL;
menu = NULL; menu = NULL;
popupScreen = NULL; popupScreen = NULL;
mGamePhase = DUEL_STATE_UNSET;
#ifdef TESTSUITE #ifdef TESTSUITE
testSuite = NULL; testSuite = NULL;
@@ -105,7 +108,7 @@ void GameStateDuel::Start()
testSuite = NEW TestSuite("test/_tests.txt",MTGCollection()); testSuite = NEW TestSuite("test/_tests.txt",MTGCollection());
#endif #endif
mGamePhase = DUEL_STATE_CHOOSE_DECK1; setGamePhase(DUEL_STATE_CHOOSE_DECK1);
credits = NEW Credits(); credits = NEW Credits();
menu = NULL; menu = NULL;
@@ -308,6 +311,19 @@ void GameStateDuel::ConstructOpponentMenu()
} }
} }
void GameStateDuel::setGamePhase(int newGamePhase) {
if (mGamePhase == newGamePhase)
return;
if (mGamePhase)
JGE::GetInstance()->SendCommand("leaveduelphase:" + string(stateStrings[mGamePhase]));
mGamePhase = newGamePhase;
if (mGamePhase )
JGE::GetInstance()->SendCommand("enterduelphase:" + string(stateStrings[mGamePhase]));
}
void GameStateDuel::Update(float dt) void GameStateDuel::Update(float dt)
{ {
switch (mGamePhase) switch (mGamePhase)
@@ -324,7 +340,7 @@ void GameStateDuel::Update(float dt)
case DUEL_STATE_CHOOSE_DECK1: case DUEL_STATE_CHOOSE_DECK1:
if (!mParent->rules->canChooseDeck()) if (!mParent->rules->canChooseDeck())
{ {
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
} }
#ifdef TESTSUITE #ifdef TESTSUITE
else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE)
@@ -332,7 +348,7 @@ void GameStateDuel::Update(float dt)
if (testSuite && testSuite->loadNext()) if (testSuite && testSuite->loadNext())
{ {
loadTestSuitePlayers(); loadTestSuitePlayers();
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
testSuite->pregameTests(); testSuite->pregameTests();
testSuite->initGame(); testSuite->initGame();
} }
@@ -340,11 +356,11 @@ void GameStateDuel::Update(float dt)
{ {
if (!game) if (!game)
{ {
mGamePhase = DUEL_STATE_ERROR; setGamePhase(DUEL_STATE_ERROR);
} }
else else
{ {
mGamePhase = DUEL_STATE_END; setGamePhase(DUEL_STATE_END);
} }
} }
} }
@@ -358,13 +374,13 @@ void GameStateDuel::Update(float dt)
else else
{ {
loadPlayer(0); loadPlayer(0);
mGamePhase = DUEL_STATE_CHOOSE_DECK2; setGamePhase(DUEL_STATE_CHOOSE_DECK2);
} }
} }
break; break;
case DUEL_STATE_CHOOSE_DECK1_TO_2: case DUEL_STATE_CHOOSE_DECK1_TO_2:
if (deckmenu->isClosed()) if (deckmenu->isClosed())
mGamePhase = DUEL_STATE_CHOOSE_DECK2; setGamePhase(DUEL_STATE_CHOOSE_DECK2);
else else
deckmenu->Update(dt); deckmenu->Update(dt);
break; break;
@@ -381,7 +397,7 @@ void GameStateDuel::Update(float dt)
else else
{ {
loadPlayer(1); loadPlayer(1);
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
} }
} }
break; break;
@@ -389,7 +405,7 @@ void GameStateDuel::Update(float dt)
if (mParent->players[1] == PLAYER_TYPE_HUMAN) if (mParent->players[1] == PLAYER_TYPE_HUMAN)
{ {
if (deckmenu->isClosed()) if (deckmenu->isClosed())
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
else else
deckmenu->Update(dt); deckmenu->Update(dt);
} }
@@ -397,7 +413,7 @@ void GameStateDuel::Update(float dt)
{ {
ConstructOpponentMenu(); ConstructOpponentMenu();
if (opponentMenu->isClosed()) if (opponentMenu->isClosed())
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
else else
opponentMenu->Update(dt); opponentMenu->Update(dt);
} }
@@ -448,18 +464,18 @@ void GameStateDuel::Update(float dt)
if (game->gameOver) if (game->gameOver)
{ {
if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game->players[0], game->players[1], mParent); if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game->players[0], game->players[1], mParent);
mGamePhase = DUEL_STATE_END; setGamePhase(DUEL_STATE_END);
#ifdef TESTSUITE #ifdef TESTSUITE
if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) if (mParent->players[1] == PLAYER_TYPE_TESTSUITE)
{ {
if (testSuite->loadNext()) if (testSuite->loadNext())
{ {
loadTestSuitePlayers(); loadTestSuitePlayers();
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
testSuite->initGame(); testSuite->initGame();
} }
else else
mGamePhase = DUEL_STATE_END; setGamePhase(DUEL_STATE_END);
} }
else else
#endif #endif
@@ -489,7 +505,7 @@ void GameStateDuel::Update(float dt)
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu"); menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
menu->Add(MENUITEM_CANCEL, "Cancel"); menu->Add(MENUITEM_CANCEL, "Cancel");
} }
mGamePhase = DUEL_STATE_MENU; setGamePhase(DUEL_STATE_MENU);
} }
break; break;
#ifdef NETWORK_SUPPORT #ifdef NETWORK_SUPPORT
@@ -499,7 +515,7 @@ void GameStateDuel::Update(float dt)
{ // Player loaded { // Player loaded
menu->Close(); menu->Close();
SAFE_DELETE(menu); SAFE_DELETE(menu);
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
} else if(menu == NULL) } else if(menu == NULL)
{ {
loadPlayer(1, 42/* 0 not good*/, false, true); loadPlayer(1, 42/* 0 not good*/, false, true);
@@ -522,7 +538,7 @@ void GameStateDuel::Update(float dt)
menu->Update(dt); menu->Update(dt);
if (menu->isClosed()) if (menu->isClosed())
{ {
mGamePhase = DUEL_STATE_PLAY; setGamePhase(DUEL_STATE_PLAY);
SAFE_DELETE(menu); SAFE_DELETE(menu);
} }
break; break;
@@ -665,7 +681,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
if (!popupScreen->isClosed()) if (!popupScreen->isClosed())
{ {
popupScreen->Close(); popupScreen->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK1; setGamePhase(DUEL_STATE_CHOOSE_DECK1);
SAFE_DELETE( popupScreen ); SAFE_DELETE( popupScreen );
} }
else else
@@ -682,7 +698,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
if (!popupScreen->isClosed()) if (!popupScreen->isClosed())
{ {
popupScreen->Close(); popupScreen->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY);
SAFE_DELETE( popupScreen ); SAFE_DELETE( popupScreen );
} }
else else
@@ -700,7 +716,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
case MENUITEM_RANDOM_AI: case MENUITEM_RANDOM_AI:
loadPlayer(1); loadPlayer(1);
opponentMenu->Close(); opponentMenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY);
break; break;
default: default:
// cancel option. return to player deck selection // cancel option. return to player deck selection
@@ -710,7 +726,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
opponentMenu->Close(); opponentMenu->Close();
deckmenu->Close(); deckmenu->Close();
mParent->SetNextState(DUEL_STATE_CHOOSE_DECK1); mParent->SetNextState(DUEL_STATE_CHOOSE_DECK1);
mGamePhase = DUEL_STATE_CHOOSE_DECK1; setGamePhase(DUEL_STATE_CHOOSE_DECK1);
break; break;
} }
@@ -728,7 +744,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
{ {
popupScreen->Update(selectedDeck); popupScreen->Update(selectedDeck);
} }
mGamePhase = DUEL_STATE_DECK2_DETAILED_INFO; setGamePhase(DUEL_STATE_DECK2_DETAILED_INFO);
break; break;
} }
else if (controlId == MENUITEM_MORE_INFO && !opponentMenu->showDetailsScreen()) else if (controlId == MENUITEM_MORE_INFO && !opponentMenu->showDetailsScreen())
@@ -741,7 +757,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
loadPlayer(1, deckNumber, 1); loadPlayer(1, deckNumber, 1);
OpponentsDeckid = deckNumber; OpponentsDeckid = deckNumber;
opponentMenu->Close(); opponentMenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY);
break; break;
} }
break; break;
@@ -754,13 +770,13 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
deckNumber = playerDeckList->at(WRand() % (playerDeckList->size()))->getDeckId(); deckNumber = playerDeckList->at(WRand() % (playerDeckList->size()))->getDeckId();
loadPlayer(0, deckNumber); loadPlayer(0, deckNumber);
deckmenu->Close(); deckmenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY);
break; break;
} }
else if (controlId == MENUITEM_MAIN_MENU || controlId == MENUITEM_CANCEL) // user clicked on "Cancel" else if (controlId == MENUITEM_MAIN_MENU || controlId == MENUITEM_CANCEL) // user clicked on "Cancel"
{ {
if (deckmenu) deckmenu->Close(); if (deckmenu) deckmenu->Close();
mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU; setGamePhase(DUEL_STATE_BACK_TO_MAIN_MENU);
break; break;
} }
else if (controlId == MENUITEM_MORE_INFO && deckmenu->showDetailsScreen()) else if (controlId == MENUITEM_MORE_INFO && deckmenu->showDetailsScreen())
@@ -777,7 +793,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
{ {
popupScreen->Update(selectedDeck); popupScreen->Update(selectedDeck);
} }
mGamePhase = DUEL_STATE_DECK1_DETAILED_INFO; setGamePhase(DUEL_STATE_DECK1_DETAILED_INFO);
break; break;
} }
else if (controlId == MENUITEM_MORE_INFO) else if (controlId == MENUITEM_MORE_INFO)
@@ -804,12 +820,12 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
#ifdef NETWORK_SUPPORT #ifdef NETWORK_SUPPORT
if(mParent->players[1] == PLAYER_TYPE_REMOTE) if(mParent->players[1] == PLAYER_TYPE_REMOTE)
{ // no need to choose an opponent deck in network mode { // no need to choose an opponent deck in network mode
mGamePhase = DUEL_STATE_OPPONENT_WAIT; setGamePhase(DUEL_STATE_OPPONENT_WAIT);
} }
else else
#endif //NETWORK_SUPPORT #endif //NETWORK_SUPPORT
{ {
mGamePhase = DUEL_STATE_CHOOSE_DECK1_TO_2; setGamePhase(DUEL_STATE_CHOOSE_DECK1_TO_2);
} }
playerDeck = NULL; playerDeck = NULL;
} }
@@ -817,7 +833,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
{ {
loadPlayer(1, controlId); loadPlayer(1, controlId);
deckmenu->Close(); deckmenu->Close();
mGamePhase = DUEL_STATE_CHOOSE_DECK2_TO_PLAY; setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY);
} }
break; break;
@@ -828,18 +844,18 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId)
case MENUITEM_MAIN_MENU: case MENUITEM_MAIN_MENU:
menu->Close(); menu->Close();
mGamePhase = DUEL_STATE_BACK_TO_MAIN_MENU; setGamePhase(DUEL_STATE_BACK_TO_MAIN_MENU);
break; break;
case MENUITEM_CANCEL: case MENUITEM_CANCEL:
menu->Close(); menu->Close();
mGamePhase = DUEL_STATE_CANCEL; setGamePhase(DUEL_STATE_CANCEL);
break; break;
case MENUITEM_MULLIGAN: case MENUITEM_MULLIGAN:
//almosthumane - mulligan //almosthumane - mulligan
game->currentPlayer->takeMulligan(); game->currentPlayer->takeMulligan();
menu->Close(); menu->Close();
mGamePhase = DUEL_STATE_CANCEL; setGamePhase(DUEL_STATE_CANCEL);
break; break;
//END almosthumane - mulligan //END almosthumane - mulligan
+2 -2
View File
@@ -52,7 +52,7 @@ enum ENUM_MENU_STATE_MINOR
}; };
GameStateMenu::GameStateMenu(GameApp* parent) : GameStateMenu::GameStateMenu(GameApp* parent) :
GameState(parent) GameState(parent, "menu")
{ {
mGuiController = NULL; mGuiController = NULL;
subMenuController = NULL; subMenuController = NULL;
@@ -437,7 +437,7 @@ void GameStateMenu::ensureMGuiController()
mGuiController->Add(NEW MenuItem( mGuiController->Add(NEW MenuItem(
item->mActionId, item->mActionId,
mFont, item->mDisplayName, mFont, item->mDisplayName,
startX + (i * space), 50 + SCREEN_HEIGHT / 2, startX + (i * space), 40 + SCREEN_HEIGHT / 2,
mIcons[iconId].get(), mIcons[iconId + 1].get(), mIcons[iconId].get(), mIcons[iconId + 1].get(),
item->mParticleFile.c_str(), WResourceManager::Instance()->GetQuad("particles").get(), item->mParticleFile.c_str(), WResourceManager::Instance()->GetQuad("particles").get(),
(i == 0))); (i == 0)));
+1 -1
View File
@@ -17,7 +17,7 @@ namespace
} }
GameStateOptions::GameStateOptions(GameApp* parent) : GameStateOptions::GameStateOptions(GameApp* parent) :
GameState(parent), mReload(false), grabber(NULL), optionsMenu(NULL), optionsTabs(NULL) GameState(parent, "options"), mReload(false), grabber(NULL), optionsMenu(NULL), optionsTabs(NULL)
{ {
} }
GameStateOptions::~GameStateOptions() GameStateOptions::~GameStateOptions()
+1 -1
View File
@@ -49,7 +49,7 @@ bool BoosterDisplay::CheckUserInput(JButton key)
} }
GameStateShop::GameStateShop(GameApp* parent) : GameStateShop::GameStateShop(GameApp* parent) :
GameState(parent) GameState(parent, "shop")
{ {
menu = NULL; menu = NULL;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
+1 -1
View File
@@ -7,7 +7,7 @@
#include <dirent.h> #include <dirent.h>
GameStateStory::GameStateStory(GameApp* parent) : GameStateStory::GameStateStory(GameApp* parent) :
GameState(parent) GameState(parent, "story")
{ {
flow = NULL; flow = NULL;
menu = NULL; menu = NULL;
+1 -1
View File
@@ -9,7 +9,7 @@
#include "OptionItem.h" #include "OptionItem.h"
TransitionBase::TransitionBase(GameApp* parent, GameState* _from, GameState* _to, float duration) : TransitionBase::TransitionBase(GameApp* parent, GameState* _from, GameState* _to, float duration) :
GameState(parent) GameState(parent, "transition")
{ {
from = _from; from = _from;
to = _to; to = _to;
+1 -1
View File
@@ -51,7 +51,7 @@ void MenuItem::Render()
onQuad->SetColor(ARGB(70,255,255,255)); onQuad->SetColor(ARGB(70,255,255,255));
renderer->RenderQuad(onQuad, SCREEN_WIDTH, SCREEN_HEIGHT / 2, 0, 8, 8); renderer->RenderQuad(onQuad, SCREEN_WIDTH, SCREEN_HEIGHT / 2, 0, 8, 8);
onQuad->SetColor(ARGB(255,255,255,255)); onQuad->SetColor(ARGB(255,255,255,255));
mFont->DrawString(mText.c_str(), SCREEN_WIDTH / 2, 20 + 3 * SCREEN_HEIGHT / 4, JGETEXT_CENTER); mFont->DrawString(mText.c_str(), SCREEN_WIDTH / 2, 3 * SCREEN_HEIGHT / 4, JGETEXT_CENTER);
renderer->RenderQuad(onQuad, mX, mY, 0, mScale, mScale); renderer->RenderQuad(onQuad, mX, mY, 0, mScale, mScale);
} }