Help With Game Develeopment

You could leave the gun out of the sprite you drew and instead use drawLine, fillRect, fillRoundRect, etc. whatever fits the shape the most to draw the gun over the sprite. Changing the x&y values with user impute would then redraw the shape as it “moves”. I’m assuming this is from a side angle and not top down since you said up/down

arduboy.drawBitmap(0,0 playField, 128, 64);
arduboy.drawLine(x1, y1, x2, y2, WHITE);
if( arduboy.justPressed(UP_BUTTON) == true){
      y2++;
}
if( arduboy.justPressed(DOWN_BUTTON) == true){
      y2--;
}`

So it took me a few minutes to figure out that the “drawLine” function needed a color assigned XD, but otherwise, it is a much better solution that what i had before. Greatly reduced my overall storage usage.

In case anyone wants to look at it, here is what I have so far. It’s pretty much just the code to display the images and move the gun on the tower. I am brand new to C++, having spent all of thirty minutes going through the tutorials, and maybe a total of 90 minutes actually working on this XD. Any suggestions or comments are greatly appreciated!

//ThaddeusSM
//03/16/18

//Libraries
#include <Arduboy2.h>
Arduboy2 arduboy;

//Variables
const unsigned char titleScreen[] PROGMEM = { 
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x1f, 0xf, 0x8f, 0xc7, 0xc7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf1, 0xf1, 0xf1, 0xe1, 0xc3, 0x87, 0x8f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x8f, 0x87, 0xc3, 0xe1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xe3, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xc7, 0xc7, 0x8f, 0xf, 0x1f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x3, 0x80, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x3f, 0x3, 0x3, 0x3, 0x3, 0x3f, 0x3f, 0x3f, 0x3, 0x3, 0x3, 0x3, 0x3f, 0x3f, 0x3f, 0x3, 0x3, 0x3, 0x3, 0x3f, 0x3f, 0x3f, 0x3, 0x3, 0x3, 0x3, 0x3f, 0x3f, 0x3f, 0x3, 0x3, 0x3, 0x3, 0x3f, 0x3f, 0x1f, 0xf, 0x7, 0x3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x80, 0x3, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x7, 0x00, 0xe0, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xe2, 0xe2, 0x6, 0x6, 0xdc, 0xc0, 0x9e, 0x5e, 0xc0, 0xdc, 0xdc, 0x1c, 0xd0, 0x80, 0x1c, 0xc0, 0x9c, 0x9c, 0x9c, 0x1c, 0x1c, 0x9c, 0x9c, 0x9c, 0xc0, 0xdc, 0xdc, 0xdc, 0x1c, 0xdc, 0xdc, 0xc0, 0xde, 0xde, 0xde, 0xde, 0x6, 0x6, 0xe2, 0xe2, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xe0, 0x00, 0x7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7, 0x00, 0xf0, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1, 0xf7, 0x6, 0x21, 0xc3, 0xe7, 0xc0, 0xb7, 0x77, 0x64, 0xe9, 0xe7, 0xef, 0xcf, 0x00, 0x00, 0xef, 0xef, 0xef, 0xef, 0xe7, 0xf7, 0xf7, 0xf0, 0xf7, 0xf7, 0xf7, 0x7, 0xb7, 0x1, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0xbf, 0xbf, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf0, 0x00, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x9f, 0x9f, 0x8f, 0x87, 0xc7, 0xe1, 0xe0, 0xfc, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x7f, 0xbf, 0xbf, 0xbf, 0x7f, 0xff, 0x7f, 0x3f, 0xbf, 0x3f, 0x7f, 0x1, 0xff, 0x7f, 0xbf, 0xbf, 0xbf, 0x7f, 0xff, 0x3f, 0x7f, 0xbf, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x3e, 0xbc, 0xb2, 0xae, 0x80, 0xbe, 0xbe, 0xbe, 0x3c, 0x3c, 0x00, 0x5d, 0x00, 0x00, 0x7d, 0x3d, 0xbd, 0xbc, 0x2, 0xb8, 0xbc, 0x80, 0xbc, 0xbe, 0xbe, 0x3e, 0xa2, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xef, 0xef, 0xef, 0xef, 0x00, 0xff, 0xef, 0x1, 0xef, 0xff, 0xef, 0x1, 0xef, 0xff, 0x7f, 0xbf, 0xbf, 0xbf, 0x7f, 0x3f, 0xff, 0x7f, 0xbf, 0xbf, 0xff, 0x1, 0xff, 0x7f, 0xbf, 0xff, 0xff, 0xfc, 0xe0, 0xe1, 0xc7, 0x87, 0x8f, 0x9f, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xfc, 0xf9, 0xfb, 0xf9, 0xfc, 0xf8, 0xff, 0xfc, 0xfa, 0xfa, 0xfa, 0xfa, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x00, 0x00, 0xf0, 0xf6, 0xf7, 0xf0, 0xf7, 0xf7, 0xf7, 0x7, 0xf7, 0xf7, 0xe7, 0xef, 0x6f, 0x28, 0x43, 0x00, 0x00, 0xcf, 0xcf, 0xcf, 0xef, 0xe0, 0xf7, 0xf7, 0x7, 0xf7, 0xf7, 0xf7, 0xf0, 0xf7, 0xf6, 0xf0, 0x00, 0x00, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xfc, 0xfb, 0xfb, 0xfb, 0xfc, 0xf8, 0xff, 0xfc, 0xfb, 0xfb, 0xff, 0xf8, 0xfe, 0xfd, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xdf, 0xdf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x7f, 0xff, 0x3f, 0x9f, 0xdf, 0x9f, 0x3f, 0xff, 0x7f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x7, 0x3, 0x1, 0x00, 0x00, 0x00, 0x30, 0xb8, 0x3d, 0x9d, 0x9d, 0x81, 0xad, 0xb5, 0x81, 0x38, 0xbd, 0x3d, 0xbc, 0x80, 0xbd, 0xbc, 0xb1, 0xa4, 0x8c, 0x1d, 0xbd, 0xbd, 0x81, 0xbd, 0x3d, 0xbd, 0xbc, 0xbd, 0xbd, 0xbd, 0x81, 0xbd, 0xbd, 0x3d, 0xb8, 0xb0, 0x80, 0x00, 0x00, 0x1, 0x3, 0x7, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xfd, 0xfd, 0xfe, 0x83, 0xf7, 0xfb, 0xf7, 0xff, 0xc7, 0xab, 0xff, 0xa7, 0xab, 0xdb, 0xff, 0xa7, 0xab, 0xdb, 0xff, 0xff, 0xff, 0xff, 0x80, 0xfb, 0xfb, 0xfb, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xf0, 0xf7, 0xf7, 0x7, 0xe0, 0xe7, 0x7, 0xf3, 0x3, 0x73, 0x4, 0xf6, 0xf7, 0xf0, 0x7, 0xf7, 0xf7, 0xf7, 0x7, 0xf7, 0xf7, 0x00, 0xf7, 0xe7, 0xe7, 0x7, 0xd0, 0xd7, 0xb7, 0x7, 0x97, 0xd7, 0xb7, 0x7, 0x27, 0xe0, 0x7, 0xf7, 0xf7, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
};
const unsigned char PROGMEM Gameplay1[] =
{
// width, height,
128, 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, 
0xff, 0x7f, 0x3e, 0x18, 0x18, 0xf8, 0x1e, 0x1f, 0x3f, 0x7e, 0xf8, 0xf8, 0xf8, 0x3e, 0x1f, 0x07, 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, 
0x04, 0xfc, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0xfc, 0x04, 0x0f, 0xff, 0xf0, 0x80, 0x80, 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, 
0x59, 0xc9, 0x49, 0x49, 0x49, 0x7f, 0x51, 0x51, 0x59, 0xc9, 0x49, 0x49, 0xff, 0xff, 0xa2, 0xa2, 0xff, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x10, 0x1f, 0x10, 0x10, 0x10, 0xf0, 0x10, 0x10, 0x10, 0x1f, 0x10, 0x10, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0xfc, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0xfc, 0x04, 0x04, 0x04, 0x05, 0x07, 0x07, 0x0e, 0x1c, 0xfc, 0xf8, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x0c, 0x0f, 0x4c, 0x8c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0c, 0x0c, 0x8c, 0x8c, 0x0c, 0x4c, 0x0c, 0x0e, 0x0f, 0x4f, 0x0f, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x88, 0x48, 0x48, 0x48, 0x48, 0x08, 0x08, 0x08, 0x08, 0x08, 0xc8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xc8, 0x88, 0x48, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x48, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x88, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xc8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x48, 0x08, 0x08, 0x08, 0x08, 0x08, 0x88, 0x88, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
0x00, 0x00, 0x08, 0x18, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x20, 0x21, 0x60, 0x00, 0x00, 0x04, 0x03, 0x04, 0x04, 0x00, 0x40, 0x20, 0x00, 0x00, 0x0e, 0x08, 0x06, 0x00, 0x22, 0x60, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x60, 0x20, 0x46, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x40, 0x00, 0x30, 0x0c, 0x40, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 0x10, 0x20, 0x28, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x01, 0x10, 0x50, 0x00, 0x05, 0x04, 0x00, 0x00, 0x1c, 0x30, 0x00, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x84, 0x04, 0x04, 0x00, 0x70, 0x00, 0x03, 0x06, 0x00, 0x60, 0x00, 0x09, 0x01, 0x01, 0x01, 0x00, 0x04, 0x01, 0x21, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x20, 0x24, 0x06, 0x00, 
};



int gamestate = 0;
int justpressed = 0;
int x1 = 20;
int y1 = 28;
int x2 = 28;
int y2 = 28;

//Setup Script
void setup() {
  arduboy.begin();
  srand(7/8);
  arduboy.setFrameRate(30);
  arduboy.clear();
}

//Game Code
void loop() {
  if(!arduboy.nextFrame()) {
    return;
  }
  arduboy.clear();
  switch(gamestate){
    case 0:
    arduboy.drawBitmap(0, 0, titleScreen, 128, 64, WHITE);
    if(arduboy.pressed(A_BUTTON) and justpressed == 0) {
      justpressed = 1;
      gamestate = 1;
    }
      break;
    case 1:
    arduboy.drawBitmap(0, 0, Gameplay1, 128, 64, WHITE);
    arduboy.drawLine(x1, y1, x2, y2, WHITE);
    if(arduboy.pressed(A_BUTTON) and justpressed == 0) {
      justpressed = 1;
      gamestate = 0;
    }
    if(arduboy.pressed(UP_BUTTON)) {
      y2--;
    } 
    if(arduboy.pressed(DOWN_BUTTON)){
      y2++;
    }
    if(y2 > 40) {
      y2--;
    } else if(y2 < 14) {
      y2 ++;
    }
      break;
   }
  if(arduboy.notPressed(A_BUTTON)) {
    justpressed = 0;
  }


  arduboy.display();
}

Its looking good.

if(arduboy.pressed(UP_BUTTON)) {
   y2–;
}
if(arduboy.pressed(DOWN_BUTTON)){
   y2++;
}
if(y2 > 40) {
   y2–;
} 
else if(y2 < 14) {
   y2 ++;
}

[/quote]

In a couple of spots you have y2-; which should. be y2 - -;

The way you have implemented the gun looks a little strange as the gun stretches at the top and bottom of the arc. Currently you store X1/y1 and x2/y2 coordinates for the barrel and you can calculate a 1:n gradient and move the bullets forward 1: and up or down n each frame.

An alternate approach that makes the gun look a little better as it rotates through its arc is to actually not store the coordinates of the right hand side of the barrel but instead have an angle you increase / decrease with the A and B buttons. You could then calc the end point using a little trigonometry and get a better rendering.

The angle can then be used to calculate the gradient for the actual bullet movement.

I would change the bullet struct to look like this:

struct Bullet {
  uint8_t x;
  uint8_t y
  uint8_t xDelta;
  int8_t yDelta;
  bool active;
}

So when you launch the bullet you calculate the number of pixels you want the bullet to move each frame in both the X or Y axis and store them in the bullet struct. On each frame, loop through the bullets and for each active one, increase the X and Y by the delta. Y can be negative if they are shooting up in the air. As the bullet hots the ground or leaves the screen set it to inactive.

How can I change the way the gun rotates so that I can use the angle to calculate the bullet travel? Also, am I correct in assuming that I put the bullet struct code into my gameplay gamestate?

Edit: I looked at those places which showed one minus sign instead of two, it seems as though it was just the webpage that formatted it like that. Next time I share a big piece of code, I’ll upload it to github or something.

So your gun starts at X1 and Y1, right?

Define another variable that records the angle of the gun from say -30 degrees to 30 degrees above the horizon.

To calc the barrel end position, use the maths:

x2 = x1 + cos(angle) * barrelLength;
y2 = y1 + sin(angle) * barrelLength;

To the calc the XDelta and yDelta for the bullet, you can take the ratio of cos(angle) compared with sin(angle). When the angle is 45 degrees sin() and cos() will return the same value (0.707…) so the ration is 1:1 or 1 upward and 1 right movement per frame.

When the guns barrel is at 30 degrees, sin() returns 0.500 and cos() returns 0.866 which is a 1:1.732 ratio. Therefore for every 1.732 the bullet travels in the right direction, it travels one pixel in the Y direction.

The Arduboy sucks at sin / cos / tan and floating point in general.

Have a look at > Arduboy 3D demo and [WIP] 3D starfield Demo for discussion and code on how to do it in such a little environment.

@Pharap released a great little library for fixed point calculations if you find the math and rendering is too slow or two large (from a memory point of view) when using floating points. See here > A Fixed Point Arithmetic Library

Finally, shooting at arbitrary angles is probably one of the hardest things you can do on an Arduboy. Stick at it and ask questions!

If it all gets too hard, you can change the gun movement so it only moves between fixed, known angles - you can then have an array of the pre-calculated barrel end points and gradients. It will make the game easier to program but not quite as nice.

That makes sense as I simply couldn’t compile it and it was complaining about some unknown character at that point.

Alright, so i went ahead and installed @Pharap’s library, but I’m pulling a blank on what to do next. I have created the variable “gunAngle” for storing the angle of my gun; but I’m not sure how to measure said angle.

You don’t need to measure it, it just increases and decreases based on the players pressing the A and B button. Everything is then calculated from it.

Doesn’t your original code:

if(arduboy.pressed(UP_BUTTON)) {
   y2–;
}
if(arduboy.pressed(DOWN_BUTTON)){
   y2++;
}
if(y2 > 40) {
   y2–;
} 
else if(y2 < 14) {
   y2 ++;
}

Simply become:

#define MIN_GUN_ANGLE -30;
#define MAX_GUN_ANGLE 30;

if(arduboy.pressed(UP_BUTTON)) {
   gunAngle--
}
if(arduboy.pressed(DOWN_BUTTON)){
   gunAngle++;
}
if(gunAngle > MAX_GUN_ANGLE) {
   gunAngle = MAX_GUN_ANGLE;
} 
else if(gunAngle < MIN_GUN_ANGLE) {
   gunAngle = MIN_GUN_ANGLE;
}

I have used angles in degrees here but you may find that Radians work better in the Arduboy environment.

@Pharap’s library is a fixed point library but does not specifically address your situation. Unfortunately, you will still need to know how the maths works - google sin / cos / tan for an explanation.

Alright, I actually got it (sort of) working in my own code, but i think i better check out for now. Thanks for all of your help. I will continue working on it tomorrow.

No problem. Sorry my answers were a little ‘you could do this’ or ‘you could do that’ and they all led to areas that the Arduboy is not great at (floating point, sin / cos / tan) but if you get it right, the game will be great!

Suggestion 1:
Consider moving your images into a separate file and #include-ing that file.

Suggestion 2:
Avoid srand, use arduboy.initRandomSeed(),
unless you actually want the same random numbers each time.

Suggestion 3:
You don’t need your justPressed variable, Arduboy2 has a justPressed function, e.g. arduboy.justPressed(A_BUTTON)

Suggestion 4:
All the functions that take a colour are set to use WHITE by default if you don’t provide it so you could omit those if you wanted.

Suggestion 5:
Use &&, not and.
and is obscure and rarely used, and I’m pretty sure it only originally existed to provide support for computers that used a character encoding that didn’t have and ampersand (back in the days where computers used things other than ASCII and Unicode-based encodings).

Suggestion 6:
Instead of incrementing/decrementing y2 and then trying to correct it afterwards, avoid having to increment/decrement in the first place.
e.g.

if(arduboy.pressed(UP_BUTTON)) {
  if(y2 > 14) // y2 cannot go below 14
    y2--;
}
if(arduboy.pressed(DOWN_BUTTON)){
  if(y2 < 40) // y2 can only go up to 40
    y2++;
}

Incorporating @filmote’s gun angle code that becomes:

if(arduboy.pressed(UP_BUTTON)) {
  if(gunAngle > MIN_GUN_ANGLE)
    gunAngle--;
}
if(arduboy.pressed(DOWN_BUTTON)){
  if(gunAngle < MAX_GUN_ANGLE)
    gunAngle++;
}

Some other tips:

Tip 1:
Consider getting a Github account and posting your code there.
It makes it easier to ask for feedback without cluttering the forum with large blocks of code.

Tip 2:
If you do post code on the forum, format it using ` (graves).

For in-line code you can use single graves.
E.g. doing `this` would get you this

For blocks of code you can do:
```
this
```
Which becomes:

this

You can also specify the language by putting it after the first three graves, e.g.
```cpp
this
```
Becomes:

this

@ThaddeusSM, if you decide to try using fixed points,
I suggest you read A Fixed Point Primer first, to understand how they work.
Otherwise you might be a bit surprised by which numbers they can and can’t represent.

The short version is that they represent the stuff after the decimal point as a fraction over a power of two, so they have limited precision.
In the case of the Arduboy though, you don’t really need good precision because the screen is small.

I agree with @filmote here.
Working with angles almost always requires using fractional numbers (i.e. floating points or fixed points) and usually involves pi, trigonometry and other not very fun maths.

Personally I think this would be the best approach for a beginner to use.
(And for anyone who isn’t very good at maths, like me a few years ago.)

@ThaddeusSM, depending on how good your maths skills are and how much programming experience you have, you might want to do this instead. It won’t look as nice, but it would be easier to do and you wouldn’t have to do as much reading.

More importantly, look up “Unit Circle”.
I never fully understood sine or cosine until I saw a diagram of a unit circle.

In fact I think the explanation that worked for me was this one.
“Maths is fun” is my favourite website for maths stuff because it explains things in plain English instead of using a load of maths symbols that only experts understand anyway (like and and ).


(P.S. My ears are burning from all the @-mentions :P.)

No it doesn’t. If you leave off the color parameter for drawLine() (and the other drawing functions) it defaults to WHITE. That is, if you’re using the recommended Arduboy2 library, not the Ardbuboy library.

https://mlxxxp.github.io/documents/Arduino/libraries/Arduboy2/Doxygen/html/index.html

@ThaddeusSM,
I’ve done this for your previously posted code.

Thank you for pointing me to the unit circle! That helped. I think I’d like to go with the more complicated option, as I think the way the game feels and plays will be a big portion of the overall game, as there won’t be much story or anything like that.

I’ll make sure to fix all of things you pointed out as well.

So now that I know how to properly do the gun animation, how can I use that bullet struct @filmote showed me in my gameplay code? As in, how do I initialize the bullet and where do I plop in that segment of code?

Thanks!

1 Like

Well, here I am, couple hours later, asking for help on how to make an array of fixed points. The problem I am having is that in the current config the angle of the gun varies too wildly. When my ‘gunAngle’ variable is changed, since the gun is very small, an increment of just 1 increases the actual angle by maybe 40, so I either need to know how to change the variable by a decimal, or take the time to make the fixed angles.

Here is my current iteration of code;

I tried to make a separate file for the images, by looking at the way other games had done it, and i couldn’t get the IDE to recognize the file, even though the .ino and .h were in the same folder.

As for the justpressed thing, i found that my way of using the variable seemed faster and more reliable than the justPressed function.

Upload the code to your arduboy or emulator or whatever and you will quickly see what I mean about the angle increments.

I need to start spending more time before asking for help. I got it to work XD

Edit: i will just keep the github page up to date whenever i add something new.

@filmote, I have absolutely no idea where to start on launching the bullets. I see the struct in your earlier message, but I’m not sure where to put that or even how to use it. If you could point me to an article or give me some basic instructions on how to initialize said bullet, that would be awesome.

I’ve spent the past 30 minutes looking over 1943’s code, but I can’t find where to start with shooting the bullets. Thanks!

Alright, I went ahead and submitted one last revision for the day. I have a laser which fires (without looking super weird) when the gunAngle variable is at 0, 0.20, and 0.39. Putting in the others is just a matter of time. Thank you for all of your guy’s help on this! I really appreciate it.

I thought it would.
The unit circle is often overlooked when teaching trigonometry,
but I find it illustrates the meaning of sin and cos perfectly.

Firstly it’ll need a semicolon on the end,
and I think both 'delta’s are supposed to be signed:

struct Bullet
{
  uint8_t x;
  uint8_t y
  int8_t xDelta;
  int8_t yDelta;
  bool active;
};

(If you’re definitely going with fixed points, I’d suggest changing the types of x and y to UQ8x8 and xDelta and Delta to SQ7x8.)

You have to put this either at the top of your code, or in a separate header file that you then #include at the top of your code (e.g. #include "Bullet.h").

Then to initialise a bullet you can use value initialisation, e.g:

// Bullet at 32, 32, travelling right and up
Bullet bullet = { 32, 32, 1, -1, true };

You then have to handle the movement yourself by doing bullet.x += bullet.xDelta; and bullet.y += bullet.yDelta;.
You’ll probably want to do collision checks either immediately before, during or immediately after moving the bullets.

The same way you make an array of any type.
Declare with type name[size]; or initialise with type name[] = { values };

For example UQ8x8 values[10]; or UQ8x8 values[] = { 0.5, 1.4, 3.5 };

If you’re using a fixed point type or a floating point type, something like gunAngle += 0.25 will work.

Strange, it should be able to.
Were you using #include <Images.h> instead of #include "Images.h"?

That shouldn’t be the case.
Perhaps you weren’t calling arduboy.pollButtons()?
Or perhaps you were calling it at the top of loop() instead of after the if(!arduboy.nextFrame()) return; line?

The bullet arrays are declared here (EnemyBullet is effectively the same as Bullet).
The player bullets are ‘launched’ here.
Player bullets are moved and rendered here, the same is done for enemy bullets here.
The code for bullet.move is here.
I’m not quite sure where the collision checking is, but @filmote will probably be able to find that when he wakes up.

(In hindsight, separating the player and enemy bullets into two different classes makes no sense other than for conserving RAM.)

Lasers can be done by doing ray-box or ray-circle collisions,
but it’s been a while since I’ve done one of those so I can’t remember offhand how to do it, I’d have to look into it.
(I vaguely remember ray-circle being easier.)


The reason you haven’t had much feedback on this for several hours from either of us is that I’ve been busy sorting other stuff (mainly handling github issues and doing some work on another project) and @filmote’s been asleep since it was nighttime in Australia when you asked (at the time of posting this it’s morning, but only ~9am.)

(Also I only got a notification for your first comment.
People only get notifications for @-mentions, direct replies and having something they said quoted.)