In this mini-project we will draw a moving, controllable sprite to your Android device. We will draw Bob to the screen and when the screen is touched he will move to the right and when the screen is released he will stop. However, we will have achieved much more than this as this simple 2D game engine will be easy to upgrade to handle many more game objects. You will also be able to just copy/paste most of the code to get our first real, playable game; which will be the next project. You will also be able to use this code as a springboard to get started with 2D games of your very own design.
Create a simple game engine project
Create a new Android Studio project and call it Simple Game Engine. Create a blank Activity and call it SimpleGameEngine. Add the bob.png file (below) to the drawable folder as we did in the Drawing graphics demo.
Here is a little bit of pseudo-code so we can appreciate the structure of the real code we will write soon. The real code is quite long and with just a quick glance might appear complex although it really isn’t. This pseudo code will clarify things a little and enable us to present and discuss the code in manageable chunks. You can also skip to the end of the article and see the code in its entirety for explicit clarification and context. You might like to simply copy and paste the full completed code into your project and get the simple game engine working; then come back and read all about it.
Pseudo code not real code…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
SimpleGameEngine class{ onCreate method{ Initialize new GameView object Set new GameView object as the view }// End onCreate GameView class{ // An inner class within SimpleGameEngine Setup the class in special constructor method Run method calls update, draw and controls frame rate Update method draw method resume method:runs when game starts and sets up our thread pause method:runs when the game is shut down and stops our thread onTouchEvent method is called by Android when screen touched by player }// End of GameView inner class // Back in SimpleGameEngine class 2 more methods onResume method is called by Android when game starts and calls GameView resume onPause method is called by Android when game shuts down and calls GameView pause }// End of SimpleGameEngine and all of our code |
How it works
Let’s run through how that works in sequence. Remember that although methods execute their code starting from the first line; the order in which methods are executed is determined by when they are called. So here is what will happen with our finished game engine.
The player presses the icon on their device to play our game. Android does some stuff in the background that we don’t need to worry about; it then calls our onCreate method. In onCreate we declare and initialize a new class that we will code, called GameView. The last thing that onCreate does is to set our new GameView object as the view for the app. Once onCreate completes the Android operating system calls the onResume method (in the SimpleGameEngine class). This method calls the resume method, that we will write, in our new GameView class. Our resume method starts our thread which causes the run method to execute. The run method calls update and draw which essentially is the entire functionality of our game. The operating system will continually call run many times per second.
So the GameView class handles our entire game, specifically, from the run method, until the user presses a button on their device (perhaps back or home) that causes the operating system to execute the onPause method in the SimpleGameEngine class which in turn calls the pause method in the GameView class and stops our thread. The run method will not be called anymore and our game will cease to function.
In addition to the operating system calling our run method, it will also call our onTouchEvent method (also in GameView) in the main/default thread. It is here we can then code a response to the player’s touches.
Coding the Simple game engine class
Here is the code for our SimpleGameEngine class with the extra methods ( onPause and onResume) as well as our GameView class left out for now. Copy and paste this into your project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; public class SimpleGameEngine extends Activity { // gameView will be the view of the game // It will also hold the logic of the game // and respond to screen touches as well GameView gameView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize gameView and set it as the view gameView = new GameView(this); setContentView(gameView); } // GameView class will go here // More SimpleGameEngine methods will go here } |
Above we add all the required imports we will need and an GameView object called gameView. Then we coded the onCreate method which simply initializes our GameView object and sets it to the view of the entire game which is what the player will see on the screen.
Coding the GameView class
We will now code this all important GameView class and we will do so in chunks so we can talk about what is going on as we progress. We will add the simple extra methods ( onResume and onPause) in the SimpleGameEngine class when we have completed GameView.
If you think back to the Drawing Graphics demo, we drew everything to an object of the type ImageView. And we set the object using setContentView as the view for the app. We can’t just set any old object to be the view for the app. Fortunately Android has some ready-made classes that we can extend that provide us with everything we need. In the next block of code, you see we declare our GameView class and use the extends keyword to give it all the functionality of an Android SurfaceView. This not only means we can easily draw graphics on it as we did with ImageView but we can also use it in setContentView. Also in the very first line of code (excluding comments) we use the implements keyword followed by Runnable which means our class implements the Runnable interface that gives us all the thread functionality and allows us to use/override the run method that will become a kind of de-facto loop for our entire game.
We also declare some objects and variables that we will need in the game. Enter the code below where the comment // GameView class will go here indicates. We will discuss the variables and objects afterward.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
// Here is our implementation of GameView // It is an inner class. // Note how the final closing curly brace } // is inside SimpleGameEngine // Notice we implement runnable so we have // A thread and can override the run method. class GameView extends SurfaceView implements Runnable { // This is our thread Thread gameThread = null; // This is new. We need a SurfaceHolder // When we use Paint and Canvas in a thread // We will see it in action in the draw method soon. SurfaceHolder ourHolder; // A boolean which we will set and unset // when the game is running- or not. volatile boolean playing; // A Canvas and a Paint object Canvas canvas; Paint paint; // This variable tracks the game frame rate long fps; // This is used to help calculate the fps private long timeThisFrame; // Declare an object of type Bitmap Bitmap bitmapBob; // Bob starts off not moving boolean isMoving = false; // He can walk at 150 pixels per second float walkSpeedPerSecond = 150; // He starts 10 pixels from the left float bobXPosition = 10; |
In the code above, after the class declaration that we have already discussed, we declare and initialize an Thread object called gameThread. We initialize it to null which is kind of like zero or no value as we are not ready to use it yet. After that, we declare an object of the type SurfaceHolder called surfaceHolder. This is new to us and it is an extra requirement when drawing graphics in a thread. As the operating system might like to draw to the screen as well, perhaps a text notification, etc, we need to lock the drawing surface each time the run method calls our draw method. We will see this in action soon.
We then declare a boolean called playing. You might have noticed the odd-looking volatile the keyword we used as well. The variable will be used to determine if the game is playing and we can then wrap the calls to draw and update in a while(playing) loop. We use volatile because it is a variable that can be used from inside and outside the thread, as we will see.
We then declare two variables fps and timeThisFrame. We will see how we use them to measure the frames per second of our game and use this measurement to make Bob move at the same speed on different devices with different hardware and therefore different frame rates. This consistency is essential for any game we code because a game shouldn’t give a different experience between devices.
Next, we declare a Bitmap, bitmapBob to hold our image of Bob. Following this, we have a boolean isMoving. We will use this to decide when to move Bob and when to leave him stationary. We then declare and initialize walkSpeedPerSecond which will determine the speed in pixels per second that Bob can walk. Finally bobXPosition will be used when we call canvas.drawBitmap to position Bob on the horizontal axis; so we can manipulate it and Bob will glide across the screen as intended.
In the next block of code, we have a curiously named method GameView. Even more curious is it has no return type. This is a special method called a constructor. We do not have to code a constructor unless we want to, but here it is really useful. When we initialize our gameView object, that is, when we call gameView = new GameView(), this constructor method is called. It allows us to do all sorts of initialization ready for when we use our class for its main intended purpose.
Also in the method signature, we can see the this object is passed in. We need this to initialize our bitmap and call the constructor of the SurfaceView class.
In our constructor method, we see that we first call the SurfaceView constructor using the super keyword, then initialize ourHolder, paint and bitmapBob objects. Enter the code below that we have just discussed and we will take a look at our run method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// When the we initialize (call new()) on gameView // This special constructor method runs public GameView(Context context) { // The next line of code asks the // SurfaceView class to set up our object. // How kind. super(context); // Initialize ourHolder and paint objects ourHolder = getHolder(); paint = new Paint(); // Load Bob from his .png file bitmapBob = BitmapFactory.decodeResource(this.getResources(), R.drawable.bob); } |
Now we come to the center of the universe as far as our simple game engine is concerned. The run method. Remember that the operating system continuously calls this method from when we start our thread right around to when we stop it. So we can think of the run method as an infinite loop that will execute until the game is shut down. This is sometimes referred to as the game loop or game main.
In it, we wrap our code in a while (playing) loop because the thread can feasibly start before we are fully set up.
The first thing we do if playing is true is to get the system time in thousandths of a second and store it in the startFrameTime variable.
Then we call update and draw. These two methods will hold the logic and graphics code of our game.
After this, we get the current system time again, subtract startFrameTime from it and store the result in timeThisFrame. This is the number of milliseconds it took to execute our update and draw methods this frame.
The if statement that follows makes sure the answer is not zero and if it isn’t we assign the result of 1000 divided by timeThisFrame to fps. This is our current frames per second. We will see how we use that really soon. Enter the run method below and we can move on to discussing the update method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Override public void run() { while (playing) { // Capture the current time in milliseconds in startFrameTime long startFrameTime = System.currentTimeMillis(); // Update the frame update(); // Draw the frame draw(); // Calculate the fps this frame // We can then use the result to // time animations and more. timeThisFrame = System.currentTimeMillis() - startFrameTime; if (timeThisFrame > 0) { fps = 1000 / timeThisFrame; } } } |
Here is update below. All we do is check if isMoving is true and if it is we increase Bob’s x position ( bobXPosition) by walkSpeedPerSecond divided by fps. This will achieve the same movement speed for Bob regardless of the current frames per second ( fps) the device is running at. That’s it for update.
1 2 3 4 5 6 7 8 9 10 11 12 |
// Everything that needs to be updated goes in here // In later projects we will have dozens (arrays) of objects. // We will also do other things like collision detection. public void update() { // If bob is moving (the player is touching the screen) // then move him to the right based on his target speed and the current fps. if(isMoving){ bobXPosition = bobXPosition + (walkSpeedPerSecond / fps); } } |
Now we will draw Bob and some extra text to display the current frames per second. We have seen all the drawing code before in the Drawing graphics demo but there are some extra lines of code and one more subtle difference as well.
First, we attempt to get a lock on the drawing surface and if successful we make the drawing surface our canvas.
If you look closely at the call to canvas.drawBitmap, instead of providing a number for the x coordinate we use bobXPosition. We have already seen in the update method how we manipulate this variable. The only thing we haven’t seen but we will very soon is how we toggle between isMoving being true or false. Lastly, we draw everything to the screen, unlock the drawing surface, and hand control back to the operating system- for a few milliseconds anyway. Add the draw method to your project.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// Draw the newly updated scene public void draw() { // Make sure our drawing surface is valid or we crash if (ourHolder.getSurface().isValid()) { // Lock the canvas ready to draw // Make the drawing surface our canvas object canvas = ourHolder.lockCanvas(); // Draw the background color canvas.drawColor(Color.argb(255, 26, 128, 182)); // Choose the brush color for drawing paint.setColor(Color.argb(255, 249, 129, 0)); // Make the text a bit bigger paint.setTextSize(45); // Display the current fps on the screen canvas.drawText("FPS:" + fps, 20, 40, paint); // Draw bob at bobXPosition, 200 pixels canvas.drawBitmap(bitmapBob, bobXPosition, 200, paint); // Draw everything to the screen // and unlock the drawing surface ourHolder.unlockCanvasAndPost(canvas); } } |
Now we have our two methods which are called by the methods of the similar name in SimpleGameEngine. Remember that the near namesakes in SimpleGameEngine are called by the operating system when our game is started and stopped.
The pause method looks more complicated than it really is. The unusual looking try and catch blocks are a requirement forced upon us because of the design of the Thread class. We don’t need to completely understand them in order to make games. The try block is the code to execute and the catch block is what to do if the try block fails. Not unlike if and else. The important code for the pause method is when we call gameThread.join() and set playing to false this will shut down our game thread.
The resume method sets the playing variable to true, initializes our thread then starts it. The game is now running.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// If SimpleGameEngine Activity is paused/stopped // shutdown our thread. public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { Log.e("Error:", "joining thread"); } } // If SimpleGameEngine Activity is started theb // start our thread. public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } |
Getting player input
One extra benefit of the SurfaceView class which we extended to make GameView is that it allows us to override the onTouchEvent method. The onTouchEvent method is called directly by the operating system every time the screen is touched. Within this method, we can use the data passed in, in the MotionEvent object to determine if the player is telling our game to do something.
This method will get more complicated depending on the control system you are trying to implement. Future game projects will go into this method in much more detail. For now, all we need to do is switch as shown in the code below, and handle two cases. ACTION_DOWN when the player touches the screen and ACTION_UP when they remove their finger from the screen.
All we do is set isMoving to either true or false for each of those cases respectively and we have implemented our game controls.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// The SurfaceView class implements onTouchListener // So we can override this method and detect screen touches. @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { // Player has touched the screen case MotionEvent.ACTION_DOWN: // Set isMoving so Bob is moved in the update method isMoving = true; break; // Player has removed finger from screen case MotionEvent.ACTION_UP: // Set isMoving so Bob does not move isMoving = false; break; } return true; } |
Now we are at the end of our GameView inner class so add the closing curly brace }.
1 2 |
} // This is the end of our GameView inner class |
Finishing off the main class
Now we are back in the SimpleGameEngine class where we add the overridden methods onResume and onPause which will be called by the operating system when the game is started or stopped. All they do is call the near-namesake methods in the GameView class to control our thread- and by default our entire game. Enter the last block of code for our simple game engine. Be sure to do so within the final closing curly brace } of the SimpleGameEngine class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// This method executes when the player starts the game @Override protected void onResume() { super.onResume(); // Tell the gameView resume method to execute gameView.resume(); } // This method executes when the player quits the game @Override protected void onPause() { super.onPause(); // Tell the gameView pause method to execute gameView.pause(); } |
Running the simple game engine
You can now run the game on a device and see Bob glide smoothly across the screen when it is pressed. Albeit backward:-D.
Although that was a slightly more lengthy project than some of the previous ones; we have achieved even more than it might seem. We now have a framework/engine which we can reuse again and again. If every single line of code is not crystal clear don’t worry because as we expand and improve the code we will become more familiar with what is going on. As each of the future projects gets progressively more advanced we will also introduce more Java and Android concepts.
Let’s move on and make a full, playable game or you might want to add a scrolling parallax background to this simple engine.
Complete code listing
Here is all the code for quick copying and pasting.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; public class SimpleGameEngine extends Activity { // gameView will be the view of the game // It will also hold the logic of the game // and respond to screen touches as well GameView gameView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize gameView and set it as the view gameView = new GameView(this); setContentView(gameView); } // GameView class will go here // Here is our implementation of GameView // It is an inner class. // Note how the final closing curly brace } // is inside SimpleGameEngine // Notice we implement runnable so we have // A thread and can override the run method. class GameView extends SurfaceView implements Runnable { // This is our thread Thread gameThread = null; // This is new. We need a SurfaceHolder // When we use Paint and Canvas in a thread // We will see it in action in the draw method soon. SurfaceHolder ourHolder; // A boolean which we will set and unset // when the game is running- or not. volatile boolean playing; // A Canvas and a Paint object Canvas canvas; Paint paint; // This variable tracks the game frame rate long fps; // This is used to help calculate the fps private long timeThisFrame; // Declare an object of type Bitmap Bitmap bitmapBob; // Bob starts off not moving boolean isMoving = false; // He can walk at 150 pixels per second float walkSpeedPerSecond = 150; // He starts 10 pixels from the left float bobXPosition = 10; // When the we initialize (call new()) on gameView // This special constructor method runs public GameView(Context context) { // The next line of code asks the // SurfaceView class to set up our object. // How kind. super(context); // Initialize ourHolder and paint objects ourHolder = getHolder(); paint = new Paint(); // Load Bob from his .png file bitmapBob = BitmapFactory.decodeResource(this.getResources(), R.drawable.bob); // Set our boolean to true - game on! playing = true; } @Override public void run() { while (playing) { // Capture the current time in milliseconds in startFrameTime long startFrameTime = System.currentTimeMillis(); // Update the frame update(); // Draw the frame draw(); // Calculate the fps this frame // We can then use the result to // time animations and more. timeThisFrame = System.currentTimeMillis() - startFrameTime; if (timeThisFrame > 0) { fps = 1000 / timeThisFrame; } } } // Everything that needs to be updated goes in here // In later projects we will have dozens (arrays) of objects. // We will also do other things like collision detection. public void update() { // If bob is moving (the player is touching the screen) // then move him to the right based on his target speed and the current fps. if(isMoving){ bobXPosition = bobXPosition + (walkSpeedPerSecond / fps); } } // Draw the newly updated scene public void draw() { // Make sure our drawing surface is valid or we crash if (ourHolder.getSurface().isValid()) { // Lock the canvas ready to draw canvas = ourHolder.lockCanvas(); // Draw the background color canvas.drawColor(Color.argb(255, 26, 128, 182)); // Choose the brush color for drawing paint.setColor(Color.argb(255, 249, 129, 0)); // Make the text a bit bigger paint.setTextSize(45); // Display the current fps on the screen canvas.drawText("FPS:" + fps, 20, 40, paint); // Draw bob at bobXPosition, 200 pixels canvas.drawBitmap(bitmapBob, bobXPosition, 200, paint); // Draw everything to the screen ourHolder.unlockCanvasAndPost(canvas); } } // If SimpleGameEngine Activity is paused/stopped // shutdown our thread. public void pause() { playing = false; try { gameThread.join(); } catch (InterruptedException e) { Log.e("Error:", "joining thread"); } } // If SimpleGameEngine Activity is started then // start our thread. public void resume() { playing = true; gameThread = new Thread(this); gameThread.start(); } // The SurfaceView class implements onTouchListener // So we can override this method and detect screen touches. @Override public boolean onTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { // Player has touched the screen case MotionEvent.ACTION_DOWN: // Set isMoving so Bob is moved in the update method isMoving = true; break; // Player has removed finger from screen case MotionEvent.ACTION_UP: // Set isMoving so Bob does not move isMoving = false; break; } return true; } } // This is the end of our GameView inner class // More SimpleGameEngine methods will go here // This method executes when the player starts the game @Override protected void onResume() { super.onResume(); // Tell the gameView resume method to execute gameView.resume(); } // This method executes when the player quits the game @Override protected void onPause() { super.onPause(); // Tell the gameView pause method to execute gameView.pause(); } } |
Hey! Thanks a lot for your tutorials! There are a lot of things I’m not grasping yet but it will come with time and research I hope!
In this tutorial though I’m having a lot of build errors in the onTouchEvent method saying it misses parentesis and stuff. What are the amps? My code is exactly like the one you wrote through the tutorial. Thanks a lot!
Hi Joaquim, Thanks so much for posting the problem. Please accept my apologies as it is a typo. When the code was pasted into the html editor for formatting on the page it changed all the html symbols (& >< and a few more). I thought I had changed them all. There should be a single &. Like this switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { I have corrected it in the tutorial and the code listing at the end. This should work for you now. Terribly sorry for the inconvenience. Keep making games!
hi, i am also getting errors, i have copied the code exactly but my problem is (timeThisFrame & amp;amp;amp;gt;= 1)
the first letter t is underlined in red and all the “amp and “gt” are red!
can you help with this?
loving your tutorials by the way, great stuff!
regards
james
Hi James,
The line should read
if (timeThisFrame > 0) {
Again this was caused by my sloppy copy & paste from Android studio. The code was correct in the tutorial part further up the page but I missed it in the complete listing. The website software converts “>” to all kinds of weird stuff and I need to manually spot it.
The code should be correct now!
Thanks very much for pointing out my mistake and my apologies for the inconvenience.
John
thank you john, and have to say i am loving your tutorials so far! alot is still very cloudy at the moment but will stick at it and hopefully things eventually become clear for me.
regards
jamie
Where is the image of Bob to download? cant find it anywhere.
Hi Bill,
I have added Bob near the top of the page, near the instruction to add him to the project. Sorry about that, the tutorial assumes you have done the drawing graphics demo first. Which of course not everybody has.
Thanks for your help.
Hi, i wrote this code, i understand it, but won’t run on my phone.When i press run, create the icon on my phone but app won’t run
Hi Cosmin,
Are you running it attached to USB cable? Do you get any errors or output in the logcat window underneath the code window in Android Studio. If you can’t run it via USB cable try using an emulator so you get some feeback/errors in the logcat window.
Thanks for the comment. I will see if I can work it out with you.
Yes i running it on my phone.In logcat wrote Succes!, but when i click it on my phone won;t start.
Some things to check:
You said yes running on my phone. But is it connected via USB cable with USB debugging enabled?
There should be lots more output from logcat. If you are connected via usb perhaps you have one of the drop-down filters at top of logcat preventing the output.
Try running it on an emulator if none of the above works.
If none of the above works. When you say “won’t start” does nothing happen, does it force close, do you get a blank screen?
Good luck. Let me know how you get on.
John
I’ve tried in emulator and i got force close ,and i have enabled usb debbuging.When i opened app show for few milisec white and the my homescreen.
in logcat shows me this:
Installing com.example.cosmin.simplegameengine
DEVICE SHELL COMMAND: pm install -r “/data/local/tmp/com.example.cosmin.simplegameengine”
pkg: /data/local/tmp/com.example.cosmin.simplegameengine
Success
08-14 20:47:28.937 2212-2212/com.example.cosmin.simplegameengine E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.cosmin.simplegameengine, PID: 2212
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.cosmin.simplegameengine/com.example.cosmin.simplegameengine.GameView}: java.lang.ClassNotFoundException: Didn’t find class “com.example.cosmin.simplegameengine.GameView” on path: DexPathList[[zip file “/data/app/com.example.cosmin.simplegameengine-2/base.apk”],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2236)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.ClassNotFoundException: Didn’t find class “com.example.cosmin.simplegameengine.GameView” on path: DexPathList[[zip file “/data/app/com.example.cosmin.simplegameengine-2/base.apk”],nativeLibraryDirectories=[/vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at android.app.Instrumentation.newActivity(Instrumentation.java:1066)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2226)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Suppressed: java.lang.ClassNotFoundException: com.example.cosmin.simplegameengine.GameView
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
… 13 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
Class not found exception might indicate the inner class has been named incorrectly? Check yours is called GameView.
Hello.
I have done everything in the tutorial with no errors. However, running the app just gives me a black background. I have a PNG named bob in my drawable folder and yet nothing. I had to comment out the super.onPause and super.onResume because it was giving me errors. Could that he the cause? Thanks in advance!
Hi Gabriel,
Yes, almost certainly that is the cause of the black screen. The thread will not start without onResume. What is unclear is why you would get an error with the calls to super.onResume etc. Is it possible you have accidentally typed the methods within the closing curly brace } of the inner class (GameView) instead of within the class which extends Activity (SimpleGameEngine). Try making sure onResume and onPause are in SimpleGameEngine and if they still give you errors let me know what the errors are.
Good luck and let me know how you get on.
Hi John! Just wanna say thanks for your effort you put in these tutorials. They are very helpful and your books are the main reason i started android game development!
Thank you again and if i ever become successful game developer, you are that voice inside who guided me. Keep up the great work!
Hi Goran,
Thanks very much for your kind comments. I was just trying to summon up the energy to do some writing today and you just gave it to me. I would love it if you and other readers become successful game developers!
John
Im glad that you get your motivation from your readers, its pure devotion and i admire it.
Be assured that i will mention your books and style you talk to your reader in every conversation that has a game dev as a topic!
And again, if i make it big, i have to repay my intelectual debt in form of beer or two,as a sign of all this knowledge that i managed to sqeeze inside of my head in such a short amount of time.
Keep us inspired, we will keep you motivated for more and more knowledge sharing! 😀
Thanks Goran. Keep in touch.
This tutorial is create. I already knew programming from C# and XNA but this is really helping me start learning Java for androids. Cant wait to get making some real fun games
John,
I tried to run your Bob app sample on Android Studio and this is the error I’m getting on the 4:Run tab at the bottom.
Target device: Android_2.1_API_Level_7 [emulator-5554]
Installing APK: C:\Users\jedmon\Desktop\Android Keystores\SpriteSheetAnimations\app\build\outputs\apk\app-debug.apk
Uploading file to: /data/local/tmp/com.jedmon.spritesheetanimations
Installing com.jedmon.spritesheetanimations
DEVICE SHELL COMMAND: pm install -r “/data/local/tmp/com.jedmon.spritesheetanimations”
pkg: /data/local/tmp/com.jedmon.spritesheetanimations
Success
Could not identify launch activity: Default Activity not foundWaiting for process: com.jedmon.spritesheetanimations
–> The Gradle build is successful. I created a layout folder with main.xml, since I originally did not create them. It did not fix it.
The logcat is showing that I burned some midnight oil
12-04 04:41:02.412 93-93/com.android.phone D/dalvikvm: GC freed 12357 objects / 573256 bytes in 210ms
12-04 04:43:51.382 291-291/? D/AndroidRuntime: CheckJNI is ON
12-04 04:43:51.532 291-291/? D/AndroidRuntime: — registering native functions —
12-04 04:43:51.782 291-294/? D/ddm-heap: Got feature list request
12-04 04:43:52.182 51-66/system_process D/PackageParser: Scanning package: /data/app/vmdl54288.tmp
12-04 04:43:52.672 51-66/system_process D/dalvikvm: GC freed 12783 objects / 1125448 bytes in 108ms
12-04 04:43:53.962 51-66/system_process I/PackageManager: Removing non-system package:com.jedmon.spritesheetanimations
12-04 04:43:53.972 51-66/system_process D/PackageManager: Removing package com.jedmon.spritesheetanimations
12-04 04:43:53.972 51-66/system_process D/PackageManager: Activities: com.jedmon.spritesheetanimations.SpriteSheetAnimation
12-04 04:43:54.052 51-66/system_process D/PackageManager: Scanning package com.jedmon.spritesheetanimations
12-04 04:43:54.062 51-66/system_process I/PackageManager: /data/app/vmdl54288.tmp changed; unpacking
12-04 04:43:54.122 31-31/? D/installd: DexInv: — BEGIN ‘/data/app/vmdl54288.tmp’ —
12-04 04:43:55.562 297-297/? D/dalvikvm: DexOpt: couldn’t find field Landroid/app/Notification;.fullScreenIntent
12-04 04:43:55.562 297-297/? D/dalvikvm: DexOpt: couldn’t find field Landroid/app/Notification;.actions
12-04 04:43:55.602 297-297/? D/dalvikvm: DexOpt: couldn’t find static field
12-04 04:43:55.742 297-297/? D/dalvikvm: DexOpt: couldn’t find static field
12-04 04:43:55.752 297-297/? D/dalvikvm: DexOpt: couldn’t find field Landroid/graphics/BitmapFactory$Options;.inMutable
12-04 04:43:57.092 297-297/? D/dalvikvm: DexOpt: load 458ms, verify 1556ms, opt 78ms
12-04 04:43:57.212 31-31/? D/installd: DexInv: — END ‘/data/app/vmdl54288.tmp’ (success) —
12-04 04:43:57.212 51-66/system_process D/PackageManager: Activities: com.jedmon.spritesheetanimations.SpriteSheetAnimation
12-04 04:43:57.232 51-62/system_process D/ActivityManager: Uninstalling process com.jedmon.spritesheetanimations
12-04 04:43:57.302 31-31/? I/installd: move /data/dalvik-cache/data@app@vmdl54288.tmp@classes.dex -> /data/dalvik-cache/data@app@com.jedmon.spritesheetanimations.apk@classes.dex
12-04 04:43:57.312 51-66/system_process D/PackageManager: New package installed in /data/app/com.jedmon.spritesheetanimations.apk
12-04 04:43:57.412 291-291/? D/AndroidRuntime: Shutting down VM
12-04 04:43:57.412 291-291/? D/dalvikvm: DestroyJavaVM waiting for non-daemon threads to exit
12-04 04:43:57.412 291-291/? D/dalvikvm: DestroyJavaVM shutting VM down
12-04 04:43:57.412 291-292/? D/dalvikvm: HeapWorker thread shutting down
12-04 04:43:57.412 291-291/? D/dalvikvm: HeapWorker thread has shut down
12-04 04:43:57.422 291-291/? D/jdwp: JDWP shutting down net…
12-04 04:43:57.422 291-294/? I/dalvikvm: Debugger has detached; object registry had 1 entries
12-04 04:43:57.422 291-291/? D/dalvikvm: VM cleaning up
12-04 04:43:57.432 291-291/? D/dalvikvm: LinearAlloc 0x0 used 623916 of 5242880 (11%)
12-04 04:43:57.442 51-66/system_process D/ActivityManager: Uninstalling process com.jedmon.spritesheetanimations
12-04 04:43:57.692 51-66/system_process D/dalvikvm: GC freed 18648 objects / 966984 bytes in 173ms
12-04 04:43:59.462 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f0700e5
12-04 04:43:59.462 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f020031
12-04 04:43:59.472 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f020030
12-04 04:43:59.472 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f050000
12-04 04:43:59.492 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f060000
12-04 04:43:59.502 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f060001
12-04 04:43:59.682 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f0700e5
12-04 04:43:59.682 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f020031
12-04 04:43:59.682 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f020030
12-04 04:43:59.682 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f050000
12-04 04:43:59.682 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f060000
12-04 04:43:59.692 51-60/system_process W/ResourceType: Resources don’t contain package for resource number 0x7f060001
12-04 04:44:05.122 208-208/com.svox.pico D/dalvikvm: GC freed 43 objects / 2120 bytes in 84ms
–> I haven’t tried to set fullscreen in the manifest or in the code yet. I’m not sure where to go with this error.
Please help, when you have time. Thanks!
Hi Norej,
Could be a configuration or version problem.
The first and easiest thing to try is in Android Studio select File | Invalidate Caches & Restart… then select Tools|Android|Sync Project with Gradle Files. Also restart the emulator(preferably run a newer one than 2.1)
If it still doesn’t work try creating a new project with a recent API as the minimum, perhaps 22, then copy and paste the code again into the new project. Run it on a much newer emulator as well.
Good luck!
John, first of all, I would like to thank you for taking your precious moment in reviewing my error and providing your reply in a quick manner. You are very upbeat in educating others; my hat off to you sir!
I did the Invalidate Caches & Restart and sync’d with Gradle Files. I ran it with API 10 and the same problem. I changed the Compile Sdk to API 22, Build Tools to 22.0.1, and Min Sdk to API 22.
Here’s what went wrong.
Information:Gradle tasks [:app:generateDebugSources, :app:generateDebugAndroidTestSources]
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72311Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42311Library UP-TO-DATE
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
C:\Users\jedmon\Desktop\Android Keystores\SpriteSheetAnimations\app\build\intermediates\res\merged\debug\values-v23\values-v23.xml
Error:(3) Error retrieving parent for item: No resource found that matches the given name ‘android:TextAppearance.Material.Widget.Button.Inverse’.
Error:(24) Error retrieving parent for item: No resource found that matches the given name ‘android:Widget.Material.Button.Colored’.
Error:Execution failed for task ‘:app:processDebugResources’.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process ‘command ‘C:\Users\jedmon\android-sdks\build-tools\22.0.1\aapt.exe” finished with non-zero exit value 1
Information:BUILD FAILED
Information:Total time: 13.047 secs
Information:3 errors
Information:0 warnings
Information:See complete output in console
–> Here’s from the Gradle Console
AGPBI: {“kind”:”error”,”text”:”Error retrieving parent for item: No resource found that matches the given name \u0027android:TextAppearance.Material.Widget.Button.Inverse\u0027.”,”sources”:[{“file”:”C:\\Users\\jedmon\\Desktop\\Android Keystores\\SpriteSheetAnimations\\app\\build\\intermediates\\res\\merged\\debug\\values-v23\\values-v23.xml”,”position”:{“startLine”:2}}],”original”:””,”tool”:”AAPT”}
AGPBI: {“kind”:”error”,”text”:”Error retrieving parent for item: No resource found that matches the given name \u0027android:Widget.Material.Button.Colored\u0027.”,”sources”:[{“file”:”C:\\Users\\jedmon\\Desktop\\Android Keystores\\SpriteSheetAnimations\\app\\build\\intermediates\\res\\merged\\debug\\values-v23\\values-v23.xml”,”position”:{“startLine”:23}}],”original”:””,”tool”:”AAPT”}
FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ‘:app:processDebugResources’.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process ‘command ‘C:\Users\jedmon\android-sdks\build-tools\22.0.1\aapt.exe” finished with non-zero exit value 1
–> This is leaning more towards a configuration and version problem, like you mentioned. I will keep trying different combination of your suggestions.
Again, thank you for being a hard charger in solving your student’s issues.
Hi Norej,
Thanks for your friendliness. I have been doing a bit of googling and it is suggesting missing resources. Which doesn’t make sense. Unless?? when you created the project you have used a version of Activity which expects dimension resources etc which are not in the project. Just check that your main class extends plain old Activity and NOT AppCompatActivity or ActionBarActivity or simmilar. Let me know if it doesn’t work and I’ll keep looking.
John, I will delete the Sprite Sheet Animations app and carefully create this project again. I will let you know tomorrow. Thanks for the walkthrough and your great help.
John, I finally got it to work.
You were right. It was a project version of Activity. I’m still stumbling a bit on how to use this Android Studio correctly.
I ended up having to use the compile sdk version (API 23) and build tools version 23.0.2. I told it to use the min sdk version API 11 and target sdk version API 11. The last thing I did is delete the main activity xml in the layout folder to get it to run.
Thanks John. Now I can follow your code much better, by seeing it run on the emulator.
Well done Norej!
I will leave your comments published as they might provide answers for others.
Awesome explanation this is what i was searching for thank you very much.. and give us more like this. . and i think your site loads slower please do anything to fix it .. and thank you again. I’m starting to learn. .
Thanks very much for your comment! There will be a load more articles in the new year and I will look into the page loading too.
Hello Sir,
love ur wok,
thamnks for being a teacher to the future tycoon *grin* #NotBoasting
here’s a doubt:
What do I exactly need to download ANDROID STUDIO or THE SDK DEVELOPEMENT KIT…?!?
PLZZ HELP…!!
Hi there,
Thanks for your comment. Check out the “Recommended preparation tutorials” and “Assumed previous experience” list at the top of the article as they will guide you towards being able to complete this one. They include setting up Android Studio for the first time.
Good luck,
John
First of all, I love these tutorials!
However, I am not able to run it… It is giving me an IllegalStateException:
The DialogWrapper can only be used in event dispatch thread. Current thread: Thread[ApplicationImpl pooled thread 12,4,main]
java.lang.IllegalStateException: The DialogWrapper can only be used in event dispatch thread. Current thread: Thread[ApplicationImpl pooled thread 12,4,main]
at com.intellij.openapi.ui.DialogWrapper.ensureEventDispatchThread(DialogWrapper.java:2005)
at com.intellij.openapi.ui.DialogWrapper.init(DialogWrapper.java:1185)
at com.intellij.openapi.ui.Messages$MessageDialog._init(Messages.java:1379)
at com.intellij.openapi.ui.Messages$MessageDialog.(Messages.java:1304)
at com.intellij.openapi.ui.Messages.showIdeaMessageDialog(Messages.java:170)
at com.intellij.openapi.ui.Messages.showDialog(Messages.java:157)
at com.intellij.openapi.ui.Messages.showDialog(Messages.java:126)
at com.intellij.openapi.ui.Messages.showErrorDialog(Messages.java:679)
at org.jetbrains.android.facet.AndroidFacet.reloadAvds(AndroidFacet.java:540)
at org.jetbrains.android.facet.AndroidFacet.getValidCompatibleAvds(AndroidFacet.java:555)
at org.jetbrains.android.run.AndroidRunningState.chooseAvd(AndroidRunningState.java:624)
at org.jetbrains.android.run.AndroidRunningState.chooseOrLaunchDevice(AndroidRunningState.java:743)
at org.jetbrains.android.run.AndroidRunningState.start(AndroidRunningState.java:698)
at org.jetbrains.android.run.AndroidRunningState$2.run(AndroidRunningState.java:343)
at com.intellij.openapi.application.impl.ApplicationImpl$8.run(ApplicationImpl.java:366)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jetbrains.ide.PooledThreadExecutor$1$1.run(PooledThreadExecutor.java:55)
Any idea how I can solve this issue? (I’m using Intellij btw)
Thanks!
Hi there thanks for the comment. This is a new one on me. As a coding issue I don’t recognize it at all. The only thing I can think of based on looking at the output is a virtual device issue. Are any other tutorials like this working? If your trying to run it on a virtual device can you try running it on a real device. Maybe give this a try. I would be interested to help you fix this so let me know how you get on.
The problem has been fixed!
Once I uninstalled the “Android Wear ARM EABI v7a System Image” and the “Android Wear Intel x86 Atom System Image” packages from Android SDK Manager it somehow started working again.
Many thanks for taking the time to help me. Keep up the good work!
Many thanks for updating.
Thank you sir!!!
Your explanations are very clear and well established that I almost truly understand what our project in mobile game will look like and function…. :3
This would eventually help us graduate this course!!! This really help a lot sir… Please continue to inspire people, gamers and student like me….
Thanks for the tutorial, but I have a problem. For some reasons my app only returns a black screen. And I tracked down the code and found out that ourHolder.getSurface().isValid() is false, so the app never goes into the actual drawing logic. Then I tracked again and found out that ourHolder = getHolder() actually give ourHolder a null value (because getHolder() is null I guess?). Do you have any suggestion on this? I haven’t read other tutorials before this one so I am not sure if I am missing something. Thanks!
Hi Xuannie,
If the screen is black then the app isn’t even clearing the screen. I would try starting again and copy/pasting the code from the listing at the end of the tutorial, to make sure it is 100% correct.
Let me know if it still doesn’t work and perhaps a few more details like Android Studio version and any output in logcat.
I will try and help you get this working
Hello! This is the best tutorial I have found by far, and I am really learning a lot about java. So thank you for putting in so much time and effort! I have followed every activity in this series, however, this is the first time I have encountered a problem. I copied and pasted the code into android studio, yet I get a blank screen when I run it via USB debugging. The gradle said that the build was successful and below is what the logcat and 4:run reads. At the end of the 4:Run it says “Aborted.” What should I do?
4:Run:
Target device: blu-blu_energy_x_plus-0123456789ABCDEF
Uploading file
local path: C:\Users\Nia\AndroidStudioProjects\SimpleGameEngine\app\build\outputs\apk\app-debug.apk
remote path: /data/local/tmp/com.example.app.simplegameengine
No apk changes detected.
Skipping file upload, force stopping package instead.
DEVICE SHELL COMMAND: am force-stop com.example.app.simplegameengine
Launching application: com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine.
DEVICE SHELL COMMAND: am start -n “com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine” -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String android.os.SystemProperties.native_get(java.lang.String) (tried Java_android_os_SystemProperties_native_1get and Java_android_os_SystemProperties_native_1get__Ljava_lang_String_2)
at android.os.SystemProperties.native_get(Native Method)
at android.os.SystemProperties.get(SystemProperties.java:52)
at android.os.Environment.getCanonicalPathOrNull(Environment.java:832)
at android.os.Environment.(Environment.java:78)
at android.os.Environment.getLegacyExternalStorageDirectory(Environment.java:419)
at android.os.Debug.(Debug.java:96)
at android.ddm.DdmHandleHello.handleHELO(DdmHandleHello.java:164)
at android.ddm.DdmHandleHello.handleChunk(DdmHandleHello.java:91)
at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
java.lang.UnsatisfiedLinkError: android.os.Debug
at android.ddm.DdmHandleHello.handleFEAT(DdmHandleHello.java:176)
at android.ddm.DdmHandleHello.handleChunk(DdmHandleHello.java:93)
at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
java.lang.UnsatisfiedLinkError: android.os.Debug
at android.ddm.DdmHandleProfiling.handleMPRQ(DdmHandleProfiling.java:187)
at android.ddm.DdmHandleProfiling.handleChunk(DdmHandleProfiling.java:88)
at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)
Aborted
Logcat:
03-14 09:54:27.436 25994-25994/com.example.app.simplegameengine V/PhoneWindow: DecorView setVisiblity: visibility = 4 ,Parent =null, this =com.android.internal.policy.impl.PhoneWindow$DecorView{bf52d5c I.E….. R…..I. 0,0-0,0}
03-14 09:54:27.443 25994-25994/com.example.app.simplegameengine V/ActivityThread: Resuming ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}} with isForward=true
03-14 09:54:27.444 25994-25994/com.example.app.simplegameengine V/PhoneWindow: DecorView setVisiblity: visibility = 0 ,Parent =ViewRoot{103819c7 com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine,ident = 3}, this =com.android.internal.policy.impl.PhoneWindow$DecorView{bf52d5c V.E….. R…..I. 0,0-0,0}
03-14 09:54:27.444 25994-25994/com.example.app.simplegameengine V/ActivityThread: Scheduling idle handler for ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:27.444 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-RELAUNCH_ACTIVITY handled : 0 / ActivityRecord{36a7cbf4 token=android.os.BinderProxy@29a998b1 no component name}
03-14 09:54:27.510 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: register, handle(0xb7cff048) (w:1280 h:720 s:1280 f:0x1 u:0x000f02)
03-14 09:54:27.510 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]window_type=1, is_framebuffer=0, errnum = 0
03-14 09:54:27.510 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]surface->num_buffers=4, surface->num_frames=3, win_min_undequeued=1
03-14 09:54:27.510 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]max_allowed_dequeued_buffers=3
03-14 09:54:27.512 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: unregister, handle(0xb7cff048) (w:1280 h:720 s:1280 f:0x1 u:0x000f02)
03-14 09:54:27.515 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: register, handle(0xb7d3bb60) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:27.522 25994-25994/com.example.app.simplegameengine V/InputMethodManager: onWindowFocus: null softInputMode=288 first=true flags=#81810100
03-14 09:54:27.523 25994-25994/com.example.app.simplegameengine V/InputMethodManager: START INPUT: com.android.internal.policy.impl.PhoneWindow$DecorView{bf52d5c V.E….. R…..ID 0,0-1280,720} ic=null tba=android.view.inputmethod.EditorInfo@1b928b63 controlFlags=#104
03-14 09:54:28.788 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-AM_ON_PAUSE_CALLED ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:28.806 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:28.806 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:28.806 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: unregister, handle(0xb7d3bb60) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:28.838 25994-25994/com.example.app.simplegameengine V/ActivityThread: Handling launch of ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:28.839 25994-25994/com.example.app.simplegameengine V/ActivityThread: ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}: app=android.app.Application@32483117, appName=com.example.app.simplegameengine, pkg=com.example.app.simplegameengine, comp={com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}, dir=/data/app/com.example.app.simplegameengine-1/base.apk
03-14 09:54:28.841 25994-25994/com.example.app.simplegameengine V/ActivityThread: getTopLevelResources, packageName:com.example.app.simplegameengine, name:com.example.app.simplegameengine, resDir:/data/app/com.example.app.simplegameengine-1/base.apk
03-14 09:54:28.844 25994-25994/com.example.app.simplegameengine D/SurfaceView: checkSurfaceViewlLogProperty get invalid command
03-14 09:54:28.872 25994-25994/com.example.app.simplegameengine V/ActivityThread: Performing resume of ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:28.872 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-AM_ON_RESUME_CALLED ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:28.872 25994-25994/com.example.app.simplegameengine V/ActivityThread: Resume ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}} started activity: false, hideForNow: false, finished: false
03-14 09:54:28.880 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:28.880 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:28.895 25994-25994/com.example.app.simplegameengine V/PhoneWindow: DecorView setVisiblity: visibility = 4 ,Parent =null, this =com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 I.E….. R…..I. 0,0-0,0}
03-14 09:54:28.905 25994-25994/com.example.app.simplegameengine V/ActivityThread: Resuming ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}} with isForward=true
03-14 09:54:28.905 25994-25994/com.example.app.simplegameengine V/PhoneWindow: DecorView setVisiblity: visibility = 0 ,Parent =ViewRoot{31d01a24 com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine,ident = 4}, this =com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 V.E….. R…..I. 0,0-0,0}
03-14 09:54:28.905 25994-25994/com.example.app.simplegameengine V/ActivityThread: Scheduling idle handler for ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:28.908 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-RELAUNCH_ACTIVITY handled : 0 / ActivityRecord{396a498d token=android.os.BinderProxy@29a998b1 no component name}
03-14 09:54:29.008 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: register, handle(0xb7d5d4a8) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:29.008 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]window_type=1, is_framebuffer=0, errnum = 0
03-14 09:54:29.008 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]surface->num_buffers=4, surface->num_frames=3, win_min_undequeued=1
03-14 09:54:29.008 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]max_allowed_dequeued_buffers=3
03-14 09:54:29.011 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: unregister, handle(0xb7d5d4a8) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:29.014 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: register, handle(0xb7d5d4a8) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:29.038 25994-25994/com.example.app.simplegameengine V/InputMethodManager: onWindowFocus: null softInputMode=288 first=true flags=#81810100
03-14 09:54:29.038 25994-25994/com.example.app.simplegameengine V/InputMethodManager: START INPUT: com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 V.E….. R……. 0,0-720,1280} ic=null tba=android.view.inputmethod.EditorInfo@25ab91af controlFlags=#104
03-14 09:54:31.125 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-AM_ON_PAUSE_CALLED ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:31.195 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-PAUSE_ACTIVITY handled : 1 / android.os.BinderProxy@29a998b1
03-14 09:54:31.902 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:31.902 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:31.903 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: unregister, handle(0xb7d5d4a8) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:32.186 25994-25994/com.example.app.simplegameengine V/ActivityThread: Finishing stop of ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}: show=false win=com.android.internal.policy.impl.PhoneWindow@b9c1d45
03-14 09:54:32.187 25994-25994/com.example.app.simplegameengine V/PhoneWindow: DecorView setVisiblity: visibility = 4 ,Parent =ViewRoot{31d01a24 com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine,ident = 4}, this =com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 I.E….. R……. 0,0-720,1280}
03-14 09:54:32.188 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-STOP_ACTIVITY_HIDE handled : 0 / android.os.BinderProxy@29a998b1
03-14 09:54:32.219 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 1)
03-14 09:54:37.238 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:41.282 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:41.282 25994-26020/com.example.app.simplegameengine D/OpenGLRenderer: Flushing caches (mode 0)
03-14 09:54:41.335 25994-25994/com.example.app.simplegameengine V/ActivityThread: Performing resume of ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:41.339 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-AM_ON_RESUME_CALLED ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:41.340 25994-25994/com.example.app.simplegameengine V/PhoneWindow: DecorView setVisiblity: visibility = 0 ,Parent =ViewRoot{31d01a24 com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine,ident = 4}, this =com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 V.E….. R…..ID 0,0-720,1280}
03-14 09:54:41.339 25994-25994/com.example.app.simplegameengine V/ActivityThread: Resume ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}} started activity: false, hideForNow: false, finished: false
03-14 09:54:41.340 25994-25994/com.example.app.simplegameengine V/ActivityThread: Resuming ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}} with isForward=true
03-14 09:54:41.340 25994-25994/com.example.app.simplegameengine V/ActivityThread: Scheduling idle handler for ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:54:41.342 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-RESUME_ACTIVITY handled : 1 / android.os.BinderProxy@29a998b1
03-14 09:54:41.370 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: register, handle(0xb7d666c0) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:41.371 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]window_type=1, is_framebuffer=0, errnum = 0
03-14 09:54:41.371 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]surface->num_buffers=4, surface->num_frames=3, win_min_undequeued=1
03-14 09:54:41.371 25994-26020/com.example.app.simplegameengine I/MaliEGL: [Mali]max_allowed_dequeued_buffers=3
03-14 09:54:41.373 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: unregister, handle(0xb7d666c0) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:41.381 25994-26020/com.example.app.simplegameengine D/GraphicBuffer: register, handle(0xb7d66638) (w:720 h:1280 s:720 f:0x1 u:0x000f02)
03-14 09:54:41.391 25994-25994/com.example.app.simplegameengine V/InputMethodManager: onWindowFocus: null softInputMode=288 first=true flags=#81810100
03-14 09:54:41.391 25994-25994/com.example.app.simplegameengine V/InputMethodManager: START INPUT: com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 V.E….. R…..ID 0,0-720,1280} ic=null tba=android.view.inputmethod.EditorInfo@102999cb controlFlags=#104
03-14 09:56:42.211 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-AM_ON_PAUSE_CALLED ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}
03-14 09:56:42.280 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-PAUSE_ACTIVITY handled : 0 / android.os.BinderProxy@29a998b1
03-14 09:56:42.282 25994-25994/com.example.app.simplegameengine V/ActivityThread: Finishing stop of ActivityRecord{1745f58 token=android.os.BinderProxy@29a998b1 {com.example.app.simplegameengine/com.example.app.simplegameengine.SimpleGameEngine}}: show=true win=com.android.internal.policy.impl.PhoneWindow@b9c1d45
03-14 09:56:42.282 25994-25994/com.example.app.simplegameengine D/ActivityThread: ACT-STOP_ACTIVITY_SHOW handled : 0 / android.os.BinderProxy@29a998b1
03-14 09:56:42.344 25994-25994/com.example.app.simplegameengine V/InputMethodManager: START INPUT: com.android.internal.policy.impl.PhoneWindow$DecorView{31b54d5 V.E….. R……. 0,0-720,1280} ic=null tba=android.view.inputmethod.EditorInfo@23e648c1 controlFlags=#100
Hi Nia,
Just done some research (because I didn’t know the answer). Seems like it could be a bug with certain versions of Android or certain devices. Probably the key line out of that mountain of output is “java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String android.os.SystemProperties.native_get”
Here are 3 possible solutions(easiest first):
1) Uninstall the app manually from the device and then try again.
2) Turn off “Verify apps over USB” setting on the device
3) Start a new project in case there is an obscure misconfiguration.
Good luck. Let me know if you have time.
hi john,
thanks for these helpful tutorials. Earlier I started to learn android gaming programming but left. But now I am motivated to learn from you. coz u r always here to help.
I went through ur tutorials step by step. and run the program(simple game engine). and got the output. but my bob is looking little tired i.e. walking slow. “FPS: 4″ (range 2-4). so what troubles me that is it ok… if fps is low or should it be approx. 50-60 or more?
Hi Jordi,
On an emulator this poor frame rate is probably to be expected. On a real device, even a fairly old one you should get high fifties fps.
Is this on a real device or emulator?
on emulator. thnx for sorting this out
Hi John!
I enjoy your tutorial very much, but I have an error while compiling your code. It seems that the error is similar to that what Cosmin had but the hint you gave him is not clear to me
” John Horton August 14, 2015 at 9:12 pm – Reply
Class not found exception might indicate the inner class has been named incorrectly? Check yours is called GameView. ”
And here is what logcats shows:
03-28 01:26:15.070 2610-2610/com.example.komp.simplegameengine I/art: Not late-enabling -Xcheck:jni (already on)
03-28 01:26:15.114 2610-2610/com.example.komp.simplegameengine W/System: ClassLoader referenced unknown path: /data/app/com.example.komp.simplegameengine-1/lib/x86
03-28 01:26:15.115 2610-2610/com.example.komp.simplegameengine D/AndroidRuntime: Shutting down VM
03-28 01:26:15.115 2610-2610/com.example.komp.simplegameengine E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.komp.simplegameengine, PID: 2610
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.komp.simplegameengine/com.example.komp.simplegameengine.SimpleGameEngine}: java.lang.ClassNotFoundException: Didn’t find class “com.example.komp.simplegameengine.SimpleGameEngine” on path: DexPathList[[zip file “/data/app/com.example.komp.simplegameengine-1/base.apk”],nativeLibraryDirectories=[/data/app/com.example.komp.simplegameengine-1/lib/x86, /vendor/lib, /system/lib]]
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2327)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.ClassNotFoundException: Didn’t find class “com.example.komp.simplegameengine.SimpleGameEngine” on path: DexPathList[[zip file “/data/app/com.example.komp.simplegameengine-1/base.apk”],nativeLibraryDirectories=[/data/app/com.example.komp.simplegameengine-1/lib/x86, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at android.app.Instrumentation.newActivity(Instrumentation.java:1067)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2317)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)Â
at android.app.ActivityThread.-wrap11(ActivityThread.java)Â
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)Â
at android.os.Handler.dispatchMessage(Handler.java:102)Â
at android.os.Looper.loop(Looper.java:148)Â
at android.app.ActivityThread.main(ActivityThread.java:5417)Â
at java.lang.reflect.Method.invoke(Native Method)Â
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)Â
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)Â
Suppressed: java.lang.ClassNotFoundException: com.example.komp.simplegameengine.SimpleGameEngine
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
… 12 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
03-28 01:26:17.760 2610-2610/? I/Process: Sending signal. PID: 2610 SIG: 9
Thanks in advance for help!
Hi Wojtek,
The “NoClassDefFoundError” indicates the code isn’t building because a class is used but not defined. It could be that you have pasted/typed the code into an incorrectly named .java file. Did you rename the activity when you created the project? You do need to. Try starting a new project paying extra attention to the very start of the tutorial when you create the project.
Good luck!
Oh, finally, I have found the problem. I have just copied and pasted every each line of our code. Well… I should copy except the very first one.
I mean “package com.gamecodeschool.simplegameengine;” . Eh.. It took me a while. I think my mistake is worth mentioning in an article
Anyway, thank you for fast reply.
I tried solving all the problems as I went through the code and I ended up with is: 1 problem = 2 errors
It doesn’t want to allow the use of bob
C:\Users\thomas\AndroidStudioProjects\SimpleGameEngine\app\src\main\java\com\sk8rboycreations\simplegameengine\SimpleGameEngine.java
Error:(81, 85) error: cannot find symbol variable bob
Error:Execution failed for task ‘:app:compileDebugJavaWithJavac’.
> Compilation failed; see the compiler error output for details.
Information:BUILD FAILED
Information:Total time: 6.252 secs
Information:2 errors
Information:0 warnings
Hi Kay,
The most likely causes/solutions are as follows:
The bob graphic is in the wrong folder/not in any folder
Perform a Gradle sync (via Tools > Android > Sync Project with Gradle Files)
Good luck!
Loving your tutorials! Thank you very much
Little bit off topic:
What to do when you have no artistic skills (read can’t even draw a straight line 😀 )?
How will I do my graphics, even simple ones, for my future games?
By graphics I mean my own background, players, creatures, space ships, aliens … 😀
Hi Edita,
You can “borrow” art from all over the Web while developing. As long as you don’t release it who’s to know? I like to get my games working with placeholder/borrowed art because not only does it put off the moment when you have to pay but it allows you to establish exactly which assets and sizes etc will be required. Before release you can then turn to a site like Upwork.com. You can hire anything from high quality 3d artists who cost $50 per hour to an aspiring 2d pixel artist who will complete an entire small project for $25.
Hopr this helps.
Yes, it does. Thank you
Hello John,
I came across your site while searching for tutorials on Java and I have to say, I really have enjoyed it.
I have completed level 1 (with minor bugging issues – we are human after all) and am pleased at the result of producing a game that works on another device, or at least, an animation.
Very challenging, as I spent hours, not weeks, working through the material, but I’m hoping that the areas that are vague for me at the moment, will be clear when I proceed to the next level.
Thanks for producing the tutorial.
Thanks Dennis. Keep going and enjoy yourself!
Hi John,
I’ve copied and pasted you entire class here directly and i’m getting an error that is preventing the build from working. When assign bitmapBob it says “Symbol R could not be resolved” and I can’t figure out what’s happening at all
Thanks for all your hard work on these tutorials by the way!
Hi Ryan, This error can be caused by a number of things.
1) A totally unrelated syntax error in any layout files
2) The graphic missing from the drawable folder
3) A glitch- Try Tools | Android | Sync Project with Gradle Files
Hello John,
First of all thank you very much for the tutorial! It was really helpful and easy to understand.
Now that I got it to work, when Bob leaves the screen, he simply keep going to the right. I want him to return into the screen from right side at a line below current one and heads left, repeating again once he goes out of the screen again. How do I achieve this?
I need a way to tell the program that Bob is currently outside of the screen, but I do not know how.
Thank you very much yet again
Hi Mikael,
Read the tutorial about conditions. You need to detect when bob’s x position goes beyond the width of your screen and then move him down some pixels and reverse his direction. Alternatively you can look at the Space Invaders tutorial where the space invaders do exactly what you are describing. Hope this helps.
Hello John, thank you very much for the tutorial, this is my error…
05-10 00:07:48.835 15503-15664/gametest.hfad.com.gametest E/AndroidRuntime: FATAL EXCEPTION: Thread-32169
java.lang.NullPointerException
at android.graphics.Canvas.throwIfRecycled(Canvas.java:1057)
at android.graphics.Canvas.drawBitmap(Canvas.java:1097)
at gametest.hfad.com.gametest.GameActivity$GameView.draw(GameActivity.java:157)
at gametest.hfad.com.gametest.GameActivity$GameView.run(GameActivity.java:109)
at java.lang.Thread.run(Thread.java:841)
Hi Berto,
Most likely a missing line of code. Nullpointerexception is caused by trying to use an uninitialized object. Try copy pasting the code and see if it still happens. Hope this helps.
Woks very fine! Thanks! Great Job!
Hi John,
Thanks, It was a great tutorial. It was very clearly defined and was easily understandble. I will modify the code to limit
Bobs movement within canvas only.
Thanks once again
I liked your tutorials but I thought it could be more clear about where to paste the code.
Thanks
Thanks Sean,
I take your comment seriously and will hopefully get a chance to make some improvements soon.
I have one error. bob is red and says : Cannot Resolve Symbol ‘bob’
This can be caused by the file being in the wrong folder, the filename and code not matching or sometimes a bit of a glitch with Android Studio. Check the first two possibilities and then try
Tools | Android | Sync Project with Gradle Files
Good luck!
I’m also confused with which drawable folder what is its path (I use Windows 8)
Hi Sean, drag and drop the file directly in to the drawable folder in Android Studio (as opposed to trying to identify it via your OS.)
THANKS A LOT!
How much risk is there in calling update() before the first calculation of fps? A value isn’t assigned to fps until after update() is called, and if isMoving is true it seems there’s a chance of dividing by an unassigned amount.
Hi Tyler, I think you are right, it is probably possible. If you start the app with your finger on the screen might do it. As your engine evolves you could put in a number of states which improve this situation. A pause needing the player to “tap to start”, for example, would avoid the possibility. Hope this helps a bit, thanks for your comment.
Thank you so much John, this was very helpful. You wouldn’t mind if I used this code as a foundation to build upon for my own game, would you? Again, great tutorial, really pointed me in the right direction – I’ve been looking all over the place for a good tutorial to get me started with game creation in Android Studio. Other tutorials I’ve tried yield results that aren’t very good at all, lots of stutter and lag in the frame delivery, but this one works perfectly. I was considering switching to try and use OpenGL ES until I found this – great stuff. =)
Hi Thomas, thanks very much for your comment! Yes, use the code to make as many games as you like. OpenGL ES certainly has its place. The trouble with it is the extra complexity getting started. The Canvas (which uses OpenGL behind the scenes) class can easily handle a fairly complex 2D game and is also much easier to get started.
Thank you for your tutorial. I made one following your guide. I created a menu using the xml layout. So when the app starts, i setContentView(R.layout.activity_main);, when i click on the start game button, i setContentView(gameView);. Then when the game over, I’m stuck in the gameView class, I cannot setContentView(R.layout.activity_main). I tried create Activity a = (Activity) context, which I get the context from gameView(Context context) through super(context) so that I can use a.setContentView(R.layout.activity_main) but I still can’t switch back to the main menu layout view. Please help and explain if I understand this wrong. Thank you.
Hi there,
Not sure what’s going on in your code but here are a couple of alternatives.
First try creating two separate Activities, MainMenuActivity and GameActivity. Then simply switch between Activities. Something like this:
Intent intent = new Intent(this, MainMenuActivity.class);startActivity(intent);
Second, more work but probably better. Create multiple states in GameView. PLAYING, PAUSED, MAINMENU, etc. Then, depending upon the current state your draw, update and input handling will be different. I.e. Draw your main menu using Canvas in the same game loop.
Hope this helps a bit.
Thank you for your help. I will try both. Second one will definitely work but require more code. Thank you so much
Hi John!
Thanks for these awesome tutorials!
I have a doubt. How is the fps maintained at around 60(which is what we want), without writing any code for maintaining the fps?
Hi Rishabh,
Are you concerned about wasting CPU cycles etc? If so, do some testing on a few devices and you will !!probably!! find that Canvas locks at about 60. So the only problem you will have is to take care of the poor performing devices to keep them 30+. If you switch to OpenGL ES (which Canvas is built on top of) then you would have to consider pausing strategies or doing something more useful(AI, Physics, etc) than drawing past 60 fps.
Thanks for the quick reply.
I was asking that how is the frame rate fixed to around 60. Which part of the code is responsible for that?
I saw a tutorial somewhere in net (on making games in java), it used sleep to sleep the main game loop thread passing 17 as the argument to (i.e around 1000/60 ms). It also mentioned that this is NOT a good method.
So, I am asking that how the game fps is maintained around 60 in THIS game engine?
In this game engine, it is not, explicitly in the code. However, Canvas class does, probably. Hope this helps.
Woh!!!!
That was pretty quick reply.
Thanks.
I am eagerly waiting for the Simple scrolling shooter tutorial.
Sorry about the tutorial. I hope to have it done in around 6 weeks. Keep getting delayed.
john all the code is working properly just one liltle problem, when i run the code in my cellphone it opens the game and bob move when i touch the screen and stop moving when i release the finger, but when i go home, back and then i try to open de app section of my cellphone to again touch the icon of bob game, no other app will be shown and it suddenly push me back to the main menu of my cellphone. I ended up unistalling the game in order to have my cellphone app section working again, i really love ur tutorials and i’ll be wating for ur answer thanks a lot!!
Hi Alberto, the most interesting post I have had in ages. I have no idea what in the app could possibly cause this behaviour. Is there any more detail you can give me?
Thanks for answering Jhon ! and im glad that my post was an interesting one for you!, so here we go, the first time i decided to work in a game app, i followed a tutorial in youtube, it was about a helicopter bouncing in the screen and the background map repeat itselft, i had the same problem with the app section when i installed that game, but at time i didnt even know anything i just copy paste to see if it was possible , and it was! so for some reason that i really don’tremember i had the same issue of the app section, soon as i Run the game with my android studio the game starts in my cellphone everything ok , moving and all the code , and when i exit the game or go back to my cellphone OS is okey too, BUT when i touch the icon that allow you to go to all your app sections icons, the OS try to open that new window with all the apps icons ,it won’t even show, the background turns black and then it push me back to the main menu of my cellphone.
well with the other game that i just copy pasted months ago, i had that problem too but then i copypaste the second or third video codes, and disconnected my cellphone after iinstall the game, it worked properly, i hope u can help me i mean obviously u will find the solution sooner o later, thanks and sorry for the so detailed post ><.
As long as you have the onPause method taht shuts down the thread then it should be impossible(literally) for the game engine to have any effect on your phone after it is closed. Try starting a new project. Then deploy the app without adding any code at all. See if an empty screen with the default “Hello world” causes the same problem.
Really nice tutorial to begin with ! Good job.
I’m wondering, each time you call the .draw() method, you refill the whole game screen with blue, and redraw your character and the FPS.
But is it the best method ? I mean, if there were other characters, floors, walls, stuff, we’d have to redraw each one of those 60 times a second. That doesn’t seems right.
Isn’t there a way to say “erase character at old position and redraw at the new one)
I’m absolutely a newbie about game loops and game making related stuff in general
I’m just curious about why redraw everything
Keep on the good work
It does seem like we are being inefficient. However, clearing the screen and starting again each frame is the fastest way to do things.
Works great! Understood most of it, everything felt really organized and properly chunked.
Thanks Yash!
Is there a 2-N group of tutorials out yet?
Hi Bob,
I am adding more Java and Android tutorials over the next 6 weeks. Things like simple patterns for Android games, using databases for inventories etc and eventually start a simple OpenGL ES series too.
Does that answer your question?
I have downloaded the android studio,do i need to configure the SDK manager for me to proceed,becouse it has not bee covered in your tutorials.thanks
Try the tutorial without configuring. Default will probably work ok.
Very nicely explained..Best wishes to you!!
I appreciate your comment.
‘How kind’ …. that was the best comment… you certainly have a great understanding of what code you are writing! and it is so rare!
Very happy to find people like you!
obviously like your website but you have to check the spelling on several of your posts. Several of them are rife with spelling problems and I find it very bothersome to tell the truth nevertheless Ill definitely come back again. bdfdeekeafdc
Thanks, John.
You are right and I am working on it. Hopefully, you will gradually see improvements.
i skipped on to see what me end product would be and, now a days do you have to do the first part cause there’s a opening screen now on java that lets you do classes
Sorry George, I am not sure what you are asking. Which first part? Opening screen on Java?
Can you rephrase this for me and I will try and answer.
Thanks.
Message below is what i’ve got when i tried to install it on emulator.
Installation failed with message null.
It is possible that this issue is resolved by uninstalling an existing version of the apk if it is present, and then re-installing.
WARNING: Uninstalling will remove the application data!
Do you want to uninstall the existing application?
Any suggestion where i went wrong?
I’m so sorry that I have to reply my self but this is for you John..
I have tried to install it in real device which is my device and it is SUCCESS..
well done..
but I’d like to ask you, what should I do with the coding if I want to make him to move left and not move right forever?
which line should I go?
thank you before for your patience and kindness
Hi Kevin,
This is covered in later tutorials. While moving the other way is trivial (just make x smaller rather than bigger) detecting input takes a little more work. I suggest the Breakout game coding tutorial which covers these things.
Hope this helps.
I’ve been following this tutorial. Its so much fun, very thanks
Is there Java tutorial level 2 ?
I have +1 your post.
where I can find “Simple Game Engine Bonus Content”
updated:
I have found the bonus content, thanks 😉
Hello John,
After I insert the class GameView extends SurfaceView implements Runnable code, everything is in red and not recognized. Any idea on this?
Hi Julian,
Possible solutions:
1) Have you proceeded to add the run method?
2) Have you added the imports at the top of the code?
3) Have you pasted it in exactly the right place?
If yes, try downloading the code and pasting the finished code. Keep a copy of your code to compare and discover the error if you are curious.
Hi John,
I sent you updates on different website. The latest for this simple engine is all codes are ok but i get a blank screen. I have also removed the hello world and it remains blank. what now?
Hi Julian,
Is this the latest situation? I have four messages (inc email). I answer questions every few days roughly. Unfortunately I have a job and fortunately but awkwardly I have a young family too.
I just tested the code and the only thing I can see has changed(although it shouldn’t stop it working) is to choose the “empty Activity” project type and deselect “Generate layout file” and deselect “Backwards compatibility”. Then copy & paste all the code from the bottom making sure to leave your package... declaration at the top of your code. Add bob.png. Run the code on the emulator(mine is Nexus 5X API 25…) and all should be well.
Hope this helps,
John
Hi John,
Does this work on older Android devices. My version is below 5.0. Advice if only 5.0 and upwards should be used. I did try this earlier and it didn’t work.
Hi there,
This should work on older devices. I have tested it on 4. Let me know the specific problem and I will try and help.
Hi john,
I’ve managed to get the code to compile and build, but when i try to run the resulting app it in the emulator, i just see the hello world message from the activity_main.xml. Is there a step I’m missing here? I have previously tried deleting the activity_main.xml in the layout folder, but i guess its required :/ My version of the project contains two java files, the SimpleGameEngine and MainActivity
Hi,
Check this line of code in the Activity class
setContentView(gameView);
Hi jon,
The current MainActivity class contains the line ‘setContentView(R.layout.activity_main);’, I have changed it to ‘setContentView(SimpleGameEngine.GameView);’ to test, but the compiler isn’t able to understand this. I’m assuming the onCreate function (below) should override what is in the MainActivity?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize gameView and set it as the view
gameView = new GameView(this);
setContentView(gameView);
}
I’m not sure what is going on here, any advise on what else i can check?
Have you tried the code I suggested?
Yes I have, its the same as the one I have.
Hi there,
Tell me your spefic errors, warnings etc and Ill try and help further.
Hello John,
I’m not really seeing any errors (in terms of compilation). My project contains a MainActivity class and the SimpleGameEngine class. The SimpleGameEngine class has ben copied and pasted so no issues there. However I think it might be related to my MainActivity class setup:
package com.example.simplegameengine;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); <—-
}
}
I think it has something to do with this line, but I don't have any other xml layout files so I'm confused as to what I can change this to
It should be just Activity instead of AppCompatActivity and you appear to still have the setContentView code which I suggested changing. Have you seen the Activity code in the tutorial? The difference between your code and the code in the tutorial that SHOULD be different is that you use MainActivity as the name instead of SimpleGameEngine.
I have this working now, thank you John.
I created a brand new Android project and then instead of adding a new class called ‘SimpleGameEngine’ to the existing project that already contained MainActivity, I instead refactored MainActivity to SimpleGameEngine, pasted in the completed code, popped in ‘package com.example.simplegameengine;’ at the top above the library imports and then shoved the bob image into the res > drawable folder. He seems to moonwalk on mouse-click now (testing in an emulator) so I think its all good now.
The installation to the phone has an issue. The app opens and closes in the blink of an eye! Could not verify if its working or not. All else seems to be fine in Android Studio. Followed the above instructions by chilun as I had the same issue with my blank activity showing ‘hello world’. Had to refactor the activity to ‘SimpleGameEngine’. But in the end the app crashes on my Android Pie device.
Find the “Run” window (usually at the bottom of Android Studio and there should be an error probably in red.
Hi John,
Thanks for the very quick response! I located the run window and there are no errors of sorts marked in red. But there is a peculiar message in the last 2 lines…
‘Waiting for process to come online……’
‘Timed out waiting for process to appear on (my android device ID….)’
Could be that your device is not setup for debugging. You could google that it is a little different on different models. Or try it on an emulator.
Thanks John. I dont think it’s related to debugging as the device is setup for debugging and the initial ‘Hello World’ display for the app did show on my device without issues but it was only after refactoring the name of the activity this new issue cropped up. I will see what I can dig into, I’m sure I’ve made some mistake somewhere with regards to the activity/class while creating the project.
Hmmm. The only other thing I can think you should check is the call to setContentView.
See the following post for information on switching the default activity to the SimplaGameEngine activity.
https://stackoverflow.com/questions/3631982/change-applications-starting-activity
And for those folks having issues with a blank screen, check to make sure that you have set the playing class member variable to true. You can see this on the last line inside of the GameView inner class in the complete listing. Additionally make sure you have the gameView.resume() line in the overrided onResume method and the gameView.pause() in the overrided onPause method.
Hope everyone has a wonderful day!