Why is my collision not working

Understanding the language, error messages, etc.

Why is my collision not working

Postby awesome101 » Sat Jun 20, 2015 7:23 pm

Hey guys, I am creating a mario platformer, but for some weird reason my collision isn't working.
Here is my code:
main ino file:
Code: Select all
#include <SPI.h>
#include <Gamebuino.h>

#include "mario_bitmaps.h"
#include "player.h"

#define MAX_LEVEL_WIDTH  30
#define MAX_LEVEL_HEIGHT 6

extern const byte PROGMEM levels[];

const byte *block = NULL;
int cameraPos = 0;
byte lvldata[MAX_LEVEL_WIDTH * MAX_LEVEL_HEIGHT];
byte lvl = 1;
Gamebuino gb;
Player player(0, LCDHEIGHT - 24);

byte i = 0, j = 0; // for loop variables

void loadLevel(int curLev) {
  for(i = 0; i<MAX_LEVEL_WIDTH * MAX_LEVEL_HEIGHT; i++){//Loops through the level
    lvldata[i] = pgm_read_byte(levels + (MAX_LEVEL_WIDTH * MAX_LEVEL_HEIGHT) * (curLev - 1) + i);
  }
}

void renderLevel() {
  for(i = 0;i < MAX_LEVEL_HEIGHT;i++) {
    for(j = 0;j < MAX_LEVEL_WIDTH;j++) {
      switch(lvldata[j + i * MAX_LEVEL_WIDTH]) {
        case 0:
        block = empty;
        break;
        case 1:
        block = sand_ground;
        break;
        case 2:
        block = diagonal_right;
        break;
        case 3:
        block = diagonal_left;
        break;
        default:
        break;
      }
      if(block != NULL) {
        if((j << 3) - cameraPos >= -8 && (j << 3) - cameraPos < LCDWIDTH ||
        (i << 3) > 0 && (i << 3) < LCDHEIGHT) {
          gb.display.drawBitmap((j << 3) - cameraPos, i << 3, block);
        }
      } else {
        gb.display.drawBitmap((j << 3) - cameraPos, i << 3, empty);
      }
    }
  }
  cameraPos = player.x * 2;
}

void setup() {
  gb.begin();
  gb.titleScreen(F("Super Mario Bros"));
  loadLevel(lvl);
}

void loop() {
  if(gb.update()) {
    gb.display.clear();
    renderLevel();
    player.render(gb);
    if(gb.buttons.pressed(BTN_C)) {
        gb.titleScreen(F("Super Mario Bros"));
        loadLevel(1);
    }
  }
}

Levels.ino
Code: Select all
const byte levels[] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 2, 0, 0, 0, 0,
3, 2, 0, 0, 3, 0, 0, 0, 0, 2, 0, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
};

const byte collision_levels[] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
};

////////Tile Map IDS:////////
// NULL        0
// Sand Ground 1
// Diagonal Right 2
// Diagonal Left 3

marioBitmaps.h
Code: Select all
#ifndef MARIO_BITMAPS_H
#define MARIO_BITMAPS_H

byte mario_still[] PROGMEM = {16,16,
0x1F,0x0,
0x20,0xC0,
0x4F,0x20,
0x72,0xC0,
0xB2,0x20,
0xB1,0x20,
0x63,0xC0,
0x30,0x80,
0x4F,0x0,
0x86,0x80,
0xBF,0x80,
0x4F,0x80,
0x53,0x80,
0x21,0x0,
0x3E,0x0,
0x3E,0x0,
};

byte mario_walking_1[] PROGMEM = {16,16,
0x1F,0x0,
0x20,0xC0,
0x4F,0x20,
0x72,0xC0,
0xB2,0x20,
0xB1,0x20,
0x63,0xC0,
0x30,0x80,
0x4F,0x0,
0x86,0x80,
0xBF,0x80,
0x4F,0x80,
0x5B,0x80,
0xBE,0x40,
0x96,0x40,
0x61,0x80,
};

byte sand_ground[] PROGMEM = {8,8,
0xFF,
0x0,
0xFF,
0xFF,
0x10,
0x0,
0x80,
0x21,
};

const byte diagonal_right[] PROGMEM = {8,8,
0x80,
0x40,
0x20,
0x10,
0x8,
0x4,
0x2,
0x1,
};

const byte diagonal_left[] PROGMEM = {8,8,
0x1,
0x2,
0x4,
0x8,
0x10,
0x20,
0x40,
0x80,
};

const byte empty[] PROGMEM = {8,8,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
};

#endif /* MARIO_BITMAPS_H */

Player.h
Code: Select all
#ifndef PLAYER_H
#define PLAYER_H

#include "mario_bitmaps.h"

#define MAX_COLLISION_LEVEL_WIDTH  30
#define MAX_COLLISION_LEVEL_HEIGHT 6

extern const byte PROGMEM collision_levels[];
extern byte lvl;
extern int cameraPos;
byte collvldata[MAX_COLLISION_LEVEL_WIDTH * MAX_COLLISION_LEVEL_HEIGHT];

void loadColLevel(int curLev) {
  for(byte i = 0; i<MAX_COLLISION_LEVEL_WIDTH * MAX_COLLISION_LEVEL_HEIGHT; i++){//Loops through the level
    collvldata[i] = pgm_read_byte(collision_levels + (MAX_COLLISION_LEVEL_WIDTH * MAX_COLLISION_LEVEL_HEIGHT) * (curLev - 1) + i);
  }
}

class Player {
public:
  Player(float x, float y) {
    this->x = x;
    this->y = y;
    this->velX = 0.0f;
    this->velY = 0.0f;
    this->bitMap = mario_still;
    this->flip = false;
    this->walking = false;
    this->lives = 3;
    loadColLevel(lvl);
  }
  float x, y;
  float velX, velY;
  byte *bitMap;
  boolean flip;
  boolean walking;
  byte lives;
 
  void restart() {
    this->x = 0;
    this->y = 0;
    this->velX = 0.0f;
    this->velY = 0.0f;
    this->bitMap = mario_still;
    this->flip = false;
    this->walking = false;
    loadColLevel(lvl);
  }

  void render(Gamebuino gb) {
    if(lives <= 0) {
      if(!gb.buttons.pressed(BTN_A)) {
        gb.display.clear();
        gb.display.fillScreen(BLACK);
        gb.display.setColor(WHITE, BLACK);
        gb.display.cursorX = (LCDWIDTH / 2) - 15;
        gb.display.cursorY = (LCDHEIGHT / 2) - 5;
        gb.display.println("Game over!");
        gb.display.cursorX = (LCDWIDTH / 2) - 9;
        gb.display.cursorY = (LCDHEIGHT / 2) + 1;
        gb.display.println("Press A");
      } else {
        lives = 3;
        restart();
      }
      return;
    }
    gb.display.print("x");
    gb.display.println(lives);
    gb.display.cursorX = LCDWIDTH / 2 - 3;
    gb.display.cursorY = 0;
    gb.display.print("LEVEL ");
    gb.display.println(lvl);
    if(this->x < 0) this->x = 0;
    if(this->x + 8 > LCDWIDTH) this->x = LCDWIDTH - 8;
    if(this->y < -8) this->y = -8;
    if(this->y + 16 > LCDHEIGHT) {
      restart();
      lives--;
    }
    if(gb.buttons.repeat(BTN_RIGHT, 1)){
      velX = 1.0f;
      flip = false;
      walking = true;
    }
    else if(gb.buttons.repeat(BTN_LEFT, 1)) {
      velX = -1.0f;
      flip = true;
      walking = true;
    }
    else {
      velX = 0;
      walking = false;
    }
    if((collvldata[(int)(((y / 8) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + velX) + cameraPos / 8))]) == 0 &&
    (collvldata[(int)(((y / 8 + 1) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + velX) + cameraPos / 8))]) == 0) {
      x += velX;
    }
 
    if((gb.buttons.timeHeld(BTN_UP) > 0 && gb.buttons.timeHeld(BTN_UP) < 5)){
      if((collvldata[(int)(((y / 8 - 1) * MAX_COLLISION_LEVEL_WIDTH) + (x / 8 + cameraPos / 8))]) == 0) {
        velY = -8.0f;
      }
    }
   
    y += velY;

    if((collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + (x / 8 + cameraPos / 8))]) == 0) {
      velY = 8.0f;
    } else {
      velY = 0;
    }

    if(walking) {
      if(gb.frameCount % 6 >= 0 && gb.frameCount % 6 < 3) {
        this->bitMap = mario_still;
      }
      else {
        this->bitMap = mario_walking_1;
      }
    }
    else {
      this->bitMap = mario_still;
    }
    if(flip) {
      gb.display.drawBitmap(x, y, this->bitMap, NOROT, FLIPH);
    }
    else {
      gb.display.drawBitmap(x, y, this->bitMap, NOROT, NOFLIP);
    }
  }
};

#endif


Thanks in advance
awesome 101
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Re: Why is my collision not working

Postby awesome101 » Sun Jun 21, 2015 5:15 pm

The twenty-first tile on the fifth row isn't working.If you can find the bug I would really appreciate it.
Thanks
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Re: Why is my collision not working

Postby Sorunome » Sun Jun 21, 2015 5:55 pm

You have to keep in mind when doing the collision detection that your x|y are probably from the top-left corner, so you have to check for x+TILEWIDTH and y+TILEWIDTH, and i cannot see such a thing happening here:

if((collvldata[(int)(((y / 8) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + velX) + cameraPos / 8))]) == 0 &&
(collvldata[(int)(((y / 8 + 1) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + velX) + cameraPos / 8))]) == 0) {
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Why is my collision not working

Postby awesome101 » Sun Jun 21, 2015 7:07 pm

Ok thanks for the tip! I have been trying to find this bug for days now.
The reason I say
if((collvldata[(int)(((y / 8) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + velX) + cameraPos / 8))]) == 0 &&
(collvldata[(int)(((y / 8 + 1) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + velX) + cameraPos / 8))]) == 0) {
is because I need to check the upper part of the player and the bottom part of him because his height is two tiles high if that makes sense. Thank you so much! :D
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Re: Why is my collision not working

Postby awesome101 » Sun Jun 21, 2015 7:43 pm

Sorry to bother you again, but my collision still doesnt work
when i go left on some platforms i fall down one tile behind where I am supposed to fall.
here is what i have done:
previous code:
if((collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + (x / 8 + cameraPos / 8))]) == 0) {
velY = 8.0f;
} else {
velY = 0;
}
new code:
if((collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + (((x + 8) / 8 + cameraPos / 8)))]) == 0) {
velY = 8.0f;
} else {
velY = 0;
}
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Re: Why is my collision not working

Postby Sorunome » Sun Jun 21, 2015 10:36 pm

You have to check all the corners, not only one.
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Why is my collision not working

Postby awesome101 » Mon Jun 22, 2015 12:25 am

I'm sorry to bother you again, but how do I implement that?
Sorry again I'm new to programming
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Re: Why is my collision not working

Postby Sorunome » Mon Jun 22, 2015 9:13 am

With something like


if((collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + (((x + 8) / 8 + cameraPos / 8)))]) == 0 && (collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + cameraPos / 8)))]) == 0) {
User avatar
Sorunome
 
Posts: 629
Joined: Sun Mar 01, 2015 1:58 pm

Re: Why is my collision not working

Postby awesome101 » Mon Jun 22, 2015 12:48 pm

Hi again, but my collsion still doesnt work.
This is what I did:
if((collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + ((x / 8 + cameraPos / 8)))]) == 0 &&
(collvldata[(int)(((y / 8 + 2) * MAX_COLLISION_LEVEL_WIDTH) + (((x + 8) / 8 + cameraPos / 8)))]) == 0) {
velY = 8.0f;
}
else {
velY = 0;
}
I'm sorry for bothering you but I am really desperate to get my collision working. :|
Thanks
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Re: Why is my collision not working

Postby awesome101 » Mon Jun 22, 2015 6:45 pm

I did some intensive debugging sessions, and found out it was because of my cameraPos variable.
I was trying to offset the index of the collision array by the cameraPos variable. This caused problems, as each tile in the collision array were ahead by two tiles rather than at the players position. Right now I am currently trying to fix this. If you know how, please tell me as any help is appreciated. Thanks.

Awesome101
awesome101
 
Posts: 159
Joined: Sat Jun 20, 2015 6:56 pm

Next

Return to Programming Questions

Who is online

Users browsing this forum: No registered users and 64 guests

cron