Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Tile Collision Code

Credits go to Trent Gamblin for helping out!
This thread is locked; no one can reply to it. rss feed Print
Tile Collision Code
BitCruncher
Member #11,279
August 2009
avatar

Hey guys,

I am progressing to tile-based concepts. I implemented this simple example to draw tiles and execute tile physics and logic. I am encountering complications however. My character is falling through the floor although I am certain that my collision routines are correct. If you need to see them, I will post them. Does anyone have any ideas?

#SelectExpand
1# include <allegro.h> 2# include <engine.h> 3# include <entities.h> 4# include <tile.h> 5# include <physics.h> 6# include <colors.h> 7 8 9int grass_map0[19][25] = { 10{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0 }, 12{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, 0 }, 14{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, 0, 0, 0, 0, 0 }, 16{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 170, 0, 0, 0, 0, 0, 0, 0, 0 }, 18{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 0, 0, 0, 0, 0, 0, 0, 0 }, 20{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 0, 0, 0, 0, 0, 0, 0, 0 }, 22{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0 }, 24{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 0, 0, 0, 0, 0, 0, 0, 0 }, 26{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 270, 0, 0, 0, 0, 0, 0, 0, 0 }, 28{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 0, 0, 0, 0, 0, 0, 0, 0 }, 30{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 310, 0, 0, 0, 0, 0, 0, 0, 0 }, 32{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 0, 0, 0, 0, 0, 0 }, 34{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 350, 0, 0, 0, 0, 0, 0, 0, 0 }, 36{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 370, 0, 0, 0, 0, 0, 0, 0, 0 }, 38{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 390, 0, 0, 0, 0, 0, 0, 0, 0 }, 40{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 410, 0, 0, 0, 0, 0, 0, 0, 0 }, 42{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, 0, 0, 0 }, 44{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 450, 0, 0, 0, 0, 0, 0, 0, 0 }, 46{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 471, 1, 1, 1, 1, 1, 1, 1, 1 } 48}; 49 50 51Tile tilemap [19][25] ; 52 53Character *character ; 54BITMAP *map ; 55BITMAP *tile1 ; 56BITMAP *tile2 ; 57 58 59void initiate_subengine () 60{ 61 drawer = new Drawer ; 62 layer = create_bitmap (screenWidth, screenHeight) ; 63 screenColor = BLACK ; 64 65 map = load_bitmap ("grass.bmp", NULL) ; 66 tile1 = load_bitmap ("grass_2.bmp", NULL) ; 67 tile2 = load_bitmap ("blacktile.bmp", NULL) ; 68 69 character = new Person ; 70 character->set_layer (layer) ; 71 character->set_positionX (400) ; 72 character->set_frameChangeRate (10) ; 73 74 75 // 0 is blacktile 76 for (int i = 0; i < 19; ++ i) 77 { 78 for (int j = 0; j < 25; ++ j) 79 { 80 if (! grass_map0 [i][j]) 81 { 82 tilemap [i][j].image = tile2 ; 83 tilemap [i][j].tangible = false ; 84 } 85 else 86 { 87 tilemap [i][j].image = tile1 ; 88 tilemap [i][j].tangible = true ; 89 } 90 tilemap [i][j].layer = layer ; 91 tilemap [i][j].tag = grass_map0 [i][j] ; 92 tilemap [i][j].x = j * 32 ; 93 tilemap [i][j].y = i * 32 ; 94 tilemap [i][j].cage.set_cage (tilemap [i][j].image, tilemap [i][j].x, tilemap [i][j].y, 0) ; 95 } 96 } 97} 98 99 100void execute_logicSystem () 101{ 102 if (key [KEY_RIGHT]) 103 { 104 if (character) 105 { 106 character->walk_right () ; 107 } 108 } 109 else if (key [KEY_LEFT]) 110 { 111 if (character) 112 { 113 character->walk_left () ; 114 } 115 } 116 else 117 { 118 if (character) 119 { 120 character->stand () ; 121 } 122 } 123} 124 125 126void execute_drawingSystem () 127{ 128 for (int i = 0; i < 19; ++ i) 129 { 130 for(int j = 0; j < 25; ++ j) 131 { 132 draw_sprite (layer, tilemap [i][j].image, tilemap [i][j].x, tilemap [i][j].y) ; 133 // drawer->show_cage (&tilemap [i][j], BLUE) ; 134 } 135 } 136 drawer->draw_entity (character) ; 137 // drawer->show_cage (character, WONDER) ; 138 // GRAVITY 139 for (int i = 0; i < 19; ++ i) 140 { 141 for (int j = 0; j < 25; ++ j) 142 { 143 if (is_colliding (character, &tilemap [i][j], layer) && (tilemap [i][j].tangible == true)) 144 { 145 break ; 146 } 147 else if (is_colliding (character, &tilemap [i][j], layer) && (tilemap [i][j].tangible == false)) 148 { 149 character->set_positionY (character->get_positionY () + 1) ; 150 } 151 } 152 } 153 // vsync () ; 154} 155 156 157void execute_renderingSystem () 158{ 159 blit (layer, screen, 0, 0, 0, 0, screenWidth, screenHeight) ; 160 clear_to_color (layer, screenColor) ; 161} 162 163 164void terminate_subengine () 165{ 166 delete character ; 167 delete map ; 168}

Trent Gamblin
Member #261
April 2000
avatar

post your is_colliding routine.

BitCruncher
Member #11,279
August 2009
avatar

The reason I have that particular section of code commented off was for simplicity's sake. I only wanted to keep the character from falling through the ground.

#SelectExpand
1bool is_colliding (Entity *A, Tile *t, BITMAP *bmp) 2{ 3 /* 4 if (A->cage.get_bottomLeftY () < t->y) return false ; 5 if (A->get_positionY () > t->cage.get_bottomLeftY ()) return false ; 6 if (A->cage.get_topRightX () < t->x) return false ; 7 if (A->get_positionX () > t->cage.get_topRightX ()) return false ; 8 else 9 { 10 // textout_ex (bmp, font, "COLLISION", 0, 0, WHITE, BLACK) ; 11 return true ; 12 } 13 */ 14 if (A->cage.get_bottomLeftY () >= t->cage.get_topLeftY ()) return true ; 15 else return false ; 16}

Trent Gamblin
Member #261
April 2000
avatar

Might help if I knew what this "cage" thing is.

BitCruncher
Member #11,279
August 2009
avatar

I apologize. The concept of the cage is the bounding box around the entity.

Top Left Corner (x, y)
Top Right Corner (x, y)
Bottom Left Corner (x, y)
Bottom Right Corner (x, y)

Center (x, y)

#SelectExpand
1# ifndef CAGE_H 2# define CAGE_H 3 4# include <allegro.h> 5# include <point.h> 6 7class Cage 8{ 9 public : 10 Cage () ; 11 ~Cage () ; 12 13 void set_cage (BITMAP *image, int posX, int posY, float) ; 14 15 int get_topLeftX () const ; 16 int get_topLeftY () const ; 17 int get_topRightX () const ; 18 int get_topRightY () const ; 19 int get_bottomLeftX () const ; 20 int get_bottomLeftY () const ; 21 int get_bottomRightX () const ; 22 int get_bottomRightY () const ; 23 24 int get_centralPointX () const ; 25 int get_centralPointY () const ; 26}

Trent Gamblin
Member #261
April 2000
avatar

Hmm, well, look at the logic in the executeDrawing function (which in fact is also doing logic not just drawing, which is always bad). I'm pretty sure you don't want your character to fall a pixel for every tile you check against. You should set a flag before that loop, bool colliding = false; Then in the loop, if your character collides with something, set colliding = true; and break out of the loop. After the loop, if the colliding is false, then move the character down a pixel.

BitCruncher
Member #11,279
August 2009
avatar

Thanks Trent.

Ah yes, that logic section was not supposed to be there when I posted it because I thought I cut it and placed it in the logic section, but thanks.

Go to: