Make Your Own Sideways Scroller: Part 2 - Prerequisite Concepts


(Simon) #1

The code described in these lessons can be found at https://github.com/filmote/Steve


Creating Steve the Jumping Dinosaur

Steven the Jumping Dinosaur is an endless runner where you jump oncoming cacti and duck under low-flying pterodactyls. The longer you run, the higher your score!

Before we jump (all puns intended) in to writing some code, we need to look at a few new concepts:

Structures

A structure is a way of grouping related variables together into a single construct. A structure can be passed to a function or referred to as a single unit.

An example of a structure is shown below. It represents a node and contains three variables that hold the coordinates and node value respectively.

struct Node {
  byte x;
  byte y;
  byte value;
};

Once defined, a new variable can be created using it as a datatype as shown below. The members of the structure can be referenced directly to assign or retrieve their values.

Node aNode;
aNode.x = 3;
aNode.y = 4;

int x = calc(aNode);

int calc(Node theNode) {

  return theNode.x * theNode.y;

}

The declaration and initialization code above could have been expressed in a single line as shown below. The members of the structure must be initialised in the sequence they were declared in the structure definition. Not all members must be initialized and the second example is also valid and the value member would be initialised to 0.

Node myNewNode = {3, 4, 5};
Node myNewNode = {3, 4};

Enumerations

An enumerations is a data type consisting of a set of named values. Under the covers, the values are all of type integer but the programmer may not ever need to know or care what the values are.

Enumerations can be named or anonymous as shown below. Note in the first example, I have nominated that the first element, Cat, is assigned the numeric value 10. Dog will automatically be assigned the value of 11 and Mouse, 12. In the second example where no starting number is specified, the items are numbered from zero onwards.

enum Pet {
  Cat = 10,
  Dog,
  Mouse
};

enum {
  Horse,
  Cow,
  Sheep
};

Once an enumeration is declared, it can be used as shown in the valid declarations below.

int aHorse = Horse;
Pet aCat = Cat;
Pet aDog = Pet::Dog;

Named enumerations can be used when defining parameters of a function. As you can see from the sample calls, the declaration will not prevent you from passing any other enumeration type or even an integer.

void printPetDetails(Pet thePet) {

  switch (thePet) {

    case Pet::Cat:
      Serial.println("cat");
      break;

    case Pet::Dog:
      Serial.println("dog");
      break;

    case Pet::Mouse:
      Serial.println("mouse");
      break;

    default:
      Serial.println("other");
      break;

  }

}

printPetDetails(aCat);	< prints ‘cat’
printPetDetails(aDog); 	< prints ‘dog’
printPetDetails(aHorse); 	< prints ‘other’ but is illogical as it isn’t a Pet
printPetDetails(2); 	< prints ‘other’ but is illogical as it isn’t a Pet

Sprites

A sprite is an image or graphic that represents a player, an enemy or even background elements of your game and can be drawn or moved around as a single object. The Arduboy library provides a number of functions to render sprites to the screen. In this tutorial, we will concentrate on two functions drawOverwrite() and drawExternalMask().

But before we get into those, let’s recap how we define a sprite. The image below shows Steve in his upright, ready-to-run position.

0001

The array definition for this sprite is shown below.

const byte PROGMEM dinosaur_still[] = {

  18, 21,

  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0xFE, 0xFF, 0xFB, 0xFF, 0xFF, 0xBF, 0xBF, 0x3F, 0x3E,

  0x3F, 0x7C, 0xF8, 0xF0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 
  0xFF, 0xFF, 0x7F, 0x3F, 0x04, 0x0C, 0x00, 0x00, 0x00,

  0x00, 0x00, 0x00, 0x01, 0x1F, 0x17, 0x03, 0x01, 0x03, 
  0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

};

I have formatted the array to make it a little more readable. The first line contains the width and height of the array, in this case 18 pixels wide by 21 pixels. The remaining rows contain the pixel data of the actual image.

I am not going to describe how the image data is calculated in this article – it has been described in detail in other articles in this magazine including this one on Page 23 of the Arduboy Magazine (Vol 7). Team ARG have a great online tool that allows you to drop a black and white image on to the page and calculate the image data. It can be found here.

The following code will render Steve at position x = 4, y = 5.

Sprites::drawOverwrite(3, 4, dinosaur_still, 0);

The last parameter – the zero – is the frame number. We will cover that in a few moments.

When rendering an image using drawOverwrite(), it overwrites whatever is on the screen with the image specified. There is no concept of transparent pixels so the entire rectangle that the sprite covers is affected.

Masks

The Arduboy library also provides some nice masking utilities that allow you to render a sprite over a background without clearing the entire rectangle that the sprite occupies. In a sense it allows you to mark areas of a sprite as solid (black or white) and transparent.

Consider the following image and mask:

0002 0003

As mentioned above, drawOverwrite() simply draws the sprite and overwrites what was already there. In the example below, the black corners of the ball are visible as the ball passes into the white area.

0004 0005 0006

As the name implies, the drawExternalMask() function allows the image and mask to be nominated when rendering. Bits set to 1 in the mask indicate that the pixel will be set to the value of the corresponding image bit. Bits set to 0 in the mask will be left unchanged. This can be seen clearly as the ball moves into the right hand side of the background. The top-left and bottom-right corners of the image are rendered as black as the mask is set to 1 in these areas which in turn ensures that the images pixels (both zeroes and ones) are rendered on the background.

0004 0008 0009

0010 0011 0012

A second article on Page 33 of the Arduboy Magazine (Vol 7) describes the various other mask options available and contains a link to a project that demonstrates the various techniques.

The sample code below shows a call to the drawExternalMask() function. As with the drawOverwrite() function, you must specify a frame number (explanation coming up!) for the image and additionally you must specify a frame for the mask. In the example below, the frames are both 0 (zero).

Sprites::drawExternalMask(3, 4, dinosaur_still, dinosaur_mask, 0, 0);

Frames

One challenge when writing a game is to ensure that the speed of the game is not affected by the amount of activity that is going on. The Arduboy supports a concept called frames which allows activity to be coordinated - paused even – so that game play speed is constant. Think of it like a traffic cop that slows down fast processes and waits until it’s time for the next round of activity.

The Arduboy allows you to specify the number of frames you want per second. A large number will result in many frames per second and therefore the period between frames is very short. A small number will result in a larger gap between frames. The code below shows a typical setup:

void setup() {

  arduboy.begin();
  arduboy.setFrameRate(75);
  
}

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

  …

}

The first line of code in the loop() is crucial. It induces a delay if it is not time to process the next frame.

Frames can also be used as a basic counter and to animate graphics. Later when we look at rendering Steve, we will use the frame count to alternate between an images where his left foot is down to a second where his right foot is down.


The code described in these lessons can be found at https://github.com/filmote/Steve

Prev Article > Make Your Own Sideways Scroller: Part 1 - Steve The Jumping Dinosaur
Next Article > Make Your Own Sideways Scroller: Part 3 - Moving the Ground


Make Your Own Sideways Scroller: Part 3 - Moving the Ground
New user and info
Make Your Own Sideways Scroller: Part 1 - Steve The Jumping Dinosaur
Make Your Own Arduboy Game: Part 9 - Mapping DinoSmasher
#2

These are quite a leap from the previous lessons… was there supposed to be something in between?


(Simon) #3

Thanks for the feedback.

This article (Part 9) quickly introduces a number of concepts that are required before completing the game. Unfortunately, to do anything beyond ‘pong’ requires the developer to learn new skills and extend themselves. Even creating a puzzle game or Tic Tac Toe requires the developer to understand arrays and possibly structures.

I can only encourage you to stick with it. Programming is not something you can learn overnight and it does involve a lot of trial and error … how can I make the dinosaur jump? How do I maintain his position through each loop. I can create dozens of variables with descriptive names, but is there a better way?

Out of curiosity, how much programming have you done on the Arduboy and in other languages? You obviously followed @crait’s tutorial … did you understand all of it? Did you play with some of your own code before launching into this tuorial.

I don’t mean to sound rude in the previous questions but I am interested in the skill levels required for this series of lessons to be useful. Maybe I should mark the tutorial as ‘Medium’ in terms of skills rather than ‘Beginner’ ?


(Camilla) #4

First and foremost thank you for taking the time to write this guide and for sharing your code!

You end up with a really cool game in the end, but I think this tutorial as a whole is a bit difficult to follow, and I think there are two things that might help:

(1) More detailed commenting of the code. I teach R at university level and find students are able to understand even really advanced concepts as long as every line of code is commented in extreme detail. I don’t think that is necessary to comment every line here, but I think a bit more commenting would be very helpful for beginners to programming, C++ and making games.

(2) Summary of what your code should look like in the end of every part, as it is a bit difficult to follow what is supposed to be in the code and where it is supposed to be. Even though you have linked to the github code I think this would help beginners a lot.

I also have to say that I love the pet example in this guide! I usually use a similar example when introducing students to objects (box <- "cat), arrays (box <- c(“cat”,“dog”,“rabbit”) ) and if else statements ( if(“cat” %in% box){print(“Yay!”)} ). So its really fun to see someone else using animals in their examples :slight_smile:


#5

Woah! Myself and my 13 son have just followed the Pong tutorials. No previous coding experience but my son managed to pimp the game out with different difficulty levels, graphics, title, win & lose screens and music throughout.

Then we moved onto this tutorial and have come to a dead stop. It doesn’t make sense to either of us. I think this is too advanced for beginners, or assumes that you already are a programmer of some sort. Either that or we’re just thick!

We would love to follow more tutorials but don’t really know where to go from here. Are there any plans to pad out the ‘Education’ section?


(Simon) #6

I can do that. As it stands the code was taken from the Arduboy magazine where real estate is at a bit of a premium.

This series is not really a ‘beginners’ guide - the ‘Pong’ instruction set covers that really well. This is really for people who have mastered the basics and want to learn some new skills and techniques. The C++ language as implemented in the Arduino environment allows people to get started quickly but ultimately to really progress, you need to invest time in learning some of the beginner-friendly aspects of the language.

Structures, enumerations and classes all lurk under the surface in Arduino / Arduboy development.

Thanks for the feedback … what parts didn’t make sense? I can expand the test, examples or both to make it clearer.

As mentioned above, the series is not really aimed at beginners - more at those wishing to learn some more about the underlying language behind the Arduboy, C++.

I guess what is needed is a bridging application between Pong and Steve. It could introduce a few concepts that are then used again in Steve.

@Chi and @doone128

Have you been reading the Arduboy Magazine? A number of the concepts that are used in Steve are explored in detail in the various editions. There is a series on a ‘Pipes’ game that also introduces the concepts that are used again in ‘Steve’ which may help. Additionally, there a many articles focusing on single aspects of Arduboy development.

Finally, I can offer you a game that I wrote with my son - a Tic Tac Toe game. It does not use any Structs or enums (from memory) but implements a one-player-versus-computer and a two-player game thus giving it a little more meat to chew on. Please feel free to download it, pull it apart and make it your own.

https://www.google.com.au/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwiNnKfO6praAhXEgLwKHQGRDBwQFggpMAA&url=https%3A%2F%2Fissuu.com%2Farduboymag&usg=AOvVaw3krHK8own1_TDcHyZGUWCT


#7

We didn’t understand the very first bit about structures, nodes, enumerations etc. I read it over and over and couldn’t make head nor tails of it. Please bear in mind that we have no prior coding experience. We have come do this after funding the Kickstarter campaign so following the tutorials is the only experience we’ve had so far.

My son managed to change the pong code and add music and title screens after a lot of code and post searching. He spent around 9 hours playing with those tutorials and made great progress but this seemed a major step up in concepts. Of course, I think it’s amazing that you offer such help but I do think that you are correct that a bridging tutorial set would be a great help to people like us who have come to Arduboy without any prior knowledge but want to learn.


#8

I know a “printed booket and free online coursework for an entire lesson plan for learning C++ on the Arduboy” was mentioned back on the original Kickstarter, but not sure if that ever materialised?


(Simon) #9

I might have to go and find that promise … I haven’t seen anything either.


(Pharap) #10

Unfortunately introducing some of the concepts used in programming is always a challenge.

Programming has its foundations in maths and logic and language theory, and many of it concepts come from those fields and can be very abstract at times (i.e. sometimes there’s a lot of theory and imagination required, it’s not always about tangible results).

I second the advice of reading the magazine.

It’s completly free and it has many articles discussing different concepts, some of which will be a bit closer to what you’re looking for. I recommend starting at the beginning of issue 1 and reading them in order.
It will also help you get into the history of the Arduboy so you become aware of some of the things the rest of us have lived through/been involved in (like the game jams and infrequent opinion polls).

Unfortunately the advice and tone can be a bit disjoint at times, given that all this material is produced by drastically different people in their own free time on nothing but good will (and maybe a bit of coffee).

I’d also recommend looking into some tutorials that aren’t Arduboy specific, to help fill a few of the holes we haven’t covered yet. Personally one of my prefered tutorials is here on www.cprogramming.com.


#11

Great, thanks! I’ve got my son onto the magazine now and I’m having a read of it myself. Good stuff.

Thanks to everyone for your help and advice.


(Simon) #12

Ahhh … good one.

I have discussed updating the original articles with @crait and creating a few bridging ones between his and my articles. He plans to update his articles this month (?) and then we can both look at the gaps.

Did you have a look at the Tic Tac Toe game? It is really a logical next step from Pong as it has a little more logic - single and two player - without delving too deep into the C++ stuff.


#13

Great news, thanks! Can’t wait for that!

We’ve just come back from a mini break so haven’t had time to look at TTT yet but we will for sure.

Thanks again.


(Scott R) #14

It’s still listed as part of the educational kit pack on the original Kickstarter. @ardubeast would be a likely candidate to have backed that.