Tuesday, December 30, 2008

Another monolithandroid beta is out

I just released another monolithandroid beta (monolithandroid1.0.1beta.apk). It seems that most of the previous beta 1.0.0 problems were related to 3 things.
First, the prepareAsync call used in media player to play sounds caused problems. Now synchronous playback is used.
Second, The textures that I was using were pretty big. Now the texture sizes (used for the moon and earth) are reduced below 64x64 pixels. Third, I had a starfield class that drew 3d points in order to give the player the illusion of space travel. The problem was I was trying to draw 10000 points which is way too much. Now only 100 points are drawn. So go to http://code.google.com/p/monolithandroid and grab the latest apk. Give it a try on your android phone and you may even have some fun. I hope that the music won't drive you crazy! Post your comments here or use the Issue tracker found on http://code.google.com/p/monolithandroid
Oh, and don't forget to say what device you used for your tests!
I would like to take the opportunity to wish you a happy new year.

Tuesday, December 23, 2008

MonolithAndroid needs you!

That is, I need beta testers to try the game out on a real hardware device like the T-Mobile G1. Yesterday, I published MonolithAndroid version 1.0.0 on the android market. Because I live in Greece, I cannot get hold of an actual G1 Phone, so I only tested my application on the emulator. And it seems that testing on the emulator is not enough. Hours after monolithandroid was published on android market, I got a couple of emails saying that the program presented them with a black screen and they only heard some music but they saw no graphics. So I unpublished the application. And here's where I need your help.
I would like you to download the installation package from http://code.google.com/p/monolithandroid and try it out on your TMobile G1. And here's what I would like to know:

1. Does the application start?
2. Do you hear music?
3. Can you see the letters MonolithAndroid going on and off?
4. You only see a black screen?
5. If the game seems to run, does it run smoothly, or it feels sluggish?

Tuesday, September 23, 2008

Some thoughts on google android as a gaming platform

With the launch of the first android device (T-Mobile G1) just around the corner, I would like to share with you a few thoughts regarding the viability of the android platform for gaming purposes.
Android has rich multimedia and graphics api's:
1.Support for openGL/ES and 2D drawing.
2.Media api's.
3.Support for sensors (GPS and accelerometer).
4.Networking.
5.Optional touch interface.

So in theory, it should be ideal for gaming, right?

Well yes, but there are some caveats:
1. Not all devices will support touch interfaces and sensors.
2. Not all devices will have the same screen size.
3. For gaming, some sort of joystick or D-PAD device is essential. A D-PAD was standard in the various emulator images, since the first SDK, but the first device (The T-Mobile G1) comes without a D-PAD! Instead, we get a tiny trackball, not the best IO device for gaming!
So the problem is that as it seems, we will have a lot of different devices, with different configurations. Some will have touch interfaces, some will not, some will have a D-PAD, some will have trackballs, some will have acceleration sensors and so on. So, a game developer that develops for android will have the same kind of problems that a PC game programmer has. Different screen sizes and IO devices and so on... That increases the amount of time and resources a developer has to use in order to make his game playable on most phones. The same problems that drive a lot of PC game developers to game consoles.

So how can this be remedied? Well I guess that one possible solution is the introduction of a limited set of device profiles. Something like basic, gaming and advanced profiles, that will provide the developer with the same set of IO features.
Otherwise, I see a lot of developers fleeing to the apple iPhone, with it's game console simplicity, rather than the android's PC like capabilities.

I'd love to see your opinion on those thoughts, so shoot!

Tuesday, August 26, 2008

Yet another SDK update

I just returned from my summer holidays and found a brand new android SDK (0.9beta) available for download. I downloaded it, and found that it introduces a lot of changes. Packages were renamed and openGL/ES programming has changed quite a lot. Even menus are now different. So a lot of work is required to update monolithandroid in order to make it work with this SDK. Maybe I will be able to pump out a new, compatible version till the end of the week. Since this SDK is a 0.9 beta version, not a lot of things will change in the final 1.0 release and that means that the next releases will require a lot less work. And since the first android devices are scheduled for release in Q4, maybe we will be able to get our hands on a device just in time for Christmas. Now I must leave you and return to my project. I have a lot of work to do and correct some nasty bugs. Stay tuned!

Monday, August 4, 2008

Summer <> development

Summer (especially in Greece) is really counterproductive. While the android engineers are working hard to put the finishing touches on our beloved operating system, I am going to the beach every day, drinking beer and coffee, and enjoying the summer vacations. No time for android programming. Tomorrow, my girlfriend and I are going to Crete for a twenty day vacation. We are going to visit our friends in Chania, and go to the archeological sites of Knossos and Faistos. We will end up camping in Gaidouronisi and relax next to the sea. When we return I hope that a new android SDK will be available for download and that one or more devices will be scheduled for release before the end of the year. Next summer I hope that I will be travelling with my android phone.
For those who are lucky enough to be on vacation, enjoy the sea and the sun. For those of you who are still working, take care guys, and don't burnout. Take a break, too.

Tuesday, May 27, 2008

Video for monolithandroid 1.0.3c alpha

I decided to put together a video to show graphics, gameplay and music for my game, monolithandroid. Comments are welcome!

Saturday, May 24, 2008

Working with textures in android's OpenGL/ES.


As you may recall, I use textures to draw the moon backdrop for my android application, monolithandroid. Originally, I only used one texture and I used some code from Ed Burnette's forthcoming book "Hello, Android". However, I decided to add more textures in order to improve the game's graphics. So I created a class named GLTextures, that can be used to make working with multiple textures easier.
Here's the code:

package org.teacake.monolith.apk;
import javax.microedition.khronos.opengles.*;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.lang.Integer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
public class GLTextures {
public GLTextures(GL10 gl,Context context)
{
this.gl = gl;
this.context = context;
this.textureMap = new java.util.HashMap ();
}

public void loadTextures()
{
int[] tmp_tex = new int[textureFiles.length];
gl.glGenTextures(textureFiles.length, tmp_tex, 0);
textures = tmp_tex;
for(int i=0;i {
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), textureFiles[i]);
ByteBuffer bb = extract(bmp);
// Get a new texture name
// Load it up
this.textureMap.put(new Integer(textureFiles[i]),new Integer(i));
int tex = tmp_tex[i];
int width = bmp.getWidth();
int height = bmp.getHeight();
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA,width, height, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

}
}
public void setTexture(int id)
{
try
{
int textureid = this.textureMap.get(new Integer(id)).intValue();
gl.glBindTexture(GL10.GL_TEXTURE_2D, this.textures[textureid]);

}
catch(Exception e)
{
return;
}
}
private static ByteBuffer extract(Bitmap bmp)
{
ByteBuffer bb = ByteBuffer.allocateDirect(bmp.height() * bmp.width() * 4);
bb.order(ByteOrder.BIG_ENDIAN);
IntBuffer ib = bb.asIntBuffer();
// Convert ARGB -> RGBA
for (int y = bmp.height() - 1; y > -1; y--)
{

for (int x = 0; x < bmp.width(); x++)
{
int pix = bmp.getPixel(x, bmp.getHeight() - y - 1);
int alpha = ((pix >> 24) & 0xFF);
int red = ((pix >> 16) & 0xFF);
int green = ((pix >> 8) & 0xFF);
int blue = ((pix) & 0xFF);

// Make up alpha for interesting effect

//ib.put(red << 24 | green << 16 | blue << 8 | ((red + blue + green) / 3));
ib.put(red << 24 | green << 16 | blue << 8 | alpha);
}
}
bb.position(0);
return bb;
}



public void add(int resource)
{
if(textureFiles==null)
{
textureFiles = new int[1];
textureFiles[0]=resource;
}
else
{
int[] newarray = new int[textureFiles.length+1];
for(int i=0;i {
newarray[i]=textureFiles[i];
}
newarray[textureFiles.length]=resource;
textureFiles = newarray;
}
}
private java.util.HashMap textureMap;
private int[] textureFiles;
private GL10 gl;
private Context context;
private int[] textures;
}


So, what can you use this code for?
This code enables you to load resources as textures.
At first you create a GLTextures object like this:

GLTextures textures = new GLTextures(gl, context);

Then you add the resource images you want to use as textures:

this.textures.add(R.drawable.moon);
this.textures.add(R.drawable.earth);

And then you loadup the textures:

textures.loadTextures();

When you want to use the texture in your OpenGL code, you can use:

textures.setTexture(R.drawable.moon);
.
.
//OpenGL drawing code
.
.

Actually the setTexture() method calls glBindTexture() which sets the current texture to the correct one.
Of course, you have to enable textures in your OpenGL code in order to do that! If you want more details and examples study the classes GLThread, Square and GLTextures found at http://code.google.com/p/monolithandroid
As you may find, loading pictures and converting them to textures can take a lot of time, so one improvement that you can make is to create a caching scheme. You can, for example, store the textures in a file, after converting them from a picture for the first time, so the next time the application is run, it will load the textures without having to do a conversion. Happy hacking!

Sunday, May 18, 2008

A simple class for playing music and sound effects for android

I think that android has a few problems in the area of sound/music playback. After much digging, the only way that I have found to play back music and sound effects is android.media.MediaPlayer. I wanted to add music and sound effects to my game monolithandroid. So I came up with the following class, aptly named SoundSystem. This class uses a separate thread for playback, because we don't want our sound to slowdown our game rendering.


package org.teacake.monolith;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
public class SoundSystem extends Thread
{
public SoundSystem(android.content.Context context)
{
action = SOUND_DO_NOTHING;
lastEventTime= SystemClock.uptimeMillis();
this.context = context;
try
{
musicPlayer = android.media.MediaPlayer.create(context, R.raw.intro);
soundPlayerRotateBlock = android.media.MediaPlayer.create(context, R.raw.rotate);
soundPlayerExplosion = android.media.MediaPlayer.create(context, R.raw.explosion2);
soundPlayerPlaceBlock = android.media.MediaPlayer.create(context, R.raw.place);
musicPlayer.prepare();
musicPlayer.setLooping(1);
musicPlayer.seekTo(0);
soundPlayerRotateBlock.prepare();
soundPlayerRotateBlock.seekTo(0);
soundPlayerExplosion.prepare();
soundPlayerExplosion.seekTo(0);
}
catch(Exception e)
{
}
}
private void startMusic()
{
if(musicPlayer==null)
{
return;
}
try
{
if(musicPlayer.isPlaying())
{
return;
}
else
{
musicPlayer.start();
}
}
catch(Exception e)
{
}
}
private void stopMusic()
{
if(musicPlayer==null)
{
return;
}
try
{
musicPlayer.stop();
}
catch(Exception e)
{
}
}
private void playRotateBlock()
{
int duration=0;
int currentPosition=0;
if(soundPlayerRotateBlock==null)
{
return;
}
try
{
duration=soundPlayerRotateBlock.getDuration();
currentPosition=soundPlayerRotateBlock.getCurrentPosition();
//if(currentPosition==duration-1)
{
soundPlayerRotateBlock.seekTo(0);
soundPlayerRotateBlock.start();
}
}
catch(Exception e)
{
}
}
private void playExplosion()
{
int duration=0;
int currentPosition=0;
if(soundPlayerExplosion==null)
{
return;
}
try
{
duration=soundPlayerExplosion.getDuration();
currentPosition=soundPlayerExplosion.getCurrentPosition();
//if(currentPosition==duration-1)
{
soundPlayerExplosion.seekTo(0);
soundPlayerExplosion.start();
}
}
catch(Exception e)
{
}
}
private void playPlaceBlock()
{
int duration=0;
int currentPosition=0;
if(soundPlayerPlaceBlock==null)
{
return;
}
try
{
duration=soundPlayerPlaceBlock.getDuration();
currentPosition=soundPlayerPlaceBlock.getCurrentPosition();
//if(currentPosition==duration-1)
{
soundPlayerPlaceBlock.seekTo(0);
soundPlayerPlaceBlock.start();
}
}
catch(Exception e)
{

}
}
@Override
public void run()
{
while(!done)
{
switch(action)
{
case SOUND_START_MUSIC:
startMusic();
break;
case SOUND_STOP_MUSIC:
stopMusic();
break;
case SOUND_PLAY_ROTATE_BLOCK:
playRotateBlock();
break;
case SOUND_PLAY_EXPLOSION:
playExplosion();
break;
case SOUND_PLAY_PLACE_BLOCK:
playPlaceBlock();
break;
}
action=SOUND_DO_NOTHING;
try
{
java.lang.Thread.currentThread().sleep(100);
}
catch(Exception e)
{
}
}
}
public boolean done;
public final Handler messageHandler = new Handler() {
@Override
public void handleMessage(Message msg)
{
try
{
action=msg.what;
}
catch(Exception e)
{
}
}
};
private android.content.Context context;
public long lastEventTime;
public int action;
public static final int SOUND_DO_NOTHING=-1;
public static final int SOUND_START_MUSIC=0;
public static final int SOUND_STOP_MUSIC=1;
public static final int SOUND_PLAY_ROTATE_BLOCK=2;
public static final int SOUND_PLAY_EXPLOSION=3;
public static final int SOUND_PLAY_PLACE_BLOCK=4;
private android.media.MediaPlayer musicPlayer;
private android.media.MediaPlayer soundPlayerRotateBlock;
private android.media.MediaPlayer soundPlayerExplosion;
private android.media.MediaPlayer soundPlayerPlaceBlock;
}


As you can see the run() method calls the appropriate method for playing each sound, depending on the message received. How do we send a message to the thread? By using the following code:


android.os.Message message = android.os.Message.obtain(soundSystem.messageHandler, SoundSystem.SOUND_START_MUSIC);
message.sendToTarget();


Notice that we use a MediaPlayer object for each sound. I don't know how heavyweight the MediaPlayer object is, and if it is suitable for use for playing 10's or even 100's of sounds. So that could be a problem if you use a lot of sounds for your game. Also, we use synchronous playback, and that could be a problem, too, if our sounds are long. But since it is only version 1.0, it will be improved

Thursday, May 15, 2008

Porting monolithandroid from m3 to m5


The application that I am developing, monolithandroid, currently does not run under m5 series SDK. Why? My app uses OpenGL/ES and there have been significant changes to the way OpenGL/ES works under android from m3 to m5. In a nutshell, in m3 you can use a plain view and intermix OpenGL and Canvas calls. In m5 this is not currently allowed. This was a major problem because the onPaint method of the View Object was used to draw text such as score and level information, as well as the application backdrop (a picture of the moon). There are ways to circumvent these problems and fix the application so that it works on m5. How? You can use a SurfaceView to draw the OpenGL objects, and you can use an overlay to draw text on top of the SurfaceView. And the backdrop? Actually you can use a textured image (an OpenGL object) to draw the backdrop, with the added bonus that you can easily rotate and scale the image. To sum up, monolithandroid under m3 used a class named GLView to draw everything on screen. For m5, 4 new classes were introduced in place of GLView:
  1. GameOverlay (used for drawing status text and scores)
  2. GameSurfaceView (used for holding a surface for OpenGL drawing)
  3. GLThread (used for actually drawing OpenGL objects)
  4. Square (used to load a textured square for the backdrop image of the moon)
In order to create an overlay, you can use the following code


public void onCreate(Bundle icicle) {
super.onCreate(icicle);
overlay = new GameOverlay(this);
optionsView = new OptionsView(getApplication());
android.content.AssetManager mgr = getApplication().getAssets();
gsf = new GameSurfaceView(this,overlay);
gsf.setViewType(GLThread.VIEW_GAME);
gsf.setGameType(Monolith.GAME_MONOLITH);
setContentView(gsf);
gsf.setVisibility(View.VISIBLE);
this.addContentView(overlay,new android.view.ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT,android.view.ViewGroup.LayoutParams.FILL_PARENT));
}
You can browse the full code at http://code.google.com/p/monolithandroid/source/browse

It is under svn->trunk->monolithandroid->src->org->teacake->monolith
So after I made these changes, monolithandroid sort of works. However, there are some problems to be addressed, like the time it takes on startup to load the moon image and convert it into a texture.
I would like to take the opportunity to thank Ed Burnette for sending me a preview PDF of his forthcoming android book, "HelloAndroid", and I must say that it looks very, very promising. Way to go, Ed! You can find out more about it at: http://www.pragprog.com/categories/upcoming
I admit that I shamelessly copied some code (the code for loading textures) from it.
Also I would like to thank plusminus and all the guys at http://www.anddev.org where you can find many interesting tutorials, like the following: http://www.anddev.org/textured_cube_opengl_code_sample-t813.html
Excellent work, guys.

Friday, May 9, 2008

I did not win Android Developer Challenge but it's OK

A couple of hours ago I received an email from google that informed me that I am not one of the winner of Android Developer Challenge. To tell you the truth I was not dissapointed. I did not put a lot of hours behind my application, it did not exploit a lot of the platform features and more importantly, it was unoriginal. I am sure that Google's intent behind Android Developer Challenge is to promote original applications, that showcase their platforms strengths. MonolithAndroid (my app) on the contrary only shows OpenGL/ES and touch screen functionality.
To sum up (monolithandroid versus the winning apps):

So from the above, it is easy to see why my poor tiny app did not win ADC, and why I am not whining about it. The question is, can this meek app be transformed into a winner? I don't know, but I will do my best to make it better. And since it is open source, you can take a shot at it!
On Monday we will probably have more information about the winning applications, and see how good they are. Until then, congratulations to the winners (for winning!) and the loosers (for trying). Cheers, guys.

Monday, April 14, 2008

Android Developer Challenge Part One Ends Today

Today the first part of Android Developer Challenge (ADC) ends. Good luck to all the folks who submitted an application! So in a few days or weeks we should have a new version of the SDK released, because Google did not want to release another SDK release before ADC ended, not to further confuse developers. As a lone developer, I depend on a stable SDK and toolchain and I think that the next releases of the SDK will fix things without breaking existing stuff. As you may have noticed, I did not update MonolithAndroid for the m5 series SDK, because I got an error message that informed me that the functionality I intended to use is currently broken and will be fixed in a future version of the SDK. I decided to wait for the fix, because I didn't have the time to change my code. Also, out of laziness and being put down by the major SDK changes of m5 series, I did not add any of the originally planned functionality to MonolithAndroid. Now that ADC is over, I will take my time in developing this little baby project of mine.

Wednesday, February 13, 2008

The new SDK killed my app, well almost :-(

Finally the new Android SDK (named m5-rc14) is here! So I eagerly downloaded it. Well the good news is that now Android has a brand new UI, and some enhancements. The bad news is that monolithandroid refuses to work. Hmm... you might think, maybe with a little bit of tweaking here and there you are only a few lines of code away from your app working again. Well, that maybe the case for most android apps written with the previous SDK, but not with mine.
Yes I have made the necessary changes to android.xml, and to various other xml files, and I even replaced a few method calls here and there, but the problem is that when I run my app in the emulator I get the following window.

That means, my fellow androids, that without major code changes, my app is not going to work with the current version of the android SDK! For now, if you want to use OpenGL/ES you HAVE to use surface view! Ouch! So back to the drawing board! I hope that I will be able to update my code soon. But I shouldn't complain! That's the price that an early adopter has to pay...

Waiting for the new android SDK

As some of you may have noticed I've put monolithandroid development on hiatus. The reasons: Some personal mishaps (which include my broken elbow, my desktop computer dying of old age and increased workload in my dayjob). But the main reason is that I am waiting for the brand new release of the Android SDK. I hope that the new SDK will correct a few bugs and that an increased number of API's and documentation will become available (for example javax.sound.sampled and javax.sound midi). The new SDK will sport a new UI as I hear (designed by TAT?). In the meantime, in Barcelona, Mobile World Congress is taking place. I wish I was there because I hear that a few manufacturers are demoing android powered devices and the first reviews are really positive! But no sign of monolithandoid so far ;-). Hey guys, monolithandroid is free software, load it up to your devices, I want to see it running in real hardware!

Thursday, January 3, 2008

Coding slows down when you have a fractured elbow.

Programming in the Android platform is very exciting. Unfortunately for me, it can be very slow, because from Saturday I have a fractured elbow. I went to the countryside to help my girl to handpick the olives from her olive trees. Where I live (that is Kalamata, Greece), everyone has at least one field planted with olive trees. And from November till February most folks are handpicking their olives. While I was at the field, I slipped and I unconsciously used my left arm (which is the one I use the most) to stop my fall. But in the process, I hit my elbow pretty hard. I went to the hospital and the X-Rays showed that I broke a bone near my elbow. So now my hand is tied and I can only move my fingers. The doctor said that my arm should remain tied for 15 days. So coding for MonolithAndroid will be slower. Arrgh!

Wednesday, January 2, 2008

MonolithAndroid. Block game for the android platform.

It's been a while since I created this blog. The fact that I made no posts since October does not mean that I sat idle. On the contrary the end of 2007 has been very active programming-wise. I was experimenting with the SDL library, when I realized that it would be nice to build a game in order to learn a few things. Two weeks later, I had an SDL version of tetris, with the added bonus that the rendering was done using open GL. Some of the code for the tetris game came from a tetris version I created 4 years ago, during a hot Greek August for the Mobile Windows Platform (Written in Visual C++). Creating the SDL rewrite of the app was easy, and using openGL made possible the rotation of the playfield using the mouse. I added a crude explosion effect when the player completed lines, and I came up with a rough 3d font rendering routine. All in all a nice programming project (done with Visual Studio 2005).

In parallel, I was toying with the sony PSP (playstation portable). I was trying to install and learn the open source pspsdk. After several attempts, I had an almost working version on my laptop. The next step was: "Wouldn't be cool, if I ported the sdltetris game to the psp?" PSP supposedly has SDL support so that would be a breeze eh? Well no it wasn't because I couldn't make the pspSDK SDL library work properly. The OpenGL part was misconfigured, or I don't know what. So I decided to bite the bullet and rewrite the game using psp sdk calls. It was coded in c++ using the gcc compiler and notepad++ as the editor. That took almost two weeks and the result is monolithpsp found in here: http://monolithpsp.googlecode.com

What's next? The launch of the Android platform, of course. Google launched the Android platform on November. When I read the first details, I decided to take a look at the Android SDK. After a few skimming on the API details, I saw that the platform supported OpenGL, so I decided to port my monolithpsp game to the Android Platform. I must confess that Android Developer Challenge gave me one additional reason to do so. So after a week of programming, the first version of the game became reality.(I am much more proficient in java than in C++ arghhh!). For more details, check this blog again. Oh and go check out
http://monolithandroid.googlecode.com for the monolith android game. See you soon!

Search the web