The Journey
Back home again
0So a couple of days I got back home, after being away for a little more than two weeks. I really didn’t enjoy working on a laptop, so I mainly focused on small things, and didn’t really do much work on the editor. Also it wasn’t possible for me to do a small video tutorial on art assets due to the computer being too slow.
Yesterday I started on some UI graphics together with Stefan Bachmann, and in the future I plan to share these with the libGDX community. For now just a little work in progress image, not completely done yet.
Some elements are not possible to add with Scene2d.ui yet but I created whatever I felt might be useful to have in the future.
I also plan to create a bunch of icons for the most common tasks, and people can use them as they wish.
Small update
0It’s been a little slow here the last couple of days, that doesn’t mean I haven’t been active coding though.
I’ve been busy trying to implement multiselection, and have the base methods for this finished, however I ran into some problems using the polygon class that comes with libGDX. Without going too much in to detail, due to not having an insane amount of time, the polygon class proved to have some errors in it, and with my knowledge of java it took me a while to figure out that it wasn’t actually me doing things wrong, but the class itself. Nate Sweet who has been contributing a lot to libGDX, did a small update to it and hopefully that will fix the problems I’ve been having, haven’t had the time to test it out fully yet though.
Now the next couple of days I wont be able to do much work, heading out until the 4′th of July, but I’ll have my laptop with me and I plan to do a few updates. Among things I plan to make a small tutorial on making art assets for games, using Photoshop. Also I plan to share the grid class that I’ve been using for the editor so far, which seems pretty solid.
If anyone has a topic you would like me to cover regarding art assets, both 2d and 3d, I’ll do my best to make a small video on it.
With that said, I’m out of time and got to get going again.
Progress update. Uhhhh shiny!
0Finally a little something to show from the actual stuff I’m working on. I’ll keep this post short, due to being tired out of the ordinary, so here’s a little youtube video instead.
It runs a lot smoother without the screencast program running, but fraps which I usually use, just didn’t work for some reason.
Lots of stuff to add, but I’m getting more and more familiar with Java and libGDX so hopefully things will slowly go faster and faster.
Beating your head against a brick wall
0It’s been a week now, and pretty much every day I’ve been busy trying to learn Java and libGDX. Tuesday was a really horrible day for morale, nothing seemed to go right and once I thought I “got it”, I was proven wrong and ended up even more confused. The topic that confused the hell out of me, was how to extend a class and being able to grab the information from that class. In other words, Inheritance (Definition: A class that is derived from another class is called a subclass (also a derived class, extended class, or child class). The class from which the subclass is derived is called a superclass (also a base class or a parent class).
Some things made sense, others didn’t and trying to put what I had learned into practice constantly made me bump my head against a brick wall. In the end something has got to give though, and in this case it was the brick wall!
This video on youtube, helped a lot but my biggest problem was still that I was putting different shape types in an array, and I didn’t know how to access the different types in that array. Type casting ended up being my solution for that, and eventually I got things working. Now I won’t go much deeper into type casting, since it’s still a very new subject to me, that I have yet to fully understand.
So where am I now, well I’ve gotten a basic viewport going with a grid that is made up of the the shape type Line, only the needed amount of grid lines are drawn at any given time, so there is no limit to how big a world I can build in this editor I’m trying to do, of course there will be a limit due to limitations of the platform I’m making this for, but visually there is no limit. I can also add basic shapes at rendertime, which means the first big step forward has been taken, now I just need to expand a lot on that.
I got to say, it feels great to get past this point, and while I know that I will most likely run into far bigger problems in the future once things get more complicated, it’s still a learning experience for me and this will be a very long process.
Once I get a little more functionality in the tool I am currently making, I’ll post a more interesting screenshot, but for now. Big smiley face!
Day five. The recap
2It has now been five days since I started this venture into Java. Looking back, it’s actually hard to categorize what I have learned. But I’ll try my best to recap a few of the things.
Listed in no particular order.
1. Plan your shit, use UML or Mindmaps. Draw stickmen illustrating your plan on a piece of paper, or draw it in the sand. It doesn’t matter how you do it, just do it. I can not express just how important this is. If I had been listing these things by importance, this would be on the very top, oh and it just happens to be at the top!
2. Object Oriented programming can be hard as hell, and is full of strange words, like Abstraction, Encapsulation and Exceptions.
3. Exceptions suck.
4. Learn how to use the debugger in Eclipse. It really sucks spending an hour trying to figure out why your application is crashing, only to find out you could have used the debugger to find out you had a null object. Yeah, I did that.
5. I’ll quote Eckel on this one. “A learning experience is what you get when you don’t get what you want”. I’ve found that to be true more often than not.
6. When you have something that works, look at your code, see if you can improve it. That way you will build on things you “know” and possibly find out that you don’t know them as well as you thought. You might not get where you want as quick, but at least you’re learning more, and this is what it’s all about. Eventually you will have to move on though. You can always come back to it.
7. When you’re stuck, step away from your computer, do something NOT related to computers at all. Approach the problem from a distance and there is a good chance you see things much clearer.
That’s all from me for now!
One small step for others, one giant leap for ME!
6In my previous blog post, I was talking about how I failed to extend the Rectangle class, and had to step back and learn a few more basics. Now approximately 8 hours later, a lot of pages, videos and other things (completely unrelated to Java), I’ve managed to get it working.
For me this a huge step in the right direction, and when the penny finally hit, it didn’t take more than a few minutes to actually change the code to reflect what I wanted to do.
Again, the original spawnRaindrop() code:
1 2 3 4 5 6 7 8 9 | private void spawnRaindrop() { Rectangle raindrop = new Rectangle(); raindrop.x = MathUtils.random(0, 800-48); raindrop.y = 480; raindrop.width = 48; raindrop.height = 48; raindrops.add(raindrop) lastDropTime = TimeUtils.nanoTime(); } |
private void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800-48);
raindrop.y = 480;
raindrop.width = 48;
raindrop.height = 48;
raindrops.add(raindrop)
lastDropTime = TimeUtils.nanoTime();
}
And the modified version
1 2 3 4 5 6 7 8 9 10 | private void spawnRaindrop() { Raindrop raindrop = new Raindrop(); raindrop.x = MathUtils.random(0, 800-48); raindrop.y = 480; raindrop.width = 48; raindrop.height = 48; raindrop.speed = MathUtils.random(50,200); raindrops.add(raindrop); lastDropTime = TimeUtils.nanoTime(); } |
private void spawnRaindrop() {
Raindrop raindrop = new Raindrop();
raindrop.x = MathUtils.random(0, 800-48);
raindrop.y = 480;
raindrop.width = 48;
raindrop.height = 48;
raindrop.speed = MathUtils.random(50,200);
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
The Raindrop class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package com.badlogic.drop; import com.badlogic.gdx.math.Rectangle; public class Raindrop extends Rectangle { float speed; public Raindrop() { super(); } public Raindrop(float x, float y, float width, float height, float speed) { super(x, y, width, height); this.speed = speed; } } |
package com.badlogic.drop;
import com.badlogic.gdx.math.Rectangle;
public class Raindrop extends Rectangle {
float speed;
public Raindrop() {
super();
}
public Raindrop(float x, float y, float width, float height, float speed) {
super(x, y, width, height);
this.speed = speed;
}
}
And the entire Drop.java code with the new shiny Raindrop class in action (I took the liberty of copying directly from the tutorial page since I had mangled the original code somewhat awful)
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 | package com.badlogic.drop; import java.util.Iterator; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.audio.Music; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.TimeUtils; public class Drop implements ApplicationListener { Texture dropImage; Texture bucketImage; Sound dropSound; Music rainMusic; SpriteBatch batch; OrthographicCamera camera; Rectangle bucket; Array<Raindrop> raindrops; long lastDropTime; @Override public void create() { // load the images for the droplet and the bucket, 48x48 pixels each dropImage = new Texture(Gdx.files.internal("droplet.png")); bucketImage = new Texture(Gdx.files.internal("bucket.png")); // load the drop sound effect and the rain background "music" dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav")); rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3")); // start the playback of the background music immediately rainMusic.setLooping(true); rainMusic.play(); // create the camera and the SpriteBatch camera = new OrthographicCamera(); camera.setToOrtho(false, 800, 480); batch = new SpriteBatch(); // create a Rectangle to logically represent the bucket bucket = new Rectangle(); bucket.x = 800 / 2 - 48 / 2; // center the bucket horizontally bucket.y = 20; // bottom left corner of the bucket is 20 pixels above the bottom screen edge bucket.width = 48; bucket.height = 48; // create the raindrops array and spawn the first raindrop raindrops = new Array<Raindrop>(); spawnRaindrop(); } private void spawnRaindrop() { Raindrop raindrop = new Raindrop(); raindrop.x = MathUtils.random(0, 800-48); raindrop.y = 480; raindrop.width = 48; raindrop.height = 48; raindrop.speed = MathUtils.random(0,50); raindrops.add(raindrop); lastDropTime = TimeUtils.nanoTime(); } @Override public void render() { // clear the screen with a dark blue color. The // arguments to glClearColor are the red, green // blue and alpha component in the range [0,1] // of the color to be used to clear the screen. Gdx.gl.glClearColor(0, 0, 0.2f, 1); Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // tell the camera to update its matrices. camera.update(); // tell the SpriteBatch to render in the // coordinate system specified by the camera. batch.setProjectionMatrix(camera.combined); // begin a new batch and draw the bucket and // all drops batch.begin(); batch.draw(bucketImage, bucket.x, bucket.y); for(Rectangle raindrop: raindrops) { batch.draw(dropImage, raindrop.x, raindrop.y); } batch.end(); // process user input if(Gdx.input.isTouched()) { Vector3 touchPos = new Vector3(); touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0); camera.unproject(touchPos); bucket.x = touchPos.x - 48 / 2; } if(Gdx.input.isKeyPressed(Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime(); if(Gdx.input.isKeyPressed(Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime(); // make sure the bucket stays within the screen bounds if(bucket.x < 0) bucket.x = 0; if(bucket.x > 800 - 48) bucket.x = 800 - 48; // check if we need to create a new raindrop if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop(); // move the raindrops, remove any that are beneath the bottom edge of // the screen or that hit the bucket. In the later case we play back // a sound effect as well. Iterator<Raindrop> iter = raindrops.iterator(); while(iter.hasNext()) { Raindrop raindrop = iter.next(); raindrop.y -= raindrop.speed * Gdx.graphics.getDeltaTime(); if(raindrop.y + 48 < 0) iter.remove(); if(raindrop.overlaps(bucket)) { dropSound.play(); iter.remove(); } } } @Override public void dispose() { // dispose of all the native resources dropImage.dispose(); bucketImage.dispose(); dropSound.dispose(); rainMusic.dispose(); batch.dispose(); } @Override public void resize(int width, int height) { } @Override public void pause() { } @Override public void resume() { } } |
package com.badlogic.drop;
import java.util.Iterator;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
public class Drop implements ApplicationListener {
Texture dropImage;
Texture bucketImage;
Sound dropSound;
Music rainMusic;
SpriteBatch batch;
OrthographicCamera camera;
Rectangle bucket;
Array<Raindrop> raindrops;
long lastDropTime;
@Override
public void create() {
// load the images for the droplet and the bucket, 48x48 pixels each
dropImage = new Texture(Gdx.files.internal("droplet.png"));
bucketImage = new Texture(Gdx.files.internal("bucket.png"));
// load the drop sound effect and the rain background "music"
dropSound = Gdx.audio.newSound(Gdx.files.internal("drop.wav"));
rainMusic = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
// start the playback of the background music immediately
rainMusic.setLooping(true);
rainMusic.play();
// create the camera and the SpriteBatch
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
batch = new SpriteBatch();
// create a Rectangle to logically represent the bucket
bucket = new Rectangle();
bucket.x = 800 / 2 - 48 / 2; // center the bucket horizontally
bucket.y = 20; // bottom left corner of the bucket is 20 pixels above the bottom screen edge
bucket.width = 48;
bucket.height = 48;
// create the raindrops array and spawn the first raindrop
raindrops = new Array<Raindrop>();
spawnRaindrop();
}
private void spawnRaindrop() {
Raindrop raindrop = new Raindrop();
raindrop.x = MathUtils.random(0, 800-48);
raindrop.y = 480;
raindrop.width = 48;
raindrop.height = 48;
raindrop.speed = MathUtils.random(0,50);
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
@Override
public void render() {
// clear the screen with a dark blue color. The
// arguments to glClearColor are the red, green
// blue and alpha component in the range [0,1]
// of the color to be used to clear the screen.
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// tell the camera to update its matrices.
camera.update();
// tell the SpriteBatch to render in the
// coordinate system specified by the camera.
batch.setProjectionMatrix(camera.combined);
// begin a new batch and draw the bucket and
// all drops
batch.begin();
batch.draw(bucketImage, bucket.x, bucket.y);
for(Rectangle raindrop: raindrops) {
batch.draw(dropImage, raindrop.x, raindrop.y);
}
batch.end();
// process user input
if(Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
bucket.x = touchPos.x - 48 / 2;
}
if(Gdx.input.isKeyPressed(Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();
// make sure the bucket stays within the screen bounds
if(bucket.x < 0) bucket.x = 0;
if(bucket.x > 800 - 48) bucket.x = 800 - 48;
// check if we need to create a new raindrop
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop();
// move the raindrops, remove any that are beneath the bottom edge of
// the screen or that hit the bucket. In the later case we play back
// a sound effect as well.
Iterator<Raindrop> iter = raindrops.iterator();
while(iter.hasNext()) {
Raindrop raindrop = iter.next();
raindrop.y -= raindrop.speed * Gdx.graphics.getDeltaTime();
if(raindrop.y + 48 < 0) iter.remove();
if(raindrop.overlaps(bucket)) {
dropSound.play();
iter.remove();
}
}
}
@Override
public void dispose() {
// dispose of all the native resources
dropImage.dispose();
bucketImage.dispose();
dropSound.dispose();
rainMusic.dispose();
batch.dispose();
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
}I hope this is helpful to someone else, if not at least I have some place to find this when I wake up and have forgotten all about it.
Drop 1
Me 1
Your move Java!
On another note, I really need to add a couple of things to this wordpress blog. Color coded syntax and an easier way to add the code would be a start. Also I’ve been asked to add some syndication for the entire site, so I’ll look into that sometime soon as well.
Wait.. back up a bit, I’m missing something
0After spending a little time with Eclipse and going deeper into libGDX, and going through one of the libGDX tutorials, namely this one https://code.google.com/p/libgdx/wiki/SimpleApp#Project_Setup. I decided to try and expand a bit on it.
“Drop” which is the name of the game you create in that short tutorial, taught me a few things, but I realized that I would have to stop and go back a bit when I wanted to extend on the Rectangle class in libGDX. Let me try and explain my reasons for wanting to extend that class.
If you follow the code precisely you end up with a small game, where you move a bucket in the bottom of the screen around, to catch drops falling at random spots from the top of the screen (Zen indeed). Now all these drops that are falling, fall with the same speed, so I wanted to randomize the speed of the drops, to add a little variation to the game, merely for learning purposes.
This is the section of the code that spawns the raindrops
1 2 3 4 5 6 7 8 9 | private void spawnRaindrop() { Rectangle raindrop = new Rectangle(); raindrop.x = MathUtils.random(0, 800-48); raindrop.y = 480; raindrop.width = 48; raindrop.height = 48; raindrops.add(raindrop); lastDropTime = TimeUtils.nanoTime(); } |
private void spawnRaindrop() {
Rectangle raindrop = new Rectangle();
raindrop.x = MathUtils.random(0, 800-48);
raindrop.y = 480;
raindrop.width = 48;
raindrop.height = 48;
raindrops.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
Now I wanted to add a little more to it
1 | raindrop.speed = MathUtils.random(50, 200); |
raindrop.speed = MathUtils.random(50, 200);
However to do this I needed to extend the Rectangle class, which with my knowledge of Java was not possible.
So the only way for me to go for now, is to read up a bit more about the basics of Java, and take it slower. For this I’ve allied myself with a book called “Head First Java”, which so far seems like a very good read. Also, Mario’s Beginning Android Games, but that will probably be used on a later time, since I first need to take a few steps back.
It looks like the score for now is.
Drop 1
Me 0
But the battle is not over yet!
Starting out with libGDX and documenting the journey
0In an attempt to learn game programming for smartphones, more precisely android, I’ve decided to try and document the entire journey from start to finish using libGDX.
Now this is not the first time that I have been involved with games, I’ve been involved in more than one project, ranging from large to small, but always with the focus of art.
This time however I’ve decided to go as deep as the programming.
Working with Mario Zechner, the crazy austrian guy (meant in a good way) behind libGDX in the past, have taught me a lot of things, but I’ve never really focused on the programming part, except for writing tools for softimage, which has been my weapon of choice for many years now. These tools, which were aimed at making game assets easier, have helped me not only learn more about programming, but also to understand various other things, like how to optimize your assets, what assets are actually needed and have given me a good understanding of best practices when it comes to art assets.
However, when it comes to programming for a game, and I don’t mean just parts of it, but everything that comes with making games, I’m mostly on completely new territory. Writing the things I discover down in this blog, as well as sharing what I learn, should hopefully help making the things I learn stick. Also I hope that whoever is reading this, might come away with something useful as well.
For those more interested in the process that goes into making the art, I will also share some techniques for that in the future.
The journey for this will be long and difficult, there will be times where I might run out of steam, but hopefully I’ll be able to keep pounding away at my keyboard.
And now, time to open up Eclipse again.

