Previous Tutorial
Next Tutorial
Posted on: 15-11-2012

Gravity Platformer Tutorial #8 : Adding an Objective

Because our game keeps growing and because you have come this far already, I am only going to highlight the important changes in the code from now on, there will be a download to the full new working source at the beginning of each tutorial.

I've decided to do this because the reason I've started this tutorial series is to learn you the concepts and basics of programming a 2D platformer in Java with the use of Slick2D and LWJGL. So instead of copy and pasting all the small little pieces, I will walk you through the changes and how and why they work.

Zip file: download

Our objective

So what is our objective?

Remember the story we wrote in tutorial 3? There was something stated about collecting scrap metal parts to repair our spaceship.

So this means we have to have some kind of scrap metal object in our game, so we start off with a new class called Objective.

  1. public class Objective extends LevelObject {
  3. protected Animation animation;
  5. public Objective(float x, float y) throws SlickException {
  6. super(x, y);
  8. //add the right animation for this objective
  9. animation = new Animation(new Image[]{new Image("data/img/objects/scrap_part/scrap_part_1.png"),new Image("data/img/objects/scrap_part/scrap_part_2.png"),
  10. new Image("data/img/objects/scrap_part/scrap_part_3.png"),new Image("data/img/objects/scrap_part/scrap_part_4.png")}
  11. ,new int[]{200,125,125,200});
  13. animation.setPingPong(true);
  15. //we will just keep the default boundingrect of 32x32 for the objective
  16. }
  18. public void render(float offset_x, float offset_y) {
  19. animation.draw(x-2-offset_x,y-2-offset_y);
  20. }
  22. }

What you see here is that it is almost the same as a LevelObject, but we also have an animation.

I thought it would look a bit nicer if the scrap metal part would float a bit around on the ground, so thats why I decided to go for an animation here.

Another thing here is the setPingPong(true) part, this basicly means it will go from the first image to the last, and then back again from the last to the first.

Also an important change is that the render method is also added to LevelObject, this will enable us to render the LevelObjects without us knowing what the object exactly is.

Adding and rendering our objective

We will start off by adding a list of LevelObject objects to our Level class, it is important to keep in mind that this will be the list for our basic and somewhat static objects (such as the objective).

Now if we look at back what our objective was, we have to collect scrap metals, so in a way we have to pick them up.

So lets not forget to add the means to remove objects from our level:

  1. public void removeObject(LevelObject obj){
  2. levelObjects.remove(obj);
  3. }
  5. public void removeObjects(ArrayList<LevelObject> objects) {
  6. levelObjects.removeAll(objects);
  7. }

The latter we come in handy later on in this tutorial.

And for the rendering it will be quite simple:

  1. for(LevelObject obj : levelObjects){
  2. obj.render(offset_x, offset_y);
  3. }

Last but not least we have to add our objectives to the map, we will just do this hard coded for now. It is important to keep our progress going for now, we can always clean things up later.

So we add the following to the init method of LevelState:

  1. level.addLevelObject(new Objective(128,315));
  2. level.addLevelObject(new Objective(528,315));
  3. level.addLevelObject(new Objective(328,615));

Applying the physics

Now here comes the tricky part, we have to do a few things here:

  1. We have to apply the gravity to the LevelObjects
  2. We have to check if the player and the Objective collide and do something about it

Lets start with a method for the LevelObject's:

  1. private void handleLevelObjects(Level level, int delta){
  2. for(LevelObject obj : level.getLevelObjects()){
  3. handleGameObject(obj,level,delta);
  4. }
  5. }

All we have to do is call this one in the handlePhysics method and we have our objects falling towards the ground if they are not on the ground.

Now for number 2 on our list, we have to expand our handleCharacters method

  1. private void handleCharacters(Level level, int delta){
  2. for(Character c : level.getCharacters()){
  4. //and now decelerate the character if he is not moving anymore
  5. if(!c.isMoving()){
  6. c.decelerate(delta);
  7. }
  9. handleGameObject(c,level,delta);
  11. //special cases for the player
  12. if(c instanceof Player){
  14. ArrayList<LevelObject> removeQueue = new ArrayList<LevelObject>();
  16. //we have to check if he collides with anything special, such as objectives for example
  17. for(LevelObject obj : level.getLevelObjects()){
  19. if(obj instanceof Objective){
  20. //in case its an objective and its collides
  21. if(obj.getBoundingShape().checkCollision(c.getBoundingShape())){
  22. //we have to remove the object from the level, and add something to the score
  24. removeQueue.add(obj);
  25. }
  26. }
  27. }
  29. level.removeObjects(removeQueue);
  30. }
  32. }
  33. }

So what you see here is that we do the usual for the characters, but when the character is in fact a player we will do some additional checking.

And that additional checking is walking through the objects in the level, if then one of those objects is a Objective we check if we collide with the player. And if we collide we want to remove the Objective from the level and add to our score.

Closing notes

And there we go, we have the objective in the game, next time we will look into cleaning up the hard coded objectives.
Categories: Game Design, Game Development, Java, Tutorial


jL said: (15-11-2012)
Thanks a lot again. Like the idea of just highlighting changed code instead of holding our hand through it.

Keep 'em coming!
Frums said: (16-11-2012)
Thanks for the feedback! It also saves me a lot of time by doing it this way, enabling me to create tutorials more frequently.

What is the name of the website? (to counter the spam)