hey, not sure if you address this in a different video but in this part of the code: velocity = Vector2Rotate(velocity, (float)GetRandomValue(-ASTEROID_RANDOM_ANGLE, ASTEROID_RANDOM_ANGLE)); doesnt GetRandomValue only accept integers but you are using floats so theres no rotation or its either -1 or 0 in radians
I think in this case GetRandomValue should have no problem downcasting the -30.0f and 30.0f to ints as -30 and 30 respectively, but you are right that we won't get a proper float value back, it'll just be an int casted back to a float. Then of course it also means that the rotation should be very wrong, it is indeed surprising that the asteroid spawning + splitting implemented later seem to work at all. Normally you'd have [0, 2*PI) of values, but since it's an int we only have {0, 1, 2, 3, 4, 5, 6}. For this simple of a game it seems to work fine, but this is definitely the wrong way to do it!
Raygui might not have enough coverage on here! I have a couple videos in the pipeline to help address that. One to overview the extension, and one to build some static wrappings to make adding entries simpler.
Your videos are great, and your class is one of the best, seriously, I've watched a lot of videos on the topic and my understanding is shallow. Please continue with your raylib tutorial videos, they help a lot, you gained another subscriber. If you want the next topic to show here, it would be a top one about GObject, which is a library for C where you work with OOP using C and you can use Python, Java, among others .....
Cool and informative video. I liked it. I wanted to point out that the asteroids, in the initial version, screen wrap so you wouldn’t have to worry about tracking them off screen if you wanted to go that route. The original game was a “waves” game in that you cleared waves of asteroids to get ready for the next wave. I’m sure you know a lot of this stuff already but just in case… Shooting an asteroid breaks it down into a handful of smaller ones. And shooting the smaller ones creates a handful of tiny ones. You clear the wave by shooting all of the tiny ones. Also don’t forget to add the random UFO that zigzags across the screen randomly shooting bullets. You’d shoot those for extra points. Anyway, I really like your videos and am looking forward to seeing part 2.
We need people like you because of people like me 🤣. For the scope of the main chunk of the series (spoiler, there's 4 parts) I focus on showing how I build a system to spawn asteroids, a system to control the player, how I handle destroying asteroids and awarding points and then how it all comes together with player and game state. There's no UFO or waves.. yet. For now it's just the 4 parts but I reserve the right to make little bonus videos later that might go back and add these more faithful items.
Instead of iterating through the array of asteroids It might be better to have a variable for the current amount of asteroids so you can just index into the array with the asteroidCount + 1 to get a open spot for a new asteroid. With bounds checking of course to make sure it's not over the size of the array. It would also allow to not need to check whether a asteroid is active or not every frame because you can just update or draw the array from 0 to asteroidCount - 1.
This is true until you destroy an asteroid: as asteroids are destroyed you create holes in the array, so when I want to create a new asteroid I look for a hole in that array. Additionally, this level of optimization is not necessary for something that happens occasionally as opposed to *every frame*. The most important rule when it comes to optimization vs code complexity: "measure don't guess!"
Thanks for making this! Your videos help me a lot in understanding how to approach gamedev in C :) Btw, did you ever actually implement that the asteroids will deviate from tbe center? In the demo at the end, they all seem to be going straight through the center anyway
The more I stare at the gameplay clips, the more I become unsure. They REALLY don't look like they're avoiding the center.. so that's fun 😂 should have gone the route of "pick a random spot in a circle / box around the center and target that"
@@w花b The main reason to use the one-file for raylib examples is that you can build the game with a very simple gcc invokation, as opposed to a multi-file project where it makes more sense to employ Make / CMake. That kind of build stuff is complicated and can stunt learning, so I'm not against the one-file approach, but when I CAN I will show the multi file style.
I enjoyed following along. I noticed there is a bit of a ghosting effect coming from the asteroids. I'm seeing it in your recording too. Seems to have been fixed in the later parts of the tutorial. Do you know what is causing it? Or may be I am seeing stuff.
hello! I'm kinda new in C development. Is there a way to create a general "Entity" that has an update method and then instead of having an array of asteroids, have an array of entities that have different behavior? A way to "simulate" polimorphysm or composition maybe? I mean: Entity entities[MAX_ENTITIES]; for(int i = 0; int < MAX_ENTITIES; i++) { entities[i].update(); } In order to prevent having this: Asteroid asteroids[MAX_ENTITIES]; AnotherKindOfEnemy blabla[MAX_ENTITIES]; // ... more and more enemy types for(int i = 0; int < MAX_ENTITIES; i++) { asteroids[i].update(); blabla[i].update(); // ... all enemy types update() call } thank you in advance
Not really.. yes you "can" with Function Pointers but one of the main reasons to use C is to achieve better performance and a pattern like this is inherently not performant. For larger projects a common practice for C is ECS. You can check out FLECS to see an example of this.
When I start debugging (when using GuiButton() from raygui) it gives me an error "undefined reference to GuiButton" even though I followed all of your steps
Try switching BUILD_MODE from RELEASE to DEBUG at the top of the Makefile. This should cause the -O0 flag to be used when compiling which will prevent the function from being inlined which *may* be what happened when you built. It's hard to say what causes the optimizations, when in doubt I'd switch to debug mode wherever applicable.
hey, not sure if you address this in a different video but in this part of the code:
velocity = Vector2Rotate(velocity, (float)GetRandomValue(-ASTEROID_RANDOM_ANGLE, ASTEROID_RANDOM_ANGLE));
doesnt GetRandomValue only accept integers but you are using floats so theres no rotation or its either -1 or 0 in radians
I think in this case GetRandomValue should have no problem downcasting the -30.0f and 30.0f to ints as -30 and 30 respectively, but you are right that we won't get a proper float value back, it'll just be an int casted back to a float.
Then of course it also means that the rotation should be very wrong, it is indeed surprising that the asteroid spawning + splitting implemented later seem to work at all. Normally you'd have [0, 2*PI) of values, but since it's an int we only have {0, 1, 2, 3, 4, 5, 6}. For this simple of a game it seems to work fine, but this is definitely the wrong way to do it!
THANK GOD FINALLY A PERSON DOING RAYLIB!! EASY SUBS ON YOU!
The whole vid was good, but the Raygui examples were totally worth the price of admission. Why have I not been using that?!
Raygui might not have enough coverage on here! I have a couple videos in the pipeline to help address that. One to overview the extension, and one to build some static wrappings to make adding entries simpler.
Your videos are great, and your class is one of the best, seriously, I've watched a lot of videos on the topic and my understanding is shallow. Please continue with your raylib tutorial videos, they help a lot, you gained another subscriber. If you want the next topic to show here, it would be a top one about GObject, which is a library for C where you work with OOP using C and you can use Python, Java, among others .....
I have never heard of / seen GObject! Seems interesting..
Cool and informative video. I liked it.
I wanted to point out that the asteroids, in the initial version, screen wrap so you wouldn’t have to worry about tracking them off screen if you wanted to go that route. The original game was a “waves” game in that you cleared waves of asteroids to get ready for the next wave.
I’m sure you know a lot of this stuff already but just in case…
Shooting an asteroid breaks it down into a handful of smaller ones. And shooting the smaller ones creates a handful of tiny ones. You clear the wave by shooting all of the tiny ones.
Also don’t forget to add the random UFO that zigzags across the screen randomly shooting bullets. You’d shoot those for extra points.
Anyway, I really like your videos and am looking forward to seeing part 2.
We need people like you because of people like me 🤣. For the scope of the main chunk of the series (spoiler, there's 4 parts) I focus on showing how I build a system to spawn asteroids, a system to control the player, how I handle destroying asteroids and awarding points and then how it all comes together with player and game state. There's no UFO or waves.. yet.
For now it's just the 4 parts but I reserve the right to make little bonus videos later that might go back and add these more faithful items.
@@andrewhamelcodes712 fantastic!
Ah soooooo cool! Learning and loving c, wanted to make more game stuff with it. Happy to find this 🎉
Great video! Looking forward to part 2 :)
Instead of iterating through the array of asteroids It might be better to have a variable for the current amount of asteroids so you can just index into the array with the asteroidCount + 1 to get a open spot for a new asteroid. With bounds checking of course to make sure it's not over the size of the array. It would also allow to not need to check whether a asteroid is active or not every frame because you can just update or draw the array from 0 to asteroidCount - 1.
This is true until you destroy an asteroid: as asteroids are destroyed you create holes in the array, so when I want to create a new asteroid I look for a hole in that array.
Additionally, this level of optimization is not necessary for something that happens occasionally as opposed to *every frame*. The most important rule when it comes to optimization vs code complexity: "measure don't guess!"
Randy that finishes games
How did you know Randy was my real name?
@@andrewhamelcodes712 you won't believe this
Thanks for making this! Your videos help me a lot in understanding how to approach gamedev in C :)
Btw, did you ever actually implement that the asteroids will deviate from tbe center? In the demo at the end, they all seem to be going straight through the center anyway
The more I stare at the gameplay clips, the more I become unsure. They REALLY don't look like they're avoiding the center.. so that's fun 😂 should have gone the route of "pick a random spot in a circle / box around the center and target that"
@@w花b The main reason to use the one-file for raylib examples is that you can build the game with a very simple gcc invokation, as opposed to a multi-file project where it makes more sense to employ Make / CMake.
That kind of build stuff is complicated and can stunt learning, so I'm not against the one-file approach, but when I CAN I will show the multi file style.
Hello sir. Will you do more C and raylib tutorials? Maybe C++ too? Thanks in advance.
In time I'd really like to do more. It's hard to say when the next will come
I enjoyed following along. I noticed there is a bit of a ghosting effect coming from the asteroids. I'm seeing it in your recording too. Seems to have been fixed in the later parts of the tutorial. Do you know what is causing it? Or may be I am seeing stuff.
I think that's just an artifact of the recording, I didn't notice it before and now can't unsee it 😭
subed, thanks for video
hello! I'm kinda new in C development. Is there a way to create a general "Entity" that has an update method and then instead of having an array of asteroids, have an array of entities that have different behavior? A way to "simulate" polimorphysm or composition maybe? I mean:
Entity entities[MAX_ENTITIES];
for(int i = 0; int < MAX_ENTITIES; i++) {
entities[i].update();
}
In order to prevent having this:
Asteroid asteroids[MAX_ENTITIES];
AnotherKindOfEnemy blabla[MAX_ENTITIES];
// ... more and more enemy types
for(int i = 0; int < MAX_ENTITIES; i++) {
asteroids[i].update();
blabla[i].update();
// ... all enemy types update() call
}
thank you in advance
Not really.. yes you "can" with Function Pointers but one of the main reasons to use C is to achieve better performance and a pattern like this is inherently not performant. For larger projects a common practice for C is ECS. You can check out FLECS to see an example of this.
I have got a question. Why didnt't you use pointers with structs? Isn't that more efficient?
More efficient than what? Technically if I use an array, I am using pointers :)
@@andrewhamelcodes712 managing memory
When I start debugging (when using GuiButton() from raygui) it gives me an error "undefined reference to GuiButton" even though I followed all of your steps
Try switching BUILD_MODE from RELEASE to DEBUG at the top of the Makefile. This should cause the -O0 flag to be used when compiling which will prevent the function from being inlined which *may* be what happened when you built. It's hard to say what causes the optimizations, when in doubt I'd switch to debug mode wherever applicable.
@@andrewhamelcodes712 still wont work :/
@@andrewhamelcodes712 I got it to work!
This is not a tutorial coz you are speeding up the video while coding, nothing can be understood in the flow and functionality of the code here.
This comment haunts me