Using a sprite in a Monster class

(Andrew) #1

I am working on a little dungeon game. I’m not a super experienced C++ programmer. I wrote a class for my Monsters, but I’m not exactly sure how I can attach a sprite declared as a const in progmem when I create an instance.

1 Like

#2

There’s a couple of options, but the easiest might just be to use a pointer to the sprite data.
Assuming your sprite is of the form uint8_t monsterSprite[]
You could add the field to your class

enemy(const char * name, const uint8_t * sprite, int lvl)
//whatever is in your construtor + * sprite
{
    //rest of monster constructor
    const * pointerToMySprite = sprite;
}

and you can just draw it with

arduboy.drawBitmap(x, y, monster.pointerToMySprite, xDimension, yDimension, WHITE);

You can also use the Sprites class to draw it but I forget the syntax off the top of my head. I’m sure someone else will comment on that. Sprites is better overall but I think bitmap is a litter easier to work with if its your first game for the arduboy.

1 Like

(Pharap) #3

It would have to be a const uint8_t *.

The way you’ve written it there you’re assigning it to a local uint8_t * variable.

Something more like:

class Monster
{
private:
	const uint8_t * sprite;
	// Other fields

public:
	Monster(const uint8_t * sprite, /* other parameters */) :
		sprite(sprite), // etc
	{
	}
	
	const uint8_t * getSprite() const
	{
		return this->sprite;
	}
};

It’s:

Sprites::drawOverwrite(x, y, sprite, frame);

(As documented here.)

0 Likes

#4

dropped the const. I always drop something.

I’m guessing @bridge2nowhere might not know about initialising lists though.

1 Like

(Scott) #5

I don’t know which sprite drawing method @bridge2nowhere wants to use but Sprites::drawSelfMasked() is a better equivalent to Arduboy2Base::drawBitmap() than Sprites::drawOverwrite() is.

0 Likes

(Pharap) #6

Fair enough, but they’re easy enough to understand.

Though if transparency is needed then using a proper mask is usually a better option than either.

0 Likes

(Andrew) #7

Is there a benefit to using uint8_t over unsigned char as a datatype for the sprites?

0 Likes

(Andrew) #8

Here is where I am so far if anyone is interested:

https://github.com/bridge2nowhere/pocketDungeon

0 Likes

(Scott) #9

Though you can use drawBitmap() to do proper masking. You use a bitmap for the pixels you want black and set the drawBitmap() color parameter to BLACK. You then use a bitmap for the pixels you want white and call drawBitmap() again with the color parameter set to WHITE, at the same coordinates. The pixels not set to 1 in either bitmap will then be transparent (left unchanged).

You can also do the same thing with a combination of Sprites::drawErase() and Sprites::drawSelfMasked().

That said, Sprites::drawPlusMask() or Sprites::drawExternalMask() are usually better options for this.

0 Likes

(Andrew) #10

Something weird happened, my sprites no longer show up correctly. They show up as the right size, and still move around.

I’m sure I did something silly, but if any of you could take a look at this, I would appreciate it.

0 Likes

(Pharap) #11

Your last commit didn’t actually change anything.

The version on GitHub seems to be drawing correctly.

0 Likes

#12

If I remember right they’re actually the same thing.
It doesn’t matter though. Just make the pointer a char

0 Likes

(Andrew) #14

I uploaded the wrong code, it’s been fixed (I uploaded the correct files, my issue hasn’t been fixed).

0 Likes

(Pharap) #15

There’s no major benefit, on Arduboy at least unsigned char and uint8_t are the same type.
Although if someone were trying to port the code to a different system then using uint8_t is probably a better indicator that you intend the type to be exactly 8 bits.
(On some systems unsigned char might be larger than 8 bits, whereas uint8_t will either be 8 bits or won’t exist.)

You remember rightly:

https://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html

The problem is here:

Monster::Monster(byte health, byte att, byte def, byte imgSize, const uint8_t * sprite)
{
  hp = health;
  attMod = att;
  ac = def;
  spriteSize = imgSize;
  posnX = 8;
  posnY = 8;
  // This is assigning to a local variable
  const uint8_t * pointerToMySprite = sprite;
};

You need to do this instead:

Monster::Monster(byte health, byte att, byte def, byte imgSize, const uint8_t * sprite)
{
  hp = health;
  attMod = att;
  ac = def;
  spriteSize = imgSize;
  posnX = 8;
  posnY = 8;
  // This is assigning to a member variable
  pointerToMySprite = sprite;
};

For future reference, to make sure you’re assigning to a member variable you can put this-> in front of the variable.
E.g.

Monster::Monster(byte health, byte att, byte def, byte imgSize, const uint8_t * sprite)
{
  this->hp = health;
  this->attMod = att;
  this->ac = def;
  this->spriteSize = imgSize;
  this->posnX = 8;
  this->posnY = 8;
  this->pointerToMySprite = sprite;
};

If any of the names after this-> aren’t member variables you’ll get an error.

This approach also allows you to use the same name for both member variables and function parameters.
E.g.

Monster::Monster(byte hp, byte attMod, byte ac, byte spriteSize, const uint8_t * pointerToMySprite)
{
  this->hp = hp;
  this->attMod = attMod;
  this->ac = ac;
  this->spriteSize = spriteSize;
  this->posnX = 8;
  this->posnY = 8;
  this->pointerToMySprite = pointerToMySprite;
};
0 Likes

#16

Oh jeez you know I completely gapped on the local thing.

It’s because I had just written that uint8_t part then went back and added the constructor around it to give more context. @bridge2nowhere my mistake leading you astray, I really should of caught that one. I’ve fixed it in my original post in-case someone else ever reads this.

1 Like

(Pharap) #17

No harm done.

猿も木から落ちる。
Or in English: even monkeys fall from trees.

(Sorry, couldn’t resist. I’ve been waiting at least a month to have an excuse to say that.)

1 Like

(Andrew) #18

Thank you, I’m all fixed now!

1 Like

#19

I just :heart: love that expression. Must memorise thato one!

1 Like

(Pharap) #20

If you want to know how to pronounce it, it’s “saru mo ki kara ochiru”.

  • ‘saru’ (猿) means monkey (as in nihonzaru (ニホンザル, from 日本 and 猿).)
  • ‘mo’ (も) means ‘even’ (or ‘as well as’, or ‘also’)
  • ‘ki’ (木) means tree
  • ‘kara’ (から) means ‘from’ (or ‘out of’),
  • ‘ochiru’ (落ちる) is the verb meaning means ‘to fall’ (or ‘to drop’)

Though given your knowledge of たまごっち I wouldn’t be surprised if you already knew some of those words.
(I knew saru, mo and ki, but not kara and ochiru.)


If you want to know some more Japanese idioms/proverbs/kotowaza (ことわざ) then let me know.
(I’ve been collecting resources discussing them.)

But it’s probably best to do it in a PM or separate thread,
I think this thread has been derailed enough for now.

1 Like