Kilobolt
  • Home
  • Tutorials
    • Game Development Tutorial >
      • Unit 1: Beginning Java >
        • Before you begin...
        • Day 1: Setting Up
        • Day 2: Java Basics
        • Day 3: More Basics
        • Day 4: Java Math
        • Day 5: More Math
        • Day 6: If... else...
        • Day 7: More Control Flow
        • Day 8: Looping
        • Day 9: More on Looping
        • Day 10: Inheritance, Interface
        • Day 11: Threads and Graphics
      • Unit 2: Creating a Game I >
        • Day 1: Foundations
        • Day 2: Basic Framework
        • Day 3: Taking User Input
        • Day 4: Enter the Robot
        • Day 5: Background and Sprites
        • Day 6: Adding Enemies
        • Day 7: Shooting Bullets
        • Day 8: Animations
        • Day 9: 2D-Arrays
        • Day 10: Painting the Tilemap
      • Unit 3: Creating a Game II >
        • Day 1: Level Creation - Part 1
        • Day 2: Level Creation - Part 2
        • Day 3: Level Creation - Part 3
        • Collision Detection Basics
        • Day 4: Collision Detection Part 1
        • Day 5: Collision Detection Part 2
        • Day 6: Collision Detection Part 3
        • Day 7: Health System & Death
        • Day 8: Basic AI & Final Touches
      • Unit 4: Android Game Development >
        • Day 1: Introduction to Android
        • Day 2: Setting up for Development
        • Day 3: Creating our First Android Application
        • Day 4: Parts of an Android Application
        • Day 5: The Android Game Framework: Part I
        • Day 6: The Android Game Framework: Part II
        • Create an Android Game From Scratch (or port your existing game)
        • Day 7: Creating an Android Game (From Start to Finish)
      • Reference Sheet
    • Zombie Bird Tutorial (Flappy Bird Remake) >
      • Unit 1: Building the Game >
        • Introduction
        • Day 1: Flappy Bird - An In-depth Analysis
        • Day 2: Setting up libGDX
        • Day 3: Understanding the libGDX Framework
        • Day 4: GameWorld and GameRenderer and the Orthographic Camera
        • Day 5: The Flight of the Dead - Adding the Bird
        • Day 6: Adding Graphics - Welcome to the Necropolis
        • Day 7: The Grass, the Bird and the Skull Pipe
        • Day 8: Collision Detection and Sound Effects
        • Day 9: Finishing Gameplay and Basic UI
        • Day 10: GameStates and High Score
        • Day 11: Supporting iOS/Android + SplashScreen, Menus and Tweening
        • Day 12: Completed UI & Source Code
    • Android Application Development Tutorial >
      • Unit 1: Writing Basic Android Apps >
        • Before you begin...
        • Day 1: Android 101
        • Day 2: Getting to Know the Android Project
        • Day 3: The Development Machine
        • Day 4: Building a Music App - Part 1: Building Blocks
        • Day 5: Building a Music App - Part 2: Intents
        • Day 6: Building a Music App - Part 3: Activity Lifecycles
  • New Forum
  • About Us
    • Contact Us
  • Our Games
    • TUMBL: FallDown
  • Facebook
  • Twitter

GAME DEVELOPMENT TUTORIAL: DAY 2-2: Basic Framework

10/5/2012

49 Comments

 
Picture
I've been thinking about the direction that I want to go with this game, and as of now, I am considering making it a game about a Q-bot (cube robot)* going around shooting things and jumping across platforms. Two games that I am taking inspiration from are Metal Slug and Megaman.

As we get deeper into the series, I want to add character upgrades, different types of platforms and power ups, and much more.

But first, let us talk about the game thread and the game loop.

(*Name not final)

Lesson #2-3: Implementing a Thread:
As mentioned in the previous unit, threads are a way of running simultaneous processes. 
We will be adding a thread to our code like so:

Figure 2-4: start() in StartingClass.java

 @Override
public void start() {
Thread thread = new Thread();
thread.start();
}

Simple right? The first line creates a new instance of a thread (a Thread object called "thread"), and the second line starts the thread.

When you call: thread.start(); , however, nothing will happen. Why?

Refer to this example from Lesson #1-21:

Figure 2-5: Example of a Thread

 Thread thread = new Thread() {
public void run() {
for (int i = 0; i < 10; i += 2) {
System.out.println("hello");
}
}

};
Threads require a run method that determines what will happen in that thread. In Figure 2-4 we never declared a run method. There's a reason for this. We will be extracting the run method from the thread and creating a separate method in the class by doing the following:

1. Implement the Runnable interface by adding: "implements Runnable" to the class declaration like so:

public class StartingClass extends Applet implements Runnable{...

2. Create a run() method in the class by typing out run and then pressing Ctrl + Space and selecting the first option: run() : void. It will auto complete the method for you.

When you try to create a run method, it will give you the following information:
Picture
This tool tip describes that when we implement interface, we can extract the run method from the Thread that we created. 

So to "bridge" or connect this newly created run() method and the thread that we have created above:

3. Go back to this statement in the start method:

Thread thread = new Thread();

and add "this":

Thread thread = new Thread(this);

We will talk more about "this" in the future. It is quite a flexible keyword, and therefore I think it's best if we talk about it from another perspective with more understanding. For now, think of it as "this" class. More specifically, "this" instance of the class.

The final result:

Figure 2-6: StartingClass.java

 package kiloboltgame;

import java.applet.Applet;

public class StartingClass extends Applet implements Runnable {

@Override
public void init() {

}

@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}

@Override
public void stop() {
// TODO Auto-generated method stub
}

@Override
public void destroy() {
// TODO Auto-generated method stub
}

@Override
public void run() {
// TODO Auto-generated method stub
}
}
Lesson #2-4: Creating the infinite game loop:
In this lesson, we will be creating a game loop. I mentioned in Day 1 that a game loop is the heartbeat of the game. It constantly checks for changes and makes updates to the game accordingly.

More sophisticated game loops will be used in our later games, but for our purposes, all our game loop needs to do is the following:

1. Update characters
2. Update environment
3. Repaint the scene.
4. Sleep for 17 milliseconds.

Why 17 milliseconds you ask? I'll tell you why.

I'm sure many of you know that when you go on YouTube and watch the Epic Rap Battles or something, you are seeing a sequence of still images that are changing fast enough to give your brain the illusion of fluid motion. The number of times that the image changes in one second is referred to as FPS or frames per second (frame rate). 

At about ~30, we are able to see a smooth movement in games and movies; however, 60 fps is what most people consider an ideal to have no noticeable glitches or stuttering. 

Sleeping for 17(1000/60) milliseconds each time that the game loop runs means that the game will update every 17 milliseconds (which results in 60 updates per second). Of course this assumes that the computer is capable of handling the processes every 17 milliseconds and can be disastrous when the machine slows down (hence this is a bad game loop), but for the purposes of our simple Java game on your modern day computer (and for this beginner's tutorial), it is simple, effective, easy to implement, and very intuitive. 

So first we create a game loop in the run() method of the class:

1. This loop will be a while loop, and will run indefinitely. To make a while loop run forever, we just write true as the condition for the loop:

while(true){


}

2. Within this add the following segment of code:

repaint(); // this calls paint

try {
   Thread.sleep(17);
} catch (InterruptedException e) {
   e.printStackTrace();
}



Your run() method will look like this:

Figure 2-7: run() in StartingClass.java

 @Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Let's look at this line by line:

repaint(); - built in method - calls the paint method (in which we draw objects onto the screen). We haven't created the paint method yet, but every 17 milliseconds, the paint method will be called..

Whenever we do something that may fail (like Thread.sleep(17);) the Java Compiler gives us an error saying that we need to surround the statement with a Try and Catch.

Picture
Surround with try/catch - error
What a try/catch does is the following.

1. In try, we attempt to do something, like sleep.
2. If something goes wrong, then the catch will save information regarding errors, and will print it to a console. 

Don't worry too much about it. It's just a built-in fail-safe system. It won't fail here. Just click the suggested quick fix.

At this point the StartingClass.java will look like this:

Figure 2-8: StartingClass.java

 package kiloboltgame;

import java.applet.Applet;

public class StartingClass extends Applet implements Runnable {

@Override
public void init() {
}

@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}

@Override
public void stop() {
// TODO Auto-generated method stub
}

@Override
public void destroy() {
// TODO Auto-generated method stub
}

@Override
public void run() {
while (true) {

repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}
Lesson #2-5: Defining size, background, and title.
This will be a short lesson that should wrap up most of our setup process.

We briefly talked about the four methods that we setup in Day 1: init(), start(), stop(), and destroy().

These four methods run according to the program's life cycle. We will now discuss the init() method.
When the applet runs for the first time, it will run the init() method (much like how a typical program runs the main(String args[]) method). 

So within this method, we define certain parameters for the applet including:

1. Size of the applet
2. Background color.
3. Applet Title.

Inside this method, we will be adding

1. setSize(800, 480);
to change the size to 800 pixels by 480 pixels (the most common Android resolution)

2. setBackground(Color.BLACK);
to set background with the Color Black. NOTE: Color.BLACK refers to a constant called BLACK in the Color superclass, and hence you must import Color:
Picture
To use a constant from the Color superclass, we must import the Color superclass.
3. setFocusable(true);
This statement makes sure that when the game starts, the applet takes focus and that our input goes directly into it. If this is not enabled, then you would have to click inside the applet before it starts handling keyboard events.

4.  Frame frame = (Frame) this.getParent().getParent();
     frame.setTitle("Q-Bot Alpha");


Here again, you must import Frame to create a Frame object called frame. This is slightly complicated, but just know that the first line assigns the applet window to the frame variable an the second line just sets the title to be Q-Bot Alpha. 

At this point, you will have this:

Figure # 2-9: StartingClass.java, end of Day 2

 package kiloboltgame;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Frame;

public class StartingClass extends Applet implements Runnable {

@Override
public void init() {

setSize(800, 480);
setBackground(Color.BLACK);
setFocusable(true);
Frame frame = (Frame) this.getParent().getParent();
frame.setTitle("Q-Bot Alpha");
}

@Override
public void start() {
Thread thread = new Thread(this);
thread.start();
}

@Override
public void stop() {
// TODO Auto-generated method stub
}

@Override
public void destroy() {
// TODO Auto-generated method stub
}

@Override
public void run() {
while (true) {

repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Short Cut Reminders:

Ctrl+Shift+O: Auto import code (may import the wrong classes)
Ctrl+Shift+F: Auto format code into proper indents
Ctrl+Space: Open auto complete suggestions.

Thank you everyone for reading, and feel free to leave comments and questions below!
Picture
From now on, I will be including the project folder as a source code for people who don't want to write their own code, or just want to examine their own.
KiloboltGame - Day 2
File Size: 9 kb
File Type: zip
Download File

Instructions on importing projects can be found here.
Go to Day 1: Foundations
Day 3: Taking User Input
49 Comments
Michael
10/6/2012 06:36:10 am

Found a mistake, step 1 in lesson 2-4 with the game loop, you wrote this:

while(true):{


}

But there shouldn't be a colon there. So just:

while (true){


}

Reply
James C
10/6/2012 05:11:35 pm

Fixed. Thank you.

Reply
Hymosi
10/6/2012 05:03:39 pm

What is Thread.sleep(17); do?

and why 17?

Reply
James C
10/6/2012 05:10:26 pm

There are three paragraphs explaining that single statement. Sleep pauses the thread for that many milliseconds. We sleep so the game only updates 60 times per second, which allows smooth animation. If we don't sleep, the computer will update as fast as possible. Not a very good game loop if there's so much variability between two updates.

Reply
Kőhegyi Richárd
10/6/2012 05:32:57 pm

I have another question too.

How did you make sound effects for TUMBL: FallDown?

Sorry for my english

Reply
James C
10/7/2012 12:27:02 am

Sound effects were created using : http://www.bfxr.net/

Reply
Michael Awetahegn
10/6/2012 09:34:22 pm

Nice tutorials. I downloaded all of them into one pack as a PDF and if anyone wants them email me at

Tripplemin@gmail.com

Reply
UpGado link
10/7/2012 10:35:40 pm

Found a mistake at Figure 2-6 , there shouldn't be import color or frame , They are imported later at #2-5. Just delete these two lines because they can confuse some people
Thanks for Good tutorials , Really I had been trying to learn Android Programming for 1 months and failed ,, These tutorials made me understand successfully Thank You

Reply
UpGado
10/7/2012 10:44:23 pm

Another one the line of resolution of applet should be
setSize(480, 800);
Instead of setSize(800, 480);
Both resolution are different , Thanks Again

Reply
James C.
10/8/2012 02:23:19 am

I intentionally set it as landscape.

David link
10/11/2012 08:45:33 pm

Doesn't the sleeptime change because of how long the game logic/screen takes to update?

Something like:

Thread.sleep(17-timeSpentInCode);

Reply
James C.
10/15/2012 06:40:47 am

We are using a simplified game loop for this Unit. If you know how to incorporate a better one, then feel free to use it, but we will talk about why it is not a good idea to even sleep at all. Later game loops that we discuss will be more sophisticated and will depend on the duration between updates.

Reply
Reece
11/18/2012 04:15:49 pm

Great stuff! Thank you! I'm really happy to be learning this.

Reply
TRD
11/23/2012 01:40:10 pm

Great Tutorial.. Very Clear

Reply
driff
12/5/2012 03:23:18 pm

could u explain this a little more? ir is it explained later?
Frame frame = (Frame) this.getParent().getParent();
anyhow thanks for the tutorial ^^

Reply
James C.
12/5/2012 03:44:25 pm

Frame frame = (Frame) this.getParent().getParent();

We create a Frame object called frame. (http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/Frame.html)

We assign it the value of the parent of the current applet's ("this") parent (so kinda like a grandparent), which refers to the window that we are renaming.

I hope that helps!

Reply
sd
2/7/2013 07:37:25 am

I have been keeping up with everything thus far except the Frames, you have lost me a bit :). I understand what they are, but I am lost as to what you are inheriting from the grandparent (the second getParent()). Can you break this down a bit and explain it? Or is this going to be discussed later and for now we simply don't worry beyond "the window we are creating is going to inherit stuff from the applet"?

James C.
2/9/2013 09:06:42 am

sd, I would just recommend ignoring it and moving on :) It's something that has a very steep learning curve and it might confuse you more if you try to wrap your head around it completely.

KArthik
12/16/2012 01:53:52 am

Thanks for the tutorial...........just simply awesome explanation.......

Reply
irvan
2/20/2013 02:30:29 am

wowww nice tutorial,,it really helped me to learn game dev
thx :)

Reply
SarkEnt
3/1/2013 05:05:10 pm

This is amazing stuff guys! For those of us who are crazy about making games, this information is priceless. I put in a humble donation of $20, you guys deserve more, but that's all I can do for now. Keep it up!

Reply
Artur
4/4/2013 10:25:37 am

Hello,

I was looking to get into Java and recently found your site and it helped me alot (thank you!)

I know you wrote that we should it ignore for now but I need to know it, telling me to skip it makes me want to know it even more :)

I need a bit of explanation of the current line:
Frame frame = (Frame) this.getParent().getParent();

basically we call this.getParent().getParent() and assign it to the newly created frame, oke I got it so far, didn't I?

I checked the Java API and it tells me that "Applet" extends "Panel" and "Panel" extends "Container". Logically this would mean that this.getParent().getParent() returns "Container" which then gets turned into a "Frame" Object.

Next I checked Frame in the API and it tells me that "Frame" extends "Window" and "Window" extends "Container" (interesting! the grandparent of both is "Container")

now I need to know if I got this right. My theory is that "(Frame)" supplements the "Container" object with "Window" and "Frame" to change its type, basically the oppsite way of "extends" and it would not be possible when "Frame" werent a grandparent of "Container" (e.g. Frame frame = (Frame) this.getParent(); would not work because "Panel" is not part of "Frame")

is my theorycrafting correct or is that too far off?

Reply
rits
4/5/2013 02:17:25 am

m gtn error on ds line setBackground(Color.BLACK); n m nt able 2 import as explnd in d above steps

Reply
Florian
4/15/2013 10:16:27 pm

Hey, I have a question:

Is there a particular reason why you are using awt and not swing?

btw, great tutorials!

Reply
Sujith
4/16/2013 01:57:48 am

Why using Applet??

Reply
Alemdar
4/23/2013 04:22:48 am

Very nice tutorial, your explanation simple and clear. Big thx :)

Reply
Vani
6/9/2013 06:41:22 pm

Hi, Thanks really its very helpful and very easy to understand explanation.

Reply
Donnie Emanuel
6/28/2013 12:55:05 am

Great job!!! thank you for sharing!!!

Reply
Daemon Spade
6/29/2013 02:21:21 pm

isn't thread.start() already deprecated in Android higher versions? do you have any solution there to solve this problem?

Reply
jatin
7/5/2013 01:48:14 am

Hi,
i tried using t instead of using thread as variable, but it is showing me an error in void run() method,
i replaced the variable t with thread but then it is showing me no error y so??

Reply
jatin
7/5/2013 01:50:59 am

i got it its not the variable its the Thread class itself :D
(y)

Reply
Fan
7/5/2013 07:50:19 am

Gr8 Tutorial . Keep it up ! :)

Reply
HeiloKing
7/7/2013 01:25:30 am

To people reading this tutorial after July 2013:

The CTRL+SPACE auto complete function has been altered.

It is now Alt + / .

i.e. type init , then press Alt + / the helper box pops up.

Reply
Seung
7/22/2013 02:00:06 pm

Wow ur a great teacher. u basically explained everything in detail and able us to understand each line step by step. Thanks it helped alot

Reply
Richard
11/9/2013 02:35:30 pm

It seems what you've developed is more a generic java applet and not an android game. Why this way and not using the proper Android Activity framework?

Reply
mino
12/17/2013 05:04:54 am

great job ..thanks for this

Reply
Nikhil
2/21/2014 02:22:50 pm

Thankyou For the Great tutorials James :)

Why didn't u put the (Thread thread = new Thread(this)) , this line in the init() method??

Reply
Ben
2/27/2014 05:25:23 am

I have two questions/problems.

Thread.sleep(17); -- I am unable to change, it remains a plain text 17.

Also, same problem with setSize, the numbers are only able to be entered at plain text.

Reply
Jerry
9/21/2014 05:25:47 am

I dont understand why we need in the run fuction, the while(true)?
if the thread will call run every 17msec.

Reply
Gayan
11/19/2014 02:11:05 pm

The service you provide to the world is pricelss.keep going KiloBolt

Reply
Ali
3/9/2015 04:26:00 pm

i keep getting the following error on init() , start(), stop(), destroy()
Cannot reduce the visibility of the inherited method from Applet
i even downloaded the project file and imported it but still getting the same error!!!

Reply
Gary
4/2/2015 07:14:46 pm

How to make a character jump and climb stairs upwards and also fall down like in mario?

Reply
Mitro
5/13/2015 08:34:27 pm

I use Netbeans and I always get No Main Classes found, what should I do? I've already read all the guide, but I don't find solution.

Reply
Hardeek
6/24/2015 02:03:35 pm

i couldnt understand the line:
Frame frame=(Frame) this.getParent().getParent()

what is the use of getparent and frame precisely....

Reply
Johhny
7/1/2015 02:23:28 am

God this is just so awful. Half of the things he introduces he doesn't explain, he just says 'this is complicated so don't worry about it', if it's complicated then explain it! Just explain it in small pieces before using it in the code. I find it hard to imagine that someone would actually learn much from this tutorial other than how to cut and paste code.

Reply
amir.developer
9/1/2015 07:32:33 am

hi
thank you sooooo muchhhhhhhh fore useful tutorial.
i read the comments (oops) this seems that you just answered the questions for two years ago and here in not active for now ...
can we ASK our questions and contact with you now ?
is any way for this ?
thank so much...
againg thank for your excellent tutorials

Reply
Jaymesh link
10/1/2015 04:52:39 pm

Hi,
Thread thread = new Thread(this);
I don't know whether I missed some concept. I read that this object(here our class name) pass over to the Thread class in that it will execute this constructor -> public Thread(Runnable o) . It will check in the condition if( o != null ) then it executes the o.start() method of our class. Am I right?. Please, email me if I not. Thanks

Reply
sumit garg link
10/29/2017 07:47:19 am

Warning: Applet API and AppletViewer are deprecated.

i found this error while i copied your program from day 2 basic framework

Reply
Vonia
2/28/2018 08:06:03 pm

I'm overall confused on how to actually run the code. I tried doing:
StartingClass prototype = new StartingClass();
prototype.init();
but that gave me a nullpointerexception error and I don't know how to fix it.

Reply



Leave a Reply.

    Author

    James Cho is the lead developer at Kilobolt Studios. He is a college student at Duke University and loves soccer, music, and sharing knowledge.


© 2014 Kilobolt, LLC. All rights reserved.