CHRONICLES OF A VIDEOGAME IN JAVA – 6. NPCs

Previously on the Chronicles of a Videogame in Java: Collision Detection for Dummies.

The code discussed below is already available on my GitHub page at theBoyWithNoName (“npcs” branch). Please feel free to download it to take a better look. Ask me anything about it.

dsads
Welcome back to the journey of “The Boy With No Name”, a 2D platform game that I’m coding from scratch in Java. Today I’m going to talk a bit about NPCs, acronym that stands for Non-Playable Character. For those of you who may not know, NPCs in videogames are basically characters that you meet but can’t directly control. In my experience, there can be three types of NPC in a videogame:

The unavoidable one is a part of the story. The main character is forced to interact with him in order to move forward in the game. (example: Professor Oak in the Pokémon series)

The helpful one helps the main character through his journey giving him wise words or even objects to overcome adversities. (example: the merchant from Resident Evil 4)

The useless one is really just a piece of furniture. He may even speak two or three words in a row but there’s no purpose in those words. They don’t help you finish the game. (example: the citizens in Zanarkand at the beginning of Final Fantasy X)

The kind of NPCs that I’m adopting for “The Boy With No Name” is the second one, the helpful kinda guy. Here’s how it works: all the secondary characters in the game will wait idle in a specific place of a specific level and, only if talked to, they will suggest something or maybe give something to the main character. They will not be unavoidable though: the player will be perfectly able to just walk past them and go on with his adventure. Pretty simple.

npcs

At this point we have delined the standard behaviour of the NPCs in the game. Now it’s time to put this thoughts to code.

From an architectural point of view, I found inconvenient to use some sort of map or bidimensional array for the positioning of the secondary characters in the stage. Do you remember the tiled map we used to position blocks of terrain? Well we could have used the same concept to store current NPCs, but to me that’s a crazy thing to do if you don’t plan to put hundreds of secondary little characters in the game.

So yeah, the NPCManger class stores all of the stage’s Non-Playable Characters in a simple array of objects. Informations about where to put the NPC and what the NPC has to say is stored in text files that the NPCManager consults accordingly to the level currently played by the user. So here’s what the class looks like:

public class NPCManager {
	public NPCManager(int currentLevel){
		this.currentLevel=currentLevel;
		currentNPCs=new ArrayList<NPC>();
		loadInformations();
	}
	
	public void initializeStage(int currentLevel) {
		currentNPCs.clear();
		this.currentLevel=currentLevel;
		loadInformations();
	}
	
	private void loadInformations() {
		InputStream is=this.getClass().getResourceAsStream("/npc_info/level"+String.valueOf(currentLevel)+".txt");
		if(is==null){
			return;
		}
		BufferedReader reader=new BufferedReader(new InputStreamReader(is));
		String line=null;
		String[] singleNPCInfo;
		try {
			while((line=reader.readLine())!=null){
				singleNPCInfo=line.split(" ");
				currentNPCs.add(new NPC(singleNPCInfo[0],Integer.valueOf(singleNPCInfo[1]),
						Integer.valueOf(singleNPCInfo[2]),Integer.valueOf(singleNPCInfo[3]),currentLevel));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public ArrayList<NPC> getNPCs() {
		return currentNPCs;
	}
	
	//returns the closest enemy within two tiles of distance (which is 
	//the maximum distance allowed for an interaction with a NPC)
	public NPC closestNPC(int boyRow, int boyCol) {
		NPC closestNPC=null;
		int currentDistance;
		for(int i=0; i<currentNPCs.size(); i++){
			if(boyRow!=currentNPCs.get(i).getRow()){
				continue;
			}
			if((Math.abs(currentNPCs.get(i).getCol()-boyCol))<=MAXIMUM_TALKING_DISTANCE){
				currentDistance=Math.abs(currentNPCs.get(i).getCurrentX()-(boyCol*Tile.TILE_SIZE));
				if(closestNPC==null){
					closestNPC=currentNPCs.get(i);
				} else {
					if(currentDistance<Math.abs(closestNPC.getCurrentX()-boyCol+Tile.TILE_SIZE)){
						closestNPC=currentNPCs.get(i);
					}
				}
			}
		}
		
		return closestNPC;
	}	
	
	private static final int MAXIMUM_TALKING_DISTANCE=2;
	private ArrayList<NPC> currentNPCs;
	private int currentLevel;
}

As you may notice there’s a closestNPC() function that, as you can imagine, is called every time you try to interact with a non playable character. This function finds the closest Non-Playable-Character given the protagonist’s position. But the character can’t interact with people further than 2 tiles, and that’s the reason of the control at line 46 based on the constant MAXIMUM_TALKING_DISTANCE.

An instance of the NPCManager class is stored in the GameManager, the main thread of the game which also controls a set of currently pressed keys and reacts to them in the proper way via the manageKeys() function. Here’s what the manageKeys() function will look like if we bound the <enter> key to the interaction with an NPC:

private void manageKeys() {
		[...]
		if(currentKeys.contains(KeyEvent.VK_ENTER)){
			NPC tempNpc;
			//find the closest npc according to the character's position
			if((tempNpc=npcManager.closestNPC(boy.getRow(),boy.getCol()))!=null){
				
				//if the npc is already talking, keep talking...
				if(tempNpc.isTalking()){
					if(!(tempNpc.continueTalking())){
						listening=false;
					}
				
				//otherwise interact with the npc
				} else {
					tempNpc.interact();
					
					//put the character in &amp;amp;amp;lt;idle&amp;amp;amp;gt; status when he's talking
					boy.stop();
					
					//prevent the character from moving when talking
					listening=true;
				}
			}
			currentKeys.remove(KeyEvent.VK_ENTER);
		}
		
	}

Now what remains to be seen is the actual NPC class, but to be honest there’s not much to explain here. The NPC is similar to the Protagonist (class Boy) in the sense that it has a couple of pixel coordinates and a couple of “tile-coordinates” that identify the position of the secondary character in the tiled map. The pixel coordinates are really just the tile-coordinates multiplied by the size of a tile (which in my case is 64) but you know, it’s handy and a lot more polished to have them stored separately.

What really makes the difference in the NPC class are these guys:

	private boolean talking=false;
	private String[] sentences;
	private int currentSentence=0;
	private int numberOfSentences;	

If the talking boolean is false the game will not display any of the speech balloons associated with the NPC. If true it will display a specific speech depending on how many times the player has talked to this NPC. The times you talk to an NPC are stored in the currentSentence variable, that increments each time you press in front of the guy you want to talk to. The currentSentence integer is also used to iterate over the sentences array, which contains all the lines the NPC is supposed to say in that specific spot of that specific level. The PlayPanel (the JPanel that shows the actual game) will draw the speech balloons accordingly to the NPC position and will fill the speech balloon with the words defined by sentences[currentSentence].

So yep, this is probably the easiest approach you can have to build a working NPC system. But it works:

Aaaaaaand that would be all for today’s diary. Once again, remember that this is not a proper tutorial, but just a “how I make things” kind of thing. So if you have suggestions or you don’t understand what I say, please comment below or get in touch with me on twitter. I’m also on tumblr, drawing stuff. See you soon guys!

Advertisements
CHRONICLES OF A VIDEOGAME IN JAVA – 6. NPCs

Chronicles of a Videogame in Java – 5. Collision detection for dummies

Previously on the Chronicles of a Videogame in Java: Bulding a tiled map.

The code discussed below is already available on my GitHub page at theBoyWithNoName (“collisions” branch). Please feel free to download it to take a better look. Ask me anything about it.

Hi guys and welcome back to our beautiful journey through the development of a 2D platform-game in Java Swing. Today we’re gonna talk about collisions, maybe one of the trickiest topics in the making of a bidimensional game.

Before we start I want to make sure that you remember what a Block object is in my project. A Block object has two important features:

  • It is not movable.
  • It doesn’t involve interactions with the player whatsoever.

Pretty basic stuff. So how did I approach collisions with blocks in my code? Well, what we know is that there are essentially three cases in which you can collide with an immovable block in a 2D platform, and those are: you’re running left, running right or jumping/falling in the air. Now, remember those rectangles we built around each and every object of the game? The bounding boxes? Well, those rectangles are the foundation of collision detection. Here’s a simple picture that explains why:

collisionNoCollision

See the red rectangle around our chill protagonist? That’s his bounding box. The block object you see next to the main character in the picture above has its own bounding box, visually represented by a blue outline. If two bounding boxes intersect, a collision happens.

On the left you can see a situation where the character and the block do not collide. On the right side of the picture, instead, they are colliding pretty hard I’d say. And that’s a situation we don’t want to happen in the game. If the Character is running right and faces a Block object, his bounding box must never intersect the Block’s one.

Now let’s put it to code.

	public void checkBlockCollisions(){
		[...]
		//if last direction was right..
		if(last_direction==KeyEvent.VK_RIGHT){
			
			//get the left side of the bounding box
			int footX=(int)boundingBox.getMinX();
			
			//get the tile position (in the tiled map) 
			//relative to the tile in front of the character
			int tileInFrontOfFootRow=((footY-1)/Tile.TILE_SIZE);
			int tileInFrontOfFootCol=(footX/Tile.TILE_SIZE)+1;
			
			if(tileInFrontOfFootCol<World.COLS){
				//if the tile in front of the character contains a block..
				if(World.tiledMap[tileInFrontOfFootRow][tileInFrontOfFootCol] instanceof Block){
					//..and the character's bounding box intersect the block's one
					if(boundingBox.intersects(World.tiledMap[tileInFrontOfFootRow][tileInFrontOfFootCol].getBoundingBox())){
						//push the character away and re-set its position
						currentX-=DISPLACEMENT;
						boundingBox.setLocation(currentX, currentY);
						currentCol=currentX/Tile.TILE_SIZE;
					}
				}
				
				if(World.tiledMap[currentRow][currentCol] instanceof Block){
					//if the tile the character finds himself in contains a block, act like above
					if(boundingBox.intersects(World.tiledMap[currentRow][currentCol].getBoundingBox())){
						currentX-=DISPLACEMENT;
						boundingBox.setLocation(currentX, currentY);
						currentCol=currentX/Tile.TILE_SIZE;
					}
				}
			}
		} else {
			//the same thing you see above happens here for the left direction 
			[...]	
		}
	}

Notice that when the character runs left or right and his bounding box intersects a Block’s one, he’s pushed away of an amount of pixels equals to the number of pixels he covers with a single step (the DISPLACEMENT value). This way the character’s bounding box can never intersect the Block.

The code you see above works perfectly for side collisions, but it doesn’t help much if our little protagonist is jumping and slamming his head on a block that is placed above him.

As for jump collisions I had to rethink the jump mechanic I talked about in one of my previous posts. “How” you say? Well, first thing I did was splitting the ascending phase and the descending phase of the jump. In particular, when the character is going up we have that the jumping boolean is set to true and the falling is set to false. When the character is going down we have the opposite setting of those variables. To have a specific falling state is really helpful even in other situations: for example I can set it to true when the character doesn’t have a Block object under his feet. This way I can make character fall (increment y position) while falling=true. But collision-wise, we have that the character’s head can only collide if he’s in ascending phase. So here’s how I dealt with the problem:

		
		//if the character is jumping, his head must not touch a block;
		//if it touches a block, stop the ascending phase of the jump (start falling)
		if(jumping){
			
			//row position of the cell above the character's head (in the tiled map)
			int upRow=(int)((boundingBox.getMinY()-1)/Tile.TILE_SIZE);
			
			//tile position relative to the upper-left corner of the character's bounding box
			int upLeftCornerCol=(int)(boundingBox.getMinX()/Tile.TILE_SIZE);
			
			//tile position relative to the upper-right corner of the character's bounding box
			int upRightCornerCol=(int)((boundingBox.getMaxX())/Tile.TILE_SIZE);

			if(currentRow>=0){
				if(World.tiledMap[upRow][upLeftCornerCol] instanceof Block){
					//if the upper-left corner stats intersecting a block, stop the jumping phase
					//and start the falling phase, setting the jump_count to 0
					if(World.tiledMap[upRow][upLeftCornerCol].getBoundingBox().intersects(boundingBox)){
						jumping=false;
						jump_count=0;
						falling=true;
						return;
					}
				}
				if(World.tiledMap[upRow][upRightCornerCol] != null){
					//if the upper-right corner stats intersecting a block, stop the jumping phase
					//and start the falling phase, setting the jump_count to 0
					if(World.tiledMap[upRow][upRightCornerCol].getBoundingBox().intersects(boundingBox)){
						jumping=false;
						jump_count=0;
						falling=true;
						return;
					}
				}
			}
		
		}

This chunk of code you see above is still part of the checkBlockCollision() function we saw earlier, so now we have all the stuff we need to make the character move around the screen, jump on blocks, collide with blocks and well, even die…if he falls too deep.

Aaaaaaand that would be all for today’s diary. Once again, remember that this is not a proper tutorial, but just a “how I make things” kind of thing. So if you have suggestions or you don’t understand what I say, please comment below or get in touch with me on twitter. I’m also on tumblr, drawing stuff. See you soon guys!

Chronicles of a Videogame in Java – 5. Collision detection for dummies

Chronicles of a Videogame in Java – 4. Building a tiled map

Previously on the Chronicles of a Videogame in Java: How to Make the Character Jump.

Here we are again ladies and gentlemen! Today we’re going to see how to build a tiled map for our still not so beautiful platform game. But first, let’s see what a tiled map is and especially what a single tile is.

There’s not a one-way definition of “tile”, as the term applies to both data structures and images. Let’s look at this picture to understand the concept:

tiledMap

Ok, the entire grid you see in the screenshot above it’s called a tiled map. The tiled map for this game has 9 rows and 20 columns for a total of 180 cells that will contain single static elements of the game. Here’s an example: the red square in the picture above contains a piece of terrain, so it is infact a static element of the game because it is placed there forever. From a logic kind of perspective then, that piece of terrain is a tile placed in the 7th row and 7th column of the tiled map. Pretty easy uh?

What do we place in a tiled map? Usually just terrain, blocks on which you may jump, spikes, maybe doors and other static elements. Don’t be misleaded by the image above though, the trees you see behind the characters are not part of the tiled map, contrariwise that’s just a background image. We have basically three layers in the world of the picture:

  1. The first and stupidest thing is the background. It is just a plain png image we draw on the background of the panel where the game is played. It does not involve interactions with the player whatsoever.background1
  2. The second layer you see is the one with the terrain tiles. Here’s now how the image above looks like if we add the tiled map with all the tiles (for now just terrain pieces). The terrain tiles do involve an interaction, for example the character can walk on terrain tiles and collide running towards them. terraintiles
  3. The last things are the characters and enemies moving on the world. They do not need to stay inside the tiled map of course, indeed I would say it is hugely inconvenient do put the main character inside a tiled map. Our protagonist just needs to be drawn above the other layers and the class representing him in the code should always reference the position of the character inside the tiled map (in terms of row and col).terraintiles

Now let’s put it all to code. First the Tile class, which is an abstract class as we do not want to istantiate a generic Tile, but rather specific types of tiles that behave in different ways.

public abstract class Tile {
	public Tile(int i, int j){
		this.row=i;
		this.col=j;
		initializeStuff();
	}
	
	protected abstract void initializeStuff();
	
	protected abstract void loadInformations();
	
	public BufferedImage getImage(){
		return image;
	}
	
	public Rectangle getBoundingBox() {
		return boundingBox;
	}
	
	protected int row;
	protected int col;
	protected BufferedImage image;
	protected Rectangle boundingBox;
	public static final int TILE_SIZE=64;
}

The piece of terrain we discussed earlier is a Block object in the code. The Block class extends Tile: you can think of a block as any piece of material you can walk on and collide with. Its bounding box occupies the entire perimeter of a cell in the tiled map grid.

public class Block extends Tile {

	public Block(String imgName,int i, int j) {
		super(i,j);
		this.imgName=imgName;
		loadInformations();
	}

	@Override
	protected void initializeStuff() {
		x=col*TILE_SIZE;
		y=row*TILE_SIZE;
		boundingBox=new Rectangle(x,y,TILE_SIZE,TILE_SIZE);
	}
	
	protected void loadInformations() {
		try {
			image=ImageIO.read(getClass().getResource(&amp;quot;../images/&amp;quot;+imgName+&amp;quot;.png&amp;quot;));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private String imgName;
	private int x;
	private int y;
}

All the tiles of the current stage are stored in the bidimensional array named “tiledMap” in the World class. As you may notice the tiledMap is public, that’s because there’s no need to hide informations about the world as you see it and, even more important, it is really convenient to be able to grab te tiled Map from anywhere in the code. The world class actually loads the current disposition of tiles from a simple text file.

public class World {
	public World(){
		tiledMap=new Tile[ROWS][COLS];
	}
	
	public void initializeStage(String stageName){
		try {
			CURRENT_BACKGROUND=ImageIO.read(getClass().getResource(&amp;quot;../images/background1.png&amp;quot;));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		InputStream is=this.getClass().getResourceAsStream(&amp;quot;/levels/&amp;quot;+stageName+&amp;quot;.txt&amp;quot;);
		BufferedReader reader=new BufferedReader(new InputStreamReader(is));
		String line=null;
		String[] tilesInLine=new String[ROWS];
		try {
			int i=0;
			while((line=reader.readLine())!=null){
				tilesInLine=line.split(&amp;quot; &amp;quot;);
				for(int j=0; j&amp;lt;COLS; j++){
					if(!tilesInLine[j].equalsIgnoreCase(&amp;quot;empt&amp;quot;)){
						tiledMap[i][j]=newTileInstance(tilesInLine[j],i,j);
					} else {
						tiledMap[i][j]=null;
					}
				}
				i++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private Tile newTileInstance(String name, int i, int j) {
		switch (name) {
			case "ter0":
				return new Block("ter0", i, j);
			case "ter1":
				return new Block("ter1", i, j);
			case "terR":
				return new Block("terR", i, j);
			case "terL":
				return new Block("terL", i, j);
			case "terQ":
				return new Block("terQ", i, j);
			case "terP":
				return new Block("terP", i, j);
			case "term":
				return new Block("term", i, j);
		}
		return null;
	}

	public static BufferedImage CURRENT_BACKGROUND;
	public static Tile[][] tiledMap;
	public static final int ROWS=9;
	public static final int COLS=20;
}

Finally here’s what the .txt representation of a level looks like:

empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt empt
ter0 ter1 ter0 ter1 ter0 ter1 ter0 ter1 terR empt terL ter1 ter0 ter1 ter0 ter1 ter0 ter1 ter0 ter1
term term term term term term term term terQ empt terP term term term term term term term term term

Yep, I know I know. It looks barely readable. But if you look closely and you relate this text to the first picture of the post you’ll notice the parts with no terrain tiles (or tiles of any sort) are represented by the “empt” keyword and the several types of terrain tiles are “ter0” or “ter1” or ter+something_else.

Aaaaaaand that would be all for today. I’m sorry for this very theoretical post but the tiled-map one is really a concept you want to fully understand before you go on and code the funny things. Once again, remember that this is not a proper tutorial, but just a “how I make things” kind of thing. So if you have suggestions or you don’t understand what I say, please comment below or get in touch with me on twitter. I’m also on tumblr, drawing stuff.

In the next episode…we will die!

Chronicles of a Videogame in Java – 4. Building a tiled map

CHRONICLES OF A VIDEOGAME IN JAVA – 3. JUMPING

Previously on the Chronicles of a Videogame in Java: How to Make the Character Move + Simple Animation.

The code discussed below is already available on my GitHub page at theBoyWithNoName (“jump” branch). Please feel free to download it to take a better look. Ask me anything about it.

Hi guys and welcome to the third part of my diary/tutorial about making a game in Java Swing. So today we’re not gonna make huge steps forward, but we’re gonna see how to make our little main character jump around a black screen (which will soon be a lot less black-ish, I promise). Before we start here’s another little mockup I drew about a week ago. Hopefully this is how the game will start to look in a week. Or a couple of weeks maybe. Check it out: mockup2 Not that bad, uh? Sadly for now we’ll have to settle with our “beautiful” black screen. Anyway let’s get into code business. At the end of the last part of the Chronicles I left you with a character able to just run around with a simple animation. Today we’re adding the simplest jump mechanic you can make in a Java game. So, here’s how it works when the player presses <jump>, established that we’re going to associate <jump> with the SPACE key:

  1. The KeyboardController detects a new SPACE key pressed and stores it in the activeKeys HashSet.
  2. The GameManager (main thread of the game) checks activeKeys continuously. When it finds a SPACE key in it, the GameManager tells the boy to jump (if he’s not already in the process of jumping).
  3. The boy, magically, jumps.

If you don’t remember how the GameManager and KeyboardController classes work, please check my last post. If you do, then take a look at how the GameManager has slightly changed since last time:


@Override
      public void run() {
          while(gameIsRunning){
            
               //updates the character movement if he's 'jumping'
               boy.checkJumpState();

               //manage the keys currently pressed
               manageKeys();

               gamePanel.repaintGame();

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

	//the function manages the keys currently pressed associating concrete
	//actions to them
	private void manageKeys() {
		//get the currently pressed keys from the KeyboardController
		HashSet<Integer> currentKeys=KeyboardController.getActiveKeys();
		
		//manage the two possible run direction
		if(currentKeys.contains(KeyEvent.VK_RIGHT)){
			//move right
			boy.move(KeyEvent.VK_RIGHT);
		} else if (currentKeys.contains(KeyEvent.VK_LEFT)){
			//move left
			boy.move(KeyEvent.VK_LEFT);
		} else if(currentKeys.isEmpty() && !boy.getJumping()){
			//if the player is not pressing keys, the protagonist stands still
			boy.stop();
		}
		
                //if the character is not jumping, tell him to jump
		if(currentKeys.contains(KeyEvent.VK_SPACE)) {
			if(!boy.getJumping()){
				boy.jump();
			}
		}
		
	}

As you can see, since the last post I only added a few lines of code in the GameManager class. This code you see up here is how things work from the perspective of the GameManager, but you may notice there’s no evidence of the actual jumping thing here. That’s because the GameManager does not move the character in my pattern, it simply tells the character to move. From the perspective of the Boy, infact, the first thing that happens is that he receives an “order” from the GameManager, that order is the one you see above at line 41: boy.jump(). Instead, here’s how the jump method looks like from the perspective of the character in the class named “Boy”:

        //called every time the player presses the jump key (SPACE for now)
	//if the character is not already jumping (boolean jumpin=true)
	public void jump() {
		//sets the jumping state to true
		this.jumping=true;
		
		//reinitialize the jump_count, useful to determine for how 
		//much time the character is going to stay in the air
		this.jump_count=0;
		
		//sets the current jumping frame based on the last direction 
		if(last_direction==KeyEvent.VK_RIGHT){
			currentFrame=run_R[2];
		} else {
			currentFrame=run_L[2];
		}
	}

As you can see, the function simply sets the jumping state to true and the jump_count to zero. But what the hell is a jump_count? The variable jump_count works with a static final integer called JUMP_COUNTER_THRESH: in particular the jump_count is incremented every time the main thread (GameManager) calls the checkState() function. And it goes on and on incrementing this variable until it reaches JUMP_COUNTER_THRESH. During this period of time, the position of the character on the y-axis gets smaller and smaller. We’re in the ascending phase of the jump. When the jump_count exceeds JUMP_COUNTER_THRESH, au contrair, the jump_count keeps going up but the position of the boy on the y-axis is incremented for the character is in the descending phase of the jump. It goes on incrementing until jump_count reaches JUMP_COUNTER_THRESH*2, then the jumping boolean is set to false and the count is reinitialized. The jump is over. Here’s how I put in code the just explained operation:

public void checkJumpState() {
		if(jumping){
			if(jump_count<JUMP_COUNTER_THRESH){
				if(!idle){
					if(last_direction==KeyEvent.VK_RIGHT){
						currentX+=DISPLACEMENT/2;
					} else {
						currentX-=DISPLACEMENT/2;
					}
				} 
				currentY-=DISPLACEMENT;
				boundingBox.setLocation(currentX, currentY);
			} else {
				currentY+=DISPLACEMENT;
				boundingBox.setLocation(currentX, currentY);
			}
			
			jump_count++;
			
			if(jump_count>=JUMP_COUNTER_THRESH*2){
				jumping=false;
				jump_count=0;
			}
		}
	}

Notice that the boundingBox, or the collision box of the protagonist as you may call it, needs to be updated even when jumping (lines 12 and 15). This is going to be crucial when we get to add mobs and obstacles to the game. Aaaaaaand that would be all for today’s diary. Once again, remember that this is not a proper tutorial, but just a “how I make things” kind of thing. So if you have suggestions or you don’t understand what I say, please comment below or get in touch with me on twitter. I’m also on tumblr, drawing stuff.

CHRONICLES OF A VIDEOGAME IN JAVA – 3. JUMPING