Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (540)
Games in Android Showcase (133)
games submitted by our members
Games in WIP (603)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  2D Collision detection.  (Read 3987 times)
0 Members and 1 Guest are viewing this topic.
Offline trollwarrior1
« Posted 2013-12-12 19:06:20 »

So I noticed that a lot of people are struggling with collision detection. I thought I might be able to help you a little.
Today, 2013-12-12, I will post the part 1 of this tutorial.
Tomorrow, 20130-12-13, I will post the part 2 of this tutorial.

Part 1 of this tutorial will explain how to do collision in an array of tiles.
Part 2 of this tutorial will discuss the theory behind making collision with non-array collision. Only theory, no code.

If you want the code from this tutorial to work properly, you will need to add lwjgl.jar and lwjgl_util.jar files to your classpath.

The rendering code is really bad and deprecated and SHOULDN'T be used in any real game. (You can if it is enough for you)

So let's get started..

PART 1 - COLLISION IN AN ARRAY OF TILES!
First things first, let's create a class for general stuff of the game. That includes making game window and running the game loop at 60UPS (Updates Per Second). Pretty basic..

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  
package org.javagaming.collisiontutorial;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW;
import static org.lwjgl.opengl.GL11.GL_PROJECTION;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glMatrixMode;
import static org.lwjgl.opengl.GL11.glOrtho;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

public class GameClass {

   public GameClass() {
     
      makeDisplay();
      initGL();
     
      loop();
     
      Display.destroy();
   }
   
   private void loop() {
     
      while(!Display.isCloseRequested()) {
         
         glClear(GL_COLOR_BUFFER_BIT);
         
         tick();
         render();
     
         
         Display.update();
         Display.sync(60);
         
      }
     
   }
   
   private void tick() {
     
     
   }
   
   private void render() {
     
     
   }
   
   private void makeDisplay() {
      try {
         Display.setDisplayMode(new DisplayMode(800, 600));
         Display.create();
         Display.setVSyncEnabled(true); // Enable vsync, so that we don't get screen tearing.
      } catch (LWJGLException e) {
         e.printStackTrace();
      }
     
   }
   
   private void initGL() {
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0, Display.getWidth(), Display.getHeight(), 0, -1, 1);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
   }
   
   public static void main(String args[]) {
      new GameClass();
   }
   
}


Now we need to add some kind of method for rendering stuff. In this example I will make Render class which will render rectangles with specified color. Pretty basic lwjgl stuff.

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  
package org.javagaming.collisiontutorial;

import java.awt.Color;

import static org.lwjgl.opengl.GL11.*;

public class Render {

   public static void render(float x, float y, float width, float height, Color color) {
     
      glBegin(GL_QUADS);
     
      // Conver color from 0-255 int range to 0-1 float range.
      glColor3f(1f / 255 * color.getRed(), 1f / 255 * color.getGreen(), 1f / 255 * color.getBlue());
     
      glVertex2f(x, y);
      glVertex2f(x + width, y);
      glVertex2f(x + width, y + height);
      glVertex2f(x, y + height);
     
      glEnd();
     
   }
   
}


Now I make a level class, which has an array of tiles. When filling the array, I make it so that 1/10 tiles would be rock tile, and the rest would be grass tile.
Render method will just run through all the tiles and render them.
Get tile method will return a tile with x, y in tile precision.

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  
package org.javagaming.collisiontutorial;

import java.util.Random;

public class Level {

   public static final int TILE_SIZE = 16;

   public int width, height;
   public Tile[] tiles;

   public Level(int width, int height) {

      Random random = new Random();

      this.width = width;
      this.height = height;
      tiles = new Tile[width * height];

      for (int i = 0; i < tiles.length; i++) {

         if (random.nextInt(10) == 0) {
            tiles[i] = Tile.rockTile;
         } else {
            tiles[i] = Tile.grassTile;
         }

      }

   }

   public void render() {
      for (int y = 0; y < height; y++) {
         for (int x = 0; x < width; x++) {
            getTile(x, y).render(x, y);
         }
      }
   }
   
   public Tile getTile(int x, int y) {
      if(x < 0 || x >= width || y < 0 || y >= height) return Tile.voidTile;
     
      return tiles[x + y * width];
   }

}


After making the level class, don't forget to make an object of it in your gameclass and add call render method from gameclass, so that you can actually render the level.

Here is a tile class!
Tile is a class which will only store the color of the tile and a boolean whether the player can move on that tile or not.

GrassTile is a tile which has green color, and you're able to move on it.
RockTile is a tile which has gray color, and you can't move on it.
VoidTile is a tile which has black color, and you can't move on it.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
public static Tile grassTile = new Tile(new Color(0, 255, 0), true);
   public static Tile rockTile = new Tile(new Color(100, 100, 100), false);
   public static Tile voidTile = new Tile(new Color(0, 0, 0), false);
   
   public Color color;
   private boolean canmove;
   
   public Tile(Color color, boolean canmove) {
      this.color = color;
      this.canmove = canmove;
   }
   
   public void render(int x, int y) {
      Render.render(x * Level.TILE_SIZE, y * Level.TILE_SIZE, Level.TILE_SIZE, Level.TILE_SIZE, color);
   }
   
   public boolean canMove() {
      return canmove;
   }


At this point you should be able to see a grid of tiles. Some of them are gray. Next comes the player. He will have the update method, in which we will do the collision!
I don't really want to explain stuff.. Just work it out yourself. It is not that hard really Tongue

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  
package org.javagaming.collisiontutorial;

import java.awt.Color;

import org.lwjgl.input.Keyboard;

public class Player {

   public int width, height;
   
   public int x, y;
   
   private Level level;
   
   public Player(int width, int height, Level level) {
      this.width = width;
      this.height = height;
      this.level = level;
   }
   
   public void tick() {
      // Which direction should I move?
      boolean down = Keyboard.isKeyDown(Keyboard.KEY_S);
      boolean up = Keyboard.isKeyDown(Keyboard.KEY_W);
      boolean left = Keyboard.isKeyDown(Keyboard.KEY_A);
      boolean right = Keyboard.isKeyDown(Keyboard.KEY_D);
     
      int xa = 0;
      int ya = 0;
     
      if(down) ya += 1;
      if(up) ya -= 1;
      if(left) xa -= 1;
      if(right) xa += 1;
     
      int speed = 2;
     
      // Do it on 2 different axis.
      if(canMove(speed * xa, 0)) {
         x += speed * xa;
      }
     
      if(canMove(0, speed * ya)) {
         y += speed * ya;
      }
     
   }
   
   private boolean canMove(int xspeed, int yspeed) {
      // We will check 4 points for collision. Upper left, upper right, down right, down left.
      // We will also add the speed values.
      return canMoveP(x + xspeed, y + yspeed) && canMoveP(x + width + xspeed, y + yspeed) &&
            canMoveP(x + width + xspeed, y + height + yspeed) && canMoveP(x + xspeed, y + height + yspeed);
   }
   
   private boolean canMoveP(int x, int y) {
      // We devide to convert from pixel precision to tile precision.
      return level.getTile(x / Level.TILE_SIZE, y / Level.TILE_SIZE).canMove();
   }
   
   public void render() {
      Render.render(x, y, width, height, Color.red);
   }
   
}


Now make a player object in your GameClass and add render and tick calls for the player. You're done! Now you can move in a little level width ASDW!

So after we add level and player objects to GameClass, it looks like this. I also changed the size of the glOrtho call to make the level look bigger. From Display.getWidth(), Display.getHeight() changed to 360, 280.

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  
package org.javagaming.collisiontutorial;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW;
import static org.lwjgl.opengl.GL11.GL_PROJECTION;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glMatrixMode;
import static org.lwjgl.opengl.GL11.glOrtho;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

public class GameClass {

   public Level level = new Level(10, 10);
   public Player player = new Player(8, 8, level);
   
   public GameClass() {
     
      makeDisplay();
      initGL();
     
      loop();
     
      Display.destroy();
   }
   
   private void loop() {
     
      while(!Display.isCloseRequested()) {
         
         glClear(GL_COLOR_BUFFER_BIT);
         
         tick();
         render();
     
         
         Display.update();
         Display.sync(60);
         
      }
     
   }
   
   private void tick() {
     
      player.tick();
     
   }
   
   private void render() {
     
      level.render();
     
      player.render();
     
   }
   
   private void makeDisplay() {
      try {
         Display.setDisplayMode(new DisplayMode(800, 600));
         Display.create();
         Display.setVSyncEnabled(true); // Enable vsync, so that we don't get screen tearing.
      } catch (LWJGLException e) {
         e.printStackTrace();
      }
     
   }
   
   private void initGL() {
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(0, 360, 280, 0, -1, 1);
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
   }
   
   public static void main(String args[]) {
      new GameClass();
   }
   
}


I will make a part 2 of the tutorial tomorrow.

Here is an eclipse project, which contains source code.

http://www.mediafire.com/download/ocppa8attpp7dah/CollisionTutorial.zip
Offline trollwarrior1
« Reply #1 - Posted 2013-12-12 19:10:03 »

Hmm I didn't know I couldn't edit tutorial once posted..
Guess I will just add stuff in this post.

THERE ARE SOME BUGS IN THAT CODE. They are not "breaking" bugs, but they are little stuff that needs to be fixed. I will leave it up to you to correct them. You should be able to see what they are!
Offline Troubleshoots

JGO Knight


Medals: 36
Exp: 7-9 months


Damn maths.


« Reply #2 - Posted 2013-12-12 19:35:29 »

Nice tutorial. I'd noticed the exact same thing and I myself am pondering on whether to post a tutorial on simple collision detection and response. It's less newb friendly but I might post my own later today or tomorrow because AFAIK, it's 100% accurate whereas this method isn't pixel perfect, especially if the sprite moves faster.

Why are all OpenGL tutorials written in Brainf**k?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline SHC
« Reply #3 - Posted 2013-12-15 12:26:12 »

@trollwarrior1

You can edit posts by clicking
Click to Play
icon at the bottom right of your post.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Mr.CodeIt (24 views)
2014-12-23 03:34:11

rwatson462 (53 views)
2014-12-15 09:26:44

Mr.CodeIt (45 views)
2014-12-14 19:50:38

BurntPizza (85 views)
2014-12-09 22:41:13

BurntPizza (110 views)
2014-12-08 04:46:31

JscottyBieshaar (79 views)
2014-12-05 12:39:02

SHC (89 views)
2014-12-03 16:27:13

CopyableCougar4 (96 views)
2014-11-29 21:32:03

toopeicgaming1999 (155 views)
2014-11-26 15:22:04

toopeicgaming1999 (152 views)
2014-11-26 15:20:36
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!