GamebuinoClassic archive

Archive of the Gamebuino Classic forum (2014-2018), rebuilt from the pages kept by the Wayback Machine: only part of the topics and pages were captured. Read-only. Removal on request: hi@gamebuino.com.

Forum › Programming Questions

Why is my collision not working

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 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
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) {
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 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;
}
Sorunome Sun Jun 21, 2015 10:36 pm
You have to check all the corners, not only one.
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
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) {
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 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
REGFly Thu Jun 25, 2015 1:32 pm
You say you're pretty new but you look good in my book :D . I'm pretty new myself
rodot Sat Jun 27, 2015 7:14 am
Topic moved to "Programming Questions". Also please use the code tags when posting code :
Code: Select all
[code]your code here[/code]

Thanks !