[WIP] Ardunaut (previously Parallax rocket launch)

(Andrew Crawford) #1

Hey everyone, pretty excited to show off another WIP alongside the first game I started. Still needs some work for sure but just happy to show off that a lot of the help ive gotten so far has stuck :stuck_out_tongue: I know its very basic, just something i think i can work on alongside my other game.

This one is meant to be an 8-bit kerbal space program (just in the launching/landing aspect), but i still have some other features id like to implement, pending limitations. As of right now its just a simple gravity engine that rests/pulls the rocket towards the ground, but ive implemented a few small details like a layered background for parallax scrolling during launch/flight, padding for the rocket to takeoff and center in the screen but land back on the bottom, and animations for the rocket in a few positions (up, angled right, and angled left), and it doesnt take up all that much memory yet! (though i would still like to reorganize it as i get a better idea how, just like my other game), but suffice it to say im proud ive been able to do this in just a day vs struggling with similar parts for a few days :stuck_out_tongue:

Here is what I have so far (sorry for the mess, but its just a demo).

#include <Arduboy2.h>
Arduboy2 arduboy;
Sprites sprite;

int mapx = 0;
int mapy = 0;
int mapx2 = 0;
int mapy2 = 0;
int mapx3 = 0;
int mapy3 = 0;
int WORLD_WIDTH = 128;
int WORLD_HEIGHT = 64;
uint8_t playerx = 63;
uint8_t playery = 50;
uint8_t const *player = nullptr;

PROGMEM const unsigned char playerup[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 9
  9, 9,
  0x00, 0x00, 0xE0, 0x7C, 0x47, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char playerleft[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 16
  9, 9,
  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x1C, 0x08, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x90, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char playerright[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 16
  9, 9,
  0x00, 0x10, 0x08, 0x1C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x10, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x90, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x10, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char bg1[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char bg2[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char bg3[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

void setup() {
  arduboy.boot();
  arduboy.setFrameRate(75);
  player = playerup;
  arduboy.clear();
}

uint8_t frame = 0;

void loop() {
  if (!arduboy.nextFrame()) {
    return;
  }
  arduboy.clear();
  for (int x = 0; x < WORLD_WIDTH; x = x + 64 ) {
    //For each row in the column
    for (int y = 0; y < WORLD_HEIGHT; y = y + 64) {
      //Draw a background tile
      sprite.drawSelfMasked(x + mapx, y + mapy, bg1, 0 );
    }
  }
  for (int x = 0; x < WORLD_WIDTH; x = x + 64 ) {
    //For each row in the column
    for (int y = 0; y < WORLD_HEIGHT; y = y + 64) {
      //Draw a background tile
      sprite.drawSelfMasked(x + mapx2, y + mapy2, bg2, 0 );
    }
  }
  for (int x = 0; x < WORLD_WIDTH; x = x + 64 ) {
    //For each row in the column
    for (int y = 0; y < WORLD_HEIGHT; y = y + 64) {
      //Draw a background tile
      sprite.drawSelfMasked(x + mapx3, y + mapy3, bg3, 0 );
    }
  }
  arduboy.drawLine(60 + mapx, 58 + mapy, 73 + mapx, 58 + mapy);
  sprite.drawSelfMasked(playerx, playery, player, frame);
  if (mapy >= 2 && mapy <= 120) {
    mapy -= 1;
    mapy2 -= 2;
    mapy3 -= 3;
  }
  if (arduboy.pressed(UP_BUTTON) && playery <= 120) {
    mapy += 2;
    mapy2 += 4;
    mapy3 += 6;
    player = playerup;
    frame++;
    if (frame > 3) {
      frame = 0;
    }
    if (playery >= 30) {
      playery -= 2;
    }
  }
  if (!arduboy.pressed(UP_BUTTON) && playery <= 48) {
    playery += 2;
  }
  if (arduboy.pressed(LEFT_BUTTON) && playerx >= 2) {
    mapx += 1;
    mapx2 += 2;
    mapx3 += 3;
    player = playerleft;
    frame++;
    if (frame > 3) frame = 0;
  }
  if (arduboy.pressed(RIGHT_BUTTON) && playerx <= 120) {
    mapx -= 1;
    mapx2 -= 2;
    mapx3 -= 3;
    player = playerright;
    frame++;
    if (frame > 3) frame = 0;
  }
  if (!arduboy.pressed(UP_BUTTON) && !arduboy.pressed(DOWN_BUTTON) && !arduboy.pressed(LEFT_BUTTON) && !arduboy.pressed(RIGHT_BUTTON)) {
    frame = 0;
  }
  arduboy.display();
}
1 Like
(Andrew Crawford) #2

Sorry for a bit of spam between this and a couple other threads, just figured id get a bit more up to speed getting a Github repo and figured i would put up the simple 3D parallax scrolling demo and gravity/platformer demo i started to build my game from, along with my work in progress. Its really nothing special, just thought that putting it out there may come of some use to other beginners such as myself in future searches (and spare others some of the headaches ive surely caused them with more simple things).

(Pharap) #3

Last thing before I leave for the day…

2 Likes
(Andrew Crawford) #4

Ah, thank you! I’m gonna have to get back to it tomorrow, just gettin too tired, but I got most of my programs reorganized and running okay… could probably still use a little more organization but I got them working mostly using classes now, only thing is the rocket launch program has a couple hangs ups since it’s structured a little different (just some simple boundary parameters, should only take me a minute or so to fix), but I’ll definitely give that a look first thing tomorrow with it as well, thanks again!

1 Like
(Andrew Crawford) #5

I dont mean to spam between this and the thread for my other game, or ask for assistance with this on top of the other (one thing at a time now), but just because I reorganized and changed the code a bit I figured i may as well post an update.

I changed it a bit so that when the rocket reaches a certain height then the background starts scrolling, and so that when youre coming back down itll stop scrolling at the same point, but other than that just reorganized it a bit using classes

#include <Arduboy2.h>
Arduboy2 arduboy;

int heightCounter = 0;

struct Background1 {
  uint16_t mapX = 0;
  uint16_t mapY = 0;
};

struct Background2 {
  uint16_t mapX2 = 0;
  uint16_t mapY2 = 0;
};

struct Background3 {
  uint16_t mapX3 = 0;
  uint16_t mapY3 = 0;
};

Background1 background1;
Background2 background2;
Background3 background3;

constexpr int worldWidth = 296;
constexpr int worldHeight = 128;
constexpr int tileSize = 64;
int playerX = 63;
int playerY = 50;
uint8_t const *playerSprite = nullptr;

PROGMEM const unsigned char playerUp[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 9
  9, 9,
  0x00, 0x00, 0xE0, 0x7C, 0x47, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char playerLeft[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 16
  9, 9,
  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x1C, 0x08, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x90, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char playerRight[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 16
  9, 9,
  0x00, 0x10, 0x08, 0x1C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x10, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x90, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x10, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char backgroundTile1[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char backgroundTile2[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char backgroundTile3[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

void setup() {
  arduboy.boot();
  arduboy.setFrameRate(10);
  playerSprite = playerUp;
  arduboy.clear();
}

uint8_t frame = 0;

void loop() {
  if (!arduboy.nextFrame()) {
    return;
  }
  arduboy.clear();
  arduboy.print(heightCounter);
  arduboy.drawLine(60 + background1.mapX, 58 + background1.mapY, 73 + background1.mapX, 58 + background1.mapY);
  Sprites::drawSelfMasked(playerX, playerY, playerSprite, frame);

  for (int x = 0; x < worldWidth; x = x + tileSize ) {
    //For each row in the column
    for (int y = 0; y < worldHeight; y = y + tileSize) {
      //Draw a background tile
      Sprites::drawSelfMasked(x + background1.mapX, y + background1.mapY, backgroundTile1, 0 );
      Sprites::drawSelfMasked(x + background2.mapX2, y + background2.mapY2, backgroundTile2, 0 );
      Sprites::drawSelfMasked(x + background3.mapX3, y + background3.mapY3, backgroundTile3, 0 );
    }
  }
  if (!arduboy.pressed(UP_BUTTON) && heightCounter >= 1) {
    --heightCounter;
    if (heightCounter <= 20) {
      ++playerY;
    }
    if (heightCounter >= 20) {
      background1.mapY -= 1;
      background2.mapY2 -= 2;
      background3.mapY3 -= 3;
    }
  }
  if (arduboy.pressed(UP_BUTTON)) {
    ++heightCounter;
    if (heightCounter <= 20) {
      --playerY;
    }
    if (heightCounter >= 20) {
      background1.mapY += 1;
      background2.mapY2 += 2;
      background3.mapY3 += 3;
    }
    playerSprite = playerUp;
    ++frame;
    if (frame > 3) {
      frame = 0;
    }
  }
  if (arduboy.pressed(LEFT_BUTTON) && playerX >= 2) {
    background1.mapX += 1;
    background2.mapX2 += 2;
    background3.mapX3 += 3;
    playerSprite = playerLeft;
    ++frame;
    if (frame > 3) frame = 0;
  }
  if (arduboy.pressed(RIGHT_BUTTON) && playerX <= 120) {
    background1.mapX -= 1;
    background2.mapX2 -= 2;
    background3.mapX3 -= 3;
    playerSprite = playerRight;
    ++frame;
    if (frame > 3) frame = 0;
  }
  if (!arduboy.pressed(UP_BUTTON) && !arduboy.pressed(DOWN_BUTTON) && !arduboy.pressed(LEFT_BUTTON) && !arduboy.pressed(RIGHT_BUTTON)) {
    frame = 0;
  }
  arduboy.display();
}

EDIT: Also, i looked at your program but couldnt really make any sense of it (yet), but actually remembered playing it at some point, was really cool!

1 Like
(Andrew Crawford) #6

Sorry, dont mean to spam, just fixed the background placement (because it was generating height the opposite direction I wanted) so that looks much much better, added a working fuel bar, an arrow that points towards the launch pad when its offscreen, and added game states… nothing really useful yet, just a gamestate for the launch part up to a certain height, then the gamestate changes to space and you dont get pulled down (but the altitude remains the same or can still increment up).

Dont mean to get too ahead of myself before i can probably organize things better (and dont mean to shift focus from the other game/take up others’ time and energy on this one on top of it), just an update on progress cuz im excited. Will probably redirect my attention back to my first game tomorrow though because i dont want to neglect working on it.

#include <Arduboy2.h>
Arduboy2 arduboy;

uint8_t gamestate = 0;

uint16_t heightCounter = 0;
struct Timer {
  unsigned long currentMillis;
  unsigned long previousMillis = 0;
};

struct PlayerXY {
  uint8_t playerX = 63;
  uint8_t playerY = 50;
};

struct FuelBar {
  uint8_t fuelBarX = 0;
  uint8_t fuelBarY = 20;
  uint8_t fuelBarHeight = 30;
  uint8_t fuelBarWidth = 5;
  uint16_t fuelRate = 800;

};

struct Background1 {
  int mapX = 0;
  int mapY = -64;
};

struct Background2 {
  int mapX2 = 0;
  int mapY2 = -64;
};

struct Background3 {
  int mapX3 = 0;
  int mapY3 = -64;
};

Timer timer;
PlayerXY playerXY;
FuelBar fuelBar;
Background1 background1;
Background2 background2;
Background3 background3;


constexpr int worldWidth = 296;
constexpr int worldHeight = 128;
constexpr int tileSize = 64;
uint8_t const *playerSprite = nullptr;

PROGMEM const unsigned char playerUp[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 9
  9, 9,
  0x00, 0x00, 0xE0, 0x7C, 0x47, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x00, 0xE0, 0x7C, 0xC7, 0x7C, 0xE0, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char playerLeft[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 16
  9, 9,
  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x1C, 0x08, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x90, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x01, 0x06, 0x2A, 0x74, 0xA8, 0x3C, 0x48, 0x10, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char playerRight[] = {
  // Bitmap Image. No transparency
  // Width: 9 Height: 16
  9, 9,
  0x00, 0x10, 0x08, 0x1C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x10, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x90, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

  0x00, 0x10, 0x48, 0x3C, 0xA8, 0x74, 0x2A, 0x06, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char backgroundTile1[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char backgroundTile2[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

PROGMEM const unsigned char backgroundTile3[] = {
  // Bitmap Image. No transparency
  // Width: 64 Height: 64
  64, 64,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

void setup() {
  arduboy.boot();
  arduboy.setFrameRate(10);
  playerSprite = playerUp;
  arduboy.clear();
}

uint8_t frame = 0;

void loop() {

  if (!arduboy.nextFrame()) {
    return;
  }
  switch (gamestate) {
  case 0:

  timer.currentMillis = millis();
  arduboy.clear();
  arduboy.print("alt.");
  arduboy.print('\n');
  arduboy.print(heightCounter);
  arduboy.print("00");
  arduboy.fillRect(fuelBar.fuelBarX, fuelBar.fuelBarY, fuelBar.fuelBarWidth, fuelBar.fuelBarHeight);
  arduboy.drawLine(60 + background1.mapX, 122 + background1.mapY, 73 + background1.mapX, 122 + background1.mapY);
  Sprites::drawSelfMasked(playerXY.playerX, playerXY.playerY, playerSprite, frame);

  for (int x = 0; x < worldWidth; x = x + tileSize ) {
    //For each row in the column
    for (int y = 0; y < worldHeight; y = y + tileSize) {
      //Draw a background tile
      Sprites::drawSelfMasked(x + background1.mapX, y + background1.mapY, backgroundTile1, 0 );
      Sprites::drawSelfMasked(x + background2.mapX2, y + background2.mapY2, backgroundTile2, 0 );
      Sprites::drawSelfMasked(x + background3.mapX3, y + background3.mapY3, backgroundTile3, 0 );
    }
  }
  if (!arduboy.pressed(UP_BUTTON) && heightCounter >= 1) {
    --heightCounter;
    if (heightCounter <= 20) {
      ++playerXY.playerY;
    }
    if (heightCounter >= 20) {
      arduboy.fillTriangle(63 + background1.mapX, 50, 70 + background1.mapX, 50, 66 + background1.mapX,55);
      background1.mapY -= 1;
      background2.mapY2 -= 2;
      background3.mapY3 -= 3;
    }
  }
  if (arduboy.pressed(UP_BUTTON)) {
    ++heightCounter;
    if ((timer.currentMillis - timer.previousMillis >= fuelBar.fuelRate && fuelBar.fuelBarHeight >= 1)) {
      ++fuelBar.fuelBarY;
      --fuelBar.fuelBarHeight;
      timer.previousMillis = timer.currentMillis;
    }
    if (heightCounter <= 20) {
      --playerXY.playerY;
    }
    if (heightCounter >= 20) {
      arduboy.fillTriangle(63 + background1.mapX, 50, 70 + background1.mapX, 50, 66 + background1.mapX,55);
      background1.mapY += 1;
      background2.mapY2 += 2;
      background3.mapY3 += 3;
    }
    playerSprite = playerUp;
    ++frame;
    if (frame > 3) {
      frame = 0;
    }
  }
  if (arduboy.pressed(LEFT_BUTTON) && playerXY.playerX >= 2) {
    background1.mapX += 1;
    background2.mapX2 += 2;
    background3.mapX3 += 3;
    playerSprite = playerLeft;
    ++frame;
    if (frame > 3) frame = 0;
  }
  if (arduboy.pressed(RIGHT_BUTTON) && playerXY.playerX <= 120) {
    background1.mapX -= 1;
    background2.mapX2 -= 2;
    background3.mapX3 -= 3;
    playerSprite = playerRight;
    ++frame;
    if (frame > 3) frame = 0;
  }
  if (!arduboy.pressed(UP_BUTTON) && !arduboy.pressed(DOWN_BUTTON) && !arduboy.pressed(LEFT_BUTTON) && !arduboy.pressed(RIGHT_BUTTON)) {
    frame = 0;
  }
if (heightCounter >= 100){
  background1.mapX = 0;
  background1.mapY = -64;
  background2.mapX2 = 0;
  background2.mapY2 = -64;
  background3.mapX3 = 0;
  background3.mapY3 = -64;
  gamestate = 1;
}
break;

case 1:
  arduboy.clear();
  timer.currentMillis = millis();
  arduboy.print("alt.");
  arduboy.print('\n');
  arduboy.print(heightCounter);
  arduboy.print("00");
  arduboy.fillRect(fuelBar.fuelBarX, fuelBar.fuelBarY, fuelBar.fuelBarWidth, fuelBar.fuelBarHeight);
  Sprites::drawSelfMasked(playerXY.playerX, playerXY.playerY, playerSprite, frame);
  for (int x = 0; x < worldWidth; x = x + tileSize ) {
    //For each row in the column
    for (int y = 0; y < worldHeight; y = y + tileSize) {
      //Draw a background tile
      Sprites::drawSelfMasked(x + background1.mapX, y + background1.mapY, backgroundTile1, 0 );
      Sprites::drawSelfMasked(x + background2.mapX2, y + background2.mapY2, backgroundTile2, 0 );
      Sprites::drawSelfMasked(x + background3.mapX3, y + background3.mapY3, backgroundTile3, 0 );
    }
  }
  if (arduboy.pressed(UP_BUTTON)) {
    ++heightCounter;
    if ((timer.currentMillis - timer.previousMillis >= fuelBar.fuelRate && fuelBar.fuelBarHeight >= 1)) {
      ++fuelBar.fuelBarY;
      --fuelBar.fuelBarHeight;
      timer.previousMillis = timer.currentMillis;
    }
    if (heightCounter <= 20) {
      --playerXY.playerY;
    }
    if (heightCounter >= 20) {
      background1.mapY += 1;
      background2.mapY2 += 2;
      background3.mapY3 += 3;
    }
    playerSprite = playerUp;
    ++frame;
    if (frame > 3) {
      frame = 0;
    }
  }
  if (arduboy.pressed(LEFT_BUTTON) && playerXY.playerX >= 2) {
    background1.mapX += 1;
    background2.mapX2 += 2;
    background3.mapX3 += 3;
    playerSprite = playerLeft;
    ++frame;
    if (frame > 3) frame = 0;
  }
  if (arduboy.pressed(RIGHT_BUTTON) && playerXY.playerX <= 120) {
    background1.mapX -= 1;
    background2.mapX2 -= 2;
    background3.mapX3 -= 3;
    playerSprite = playerRight;
    ++frame;
    if (frame > 3) frame = 0;
  }
  if (!arduboy.pressed(UP_BUTTON) && !arduboy.pressed(DOWN_BUTTON) && !arduboy.pressed(LEFT_BUTTON) && !arduboy.pressed(RIGHT_BUTTON)) {
    frame = 0;
  }
  break;
}
  arduboy.display();
}
1 Like
(Simon) #7

In your code …

struct Background1 {
  int mapX = 0;
  int mapY = -64;
};

struct Background2 {
  int mapX2 = 0;
  int mapY2 = -64;
};

struct Background3 {
  int mapX3 = 0;
  int mapY3 = -64;
};

...

Background1 background1;
Background2 background2;
Background3 background3;

You could simply have:

struct Background {
  int mapX = 0;
  int mapY = -64;
};

...

Background background1;
Background background2;
Background background3; 

It would make the code much simpler. Without wanting to sound rude, I am wondering if you are understanding the struct properly?

1 Like
(Andrew Crawford) #8

Ahh, okay, apparently I wasn’t understanding them, thank you! I was under the impression you needed a separate struct for each set of objects, now I see you can just make one and declare them separately (which makes sense because I forgot classes work in this way almost like a sort of template), I’ll go back through and I’m sure that might simplify a lot, thank you!

1 Like
(Pharap) #9

Bear with me, I’m writing a bit of a novel…

What @filmote just said is the first thing I started writing about.
Except I also recommend using an array and using Point instead of writing your own struct in this case.

1 Like
(Pharap) #10

I’ll list all the good stuff first otherwise I’ll forget and my comment will probably seem really negative.

Good things:

  • Good use of constexpr
  • nullptr is being used.
  • The new names are better overall.
  • Good thinking to introduce a Timer struct
  • Good thinking to introduce a FuelBar struct

When you get to the point of understanding member functions,
you’ll be able to make your structs more powerful.
Particularly your Timer and FuelBar.

Minor issues:

  • Instead of just frame you should specify what frame is for. E.g. playerSpriteFrame or playerFrame
  • Instead of setting playerSprite in setup you could be assigning it where it’s defined if you move the images further up
  • Technically you should have a tileWidth and a tileHeight rather than just a tileSize because it would give you more flexibility and would make the code a tad clearer, but I don’t think you’re likely to have non-square tiles, so it really is a minor thing

Onto the more important stuff and the stuff that’s going to need more explaining…

First thing’s first, you need to start breaking your code up into functions because your loop function is starting to get cluttered.
You could move your drawing logic to a draw() (or render()) function, your movement handling code to an update() (or handleInput()) function and possibly move your up and down code to moveUp() and moveDown() functions.

Secondly, you should really be updating before you draw rather than the other way around, otherwise you’re drawing the previous state on the current frame.

I’ll collapse the following things into details blocks because the code examples take up quite a bit of space.

Use of structures

This is an improvement, but you’re missing the point slightly.

You ought to be doing something like this:

// Can't call it 'Point' because it would clash with
// the 'Point' from <Arduboy2.h>
struct PointS
{
	int16_t x;
	int16_t y;
};

PointS background[3] { { 0, -64 }, { 0, -64 }, { 0, -64 } };

Or if you aren’t happy with arrays yet:

// Can't call it 'Point' because it would clash with
// the 'Point' from <Arduboy2.h>
struct PointS
{
	int16_t x;
	int16_t y;
};

PointS background0 { 0, -64 };
PointS background1 { 0, -64 };
PointS background2 { 0, -64 };

(Really they ought to be backgroundPosition rather than just background, but I’ll keep this simple.)

The aim of a class/struct isn’t just to group data,
it’s also to reduce redundancy by creating a reusable type.

Ultimately the idea of OOP is for objects in the code to act as a representation of an actual object.
Where a lot of beginners go wrong with objects (and it’s usually the fault of their teachers) is to think of objects as corresponding with real world objects.
Objects are supposed to represent conceptual objects, like a point in 2D space, a 2D image, or a record of someone’s contact details.
It can take quite a bit of time to understand the idea fully because it’s something you have to experience to get the hang of, but that’s the fundamental idea of it.

You could be using Point from Arduboy2 instead of introducing a PointS.
I just added the PointS to illustrate how such a type would be defined.
Arduboy2’s Point also uses int16_t, but it has some extra ‘constructors’.

FuelBar

Continuing the theme of reducing redundancy:

struct FuelBar {
  uint8_t fuelBarX = 0;
  uint8_t fuelBarY = 20;
  uint8_t fuelBarHeight = 30;
  uint8_t fuelBarWidth = 5;
  uint16_t fuelRate = 800;
};

The word fuel is a bit overused here.

You could simply have:

struct FuelBar
{
  uint8_t x = 0;
  uint8_t y = 20;
  uint8_t width = 5;
  uint8_t height = 30;
  uint16_t rate = 800;
};

And instead of assigning defaults to the struct,
you can just populate the bar itself later.

struct FuelBar
{
	uint8_t x;
	uint8_t y;
	uint8_t width;
	uint8_t height;
	uint16_t rate;
};

Then instead of:

FuelBar fuelBar;

You do:

FuelBar fuelBar { 0, 20, 5, 30, 800 };

And instead of:

arduboy.fillRect(fuelBar.fuelBarX, fuelBar.fuelBarY, fuelBar.fuelBarWidth, fuelBar.fuelBarHeight);

You write:

arduboy.fillRect(fuelBar.x, fuelBar.y, fuelBar.width, fuelBar.height);

To be honest I’m not exactly sure what fuelRate is supposed to be.
There’s probably a better name for it, but I’m not quite sure what it’s doing.

The height and width of the world

Instead of doing:

for (int x = 0; x < worldWidth; x = x + tileSize ) {
	//For each row in the column
	for (int y = 0; y < worldHeight; y = y + tileSize) {
		//Draw a background tile
		Sprites::drawSelfMasked(x + background1.mapX, y + background1.mapY, backgroundTile1, 0 );
		Sprites::drawSelfMasked(x + background2.mapX2, y + background2.mapY2, backgroundTile2, 0 );
		Sprites::drawSelfMasked(x + background3.mapX3, y + background3.mapY3, backgroundTile3, 0 );
	}
}

It would be better to have the world width measured in tiles because it would allow you to change your tile size and would make certain calculations easier.

Your draw loop would then become something like this:

for (int x = 0; x < worldWidth; ++x)
{
	// Calculate x offset
	const int offsetX = (x * tileSize);
	
	// For each row in the column
	for (int y = 0; y < worldHeight; ++y)
	{
		// Calculate y offset
		const int offsetY = (y * tileSize);
		
		// Draw a background tile
		Sprites::drawSelfMasked(offsetX + background0.x, offsetY + background0.y, backgroundTile1, 0);
		Sprites::drawSelfMasked(offsetX + background1.x, offsetY + background1.y, backgroundTile2, 0);
		Sprites::drawSelfMasked(offsetX + background2.x, offsetY + background2.y, backgroundTile3, 0);
	}
}

Or, if you used an array of points for your backgrounds and merged the images together to make use of Sprites's frame functionality, you could do this:

for (int x = 0; x < worldWidth; ++x)
{
	// Calculate x offset
	const int offsetX = (x * tileSize);
	
	// For each row in the column
	for (int y = 0; y < worldHeight; ++y)
	{
		// Calculate y offset
		const int offsetY = (y * tileSize);
		
		// Draw background tiles
		for(size_t index = 0; index < 3; ++index)
			Sprites::drawSelfMasked(offsetX + background[index].x, offsetY + background[index].y, backgroundTiles, index);
	}
}

It’s probably slightly slower, but that shouldn’t be an issue.
(It might also use less progmem.)


You could take this a step further and do:

for (int x = 0; x < worldWidth; ++x)
{
	// Calculate x offset
	const int offsetX = (x * tileSize);
	
	// For each row in the column
	for (int y = 0; y < worldHeight; ++y)
	{
		// Calculate y offset
		const int offsetY = (y * tileSize);
		
		// Draw background tiles
		for(size_t index = 0; index < 3; ++index)
		{
			const int drawX = (offsetX + (background[index].x * static_cast<int>(index)));
			const int drawY = (offsetY + (background[index].y * static_cast<int>(index)));
			Sprites::drawSelfMasked(drawX, drawY, backgroundTiles, index);
		}
	}
}

Which would allow you to avoid doing:

background1.mapY -= 1;
background2.mapY2 -= 2;
background3.mapY3 -= 3;

And then you could just maintain a single pair of coordinates for all the background because you’d doing the scaling in the drawing rather than when you’re actually moving them.
I.e.

for (int x = 0; x < worldWidth; ++x)
{
	// Calculate x offset
	const int offsetX = (x * tileSize);
	
	// For each row in the column
	for (int y = 0; y < worldHeight; ++y)
	{
		// Calculate y offset
		const int offsetY = (y * tileSize);
		
		// Draw background tiles
		for(size_t index = 0; index < 3; ++index)
		{
			const int drawX = (offsetX + (backgroundOffset.x * static_cast<int>(index + 1)));
			const int drawY = (offsetY + (backgroundOffset.y * static_cast<int>(index + 1)));
			Sprites::drawSelfMasked(drawX, drawY, backgroundTiles, index);
		}
	}
}

But it depends whether or not you’ll always have the background scales at 1, 2 and 3.
If you think you might change that (e.g. have 1, 2 and 4) then don’t bother with this.

Lastly, instead of doing:

++frame;
if (frame > 3) frame = 0;

You could pre-empt the change and do:

if (frame < 3)
	++frame;
else
	frame = 0;

I can’t remember whether there’s a progmem difference,
but there is a logical difference.
If 3 was 255 then the former code would have a bug that would mean it wouldn’t work,
but the latter code would still work perfectly.


There’s a better way of doing gamestate, but I think I’ll have to leave that for another comment because this comment is already huge and I need to have lunch.

If you can’t wait, search the forum for enum class and filter to comments made by me and you’ll probably find the same explanation given half a dozen times to different people.

2 Likes
(Andrew Crawford) #11

Ah, thank you! I really don’t find a lot of criticism a negative thing at all, especially with my level of inexperience it’s basically invaluable, but I also don’t mean to take up too much of anyone’s time or resources hand holding either like I said (especially if you’ve already done it before) or if you just can’t afford the time/energy in general, so I apologize if that’s ever the case.

But I’m glad you told me that about functions because that’s something I had some idea I was lacking, just got kind of buried under the other stuff I didn’t know yet and forgot to go back to it. But I’ll do my homework here again and get things better organized, thanks again!

1 Like
(Scott) #12

Why not just use Point from Arduboy2? It has the same definition.

(Pharap) #13

I did mention that:

And technically the definition isn’t the same,
Point has an additional 2-argument constructor,
which makes the semantics of construction slightly different.

(Pharap) #14

Perhaps so, but I know I can be a bit overcritical at times.
When it comes to code I don’t like settling for second best,
I’m always thinking “is there a better way to do this?”.
I’m also not very good at remembering to tell people “you’ve done a good job”.
(And that goes double for myself.)

Look at it this way: every time someone provides you with advice,
that advice is then available to the whole forum.

So really it’s helping other people too, not just you.

(And failing that, at least @Botisaurus likes seeing me preaching about C++ all day. :P)

Energy isn’t a problem, I could jabber on about the ins and outs of programming for days.

Time can be though.
(There are projects I should be working on that I keep putting off because they’re boring and difficult.)

Programming is a vast and complicated thing.

It may only take a few months to get to a point where you can do a lot of cool things with it,
but it takes at least a few years to get genuinely good at it.

I think a lot of people are afraid to say that because they don’t want to put people off, but it’s true.
However, that’s true for a lot of things.
It’s true for learning an instrument.
It’s true for learning craftsmanship skills like woodworking or upholstering.

I think the difference with programming though is that there’s a lot of different tools involved,
and they’re all intertwined.
A program is like a big machine full of loads of different gears and cogs (objects and functions),
so it can be difficult to break it down into individual parts.

I’m starting to get philosophical and rambly,
so I’ll stop there before I’ve suddenly written another paragraph.

3 Likes
(Andrew Crawford) #15

Well thanks again, I certainly appreciate it, just don’t mean to clog up the threads too much or make people read between the two programs just because ive had the time on my hands lately (as I’m sure you’ve noticed ;P) I just start classes in a month and have been jobless looking for part time work for during school, unfortunately.

Spent the last 5 years in a job field that made me miserable but had my sights on this sort of stuff for the last few, just had a hard time getting started with the right momentum til more recently and know I won’t have as much time coming up, plus having been worn out and frustrated by things a long time even just the little bits of progress (and especially help) have gone a long way, both in fulfillment and information, don’t mean to be overzealous.

And I can especially appreciate a ‘better way to do it’ approach as an approach to learning it, that’s what got me interested in this sort of thing initially was that I have more of a problem solving type learning style and approach (and with microcontroller hardware and software you can do nearly anything), not to mention that I’ve admired a lot of people’s work on here from afar for the last couple years and have a pretty high amount of respect/appreciation for you guys and your work.

Anyway, sorry to get kind gooey for a minute, was just thinking to give a more sincere thanks anyway, but I’ve got plenty more homework to get back to :stuck_out_tongue:

1 Like
(Boti Kis) #16

Of course I do!
Because:

:v::heart:

2 Likes
#18

Not just him. I bow for you oh great C++ master :pray::nerd_face:

4 Likes
(Andrew Crawford) #19

Sorry, I know this is a very basic question, I just obviously don’t know and haven’t been able to find a clear answer so I’m asking… but if I made a function that modified the variable within it, would I still need a return value? All of the examples I can find use separate variables for input and output so I wasn’t sure, but I was thinking something like

void mapscrollUp(){
  background1XY.pointX -= 1;
  background1XY.pointX -= 2;
  background1XY.pointX -= 3;
}

and just calling it each time I wanted it to scroll, but I’m not sure if it would work with no return value/type.

Also, I got everything fixed using fewer structs (and removed the gamestate to get rid of clutter), but still need to fix the frame increment and progmem (which I will do now/before attempting to add any functions).

(Pharap) #20

You say sorry quite a lot, are you British by any chance? :P

That doesn’t make it any less important.

If it’s a global variable then no.
If it’s a local variable then yes, if you want to use the value outside the function.

The example you gave would presumably work because background1XY is presumably either a global variable or a member variable.

Having a gamestate variable as you had isn’t a bad idea,
it’s just that there’s a better way to do it than using bare integers.

When you’re ready to add it back in,
I’ll explain about enum classes (‘unscoped enumerations’ to give them their technical name).
(One of the examples I could find already on the forum is here. And there’s another example here.)

1 Like
(Andrew Crawford) #21

Ah, thank you! Also, I scrolled up and somehow missed your bullet point about the fuel bar (which contained a lot of much better info for populating the struct and removing name redundancy, so thanks for that) I was definitely just confused about the object oriented part, was able to follow along to degree but seeing a lot of variables named ‘x’ in someone else’s program when i knew less about what I was looking at was just confusing :stuck_out_tongue: Also, the fuel rate was because the bar was moving too fast and I was able to slow it down that way by checking if the appropriate length of time had elapsed.

Just because I was late on that I still have some more redundancy to remove before making any more of a mess, but before I get into it, I’m looking at most of my code and it seems like I can simplify it significantly just by moving some things into their own functions then calling them where they are redundant, but is it really as simple as it seems or am I missing something else? :stuck_out_tongue:

Thanks again!

1 Like