My natural instinct is to be a bottom-up developer. As such, when presented with a problem, I get the overview of what needs to be done and then start building the tools and frameworks that I need to complete it. I have to fight that urge a bit and write high-level stubs, filled with FIXME and TODO descriptions of what should be plugged in.
That is where things will begin here, to allow the most visible parts (the most important parts to the user) to be stubbed first. This forces the people writing the guts to see them on a regular basis and hopefully clean them up or make suggestions to better them.
So, where do we start? Pick a platform. As I happen to have an Android phone and the SDK installed, it makes an obvious choice. If you do not have it installed, install it, eclipse, and the android plugins for eclipse. You can find the SDK and, more indirectly, instructions for the plugin here: http://developer.android.com/sdk/index.html
Okay, now what? We need a project with a bunch of activities. On each, we will initially stub out some components to reach the others. While this could be done in a classic game programming style with everything relating to the game completed within a single game loop, I think it is easier -- at least initially -- to do things as separate activities or components.
Create a project called "AfroScratch" with package "com.example.afroscratch", and a new activity "TitleScreen". You can pick the version of android you wish to target, but 2.1 should provide the widest range of devices. If all goes well, and you have an AVD configured, you should be able to immediately run your new program in all of its "Hello World" glory. When satisfied that things run, start adding more activities. We need the "MainMenu" and "Game" activities to proceed, both of which should belong to the same package as the "TitleScreen". To create these, add a new class of the desired name and package with the superclass as "android.app.Activity".
To make things more modular, we need multiple views (layouts) defined. The default "main.xml" should be renamed to "titlescreen.xml", and another should be added for each of the activities you added above, noting that android only allows lowercase characters for resource files. It is probably also a good habit to create a new string resource file when creating a layout, so they can both be moved to a new project if required.
Now we need to define the initial stubbed UI and hook up the controls.
Title Screen
On the title screen, we need a simple TextView that we can use to display our initial message and act as a button when someone presses it.
To do so, we define the layout in res/layout/titlescreen.xml as:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/TitleText"
android:id="@+id/TitleScreenButton"
/>
</LinearLayout>
That defines a new ID for the control as "TitleScreenButton" and uses a string reference from a newly-added res/values/titlestring.xml:
<?xml version="1.0" encoding="utf-8"?>A run can be done to show what the title screen looks like (just a text label), but it still does not do anything. To make it useful, we need to add a time-delay switch to the MainMenu activity and a button-press action to do the same.
<resources>
<string name="TitleText">Click here to skip the title screen</string>
</resources>
With android applications, it should be noted that all updates to controls must be done through the main thread. It is possible to schedule the main thread to call back at a later time to update something. We are going to use this behavior to add our time-delay switch. Although not technically necessary for switching activities, this may serve useful in your future projects.
Our time delay will make use of a android.os.Handler and a Runnable in src/com/example/afroscratch/TitleScreen.java:
package com.example.afroscratch;
import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.TextView;
public class TitleScreen extends Activity implements View.OnClickListener{private static final String LOG_TAG = "TitleScreen";private void switchToMainMenu(){// Switch to the new activity.startActivity(new android.content.Intent(getApplicationContext(), MainMenu.class));finish(); // Quit the current activity
}private int m_countdown = 10;private void updateCountdown(){Log.d(LOG_TAG, "run called with countdown=" + m_countdown);if( m_countdown > 0 ){// Decrease the timer by a second and force the handler to update again in the main thread.--m_countdown;m_handler.postDelayed(m_updateTask, 1000);return;}
switchToMainMenu();}private android.os.Handler m_handler = new android.os.Handler();private Runnable m_updateTask = new Runnable() {public void run(){updateCountdown();}};public void onClick(View v){// Stop the timer.m_handler.removeCallbacks(m_updateTask);switchToMainMenu();}/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.titlescreen);// Tell the TextView to notify us when it is clicked.TextView tv = (TextView)findViewById(R.id.TitleScreenButton);tv.setOnClickListener(this);// Start the timeout update cycle, giving time for this function to return.m_handler.postDelayed(m_updateTask, 100);}}
For the activity switch to actually work, the target activity must be listed in the AndroidManifest.xml:
<activity android:name=".MainMenu" android:label="@string/app_name" />
<activity android:name=".Game" android:label="@string/app_name" />
We still need some glue for the main menu and the game. The activity switch from the main menu to the game will be done in the same manor as from the title screen to the main menu, with the exception of the timer.
More resources and glue are needed...
MainMenu:
- res/layout/mainmenu.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/Welcome"
android:id="@+id/WelcomeLabel"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/NewGame"
android:id="@+id/NewGameButton"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/Quit"
android:id="@+id/QuitButton"
/>
</LinearLayout>
- res/values/mainmenu.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="Welcome">Welcome to AfroScratch</string>
<string name="NewGame">New Game</string>
<string name="Quit">Quit</string>
</resources>
- src/com/example/afroscratch/MainMenu.java:
package com.example.afroscratch;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainMenu extends Activity implements OnClickListener
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mainmenu);
Button newGame = (Button)findViewById(R.id.NewGameButton);
Button quitButton = (Button)findViewById(R.id.QuitButton);
newGame.setOnClickListener(this);
quitButton.setOnClickListener(this);
}
public void onClick(View v)
{
if( v.getId() == R.id.QuitButton )
{
finish();
}
else if( v.getId() == R.id.NewGameButton )
{
startActivity(new android.content.Intent(getApplicationContext(), Game.class));
}
}
}And finally the game screen:
- res/layout/game.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="FIXME! Replace me with a game display" />
</LinearLayout>
- src/com/example/afroscratch/Game.java:
package com.example.afroscratch;
import android.app.Activity;
import android.os.Bundle;
public class Game extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
}
}
If all goes as planned, the title screen should appear for about 10 seconds, switching automatically to the main menu. Switching can be done faster by clicking on the title screen's one and only label.
No comments:
Post a Comment