3
\$\begingroup\$

My game uses openGL ES 2.0 on Android and it's got to the point where the pause (while loading resources) has become noticeable.

All I'm after is to show a static screen (probably via an XML layout if it's the simplest way, but through openGL is OK too). And then dismiss the view and switch to the game.

I'm loading my resources in the onSurfaceCreated method of my GLSurfaceView class and creating my sprite objects in my onSurfaceChanged method (I need the width and height to scale them, so do it here, plus Google's docs recommend it). I don't load my resources in onCreate.

I've tried creating a simple XML layout called 'loading' and putting something like this into my glSurfaceView class's constructor (glSurfaceView being an inner class of my Activity class)....

public MyGLSurfaceView(Context context) {
        super(context);
        {
loading_dialog = new Dialog(context,android.R.style.Theme_Black_NoTitleBar_Fullscreen);
loading_dialog.setContentView(R.layout.loading);
loading_dialog.show();
}

This displays my 'loading' screen OK, but I need to call:

loading_dialog.dismiss();

at the end of my onSurfaceChanged method in my GLSurfaceView.Renderer class. I obviously can't do this as the GLSurfaceView.Renderer class has no knowledge of the loading_dialog object.

I tried to create the object directly in the GLSurfaceView.Renderer class, but I don't have access to the context from here, so I tried to pass it in from the Activity class but then I got different errors at which point, I searched the net and couldn't find a clear answer on how to do this so thought I would post here in the hope that someone could point me in the right direction.

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Thank you very much for the answer below, however, I worked out a way to do this. It works, so I am going to post here in case it helps someone else.

In Activity class - in onCreate, get object to Splashscreen class and pass in width and height

    DisplayMetrics display= new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(display);
    width = display.widthPixels;
    height = display.heightPixels;

    Splashscreen splash = new SplashScreen(this.getApplicationContext(), width, height);

In 'MyGLSurfaceView' class constructor (which is an inner class of my Activity class) , I have the following:

public MyGLSurfaceView(Context context) {
        super(context);

            //Create dialogue which will be displayed over the GLSurfaceView while resources load
            Dialog loading_dialog = new Dialog(context,android.R.style.Theme_Black_NoTitleBar_Fullscreen);
            //Set it
            loading_dialog.setContentView(splash);
            //Show it
            loading_dialog.show();

            //You would have already setContentView to your GLRenderer earlier in
            //onCreate, this just goes over the top of it

            //Get object to renderer class and pass in dialogue through constructor
            renderer = new MyGLRenderer(this, loading_dialog);

Then I have my splashscreen class which uses a simple view (as I only want a basic screen with the ability to add simple animation if I want to later).

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.View;

public class SplashScreen extends View{

Bitmap loader;
Bitmap loaderScaled;
int width;
int height;

@Override
protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    //Show Scaled bitmap.
    canvas.drawBitmap(loaderScaled, x, y, null); //you can define x and y
}

public SplashScreen(Context context, int width, int height) {
    super(context);
    // TODO Auto-generated constructor stub

    this.width = width;
    this.height = height;

    //Initial Bitmap
    loader = BitmapFactory.decodeResource(getResources(), R.drawable.loading);
            //Create scaled bitmap
    loaderScaled = Bitmap.createScaledBitmap(loader, (int) (width*.25), (int) (height*.13), true);
    //And recycle the original bitmap as we no longer need it
    loader.recycle();

}



}

Then all you need to do is load your resources (I load mine in onSurfaceCreated). At the very end of onSurfaceChanged, just put the following to dismiss the loading screen and reveal you Open GL Renderer....

loading_dialog.dismiss();

It works, I've tested it on a couple of devices, There are a couple of small problemsso I'm going to improve it but the basics are there for a very simple splash screen. I hope it helps others who are looking for a simple solution.

PS I know instead of creating a Splashscreen class, I could simply use an XML layout, but I don't like working with XML, I find doing everything in code much more flexible.

\$\endgroup\$
0
\$\begingroup\$

Based on personal experience (although I haven't even touched OpenGL yet), my 2D game app has a main Screen class with different screens, independent of that XML layout do-hicky.

I'm not a total fan of XML because it can get kind of messy when trying to do more intricate things with that drag and drop graphics interface in the IDE (i.e., scaling, formatting the layout, etc.)

For me, making an abstract screen class, with subclasses like SplashScreen, LoadScreen, MenuScreen worked out with methods like update, pause, paint, etc. inherited from the abstract class.

Then, all you have to do in those screen classes is use Graphics g = game.getGraphics() in the paint method and then draw images an such for that screen. I then use touch event classes to declare a boundary where an event will occur in the update() method of that screen class like so:

public boolean inBounds(TouchEvent event, int x, int y, int width, int height) {
        if (event.x > x && event.x < x + width - 1 && event.y > y
                && event.y < y + height - 1)
            return true;
        else
            return false;
    }

public void updateMenuScreen() {

int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
        if (event.type == TouchEvent.TOUCH_UP) {
                if (inBounds(event, 260, 200, 300, 100)) {
                    game.setScreen(new GameModeScreen(game));              
      }

Obviously there are some other methods and classes that would make this post huge, but I hope you get the general idea that using screen classes and "buttons" (touch events) to navigate between those screens might help you. Also, don't be afraid to use the Graphics and Canvas classes for some 2D menus.

\$\endgroup\$
2
  • \$\begingroup\$ Hi A13X, I'm also not a fan of XML, my game currently doesn't have any (it just seemed the easiest way to do a splash screen). I'm not sure I understand your method, where would I load my resources? All I need to do is display a graphic while the resources load. Are you saying to have a check in my onDrawFrame method to see what should be displayed (splash, menu, game etc). because this was one way of doing it that I looked into but I decided against it as the onDrawFrame method should only have rendering code and not checks etc. if this isn't what you meant, could you elaborate? Thanks! \$\endgroup\$ Jun 15, 2013 at 19:58
  • \$\begingroup\$ You could load the resources right in the SplashScreen class, probably in the update method. I did it by having an Assets class with static images and sounds and just add Assets.checkLbl = g.newImage("checkOpt.png", ImageFormat.ARGB4444); statements in the update class. Then the paint/render (could be ported to your onDrawFrame class?) class picks it up with g.drawImage(Assets.checlLbl, x, y); \$\endgroup\$
    – A13X
    Jun 15, 2013 at 20:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .