Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Mappy collision detection

Credits go to Edgar Reynaldo and Neil Walker for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
Mappy collision detection
Matias Persson
Member #15,093
May 2013

Hello there, I have recently jumped into programming, as I have always dreamed about making my own game + I love programming ;).

Though I am stuck with a problem I cannot quite solve. I have been searching throughout the net, and I cannot seem to find the solution.

I am trying to make collision detection with Mappy for Allegro 5 converted by Neil.
I have tried various methods, but I just cannot seem to get it working.

Do you have any suggestions ???

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Arthur Kalliokoski
Second in Command
February 2005
avatar

They all watch too much MSNBC... they get ideas.

Matias Persson
Member #15,093
May 2013

Sorry, I meant to post the code, but completely forgot it ;)

@Arthur Kalliokoski, there is no need to be rude, it could simply be a mistake which it turned out to be.

The code is quite ugly, I know that. But again I am just learning.
I will tend to use classes, when I learn more about it.

Main.cpp: http://pastebin.com/UvpWWzW5
Objects.h: http://pastebin.com/5QHi3uQp

Refresher: I am stuck on making Collision Detection with Mappy. You can see how I tried to do it in the code..

Arthur Kalliokoski
Second in Command
February 2005
avatar

Arthur Kalliokoski, there is no need to be rude

TFA said:

hackers have a reputation for meeting simple questions with what looks like hostility or arrogance. It sometimes looks like we're reflexively rude to newbies and the ignorant. But this isn't really true.

They all watch too much MSNBC... they get ideas.

Matias Persson
Member #15,093
May 2013

Arthur, I already know this. I have been on "Hackforums" many times, back when I wanted to become a "Hacker", though this has nothing to do with the subject, but in my opinion it is rude.

Please do not reply if you cannot help me, instead of coming with rude comments.

Does anyone else besides Arthur have any suggestions, as he obviously does not intend to help me?

Mark Oates
Member #1,146
March 2001
avatar

Arthur! Since when were you dubbed "Second in Command"?

Totally deserve it. 8-)

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Here's his collision detection function,

int collided(int x, int y)
{
                BLKSTR *blockdata;
                blockdata = MapGetBlock(x/mapblockwidth, y/mapblockheight);
                return (blockdata->tl || blockdata->tr || blockdata->bl || blockdata->br);
}

and here's the movement code,

#SelectExpand
1void MovePlayerUp(Player &player) 2{ 3 if(!(collided(player.y, player.y))) 4 { 5 player.y -= player.speed; 6 } 7 if(player.y < 0) 8 player.y = 0; 9} 10void MovePlayerDown(Player &player) 11{ 12 if(!(collided(player.y + 35, player.y))) 13 { 14 player.y += player.speed; 15 } 16 if(player.y > HEIGHT) 17 player.y = HEIGHT; 18} 19void MovePlayerLeft(Player &player) 20{ 21 if(!(collided(player.x, player.y))) 22 { 23 player.animationRow = 1; 24 player.x -= player.speed; 25 } 26 if(player.x < 0) 27 player.x = 0; 28} 29void MovePlayerRight(Player &player) 30{ 31 if(!(collided(player.x + 26, player.y))) 32 { 33 player.animationRow = 0; 34 player.x += player.speed; 35 } 36 if(player.x > WIDTH) 37 player.x = WIDTH; 38}

I think it should be closer to something like this for example :
if (!collided(player.x + player.w + player.speed , player.y)) {/* move... */}

But really, you need to test each leading corner, not just one of them. Ie... if you're moving right you need to check the top right through bottom right side where it would be when it moved in the future. Right now you are checking when the right side is already on the block, and only then can you move, which means you can't move at all? Is that what is happening?

Get a min and max tile x and y of the position where your character would be if you moved it and nothing was there. Then loop over that area and see if any of the BLKSTR's at those spots are impassable.

#SelectExpand
1 2bool IsSolid(BLKSTR* block) { 3 return (block->tl || block->tr || block->bl || block->br); 4} 5 6bool collided(Player& player) { 7 int minx = (player.GetLeftX() + player.XSpeed())/mapblockwidth; 8 int miny = (player.GetTopY() + player.YSpeed())/mapblockheight; 9 int maxx = (player.GetRightX() + player.XSpeed())/mapblockwidth; 10 int maxy = (player.GetBottomY() + player.YSpeed())/mapblockheight; 11 12 for (int tilex = minx ; tilex <= maxx ; ++tilex) { 13 for (int tiley = miny ; tiley <= maxy ; ++tiley) { 14 BLKSTR* block = MapGetBlock(tilex , tiley); 15 if (IsSolid(block)) {return true;} 16 } 17 } 18 return false; 19}

Dizzy Egg
Member #10,824
March 2009
avatar

back when I wanted to become a "Hacker"

Christ ::)

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Arvidsson
Member #4,603
May 2004
avatar

Does anyone else besides Arthur have any suggestions, as he obviously does not intend to help me?

He DID help you :P Asking smart questions increases the chance of anyone helping you. You could have refined your question in the way that Edgar basically did for you, by posting only code snippets that is relevant to the problem you are having.

In other words, welcome to allegro.cc :)

Matias Persson
Member #15,093
May 2013

Arvidsson, my question was clear. At least clear enough. English is not my first language, so I'm not very good at elaborating my questions, but at least they're clear enough to understand.

Also, I don't know how post the snippets on this forum & I don't even know how to quote :(

@Edgar, I tried to use the two functions in my code, it didn't work out quite well :O?

Arthur Kalliokoski
Second in Command
February 2005
avatar

Arvidsson, my question was clear. At least clear enough. English is not my first language, so I'm not very good at elaborating my questions, but at least they're clear enough to understand.

Your English seems perfectly fine to me, it's just that an answer to your question could fill a book.

Quote:

I don't know how post the snippets on this forum & I don't even know how to quote

{"name":"607505","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/b\/3b2637cef9ec106e33a0e231506fc6d2.png","w":376,"h":225,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/b\/3b2637cef9ec106e33a0e231506fc6d2"}607505

They all watch too much MSNBC... they get ideas.

Matias Persson
Member #15,093
May 2013

Your English seems perfectly fine to me, it's just that an answer to your question could fill a book.

My English may seem fine, as it actually is :) But I'm not very good at breaking stuff down in English, like explaining myself :)

Also, thank you for helping me with the formatting.

On topic: Does anyone have any other solutions? I can't seem to figure out what Edgar explained to me :(

Neil Walker
Member #210
April 2000
avatar

Hello,
Going in steps:

A map is made up of tiles, quite probably you are using 32x32 pixels per tile.

Each tile is also called a block.

To work in blocks, e.g. to get tile at 5,5 it is 5,5. To get a pixel version it is 5*BLOCK_WIDTH, 5*BLOCK_WITDH, e.g. in this case 160,x160

A screen might only show 800x600 so can fit 25x16 tiles at a time.

Your player sprite will be working most likely in pixels, so if it's at 160,160 then it is also at tile location 5,5 with a 32 pixel tile.

Mappy provides functions to get blocks and find blocks using pixels and tile locations (but as above it's easy enough to figure out).

When you are drawing your map to the screen you first work out what part of the map to display, i.e. if you are at pixel location 2000,2000 then you will need to offset the starting point (MapDraw functions) to the players position minus whatever calculation you have made for displaying the player (e.g. centred on screen) you might end up working out to display from tile location 50,50

Now for collision, you know where the player is, e.g. 160,160 so get the block at this position (either using the pixel or block mapgetblock functions).

This block is a struct. Use the data you've provided for each block to work out whether it's a collision block or not, e.g. I use tl to indicate is a collision, etc.

Any clearer?

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

@Edgar, I tried to use the two functions in my code, it didn't work out quite well :O?

This is what they're talking about - you're being way too vague. What didn't work? Have you set up your map yet? Which member of the BLKSTR do you use to indicate it is solid? That is the one you need to test for, and perhaps not all of them. It depends entirely on how you set up your map.

Matias Persson
Member #15,093
May 2013

Alright, let's see. I made my map this is what it looks like in mappy :)
{"name":"RcSktSP.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/f\/3ffb8a17b22c28e1d2cf9e45313f67a2.png","w":960,"h":512,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/f\/3ffb8a17b22c28e1d2cf9e45313f67a2"}RcSktSP.png

This is what I did step for step in Mappy:
1. I opened Mappy.
2. I imported a tileset which I made.
3. I painted the map with the tiles.
4. I saved it as myMap.fmp.
5. I put it in my projects folder.

I ran the code posted above, and it runs perfectly. The map works and all, but the collision doesn't work. I can walk into the ground if I wanted to.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Yes, but did you set the properties for each tile? Are there any solid tiles in your map? And what struct member did you use to indicate solidity? That is entirely up to you and we can't help you write a collision function until you do that and tell us about it.

Matias Persson
Member #15,093
May 2013

:O Solid blocks, where in mappy can I use that?
I just thought u mapped the map, then C++ checks if use touches a pixel ::)

Neil Walker
Member #210
April 2000
avatar

Mappy does not have collision detection, it is just a bunch of block. When you edit a block in mappy ignore where it says 'collision' for the four checkboxes, they aren't collision flags, they just called them that.

Basically for every block/tile in mappy you can give it some data which varies from a number of booleans, a couple of shorts and a few ints and longs, e.g. imagine you have a block which is a struct:

struct MAPPYBLOCK {
 boolean tl, tr, bl, br;
 short data1;
 short data2;
 int int1;
 int int2;
 long long1;
 long long2;
}

You assign whatever you want to these via the mappy editor and they mean whatever you want them to mean.

In a map I made for example I made data1 to be an enum, e.g.
enum BLOCKTYPE { NORMAL=0,GOSLOW, CANNOTPASS, INSTANTDEATH};

Then for data1 I set a tile to be 0,1,2,3, etc

You can use tl/tr/bl/br for the same thing if you want. It doesn't matter.

What matters is you get the block data (using the MapGetBlock function) for the location the player is about to go onto then look at the data and see if any of the data matches.

Does that make sense? Where I've got MappyStruct it's something like BLOCK_STR, I can't remember.

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Matias Persson
Member #15,093
May 2013

Yeah, but I mean how do I make different blocks in mappy?
I imported my tileset and painted something, but I never edited any blocks?
And I don't know how to :O

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Matias Persson
Member #15,093
May 2013

:O I'm having problems again :(
The collision is not working anymore somehow?

Code:

#SelectExpand
1bool IsSolid(BLKSTR* block) { 2 switch(block->user1) 3 { 4 case 0: 5 return false; 6 break; 7 case 1: 8 return true; 9 break; 10 } 11} 12 13bool collided() { 14 int minx = (x + speed)/mapblockwidth; 15 int miny = (y + speed)/mapblockheight; 16 int maxx = (x + 30 + speed)/mapblockwidth; 17 int maxy = (y + 30 + speed)/mapblockheight; 18 19 for (int tilex = minx ; tilex <= maxx ; ++tilex) 20 { 21 for (int tiley = miny ; tiley <= maxy ; ++tiley) { 22 BLKSTR* block = MapGetBlock(tilex , tiley); 23 if (IsSolid(block)) 24 { 25 return true; 26 } 27 } 28 } 29 return false; 30}

#SelectExpand
1 if(al_key_down(&keyState, ALLEGRO_KEY_DOWN)) 2 { 3 active = true; 4 if(!(collided)) 5 y += speed; 6 dir = DOWN; 7 } 8 else if(al_key_down(&keyState, ALLEGRO_KEY_UP)) 9 { 10 active = true; 11 if(!(collided)) 12 y -= speed; 13 dir = UP; 14 } 15 16 if(al_key_down(&keyState, ALLEGRO_KEY_LEFT)) 17 { 18 active = true; 19 if(!(collided)) 20 x -= speed; 21 dir = LEFT; 22 } 23 else if(al_key_down(&keyState, ALLEGRO_KEY_RIGHT)) 24 { 25 active = true; 26 if(!(collided)) 27 x += speed; 28 dir = RIGHT; 29 }

Note: I set the user1 to 0 for the walkable tile & to 1 for the non-walkable tile.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

        if(al_key_down(&keyState, ALLEGRO_KEY_DOWN))
        {
          active = true;
if(!(collided))
y += speed; dir = DOWN; }

You're actually comparing the address of the collided function to true or false there..., not calling the function()...

You need to modify it a bit :

#SelectExpand
1bool collided(int newxspeed , int newyspeed) { 2 int minx = (x + newxspeed)/mapblockwidth; 3 int miny = (y + newyspeed)/mapblockheight; 4 int maxx = (x + 30 + newxspeed)/mapblockwidth; 5 int maxy = (y + 30 + newyspeed)/mapblockheight; 6 7 for (int tilex = minx ; tilex <= maxx ; ++tilex) 8 { 9 for (int tiley = miny ; tiley <= maxy ; ++tiley) { 10 BLKSTR* block = MapGetBlock(tilex , tiley); 11 if (IsSolid(block)) 12 { 13 return true; 14 } 15 } 16 } 17 return false; 18} 19 20//... 21 int newxspeed = 0; 22 int newyspeed = 0; 23 if (al_key_down(&keyState , ALLEGRO_KEY_DOWN)) {newyspeed = speed;} 24 if (al_key_down(&keyState , ALLEGRO_KEY_UP)) {newyspeed = -speed;} 25 if (al_key_down(&keyState , ALLEGRO_KEY_LEFT)) {newxspeed = -speed;} 26 if (al_key_down(&keyState , ALLEGRO_KEY_RIGHT)) {newxspeed = speed;} 27 28 if (collided(newxspeed , 0)) {newxspeed = 0;} 29 if (collided(0 , newyspeed)) {newyspeed = 0;} 30 31 playerx += newxspeed; 32 playery += newyspeed;

This way it always checks the future position of the player against the map. If it collides x-wise, the x-speed is negated, and if it collides y-wise the y-speed is negated.

Matias Persson
Member #15,093
May 2013

Oh, I see. You know, I've been learning Allegro for about a week now, and I still don't know why I couldn't figure it out :O. But now it makes sense -.-.
Thanks!

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

 1   2 


Go to: