How to create sprites properly

So I was rewriting some code for an old Arduboy game and I wanted to have the hex values in another file instead of the ino, what format and how would I use that? I’ve tried using .h or .cpp but it rather says ‘no file or directory’ or ‘no scope’. I haven’t read or done much on Arduino yet but wanted to see how to do this.

You can just put therm in another .ino file.

Or, you can put them in a .h file but they need to be in a directory calledsrc under the main directory. They can be subdirectories of src if you want.

Have a look at this game > https://github.com/filmote/Karateka < you can see the src directory and if you drill into it you will see a subdirectory called images where I have put all of the graphics assets.

Classic filmote to help out, using a src folder does work but can I just put the .h files next to the ino instead of creating a folder and allowing me access to the .h files? They are just simple hex arrays for sprite parts

Ok I just realised my mistake, I used <> instead of “” for the #include so it was looking for a library, yes I can have the .h files next to the .ino file. Seems like a rookie mistake, like I said still just learning

1 Like

The src directory is a must from memory if you are using .h and .cpp from version 1.6.x onwards of the Arduino library / IDE. I am not sure if they fixed that and ever since I have always, always used a src folder.

Anyhow, you got it going.

Yep, everything is working as expected (sort of, still a bit of bugs to the code). Also is there a way to switch between 2 .ino files? so if you had 1 for a menu, then if a requirement was met then it would switch to 2, to me this sounds space consuming and their probably is an easier solution. I just basically want a menu that shows first

Do you mean having a menu function that calls one of two different programs?

No, they don’t have to go into a directory called src. Any additional .ino, .h, .cpp and .c files can remain in the same directory as the main .ino file. It’s only if you want to put them in a subdirectory that it has to be named src.

Unless you have so many files that it makes sense to organise them into subdirectories, it’s better to keep them in the main directory and don’t use subdirectories. This way all the files will be visible in the Arduino IDE’s editor. (Files in subdirectories don’t show up in the IDE.)

1 Like

The Arduino build process just takes all your .ino files and joins them to the end of the main one, to make a single (temporary) .ino file, before compiling. So, you should be able to take a working single .ino file and split it into as many smaller .ino files as you like. You should end up with the same working program.

From the Arduino Build Process document:

All .ino and .pde files in the sketch folder (shown in the Arduino IDE as tabs with no extension) are concatenated together, starting with the file that matches the folder name followed by the others in alphabetical order, and the .cpp extension is added to the filename.

Ah … that’s right. I was trying to remember the details of the directory thingy. I happen to use subdirectories but have not bothered to go back and test that src is still a requirement - sounds like it is.

For future reference: you should never include a .cpp (or .c) file.
It makes no sense to do so because of the way compiling works.

It’s hard to explain without going into full detail, but the bottom line is that it’s likely to cause compiler errors due to things being defined multiple times.
(I’m happy to explain in more detail if you want.)

If you put all the image data in a .h file and include the .h file then in most cases it shouldn’t matter if it’s in a src folder or not.

As @filmote offered up his Karateka as an example, I’ll offer up the image folder of my joke ‘game’ LoveTester as an example: https://github.com/Pharap/LoveTester/tree/master/LoveTester/src/Images

If you don’t know what namespace means, just ignore that part.
It basically just means that instead of referring to heart or pharapLogo the game has to refer to Images::hear and Images::pharapLogo.
(In a sense namespaces are like file directories for variables, functions, datatypes et cetera.)

There are some cases where using a .h can break down,
but making sure to mark the image data as constexpr instead of const should fix the issue in most cases.

Personally I only ever use one .ino file because I think the system of using only .h and .cpp files is a lot saner and easier to control.

I’m not sure what you mean.

I feel it’s worth mentioning that files and code don’t have a 1:1 correspondance.
A program that can be written in hundreds of files can also theoretically be written as one large file and produce exactly the same machine code and have exactly the same semantics.

(In reality there’s lots of subtle reasons why it probably wouldn’t be exactly the same if you attempted something like that with a modern compiler, but the differences would probably be really minor if the code were truly equivalent.)

Ultimately what matters is the structures in the code - the datatypes (classes, structs, enums) and the functions.

It might be a bit more complex than you’re used to because of the use of classes, but the ‘LoveTester’ game/demo I linked to before also has a decent example of having a splash screen, a main menu, a gameplay state and an info/credits state, and switching between them.

If you want I can explain what the code is doing,
and/or I can demonstrate the same technique without classes.

(I think I’ve probably given an example somewhere on the forum at least once or twice before.)


Unfortunately their official stance is “it’s not a bug, it’s a feature”.

@filmote @Pharap @MLXXXp Thank you all for your advice, I have looked through and used some of the advice, here’s the github link for my game I’m recoding https://github.com/Ashteroide/Arduboy-Chrome-Dino feel free to check it out, I’m working some more bugs out of it at the moment.

2 Likes

A few bits of advice and commentary…

When you upload code to GitHub, you’re supposed to upload the code as-is, without zipping it, for several reasons:

  • GitHub will automatically put the code in a .zip file when someone tries to download it
  • GitHub allows people to preview files without downloading them if they’re uploaded as-is
  • GitHub (or more specifically git) is designed to track file changes, and that system won’t work properly if you put your code in .zip files because git then tracks the changes to the .zip file, not the changes to the file inside the .zip

You don’t need to use sprintf, it’s a waste of resources.
Instead of doing:

  sprintf(text,"%d",d);
  arduboy.print(text);

You can just do:

arduboy.print(d);

If you go into preferences and set ‘warnings’ to ‘all’ you’ll get some extra warnings about your code.

One of the warnings tells you that you have a statement that doesn’t do anything on line 172: d_tumble_t;.

Unfortunately you’ll also get some warnings about EEPROM because Arduino won’t fix that problem,
and possibly a warning about font which is due to be fixed in the next release of Arduboy2.
(Also tinyfont is producing a warning, but I’ve just made an issue about that so hopefully it’ll be fixed sometime soon.)

Otherwise, having only one warning (relevant to your code) is a good thing,
so clearly you’re doing something right :P.
(Naturally you ideally want no warnings.)

Calling setup as a way of ‘resetting’ the game is probably a bad idea.
I’m not sure whether it would have any negative consequences but I’m fairly sure arduboy.begin() is only intended to be called once.
You could make a reset() function that handled all the variable resetting, which wouldn’t be ideal from a program design standpoint but would at least avoid calling begin twice.

Using delay is generally a bad idea because it freezes the whole processor and thus interferes with the frame rate.
(Granted the alternative is quite difficult to do correctly.)
Similarly using while(!arduboy.pressed(A_BUTTON)) {} is also generally a bad idea, though it’s less of an issue because it’s being used in setup instead of loop.

As things stand, your code doesn’t actually rely on the system that’s in place to limit/regulate the frame rate, which is presumably why you’ve had to put a delay(16) at the end of the function - to stop the code running full pelt and thus making the game unplayable.

Also it seems you don’t yet know about bool (and true and false), or the F macro yet,
so those things should be top of your list of things to learn about.
(Again, I’m happy to explain what those are any why they’re important if you want.)

1 Like

I’ve used bool before for Unity walk and idle detection, I’ll definitely look into those. Some of the code is from the old version from the other person but I might try and redo the whole with Arduboy2 and much cleaner, although I have troubles with placement but will see what I can do and I know I can ask this community for a little bit of help :+1:

Edit: can I create a new void zone? say void menu() {} and setup a start screen for my game instead of using setup to wait for a input?

‘Placement’ in what sense?

The word you’re looking for is ‘function’.

Each function essentially contains a list of ‘statements’ (each statement ends with a semicolon),
and each statement performs one or more action.

A function can ‘return’ (output) a value. E.g.

// Accepts 1 int, returns 1 int
int square(int value)
{
    return value * value;
}

Which could be used as int someVariable = square(someOtherVariable); or int twoSquared = square(2);.

void is a keyword that more or less means ‘the absence of a type’.
Usually it’s used where a type would be expected to indicate that there is no type,
but it only makes sense in certain contexts.

When it’s used before a function’s name when a function is being defined it means “this function does not return any values”.

To avoid using while(!arduboy.pressed(A_BUTTON)) {} you’d have to start using a proper game loop and restructure a fair bit of your code.
Most of that is fairly straightforward, but the countdown part would be hard to convert.

I’ll make a list referring to what you asked
Placement - I don’t understand fully how to place the code, whether an if statement has to be called first or second inside another if, I can probably just keep testing
Function - How can I operate functions properly, if I wanted to create a menu using function or void on my Chrome Dino game, it waits for the user to press A or B and then goes to loop.
e.g.

void intro()
{
    arduboy.clear();
    arduboy.setCursor(35, 26);
    arduboy.print("CHROME DINO");
    arduboy.setCursor(50, 36);
    arduboy.print("v0.0.5");
    arduboy.display();
    delay(1500);
}

Also mentioning to the while(!arduboy.pressed(A_BUTTON)), any examples of code would be good

I am kind of new to this and really enjoy it, I just need the right start

Obviously void isn’t going to work

@Pharap My main goal is to just start with a basic menu and work my way up, I did search on the community and found something you did with ‘const char option0[]’, did seem a bit complicated for me but I understood the concept. I am going to try to code a basic menu myself but if you have any suggestions I’m all open :+1:

Program statements are sequential, and if is a statement.

Some examples:

// This happens first
if(i > 5)
{
    // This happens if i is greater than 5
}
// This happens regardless of what i is
// This happens first
if(i > 5)
{
    // This happens if i is greater than 5
    if(j > 6)
    {
        // This happens if i is greater than 5 _and_ j is greater than 6
    }
   // This happens regardless of what j is
}
// This happens regardless of what i or j is
// This happens first
if(i > 5)
{
    // This happens if i is greater than 5
}
// This happens regardless of what i is
if(j > 6)
{
    // This happens if j is greater than 6
    // and it happens regardless of what i is
}
// This happens regardless of what i or j is

It took me a little while because I’ve been in and out (and I had to correct a few mistakes that I made because I was rushing and wasn’t testing that the code still compiled after making changes) but here’s a version of your game’s code using a ‘state system’ to control the transition between game states:

I left out the countdown step, but put some infrastructure in place so it can be added back in later when I have chance to demonstrate how to do a countdown timer.
(Basically you have to save the value of millis(), figure out what value millis() needs to have passed for your time to have elapsed and then react to that change.
Which is pretty much how a human would figure out if a second has passed if you think about it, though a human would be looking at seconds rather than milliseconds.)

Don’t worry too much about what an enum class is at the moment, I’ll explain in more detail later after you’ve had chance to look at the code.
For now the important thing is that it creates a new type (called GameState in this case) and several distinct values of that type (GameState::TitleScreen, GameState::GameOver, GameState::Gameplay, GameState::CountDown) that can be assigned and tested for equality.

I’ll explain what a switch is now though.
It’s somewhat like an if statement because it allows the code to take multiple branches.
Here’s a really simply example using integers:

int someInteger = getSomeValue();

switch (someInteger)
{
	case 0:
		arduboy.println("Your number was 0");
		break;
		
	case 1:
		arduboy.println("Your number was 1");
		break;
		
	case 2:
		arduboy.println("Your number was 2");
		break;
		
	case 3:
		arduboy.println("Your number was 3");
		break;
}

So essentially each case statement is like an if statement doing an implicit == test to the value in the switch, and the break; ends the case.
(I won’t go into what happens if you forget the break;. It’s legal, but generally frowned upon.)

Also note that you can go through the commit history, and each commit has a reasonable comment explaining what the change does:

This:

void intro()
{
}

Means “here is a function named intro that doesn’t return anything”.

If you go around calling them ‘voids’ nobody’s going to know what you’re talking about.
It’s important to learn the proper terminology so you can adequately communicate your problems to other people and so you can understand the solutions they communicate to you.

The code I posted is part way to a menu.
Making an actual menu with more than one option will require a bit more.
I can demonstrate, but I don’t know what you want the second option to be.

Which example was it?

I’m pretty sure I’ve given several examples over time.
The complexity of my answers/advice depends on who my audience is.
I’m guessing it involved progmem if there was a character array involved.

1 Like

Don’t worry about the example, also HOLY POOP MY DUDE (PG around here), I honestly was not expecting you to take my code and fix it, thank you so much for that, it can help me learn a bit better, you fixed the repetitive arduboy.begin(); which I like, my understanding is cases contain the void reference, so TitleScreen is defined and you’ve got updateTitleScreen which basically updates its current state and then drawTitleScreen is used at the start for drawing the menu, I have seen the millis() rarely. I’ll do some basic testing with this kind of stuff and then I can work my way a HighScore board which I want to learn to do myself. Also I am pretty bad at Github repositories, but Chrome Dino is a great start of testing and learning it