Categories

Sunday, December 9, 2012

Create games with LIBGDX library in Android (3) - game menu basics

   Following feedback from blog visitors, I decided to make a short introduction of how to create a game menu. 

   I'll only cover the basics here and create a very simple menu: a button labeled "START GAME" . Once pressed, it immediately start the game screen.

   More complex menus will be created towards the end of the game development process, this is only a preview for those anxious to give the game a nicer look.




   ANDROID ACTIVITIES


   Every Android application contains one or more activities

   The game screen we created, which draws our world and Bob in it, and its entire management (updating, rendering, event handling), those are all contained into a single activity, named StarAssaultActivity.

   If we want to display a game menu on the screen, the simplest and most efficient way to do this is to create another activity which does exactly this - display a few buttons on the screen representing game menu's options. Clicking the "START GAME" button will do nothing more than start the StarAssaultActivity.


   MAIN MENU ACTIVITY


   Creating an activity is usually a 3-step process:

1) Create a layout for the activity


   The layout is the screen that is displayed by any activity. A layout can contain text, buttons to be pressed, text-input areas, display images etc., and may also display our own drawings (for which we use libraries like libgdx). Layouts have a lot of properties (e.g. specifying whether it's displayed in portrait or landscape mode) which you will learn in time. There are many things to learn about layouts, but you'll pick up new things on the way. When you need a certain feature, you'll look for it in examples, tutorials or documentation and learn to use it.
    
   The layout for our StarAssaultActivity has some properties which we haven't been interested in so far because we used libgdx to draw upon it. However, the layout is there and we can visualize it's content by browsing our project to the res/layout folder. There you'll find the layout with the default name activity_star_assault.xml.


   As you can see, the layouts are written in XML files. If you don't know anything about XML, don't worry! I had no clue about it myself when I first started, but it soon turned out to be very easy to use and most of the code you'll write in XML will be copy/paste from other projects. I learned it fast and easy also because I had previous knowledge of HTML and Javascript. If you know HTML then you'll understand the structure of a XML file easily. If you don't you'll just have to pay a little attention as the best way to learn it is by example.

   Note that once you open an XML file, there are usually two options of visualizing it. Note that under the contents of the file (the lines of code) there are two tabs: Graphical Layout and activity_star_assault.xml.
   The latter is the one you can see in the figure and it's exactly the code. The former view type shows you how the layout will be seen on screen. Making modifications in the code will change the graphical layout. This is pretty obvious. The important thing to note is the reverse: you can create a XML file directly in the graphical layout view, where you can easily drag and drop elements (text, buttons etc.) and the code will be auto-modified to match the new layout. This is pretty cool as it saves you from memorizing XML keywords and structure names.

   In this case, when I created the project, the layout was auto-generated with the ability to display "Hello world" in the middle of the screen. However, because we used libgdx to draw things, that text was never seen when we ran our application.

   Designing layouts is another topic that will be covered in another future tutorial. For now, just do the steps I tell you to create a very basic main menu layout.

  • right-click the layout folder in the package explorer (left side of the screen), choose New and then Android XML file.
  • in the window that appears, type the file name activity_main, leave everything else as it is and click Finish
  • the newly created file will open, containing a few lines; you notice the first line contains the <?xml> tag which specifies the version, and then the <LinearLayout> which tells you the created layout is linear, unlike the one auto-generated in the first layout, which was a RelativeLayout.
  • click on the Graphical layout tab just under the code and a display of the layout will appear - it's an empty screen for the moment
  • in the left side of the view there's a Palette containing elements that you can add to the layout, grouped intro multiple categories; from the Form Widgets category click the Button element and drag it into the layout; it will automatically be placed in the upper-left corner (because it's a LinearLayout)

   The layout design is not important for the moment, so we'll just leave the button where it is. Now go back to the XML code by clicking the other tab under the view and notice the modifications.

   A new structure with the tag <Button> was added. You can see some basic default properties for the new button. Among them, the android:text specifies the text displayed on the button. Replace the entire line with the following:

                android:text="@string/main_game"

and of course make sure the /> symbol marking the end of the <Button> is still there. Since an application may run in multiple languages, we don't want to hard-code the text that appears in our activity, so instead of android:text="START GAME" we chose to add a resource string containing the text for the button. Now you need to go in the package explorer, in the res/values folder and open the strings.xml file. As any XML files, it has two tabs under the view. In the Resources tab, click the Add... button, choose String then OK. Click on the newly added resource, and in the right its properties appear. For the Name write main_game and the Value will be START GAME.

   Now the layout is done. You may close the strings.xml file, save all and then look back at your layout, you'll notice it's text has changed.

2) Create the class for the activity


   Now we're finally going back to our familiar Java code to create the class containing the activity.
   In the package explorer, open the src folder, right-click the net.obviam.star-assault-android package and choose New then Class. Enter the name MainMenuActivity.java and click Finish.

   Replace the auto-generated content of the class with this:


package net.obviam.star_assault_android;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainMenuActivity extends Activity {
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
 }

 public void startGame(View clickedButton) {
                Intent newActivity = new Intent(this, StarAssaultActivity.class);
                startActivity(newActivity);
 }
}

   Our class is a subclass of Android's basic Activity class because this is the type of classes where Android searches an application to run (that's all you need to know for now). The StarAssaultActivity class extends AndroidApplication which itself is a subclass of Activity.
 
   The onCreate function is called automatically when the activity starts, so that's where we specify what to draw on the screen (the activity_main layout) using the setContentView function.
 
   We also created a public void function called startGame which I'm guessing you've already figured out what it does: when it is called, it creates and starts a new activity, defined by the StarAssaultActivity class.

   Now we're almost ready.


3) Link the .java and the .xml files


   First, we need to tell the button in the main screen what to do when it is clicked.

   For that, go to the activity_main.xml file, and inside the Button tag add the following property for the button: 

                android:onClick="startGame"

   Easy to see, this tells the button to execute the startGame function when it's clicked. The function must be defined inside the activity class that uses this layout (which is done already from previous step).

   As you can see, Android is a mixture between Java code and XML files. XML files are used for resources (layouts, strings, images, sounds), while Java code provides game functionality. 

   There is a "main" XML file which contains very important information: the AndroidManifest.xml file. Locate it in the package explorer, in the project root, down after the res folder, and open it.

   As you can see, it provides information about application version, SDK version and other things. More important for us, it specifies the activities that the application must start when it is launched by the user.
   Activities are, obviously, declared withing the <activity> tag. Right now, the StarAssaultActivity is declared as the MAIN activity, and that's why it is started when you run the application.

   What we'll do is change this file by declaring the MainMenuActivity as MAIN and specify that this activity may at any point start the StarAssaultActivity itself.
  
   Replace the contents of the AndroidManifest.xml file with this:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="net.obviam.star_assault_android"
    android:versionCode="1"
    android:versionName="1.0" 
    >
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainMenuActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                
            </intent-filter>
        </activity>
        <activity 
             android:name=".StarAssaultActivity"
                  android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
         </activity>
  

    </application>

</manifest>

   Note the line android:screenOrientation="landscape". It tells the manifest to always start this activity in landscape mode.


   Everything is ready now! Save all and run the app on your device (or emulator).

   From within the game you can go back to the menu anytime by pressing the BACK button on the device (emulator).


  You may download the full source code here: Star Assault project source code

  Jumping and other features coming up soon!

16 comments:

  1. Wow that was fast thank you so much!!! Continue this wonderful project!!

    ReplyDelete
    Replies
    1. No problem :) I hope I was clear enough with the explanations. Also please feel free to invite your friends and tell other people about this tutorial so we can brainstorm together towards completing it!

      Delete
  2. when is the next one coming out? I'm looking forward to it!!

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. is the next one going to be on terrain interraction (but in the y axis)?

    ReplyDelete
    Replies
    1. yes of course! Sorry for being late with the tutorial, but I've been caught up in the heat of the holidays now. Next part is coming up soon.

      Delete
  5. Hey I just wanted to let you know that I appreciate the continuation of this tutorial

    ReplyDelete
    Replies
    1. Thanks! I'm preparing lots of good things to come next on this blog so stay tuned.

      Delete
  6. Hey
    Does anyone know how you might implement multiple levels based on the world class we have created in the tutorial. I'm kind of stuck on how to go about it. I have a method that detects the endpoint and than I coded a Level Complete screen. I guess the thing that confuses me is that on my gamescreen I getBounds of bob from the world class. So do I build levels inside the world class?

    ReplyDelete
    Replies
    1. Hi,

      Although your question is a bit confusing I'll try to give a general answer. Each level should be built into a new instance of the World class - so each level is a World object, properly initialized with blocks and people. Also, each Bob object belongs to each World so that's why when you want Bob's bounds you get them from within the World object via its own Bob object.

      Hope this helps.
      If not, please be more specific on what you want.

      More on this we'll see once we add multiple levels in our tutorial.

      Delete
    2. Basically you want to take out everything that represents the actual world (just blocks really in this case) from the world class, then you want to create different classes for each new level, have each one extend the world class, and call the super constructor. Check out this page
      https://code.google.com/p/steigert-libgdx/source/browse/trunk/tyrian-game/src/com/blogspot/steigert/tyrian/#tyrian%2Fscreens
      if you see the abstractscreen.java is somewhat acting as our world class would. And the levelscreen.java would be like your individual levels. Maybe that helps?

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. so... when is next one coming out? I'm really looling forward to this one!

    ReplyDelete
    Replies
    1. I'm very sorry for not keeping my word, I've been very busy with the job and exams at master. I'll definitely post something this week.

      Delete
    2. awesome, i am waiting longingly ;)

      Delete