Make Your Own Arduboy Game: Part 9 - Mapping DinoSmasher

I would, but it would mean spending N years getting teaching qualifications,
and then I’d have to mark students’ work and put up with their bad behaviour,
and try to make the students not hate me.

Maybe I’ll become a tutor instead. (£20-£40 an hour is a nice incentive.)

4 Likes

5 posts were split to a new topic: Tile Collisions?

Hello! Thank you for the tutorial! First time coder here.
I’ve have done your tutorial but decided it would be fun to have the map be created randomly. I have it working but I have a puzzle I don’t understand. Here is my code based mostly from yours:

  for (int x = 0; x < WORLD_HEIGHT; x++) {
    for (int y = 0; y < WORLD_WIDTH; y++) {
      world[x][y] = random(0, 1);
    }
  }

So I’m trying to change every value of the array “world” to either 0 or 1 (which would be 0=grass and 1=water).

When I do random(0, 1) it gives me grass for ALL tiles
But if I do random(0, 2) it works – it gives me grass and water. I don’t even have a “2” ready to go yet.

What is going on? I don’t understand. Thank you for your help!

1 Like

random() stupidly accepts a min value inclusive and a maximum value exclusive.

So if you want it to return 0 and 1s, you need to do random(0, 2) as you have worked out by trial and error.

3 Likes

Ah ok got it! Thank you :slight_smile:

2 Likes

hello, quick question, what happens if i create the “const ins variables” at the beggining of the code instead of inside the functions? it’s easier for me to keep track of everything on that way, but don’t have idea if that affects something on the arduboy memory

It’s contrary to the expectations of a layman, but having an inclusive lower bound and an exclusive upper bound occurs a lot in computer science for various reasons.

I read a thing once (I think it was by Edsger Dijkstra) explaining a number of useful properties that arrangement has.

That gives you a ‘global variable’ instead of a ‘local variable’.

Global variables exist for the whole of the program so they have to be allocated in RAM and thus can be more costly to access (because RAM has to be accessed with an address and usually uses more machine code instructions to access).

Local variables only exist for the duration of the scope that they’re in (e.g. the duration of the function, the duration of an if block…) and thus can be kept in things called ‘registers’, which are a kind of faster, easier to access memory.

(Some CPUs use what’s referred to as a ‘load-store architecture’, which means they have to load the data from RAM into registers before they can operate on the data, and then they have to store the data back into RAM.
The loading and storing requires extra machine code instructions. I’m fairly sure the Arduboy’s CPU is one of these.)

In what way?

If you only need a variable for the duration of one function then it makes sense to only care about it when you’re reading that function’s code.
The rest of the time you can simply forget it exists.
You don’t need to remember every single variable.

The variables you put at the top of the code, the global variables,
should be the things that have to exist for the entire duration of the program,
or at least exist for more than one function.
E.g. the player, enemies, the game state.

Hi there,

I am new to the arduboy and these tutorials helped me a lot. Thanks for that.
I customised my DInosmasher a bit but it lacks a lot of features.

Do you know when/if the rest of the tutorial will be out ?
Take care

1 Like

Tell me please, when i try to replace the black square with a sprite i have nothing showing on the map. But that nothing can move around the map. So, how to make the image visible?
my try:

void drawplayer() {
  const unsigned char PROGMEM noname[] =
  {
    // width, height,
    16, 16,
    // TILE 00
    0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xb9, 0xb1, 0xb1, 0xb9, 0x83, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0x07, 0x73, 0x7b, 0x7b, 0x78, 0x3f, 0x9f, 0xdf, 0x9f, 0xbf, 0x38, 0x79, 0x39, 0xb3, 0x87, 
  };
}

@NoobGeek,
Welcome to the Arduboy Forum!

First:
When you post code in this forum, please enclose it in markdown code tags:

Start with a line containing three backticks followed by cpp .
Insert your code starting on the following line.
On the line following you code, put another three backticks.
The backtick character is commonly on the key below the Esc key at the top left of a U.S. keyboard. If you can’t find it on your keyboard, you can copy and paste from the tags here:

```cpp
The first line of your code
More code
The last line of your code
```

I’ve added the tags to your post above but please do it yourself in the future.


You’ll have to be more specific and/or provide more code showing how you’re trying to display and move your sprite. I wrote a simple sketch that draws and allows you to move your sprite using the D-pad. It may provide information that helps you.

#include <Arduboy2.h>

Arduboy2 arduboy;

const unsigned char PROGMEM noname[] =
{
  // width, height,
  16, 16,
  // TILE 00
  0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xb9, 0xb1, 0xb1, 0xb9, 0x83, 0x1f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0x07, 0x73, 0x7b, 0x7b, 0x78, 0x3f, 0x9f, 0xdf, 0x9f, 0xbf, 0x38, 0x79, 0x39, 0xb3, 0x87,
};

int16_t xPos = 0;
int16_t yPos = 0;

void setup() {
  arduboy.begin();
  arduboy.setFrameRate(45);
}

void loop() {
  if(!arduboy.nextFrame()) {
    return;
  }

  arduboy.pollButtons();
  arduboy.clear();

  if (arduboy.justPressed(UP_BUTTON)) {
    --yPos;
  }
  if (arduboy.justPressed(DOWN_BUTTON)) {
    ++yPos;
  }
  if (arduboy.justPressed(LEFT_BUTTON)) {
    --xPos;
  }
  if (arduboy.justPressed(RIGHT_BUTTON)) {
    ++xPos;
  }

  Sprites::drawOverwrite(xPos, yPos, noname, 0);

  arduboy.display();
}

NoobGeek1.hex (19.5 KB)

1 Like

I had a closer look at @crait’s “completed code” and now know what you’re trying to do.

The spite that you’ve created for the player is just data. You need to draw it with one of the Sprites functions. Since the bitmap array you’ve provided doesn’t include a mask, the drawOverwrite() function is likely the best to use.

You need to put your noname array in the sketch as “global” data. For my testing, I put it before the tiles array

[...]
int mapx = 0;
int mapy = 0;

const unsigned char PROGMEM noname[] = {
  // width, height,
  16, 16,
  // TILE 00
  0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xb9, 0xb1, 0xb1, 0xb9, 0x83, 0x1f, 0xff, 0xff, 0xff, 0xff, 
  0xff, 0x07, 0x73, 0x7b, 0x7b, 0x78, 0x3f, 0x9f, 0xdf, 0x9f, 0xbf, 0x38, 0x79, 0x39, 0xb3, 0x87, 
};

const unsigned char tiles[] PROGMEM  = {
// width, height,
16, 16,
[...]

Then, you need to replace the fillRect() function in drawplayer() with the function to draw the sprite

#define PLAYER_SIZE      16
#define PLAYER_X_OFFSET    WIDTH / 2 - PLAYER_SIZE / 2
#define PLAYER_Y_OFFSET    HEIGHT / 2 - PLAYER_SIZE / 2
void drawplayer() {
//  arduboy.fillRect(PLAYER_X_OFFSET, PLAYER_Y_OFFSET, PLAYER_SIZE, PLAYER_SIZE, BLACK);
  Sprites::drawOverwrite(PLAYER_X_OFFSET, PLAYER_Y_OFFSET, noname, 0);
}

You should now have your noname sprite drawn instead of a black rectangle.


Without masking, all of the pixels in your sprite are drawn over the background. So, the next thing you’ll probably want to do is create a sprite with a mask and use drawPlusMask() to draw it.

Edit:
Here’s the array (I renamed it to player) and drawplayer() functions with the outside of the image masked

// player in drawPlusMask() format (mask included in image)
const unsigned char PROGMEM player[] = {
  // width, height,
  16, 16,
  // FRAME 00
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xb8, 0xfe, 0xb4, 0xfe,
  0xb4, 0xfe, 0xb8, 0xfe, 0x80, 0xfc, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0xf8, 0x70, 0xfc, 0x78, 0xfc, 0x78, 0xfc, 0x78, 0xff, 0x3f, 0xff, 0x1f, 0x7f,
  0x1f, 0x3f, 0x1f, 0x7f, 0x3f, 0x7f, 0x38, 0xff, 0x78, 0xfe, 0x38, 0xfe, 0x30, 0x7c, 0x00, 0x78
};

void drawplayer() {
  Sprites::drawPlusMask(PLAYER_X_OFFSET, PLAYER_Y_OFFSET, player, 0);
}

NoobGeek2.hex (26.5 KB)

2 Likes

Thanks, it worked! I am surprised that you answered my question so quickly, and with a detailed answer. I am very grateful to you for that! From now on I will ask questions in the correct form. And I will try even more to delve into the software part before asking the community! Thanks again!

3 Likes

2 posts were split to a new topic: How do I create and control multiple objects (bullets)

There’s no part 10 is there :’( @crait

You can head over to @filmote’s more advanced tutorial:

Or you can:

  • Look up C++ tutorials online
  • Read through some of the other forum topics, particularly in the help sections since there’s lots of people asking common “How do I do X?” programming questions dotted around
  • Ask other people for help and advice
  • Just experiment
1 Like

There should be an Arduboy tutorial jam where everyone shares one simple thing they know how to do, or a broader project like these. Be a nice way to gather resources.

Im def gonna check out the c++ site, never seen that one before.

2 Likes

How would one even draw a rect for collisions over the specific tiles that contain a rock piece in this example? I can figure out the player, but honestly the whole drawing the player in world space and camera situation is too much for me.
Is there an easier way to draw a map for a top down style like this?
I’ve looked through…but most seem over my skill level at the moment.
Anyone have any resources on beginning C/C++ style game logic like this? Even Pico 8 abstracts some of the important bits :/.

You could technically draw a single image, but that would be a horrible waste of memory.

Either way you’d need a camera for the map to be scrollable.
No camera, no scrolling.

But really all a camera is (for a 2D game), is an amount by which the map should be offset.

Here’s a really simple diagram that might help with the idea.
(I don’t have a better one to hand.)

Coordinates

And here’s a very simple code example I wrote for someone else a few weeks/months ago:

It’s got lots of comments so hopefully you’ll be able to make some sense of it.

Drawing a rectangle and handling collisions are two separate matters that should be handled separately and actually don’t have to be correlated.

I don’t know what you mean by a ‘building piece’.
There are no buildings in the sample code, just grass, water, trees and stone.

If you’re just wanting basic tile collisions, have a look at some of the posts over in this recent topic:

(This is why I said have a read through some other forum topics as well. Sometimes you’ll find someone else has already asked a similar question.)

1 Like

I’ll check em out, thanks for being so helpful! Gonna try and unpack your example code, I’m obviously not up on everything. Know any good resources on just 2d c/c++ game logic?

1 Like

Not much in way of ‘the basics’, and not much that would be immediately applicable to Arduboy.

But honestly, if you just follow a tutorial that tells you how to make a game, you’ll probably only learn how to make that game, and without the skills and knowledge to modify it you’ll only be able to make that game.

To be able to make the games you want to make, you have to learn bits and pieces of how to do things and how to tie them together. Programming is very much about learning individual techniques and combining them to produce something new.

(It’s a bit like cooking - you learn what the ingredients do and then you put them together to make something, and you tweak the recipe as you go, discovering what works and what doesn’t. The recipe is the source code, the game is the food.)

It’s also about looking at large problems and breaking them down into smaller problems that are easier to solve. (It’s also more about solving problems than it is about telling the computer what to do.)

You can ask if you don’t understand something and want more information.

(Though perhaps it would be best to start a new topic rather than continue to reply to this one.)

You want C++ resources, not C. C++ is not C, and C is not C++.

The two are related but distinct languages, and Arduboy programming uses C++.

1 Like