Flapping Shooter Feedback & Tips

Hello All,
I’ve recently bought an Arduboy after years of watching this project and the games people have made for it. I have once again gotten the itch to (attempt to) develop a game which has been on my mind for 3 years.
In the most simplistic terms, it is a flappy bird shooter. I’ve made a few demos in Pico8, where I was pleased with the behavior of the players bat, but never completed the project.
Hopefully the attached concept art comes through. I am pretty happy with the look overall. The owl being the exception.

What do you guys think? After checking out Evade and Midway 1944, I think it is doable. My issue is that I am not super knowledgeable when it comes to programming, especially efficient programming. I do have some C++ knowledge from college, so I am not starting from nothing.

Open to collab if this strikes anyones fancy.

PNG file

  1. Bat shooting at flying snake boss, with obstacles
  2. Bat flapping. Skull and bird enemies
  3. Bat diving to avoid ghost, with obstacles
  4. Bat diving. Owl boss that shoots spinning rats. (Owl to be reworked and enlarged)

*edit to include demo 12/28/19
*edit to update demo 12/29/19
*edit to update demo 1/4/20 Thanks @Pharap!
*edit to update demo 1/9/20 (Enemy spawner!)
*edit to update demo 1/13/20 (semi-functional collisions)
*edit to update demo 1/24/20 corrected collisions, new enemy. title/game over screens have no graphics yet.

batandcollisions.ino.hex (35.1 KB)

6 Likes

Looks cool!

Cool idea, so you’d control the ship height by pushing a button and shoot with the other? Could work. I wish you the best on that project.

I almost get a Panzer Dragoon vibe with this…

2 Likes

Yes, one button provides an upwards boost and the other shoots the sonic balls.

The player continuously sinks as if in a glide. However, when the down button is pressed, you can dive at a faster rate. The dive prevents the player from getting trapped at the top of the screen by adding a quick method of descending.

I love the art! Nice work, keep going!

1 Like

Efficiency isn’t much of an issue on the Arduboy, the CPU runs fast enough that it’s difficult to write something that actually lags.

Memory is almost always the more important constraint.

How much do you remember learning about?
Datatypes, variables, functions, classes, pointers, references?

Also how important (to you) is the balance of making the game versus learning to program?

I’m happy to help you get started and offer some advice,
(particularly suggestions about how to implement gameplay features and knowledge about C++)
but I don’t think I could commit to working on it full time.

Thanks for the feedback, everyone!

As far as C++ goes, I am familiar with everything listed except pointers and references. I don’t think I have ever come across those, yet. I suppose I would classify my knowledge as basic, then?
I had not considered whether the game, or the programming was more important. With previous projects, I’ve just learned whatever was necessary to complete it, rather than learning for the sake of it. So, I would say that completion of the game is my primary goal, but I want to understand what’s under the hood for future projects.

1 Like

@Quickdrawkid I would worry too much about it if I were you, I made my first game on Arduboy with no knowledge of c++ prior and still got something decent I think. I just read the few tutorials here in this forum and ask people here for help when I needed. Even made a couple friends in the process!

If you are curious about my first game you can try it out here:
LoveRush - Cute Infinite Shooter

1 Like

It is slightly unusual to have experience with classes before pointers or references,
but personally I don’t think that’s necessarily a bad thing.

If you were programming for desktop then I’d say learn about references and don’t bother with pointers for a while, but on the Arduboy you need pointers to make more effective use of progmem because it relies on pointers.

Without knowledge of pointers you can still get by, but you’ll hit the memory ceiling faster.
So essentially you could start work on your game and not worry about pointers until you start to have memory issues, at which point you’d need to learn about both pointers and progmem to effectively use the Arduboy’s limited memory.

When it comes to programming, there’s rarely such thing as ‘learning for the sake of it’.
Every little detail has the potential to come in handy.

If you’d have said “just the game, I’m not really interested in the programming project” then I’d have suggested just finding someone who can program, giving an outline of the game mechanics and relying on them to do most of the work,
but if you’re planning to learn enough to become independent enough to make future games single handedly then I’d suggest you start working on a demo/prototype (to the best of your ability) and ask for help when you actually get stuck - you might well find that you’re able to figure out more than you expect yourself to be capable of.


If you’re looking for simple examples,
my joke entry to the recent comptetition is over-engineered for what it is,
but the state-based framework is a good basis for a proper game:

It uses some more advanced features (particularly the ‘utils’ files) but the majority of it is relatively simple.
(For someone who understands functions and classes anyway - for a beginner it would be intimidating.)

If anything about it piques your interest, feel free to ask about it.

So I looked at a couple tutorials and tried my hand at a demo last night using the project ABE emulator.
I was running into an issue where when pressing a direction key, yhe player sprite would fly off at light speed.
I was using the arduboy.pressed() function. The intention was to move the sprite one pixel per frame where a direction was pressed. Is it possible that the pressed function can somehow return true multiple time per frame?
Setting framerate to 30 or 15 helped, but did not eliminate the problem.
Using arduboy.justPressed() was only getting me one pixel per button press.
This seemed really odd to me as I had not encountered this with other things like pico8 and gamemaker.

Assuming you have a ‘pollButtons()’ at the start of your loop code, the pressed() function will return true every time you read it within a frame.

Are you looking for character movement more than once in a frame? It would seem like an odd choice but it may make sense in your code. If so, why not read the value into a variable at the start of the loop (after pollButtons()), like this:

bool aPressed = ardduboy.pressed(A_BUTTON);

Then you can clear it to false if need be in side a single frame.

As @filmote says, the state of the buttons is only updated once per frame when you call pollButtons(),
so any call to pressed() or justPressed() will report the state as it was recorded when pollButtons() was called.

Remember that a frame is typically 1/60th of a second,
so it makes sense to only update the buttons once per frame.
Human fingers are slow enough that a button will typically register as ‘pressed’ for multiple frames.
(That’s why justPressed() exists - it’s only true for the first frame the button is pressed for.)

I’m not sure what behaviour you were expecting.

The Arduboy’s screen is 128x64 pixels, and the default framerate for the Arduboy2 library is 60fps,
which means that it only takes ~2 seconds to cross the screen horizontally,
and ~1 second to cross the screen vertically.

I expect Pico8 and Gamemaker were either moving the character a fraction of pixel per second or it was just a case of having a much higher resolution screen.

The most common desktop resolution for modern computers is 1920x1080,
which would take ~32 seconds to cross horizontally at 60fps travelling 1 pixel per second,
and ~18 seconds to cross vertically.


To resolve the speed issue you have two choices:

  • Only move once every few frames
  • Use a fractional datatype to move your character a fraction of a pixel per frame
    • The primary option is float, which is a standard datatype, but it uses a fair bit of memory and some operations are relatively expensive
    • A secondary option is to use some fixed point types from the FixedPointsArduino library (by including it with #include <FixedPointsCommon.h>). These tend to be cheaper than floats, mostly in terms of memory but also in terms of speed for some operations
    • Disclaimer: I wrote the library

I’d recommend starting off by using floats because they’re easier to get used to,
and then when you’re more experienced and/or start running out of memory,
try replacing the floats with fixed points.

Moving once every few frames is viable,
but it can be a bit awkward because of the nuances of timing,
and it quickly complicates the movement code for all entities.


If you have any other questions or would like to see some examples then don’t hesitate to ask,
but it would probably be easier to demonstrate if we knew what your code currently looks like.

pressed() and notPressed() have no dependency on pollButtons(). pressed() will test the state of the button(s) at the time it’s called. pollButtons() is only needed for justPressed() and justReleased().

Making use of the everyXFrames() function is one (but in some cases maybe not the best) way of accomplishing this.

One thing I’ve done in the past with other arduino based designs (not all fun and games) is to store the value in 2x fractions as a uint16_t value. The idea is to set x to be how precise of movement you want (ex. x=4 would means values between 0-3 will move 0 pixels and 4-7 would move 1 pixel, etc.). From here the math becomes something like this:

Click for code example
if (!arduboy.nextFrame())
    return;
if (arduboy.pressed(LEFT_BUTTON))
    --positionX;
else if (arduboy.pressed(RIGHT_BUTTON))
    ++positionX;
//Code goes here for adjusting positionY
//Code goes here to limit positionX to a range depending on need.
arduboy.drawBitmap(positionX >> POSITION_PRECISION, positionY >> POSITION_PRECISION, BITMAP, SPRITE_WIDTH, SPRITE_HEIGHT); //replace POSITION_PRECISION with 1, 2, 3 etc (precision is 1/2^POSITION_PRECISION, 1/2, 1/4, 1/8, etc.)

This makes it so that if POSITION_PRECISION=2 for example your sprite will move 1 pixel every 4 frames and the system is able to handle this very well, with little performance drop, since it’s simple bit shifting. From there it’s adjusting the precision value accordingly (I usually go with 30fps, but some games will be set at 60). The other benefit to this method as opposed to arduboy.everyXFrames is that each sprite can move at different speeds by setting different levels of precision and costs less then different calls to everyXFrames for each sprite. One test I did in the beginning to experiment with sprite movement methods on the arduino was to draw a rectangle on the screen and cap its position to stay on screen, then tried different methods (floats, fixed point arithmetic, dividend precision, and powers of 2 precision) of moving the sprite, playing with the values to get a good fluid motion, while also testing cycle times and memory consumption. Powers of 2 precision typically are the fastest with the best memory footprint, and can achieve very fluid results with the right values.

NOTE: The reason for the powers of 2 is that it uses bit shifting instead of regular division, which can be far faster on the CPU (not something you’ll ever really encounter on a PC/Console platform where you have at least 3-4Ghz processor, unless you’re developing a AAA title, but on a tiny 16Mhz 32u4 the difference is definitely noticeable).

That’s basically fixed points.

if (!arduboy.nextFrame())
    return;

if (arduboy.pressed(LEFT_BUTTON))
    --positionX;
else if (arduboy.pressed(RIGHT_BUTTON))
    ++positionX;

arduboy.drawBitmap(positionX.getInteger(), positionY.getInteger(), image, width, height);

Not always though.

AVR chips (the kind the Arduboy uses) don’t have a barrel shifter, so after a certain size the compiler’s likely to translate the shift into the equivalent of a for loop, which can be quite slow.

Thank you all!
The nextFrame() function was what I needed. The game was displaying frames too quickly. My bat now moves at an appropriate speed.
I also had several issues uploading code to the Arduboy (was previously using ABE), but all is fixed.
I am working on the bat movement demo, now!

1 Like

Behold!
A demo!

The demo is for player movement only, and does not include shooting. It does have the appropriate sprites for the bat, though.
Controls:
L/R for L/R
DOWN to Dive
A BUTTON to Flap and gain altitude
Running at 30 FPS.

The code is a wreck, but I am pretty satisfied with the control of the bat. Next step, is shooting.
Flapping to maintain altitude should be timed so that you can pop off a few shots between flaps.

batmovementdemo.ino.hex (23.4 KB)

1 Like

Make sure to at least attempt to clean it up at some point.

Messy code has a tendency to breed more messy code,
which has tendency to spiral out into spaghetti and before you know it you can’t even ‘read your own handwriting’ (so to speak).


I hasten to add: if you need any help or advice, don’t hesitate to ask.

This is good advice, I had a habit of naming variables like: stuff, things, foo, bar, stuff1, stuff2 and things like that. It’s a tough habit to break!

I like the controls, I don’t know if maybe reduce the amount you need to press the button to reduce fatigue but otherwise it’s great!

1 Like