HELLO!!!
I'm making a very simple game in C with allegro5, and I'm trying to trigger a screen change by clicking on a certain key. For example, if you press ENTER, the entire screen is cleared and a new one appears, with a new message. Does anyone know how to tell me what I do wrong? Pressing ENTER does disappear the music aand the text, but the new one don't appear in the display.
There is no error message and the document compiles, but it does not do what I want.
Here is the code:
Can someone help me?
There is quite a lot wrong here; unfortunately I don't have your resources (images/sounds/music) so I can't run it myself.
You should really be running a state system, rather than having 2 places where you try and draw.
This is a very basic example, based on your code. Here the logic is seperated from the drawing. The drawing only happens once.
You need to loop these steps:
get event
workout logic
draw screen
Here is working code to get you started:
WOW, it did work!
Can you answer another question? How do I make an if() in another if() work? Example: After press ENTER, it questions if a person want option A or B. How can I do this? I try to create a new if, but it did not work...
Many thanks
This is why we need a "state"; we need to know what state the game is in, because we only want to drawn once in our loop.
We create different states, and when we press keys, we check our state to see what should happen.
In this code, we check the key pressed, but we also check the state, to see what we should do.
Now you can press enter if the state is "STATE_START". Then you can press A or B.
You can also press backspace; if you have only pressed enter, we will go back to the start; if you have pressed enter, then pressed A or B, we will go back to "STATE_PRESSED_ENTER". We can then press backspace again, to go back to start, or we can press A or B again.
It is important to know what state our game is in, then we can make decisions in our logic. If we do not know what state the game is in, we cannot make decisions:
REMEMBER...we loop every time, so we cannot check 2 key presses in a single pass; we go:
get event
work out logic
draw
So we need to get each event, every loop. This is why we need a state; we need to know what happened last loop, so we can make a decision on the next loop...
Hello. I don't know if I really understood . Actually, not kkkkkk. Thinking that I will always have an if () inside another if (), do I have to create decision levels with STATE_PRESSED?
I did below how it would look, more or less, the structure of the game. But as predicted, it is not working.
The order is: Start with ENTER, and the user chooses between A or B. If you choose A, inside you will have another choice, from A or B, and it will go on.
I'm sorry for the questions, but I don't understand anything about this library .
Thank you for your help.
You need to remember that your game is looping, with one event at a time. The reason your code does not work is because you are trying to decide on 2 things in one event.
When a key is pressed, only 1 key is pressed. You can't say:
IF key enter, IF key A....
You need to think in terms of a single pass each loop. This is why you need a state. You need to check a single key each time.
The only way your example would work would be if the user pressed ENTER and A at the same time...
Please keep asking, I like helping, and no, this is not easy, but you can only get better, and when you do understand it, you will be much happier
Okay, I think I'm starting to understand. Can you explain more about this part of STATE? I understood (I think) how to use it for one case after another, as in the code below. But what I do when an if () generates another if (), for decision?
I'm thinking in normal logic of C: the story will change according to each choice, which will generate several different ends, but I'm not able to think how to do this.
I have to create the states, correct? Just like you did below
#define STATE_START 1
#define STATE_PRESSED_ENTER 2
#define STATE_PRESSED_A_OR_B 3
What do the numbers at the end of the line indicate?
For several stories, would you have to do a different state? Example:
#define STATE_HISTORY_1 4
#define STATE_HISTORY_2 5
...?
Thank you so much for your help, I don't know what I would do without it.
Yes, for different stories, you need a state for each story. The numbers at the end are just an integer...
...the thing to remember is, the event/logic/draw happens 30 times every second! We have to constantly "loop", but the user may not press a key for 2 minutes, so we need to check each loop, and we need a "state" to know what to do.
What you will want to do, as your game grows, is to create "functions", so you seperate the code into small chunks. That way you can manage it.
You are thinking that, if I press one key then IF......no, not that way with games programming. Remember, the game is looping 30 times every second! Very fast. If we only did one thing at a time, it would be:
Draw Screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw screen
This is NOT what you want to do; games work by looping all the time. We loop and loop and loop. If no key is pressed, we draw screen. If another thing happens (user pressed key) we can work out logic. The loop is happening 30/60/120/240 times per second! Don't think that you do one thing, then one thing, then one thing....you have to get used to loop...so as I said, our logic is:
get event
logic
draw screen
over and over and over again! Not:
Draw Screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw Screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw Screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw screen
Do nothing until user presses a key
Decide on key pressed
Work out logic on key pressed
Draw screen
That is not the way! You have to loop, every loop (30 frames a second, or 60 times a second, or 240 times a second) and before you draw, work out logic...
Hi.
Can you explain this part better to me?
This is what I've done so far, and it's finally working!
I have two more questions: How can I change the style of the letters, make them bigger and how can I make the game return to the beginning of the game, as soon as it ends, letting the player play again.
Thank you soooooooooooooo much!!!
Can you explain this part better to me?
Yes; what we are doing here is reducing the number of conditions. We want to make the code as small as possible, so rather than saying:
we can wrap that up, as we don't want to check key==a every time. So, we can say:
if(key == a) //we only need to check key one time for multiple states { if(state == some_state_1) else if(state == some_state_2) else if(state == some_state_3) }
That will make our code easier to read, and easier to add new states when key==a.
How can I change the style of the letters, make them bigger
For this you will need to use the font addon. You will need to include the ttf_font header (#include <allegro5/allegro_ttf.h>) and initialise it (al_init_ttf_addon()). You can then use:
al_load_font("filename.ttf", size, flags);
The second argument will let you choose the size. Then, when you draw your text, it will be larger, depending on the size you choose when you load.
how can I make the game return to the beginning of the game, as soon as it ends, letting the player play again
Well, you don't want to wait for a key, but I guess you don't want to go there straight away, as you want to display a message first? So I would suggest, add a new timer, that you can start/stop. You can start it when it's game over, and then check it every frame - if it's counter goes up, you know it's passed and can then restart the game.
Here is working code for you. I have added the ttf_fonts (ttf file is arial unicode, I can't attach as it's too big, but you should have a unicode font on your computer), and made it larger. I have also added a new timer, gameOverTimer, that will display "GAME OVER" for 3 seconds and then restart the game.
I'll let you look at it, and then you can ask more if you need!
If you want to get fancy, and a little more advanced, try looking at allegro's event queue's. You can emit custom events, and then check for them too.
You can even write "Scenes" instead of "States". Each scene would have its own state, and its own input and display routines. I use them all the time in my own games to transition from one state to another. But that way they are encapsulated in their own class and cannot be messed up by another state (usually).
I agree; I also think it would be prudent to look into functions, start seperating out some of that code, make chunks easier to deal with, and keep that main loop nice and minimal.
We'll see how this goes, it's quite hard to learn Allegro/games programming alongside learning how to structure code etc.
But keep on keeping on, you'll get your first game out of it, and then you'll be unstoppable
Hello again. I went to test the font part, so I downloaded a file and changed it according to the code that you modified. However, it generated an error:
reference not set to "al_init_ttf_addon"
https://1drv.ms/u/s!Ak2pOptPmINYpmSnMMu1oG8rDSEY?e=oIianF
I got the file from this site: https://www.fontsquirrel.com/fonts/list/popular
I use Linux, and I'm doing everything for the terminal. To compile the file, I am using the following command:
gcc dino_allegro_1.c -o dino_allegro_1 $ (pkg-config allegro-5 allegro_font-5 allegro_image-5 allegro_primitives-5 allegro_audio-5 allegro_acodec-5 --libs --cflags)
Can you signal what I'm doing wrong? The code I modified is below:
The files I am using can be download in this link: https://1drv.ms/u/s!Ak2pOptPmINYpmN3Cnc1FrAnbgil?e=8pzBIq
The error: https://1drv.ms/u/s!Ak2pOptPmINYpmSnMMu1oG8rDSEY?e=85bZv4
Many thanks
Are you also linking the ttf addon library? Sorry, I don't use Linux, so not exactly sure.
There are 2 libraries: allegro_font & allegro_ttf
You have this line twice
must_init(al_init_image_addon(), "image addon");
enums vs defines for game states?
Also why so many else ifs?
condense some of that. Use switch statements or a separate function if a is pressed vs b is pressed.
also, since you are hard coding your text, why not do something like this?
char *text = "PRESSIONE ENTER PARA COMEÇAR O JOGO"; char *text1 = ""; //later in code switch from this sprintf(text, "%s", "DINO PERCEBE UM METEORO VINDO EM SUA DIREÇÃO E COMEÇA A FUGIR. LOGO A SUA FRENTE, DINO VÊ UM BURACO!"); sprintf(text1, "%s", "DINO PULAR O BURACO (A) OU IGNORAR O BURACO (B)?"); // to this text = "DINO PERCEBE UM METEORO VINDO EM SUA DIREÇÃO E COMEÇA A FUGIR. LOGO A SUA FRENTE, DINO VÊ UM BURACO!"; text1 = "DINO PULAR O BURACO (A) OU IGNORAR O BURACO (B)?";
@DanielH, I removed the second line: must_init(al_init_image_addon(), "image addon");
You ask about all the if(), soooo... I really don't know what I am doing, so I did the logic based on what the great @Dizzy Egg explain to me, and work. It may not be the most beautiful, but it works.
But the font is not working, it give the follow error:
The part to return to begining of the game is not work.
The complete code:
Thanks soooooo much.
//ALLEGRO_FONT* font = al_create_builtin_font(); must_init(al_init_font_addon(), "font"); //WE NEED TO INIT FONT FIRST! must_init(al_init_ttf_addon(), "ttf font"); //THEN WE NEED TO INIT TTF FONTS ALLEGRO_FONT* font = al_load_ttf_font("Antonio-Bold.ttf", 14, ALLEGRO_ALIGN_LEFT); //NOW WE CAN CHOOSE SIZE
You are defining font twice. Lose the first one.
The part to return to begining of the game is not work.
Not sure what you mean by this? return to beginning when? When game over, you stop timer, but reset it to 0. why reset it if it is stopped? Are should you not stop it, but reset it 0?
Look at this.
This part:
if (gameState == STATE_PRESSED_GAME_OVER) else if (gameState == STATE_PRESSED_GAME_OVER)
I have to remove only the first line?
It gave the follow error:
Do I have to add a new library?
At the end of the game, I would like the player to have the option to play again
Thanks
Yes, there is an allegro_font library which you already included. If you want to use TTF fonts then you also need to link the allegro_ttf library.
You need both lines
must_init(al_init_font_addon(), "font"); //WE NEED TO INIT FONT FIRST! must_init(al_init_ttf_addon(), "ttf font"); //THEN WE NEED TO INIT TTF FONTS
Just make sure you link both libraries
I don't have your resources, but everything else seems to be working. Also, I don't speak Portuguese, so I don't know if it's working correctly. This is what I was talking about with split in to functions for a or b. A little easier to manage.
I removed the wonky sprintf string copy code also
Hello.
Really cool what you did separete the A and B. But it's not working properly. For exemple, almost all the decision with B is not working, only A, and not always correctely. I will look with more attention.
About the library, how do I link
The loop in the game is not working too. You know how to correct it?
Thanks again.
Yeah, I noticed that.
Plus you had duplicate elseifs.
Best bet would be to get a pencil and paper and workout the flowchart first. Then go through the code and make sure the states are correct?
Draw it out with. make circle for each state. draw lines from state to state if you press A or B.
If state _ and press key _ what is next state?
I don't understand Portuguese to understand what is going on.
google translate does help a little
Dino sees a meteor. A - Jump in hole, B - Ignore hole
Okayyyyyyyyyyyyyyy, the last two question! (sorry, I have the sensation that will never end).
So, I discovery, that in linux, we have to add allegro_font-5 to compile
gcc jogo_dino_allegro.c -o jogo_dino_allegro $(pkg-config allegro-5 allegro_font-5 allegro_ttf-5 allegro_image-5 allegro_primitives-5 allegro_audio-5 allegro_acodec-5 --libs --cflags)
So I change the code, But now all the letters disappear. The game will stay with the black window.
And another think: I put images in the code, but they appear quickly, in milliseconds. How do I make them stay on screen longer?
See all the code and the files:
Thanks again. You all go to heaven with teleportation.
Not exactly sure about the blank text. What I did see is that you commented out al_init_font_addon.
You need to init both:
must_init(al_init_font_addon(), "font"); //WE NEED TO INIT FONT FIRST! must_init(al_init_ttf_addon(), "ttf font"); //THEN WE NEED TO INIT TTF FONTS
Are you sure the font is loading correctly? It worked for me. I used a generic TTF font and the words were there.
How about you get one font to work before trying 3.
About the image disappearing quickly:
Ideally you should separate ALL input from ALL logic from ALL drawing
1. process input
2. do logic on current state and input
3. draw based on state
You are drawing dino in the input section
Then in the drawing portion you are clearing the screen.
Hello. The font is working, thank you so much!
But I don't understand about the image. Can you explain a little bit more?
You only want to draw the image in the "draw" code, before you flip the display. You can use the gameState to see if you should draw the image:
if(redraw && al_is_event_queue_empty(queue)) { al_clear_to_color(al_map_rgb(0, 0, 0)); al_draw_text(font, al_map_rgb(255, 255, 255), 200, 500, 0, text); al_draw_text(font1, al_map_rgb(255, 255, 255), 400, 550, 0, text1); al_draw_text(font2, al_map_rgb(255, 255, 255), 400, 650, 0, text2); if(gameState == STATE_START) al_draw_bitmap(apresentacao, 70, 100, 0); al_flip_display(); redraw = false; }
I have attached full source code for you.
Hi everyone!
So, in the font, I adjust where the text will go in the windows with the lines
But can I change in the lines
sprintf(text, "%s", "DINO PERCEBE UM METEORO VINDO EM SUA DIREÇÃO E COMEÇA A FUGIR. LOGO A SUA FRENTE, DINO VÊ UM BURACO!");
?
I have a lot of different size for the lines, and like to change everyone manualy to be aesthetically more beautiful.
Thanks all of you!!!!
It's probably time to create a draw function, and draw different things depending on the state. Alternatively you could encode some characters in the string, and then have a function to print them as required. Probably easier for now, to just draw different things depending on the game state. In the attached source code, I have created a drawGame function, which is called every frame. I have put the first few states in for you (and removed them from the keypress/logic loop), to get you started....but there is a lot to move, so I'll leave the rest up to you!!
Wow, it's working perfectly. Thank you so much for everything, everyone!
I will finish this topic (finally), and I will start other projects using allegro.
But you were instrumental in helping me understand the basics and logic! Thank you very much!