Just got my Arduboy - What Game Should I Make? + Giving Away My Concept Images!

So many cool ideas for the Arduboy still floating around!

I actually wrote an article about the 5 kinds of games I’d die for on the Arduboy in the latest issue of the Arduboy Magazine.

I think a pinball game would be cool, but GTA,as suggested in the original post, would be my first pick. If you could make a game with similar gameplay, that would be awesome.

Check out the rest of the e-zine, here:

3 Likes

OMG :open_mouth: That’s exactly what I imagined. I have no problem with joining an ongoing project. The problem for me is rather GitHub - I left that place and don’t want to come back. But There are ways around that I guess, I could simply send you patches or something. I’ll go check the project out.

I actually wrote an article about the 5 kinds of games I’d die for on the Arduboy in the latest issue of the Arduboy Magazine.

Thanks for the link, going to check it out.

but GTA, as suggested in the original post, would be my first pic.

That’s what I’ve been leaning towards :slight_smile:

As long as you don’t object to interacting with GitHub only to the extent of pulling updates, this shouldn’t be a problem. I don’t think you’d need an account on GitHub for this. A git repository is a git repository no matter where it’s hosted.

You could clone and sync the GitHub repository to your local copy, make changes and then push them to your own remote git repository, hosted wherever you wish. You would then inform @Botisaurus, or whoever you’re working with, that changes are available on branch xxx of your remote repository. @Botisaurus could then merge these changes to his own local copy and then push to his GitHub repository.

2 Likes

Playing around with Tiled editor and the GTA idea.

4 Likes

Just now looking at the memory limits of Arduboy and wondering whether I’d be able to fit in all the sprites plus a let’s say 100 x 100 map :expressionless: You can compress, but then you have to uncompress into RAM, which is much smaller than the flash. I could get rid of some sprites, e.g. the buildings inner corners and go only for rectangle buildings. I’ll also have to fit in other graphics such as cars etc though.

A lot of stuff is symmetric, e.g. cars are left-right symmetric and the rotations are 8 symmetric, some tiles are just transformations of other tiles etc. So I could save space there, but that’s additional code and complexity.

I’ve been thinking about having different parts of the city with different tilesets (at least some of the tiles) for some diversity. Then if you e.g. cross a bridge into another part of the city, the appropriate tileset gets uncompressed into RAM in the place of the previous tileset.

Also Arduino doesn’t have floating point, right? Are there any other limitations? Standard library etc.? Will have to Google (DuckDuckGo actually) a bit :slight_smile:

This is definitely a different kind of programming I’ve been used to. I never really had to care about these limitations. But I like it, gives you a new view at life :slight_smile:

EDIT:

I’ll be just throwing my thoughts onto this thread, will use it as a development journal for myself and others. Feel free to ignore :slight_smile:

The map wouldn’t actually have to be that big, it might consist of let’s say three “submaps” - most likely islands connected by bridges. The rest would be filled with water.

1 Like

One of the beet things about the Arduboy is it challenges the way you think regardless if you are new or an experienced programmer! There are a lot of limitations but a lot of interesting, and some old-school, techniques for dealing with interesting situations. Check out this post for some ideas:

For map limitations, you can chunk sections to save space.

3 Likes

Thank you for the link :slight_smile:

For map limitations, you can chunk sections to save space.

Nice! I think it would also be possible to use e.g. RLE, or something like sparse matrices etc.

There are a lot of limitations but a lot of interesting, and some old-school, techniques for dealing with interesting situations.

Yes! I’ve indeed heard about these techniques, watched some videos on how old hardware worked etc., but always viewed it as something of a past. Now I’m dealing with it myself. It’s definitely exciting!

1 Like

I have used a simple RLE algorithm to decompress levels in Lode Runner and Space Cab and was pleasantly surprised at how much the levels compressed down.

I have a level editor in the Lode Runner repo that uses an Excel spreadsheet to design the levels and thumps out the compressed level data via a macro. The link locations are in the provided links.

2 Likes

Excel spreadsheet

Nice creative use of existing software :slight_smile:

Another idea for how to potentially create a huge map:

Procedurally generate the map, play around with the seed until you have a nice base map. Then take that and manually make changes to fine-tune the map. Save these changes as delta/diffs against the base map. If you didn’t make too many changes, the data, i.e. seed + changes, should only take small amount of memory.

Sprites live in progmem so that would only save progmem.

It has software floating points, but they’re not always optimal since floats are 32 bits and the processor operates on 8-bit data.

That’s one of the reasons I wrote a fixed point library.

No C++ stdlib, only C stdlib.

Partly because most of the C++ containers use dynamic memory allocation, which is bad for obvious reasons.

That said, if there’s something specific that you want from the C++ stdlib that isn’t available,
I’m willing to have a go at building it.

And if it involves templates, I’m probably the best person to ask anyway.
I understand template voodoo.

1 Like

That’s one of the reasons I wrote a fixed point library.

Awesome :slight_smile:

only C stdlib.

Actually for this kind of low level programming I’ll prefer C (style) anyway.

I understand template voodoo.

Woah :smiley: Yeah I know templates are Turing complete but I probably don’t want to know any more :smiley: BTW I love Haskell, even though I only used it once (was thinking about Arduboy port here). Can’t say the same about templates.

Why? C++ style is no less efficient than C style.

There are some expensive features (dynamic memory allocation, virtual functions) but those are usually easy enough to avoid.

I find turing completeness isn’t a particularly useful metric.
A 5 year old with a bucket of sticks is probably turing complete,
but that doesn’t mean a 5 year old with a bucket of sticks is useful for making software.

Templates can be practical even without fancy metaprogramming magic.
That project isn’t something I’d necessarily use for programming,
but it was a fun and useul programming exercise.

From experience I can safely say that templates do not deserve the contempt they receive.

A lot of people say they increase code size, but that’s usually false.
Most people who say that aren’t comparing them to the equivalent non-template code, they’re comparing to an alternate approach to solving the problem.
They can produce additional code if mishandled, but there’s almost always a good reason for that additional code and there’s also usually a way around it.

Most of the people who say bad things about them either don’t understand how they work or are just terrified of the syntax.
If used correctly, templates are safer than most C-style functions and can be safer and more efficient than function macros.

I was terrified of Haskell’s syntax until I put the effort in to learn it.
I still think a lot of it is cryptic and involves a bit of mental gymnastics, but I don’t doubt its usefulness.

I just find the whole template idea not elegant, that’s all. It’s an additional language within an already pretty complex language, you know, and then there are the weird things like having to put implementations into header files etc. I hate when compilers cause this friction. I’m no expert here and I’m not saying I know a better solution, but there’s something weird about templates. I use them in situations where their use is obvious, but I’m never happy about having to use them. When comparing C to C++ I tend to prefer the minimalism of C, but I have yet to find a language I’d be at least 99% happy with regarding the syntax and all the other stuff. Haskell is the closest so far.

I don’t want to derail the thread too much so this shall be my last post about templates.

When used correctly, I find them to be more elegant than other approaches.

An Example (click to reveal)

For example, consider:

SomeStruct a;
SomeStruct b;
std::memcpy(&a, &b, sizeof(SomeStruct));

And compare it with:

SomeStruct a;
SomeStruct b;
memoryCopy(a, b);

Made possible thanks to the template function:

template< typename T >
T & memoryCopy(T & destination, const T & source)
{
	return *std::memcpy(&destination, &source, sizeof(T));
}

The latter is less typing, completely type safe and doesn’t have to even think about null pointers.

With type_traits.h it’s even possible to make it cause a compile error if the programmer tries to invoke undefined behaviour.

To quote cppreference:

If either dest or src is a null pointer, the behavior is undefined, even if count is zero.

If the objects are not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined.

The following definition would prevent both those situations:

template< typename T, bool isTriviallyCopyable = std::is_trivially_copyable<T>::value >
T & memoryCopy(T & destination, const T & source)
{
	static_assert(isTriviallyCopyable, "Type is not trivially copyable, memcpy is undefined. Use memoryCopy<T, true> to override");
	return *std::memcpy(&destination, &source, sizeof(T));
}

That may not be very elegant to write, but it only has to be written once.
To the end user, the API isn’t difficult - it’s called just like a normal function, there’s no sizeof or pointers to wrangle, and if the compiler is doing its job (which is most of the time) the template function will be inlined anyway, so the end result will be the same machine code.

There’s nothing to stop people doing that with non-template classes or functions.

The reason it has to be that way is because of the archaic compiler design that C++ inherited from C.
.cpp files are compiled as separate translation units - they never see each other’s contents.
That wouldn’t work for templates because templates aren’t classes or functions, they’re just a pattern used for generating classes and functions, hence the whole pattern needs to be known.

Macros can’t have their definitions separated into a .cpp file for a similar reason - macros are just patterns describing ways to manipulate text.

It’s still possible to put the implementation into a separate file from the definition, but it can’t be a .cpp file, it would have to be another header file (or as some have taken to doing, a .tpp file), and that file would have to be included at the end of the first.
I’ve used a similar technique to this before when writing particularly large templates.

Isocpp has a very good explanation here

I find using C’s restrictions causes more work.
E.g. being forced to do func(a, b) instead of a.func(b), and being worried about using the wrong kind of a. Having to worry about null pointers, those sorts of things.

Unfortunately Haskell isn’t particularly suitable for embedded systems. A lot of its constructs are memory hungry and it relies on a garbage collector.

To quote something I found on ycombinator:

The problem with Haskell is that while it is very effective at expressing ideas and logic, it is just as ineffective at expressing runtime behavior. In world where everything is lazily evaluated by default and garbage collected, it is very difficult to reason about how the code will actually execute. Are you trashing the cache? Fragmenting your heap? Are you misusing the instruction cache?

Which is quite close to my sentiment.
I know C++ intimately and I can take a very good guess at what the actual behaviour of the program is in terms of the stack, the heap and sometimes even the assembly generated, and I can usually do that even if I’m using several layers of templates and abstraction.
I cannot say the same for Haskell.

If you miss type inference though, C++ has the auto keyword:

const auto a  = 5;
const auto b = 10;
const auto c = a + b;
1 Like

Good points… let’s follow your suggestion and leave further discussion of templates to other times and places then :slight_smile:

I’ve just finished Arduventure – it’s a very nice game, kinda short but that’s because of the memory constraints. I think the project of creating the free assets would be worth it. Am currently reading through the code and trying to come up with my original asset replacements. I’d probably call the game ArduRPG – Google returns no results so I guess the name is not taken. So let me hereby reserve it :slight_smile: Here’s my concept for the logo:

free_titleText_96x24

TBH looks pretty awful but I like to have things documented. Let me see if I can come up with something better.

EDIT:

This probably looks better:

image

repo

thread

OMG. Texture-mapped raycasting… so neat… I’d so want to make a game out of this as the next project :slight_smile:

If we could also texture the ceiling and/or the floor that would be some Doom stuff right here :slight_smile:

Also I’ve been thinking about level compression for this kind of mazes and have an idea involving RLE and Huffman coding that could work. But it probably already exists, like everything. Will do some research.

1 Like

I hadn’t seen this one but that is well done. As you say, almost a Doom engine!

3 Likes

Texture on the top and bottom may actually make it really hard to tell what’s going on in the screen unless you have some outline around things.

1 Like

True, floor would most likely be disturbing, but ceiling wouldn’t interfere that much. Pure black just looks very empty, however I dunno how to draw a textured ceiling without having to cast a ray for each pixel, which would be expensive. An acceptable halfway solution could be something like a fog.

Also a big problem to solve: controls. You need both turning and strafing => not enough buttons :frowning: Maybe something like:

forward/backward – move forward/backward
left/right – turn left/right
A – shoot
B + left/right – strafe left/right
B + up – cycle weapons
B + down – menu

With an option to switch turning and strafing. I wonder what these controls would feel like.

You could simply have a dithered ceiling or floor - a simple alternating pattern. I agree with @crait though, if you could get a black outline around the walls and other objects they elements will all run together.

Ard-Drvin’ used a modified display() command that populated the screen buffer with a pattern (instead of blank) when flushing of the screen buffer to the display. Doing this at the same time as the flush saves processing time and utilises dead time while waiting for the SPI transfers to complete.

At the end of each loop() you call display() which flushes the screen buffer to the actual display and resets the entire screen to a dithered background, ready for you to ray cast over the top of next loop iteration.

1 Like