I need help with chests


(Cody) #1

So I was making some progress on the game is was making and ran into a bug when coding. Using the example from arduboy mag 3 I made chests but when I activate one they all activate! Please help


Checking for enemy collisions
(Celine) #2

Hi @Cody17, we can only help when we see your code and have some more information such as what are the chests used for etc :slight_smile:


(Cody) #3

Okey dokey! I will post to night! :smile:


(Cody) #4

sorry for the delay but here is the ino

#include <Arduboy2.h>
#include <ATMlib.h>
Sprites sprites;
#include "Map.h"
Arduboy2 arduboy;


int gamestate = 0;
int FRAMES = 40;
int vol = 8;
int wait = 0;
String GameName = "Risk of Pain";
uint8_t Floor = 50;
bool jump = false;
uint8_t playerHieght = 6;
uint8_t playerWidth = 4;
bool player_walking_left = false;
bool player_walking_right = false;
int score  = 0;
byte Chests[] = {0B0000};


void setup()
{
  arduboy.begin();
  arduboy.setFrameRate(FRAMES);
  playerY = Floor;
  bitClear(Chests[0],0);
  bitClear(Chests[0],1);
  bitClear(Chests[0],2);
  bitClear(Chests[0],3);
  
}
 void loop()
 {
  if(!arduboy.nextFrame())
  return;
  switch( gamestate){
    case 0:
    arduboy.clear();
    arduboy.pollButtons();
    arduboy.setCursor(30,40);
    arduboy.print(GameName);
    arduboy.setCursor(40,50);
    arduboy.print(F("Press A"));
    arduboy.display();

    if(arduboy.justPressed(A_BUTTON))
    {
      gamestate = 1;
    }
    
    break;
    case 1:
    
    arduboy.clear();
    arduboy.pollButtons();




 uint8_t x= (playerX / TileWidth);
uint8_t y= (playerY / TileHeight);
    uint8_t tile = getMapTile(x,y);
switch((TileTypes)tile)
{
 
case TileTypes::Nothing: 
{

}
break;
case TileTypes::Ladder:

{
if(arduboy.pressed(UP_BUTTON))
{
  Floor = 16;
  vol = 3;
  jump = true;
 
}
if(arduboy.pressed(DOWN_BUTTON))
{
  Floor = 50;
  vol = 3;
  jump = true;
}
}
break;
case TileTypes::Chest:
{
 if(arduboy.justPressed(B_BUTTON))
 {
  for(byte i = 0; i < 4; i++)
  {
    if(bitRead(Chests[i / 4],i) == false)
    {
      bitSet(Chests[i / 4],i);
      score+=10;
    
    }
    
  }
 }
}
break;

}
        for(uint8_t y = 0; y < MapHeight; ++y)
{
  for(uint8_t x = 0; x < MapWidth; ++x)
  {
    sprites.drawOverwrite(x * TileWidth, y * TileHeight, tileSheet, getMapTile(x,y));
  }
}

   if(!(arduboy.pressed(LEFT_BUTTON)||arduboy.pressed(RIGHT_BUTTON)))
   {
    arduboy.drawBitmap(playerX,playerY,Idle,16,16,WHITE);
   }
    if(arduboy.justPressed(A_BUTTON) and playerY == Floor and !(Floor == 16))
    {
      jump = true;
      vol = 6;
    }
   
   
if(jump == true)
    {
      playerY=playerY-vol;
      vol--;
      
    }
    if(vol == 0)
    {
      jump = false;
    }
    if(jump == false)
    {
     playerY=playerY+vol; 
     vol++;
    
    }
    if(vol > 10)vol = 10;
    if(vol < 0)vol = 0;
    if(playerY > Floor)playerY=Floor;
    if(arduboy.pressed(LEFT_BUTTON))
    {
      player_walking_left = true;
    }
    else 
    {
      player_walking_left = false;
    }
    if(arduboy.pressed(RIGHT_BUTTON))
    {
      player_walking_right = true;
    }
    else
    {
      player_walking_right = false;
    }
  
    if(player_walking_left == true)
    {
      playerX--;
      wait++;
      if(wait == 1)
      {
           arduboy.drawBitmap(playerX,playerY,WalkLeft,16,16,WHITE);
      }
      if(wait > 1)wait = 0;
      if(wait < 1)
      {
        arduboy.drawBitmap(playerX,playerY,WalkRight,16,16,WHITE);
      }
      
    }
    if(player_walking_right == true)
    {
      playerX++;
      wait++;
     
      if(wait == 1)
      {
           arduboy.drawBitmap(playerX,playerY,WalkLeft,16,16,WHITE);
      }
      if(wait > 1 )wait = 0;
      if(wait < 1)
      {
        arduboy.drawBitmap(playerX,playerY,WalkRight,16,16,WHITE);
      }
      
    }
    if(arduboy.justPressed(B_BUTTON))
    {
      
    }
   arduboy.print(score);
Serial.println(uint8_t(tile));
    arduboy.display();
 }}

(Pharap) #5

They all activate because you aren’t checking which chest the player is interacting with, you’re just looping through all of them at once.

You need a way of knowing which chest number the player is interacting with.


(Cody) #6

Oh…and ah how do I do that?


(Pharap) #7

First you’ll need a way of knowing which chest in your list corresponds to what tile since you don’t already have one.

You’ll either need to store the chest index with the tile in the map somehow or you’ll need to store an x and y for each chest in your list. The second option is probably easier.


(Cody) #8

Could you show an example? Of the second of course.


(Pharap) #9
struct Chest
{
  uint8_t x;
  uint8_t y;
  bool opened;
};

Chest chests[] =
{
  { 3, 4, false }
};

constexpr const static uint8_t ChestCount = 1;

Then your old code becomes:

case TileTypes::Chest:
{
	if(arduboy.justPressed(B_BUTTON))
	{
		for(byte i = 0; i < ChestCount; i++)
		{
			if(Chests[i].x == x && Chests[i].y == y)
			{
				score += 10;
				Chests[i].opened = true;
				break;
			}
		}
	}
	break;
}

(Simon) #10

Its probably worth noting for @Cody17 that to initialise multiple chests you can do this:

Chest chests[] =
{
  { 3, 4, false },
  { 6, 7, false },
  { 12, 6, false },
  { 8, 4, false },
... and so on.
};

(Pharap) #11

Yep, but don’t forget to update the ChestCount:

constexpr const static uint8_t ChestCount = 4;


(Scott) #12

It’s better to calculate the array size, so you don’t have to remember to manually keep it in sync.

constexpr size_t ChestCount = sizeof(chests) / sizeof(chests[0]);


(Pharap) #13

Yep, you could even go a step further and just write a function to get you the size of any array:

template<typename T, size_t size>
constexpr size_t getArrayLength(T(&)[size])
{
  return size;
}

(Scott) #14

Didn’t want to overly confuse @Cody17 with templates at this stage.


(Pharap) #15

That’s the same reason I didn’t want to get into sizeof(chests) / sizeof(chests[0]).


(Cody) #16

Thanks I will try this in the afternoon😃


(Cody) #17

It comes with a error message saying


(Pharap) #18

Woops, my fault for multitasking. Forgot the type:
constexpr const static uint8_t ChestCount = 4;

(Though I’d like to point out at least three experienced programmers (including myself) saw my post and none of them noticed. Amusingly ironic.)


(Cody) #19

So I found another error


(Pharap) #20

That’s because you haven’t changed

byte Chests[] = {0B0000};

to

Chest chests[] =
{
  { 3, 4, false }
};

Yet.

Also make sure that if Chest looks like this:

struct Chest
{
  uint8_t x;
  uint8_t y;
  bool opened;
};

You do this:

if(Chests[i].x == x && Chests[i].y == y)
{
	score += 10;
	Chests[i].opened = true;
	break;
}

Otherwise if Chest looks like this:

struct Chest
{
  uint8_t Chestx;
  uint8_t Chesty;
  bool opened;
};

You do this:

if(Chests[i].Chestx == x && Chests[i].Chesty == y)
{
	score += 10;
	Chests[i].opened = true;
	break;
}

(Though calling it Chestx instead of x is a bit redundant.)