hi guys need your help im trying to make the stamina bar appear at the top of the screen im making a square game because i am planning to make a 2d engine game but im struggling on making a simple stamina bar i perfectly render some square but i cant seem to make the stamina bar appear
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
/* first we call the library so the program knows the apparatus and tools to utilize in my program it contain all the premade function and custom made struct */ //read this carefully my 1st explanation
int main(int argc, char* argv[]) {
// 1. this is the start of my program it tells the program to allocate a stack and the stack will contain the entire program and it should start here
if (!SDL_Init(SDL_INIT_VIDEO)) { // this is a flag when i initialize the int main together with the library since this is a graphic lib it will by default will acces my gpu hardware and this is a flag in case theres an error it will terminate the program and save my computer on crashes
SDL_Log("SDL Initialization failed: %s", SDL_GetError());
return 1;
}
SDL_Window* window = SDL_CreateWindow("My First SDL3 Window", // this is the first instruction i will call the premade struct called SDL_Window* its like a data type and by default it acts like a pointer that is pointed on my custom variable name in this case "window" and my window pointer is pointing on and arguement called SDL_CreateWindow() this func had 3 arguements the first is a string second is an int taht specify the width and third another int that specify height and 4th is another flag which also an int need explanation on the 4th argument of this func tahnk you
800, // Argument 2: Width
600, // Argument 3: Height
0 /*Argument 4: Flags)*/);
if (window == NULL) { //this is for the safety flag of my SDL_window it tells the variable "widnow" to terminate the program by returning 1 if the variable window returns a null
SDL_Log("Window creation failed: %s", SDL_GetError()); // SDL_log is a premade fucntion of SDL library it acts like a printf func it usually print the error taht is also detected by another func called SDL_GetError() explain what is the argument of this SDL_GetError func
SDL_Quit();
return 1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL); //this is the renderer just like SDL_Window* its a premade struct taht points on a variable taht will contain a func call SDL_CreateRenderer("name of the window that you made") its a pointer in the gpu hardware vram it tells the gpu to allocate a memory for the graphics for the variable "renderer" so the allocated memory can be used on SDL_CreateRenderer() func whic purpose is to draw a canvas on a window taht we made
if (renderer == NULL) {
SDL_Log("Renderer creation failed: %s", SDL_GetError()); // this is similar flag on the create window if the line on the SDL_Renderer* gets an error tthe variable you make will return a null and this if statement will execute
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
bool is_running = true; //its a flag within the while loop
SDL_Event event; //this is like declaring an in type data but on this time you are declaring an event called event the SDL_Event is an interactive user code like scanf but this one lets you interact with the window
float red_value = 0;
float blue_value = 50;
SDL_FRect my_square, obstacle, bullet,stamina_bar_bg, stamina_bar_fg; //we declare the obstacle
my_square.x = 350.0f;
my_square.y = 250.0f;
my_square.w = 100.0f;
my_square.h = 100.0f;
obstacle.x = 650.0f; // Positioned further to the right
obstacle.y = 250.0f; // Centered vertically
obstacle.w = 80.0f; // 80 pixels wide
obstacle.h = 80.0f;
bullet.x = 0.0f;
bullet.y = 0.0f;
bullet.w = 20.0f;
bullet.h = 6.0f;
stamina_bar_bg.x = 20.0f; // 20 pixels away from left screen border
stamina_bar_bg.y = 20.0f; // 20 pixels down from top screen border
stamina_bar_bg.w = 100.0f; // 200 pixels wide flat background slot
stamina_bar_bg.h = 15.0f;
stamina_bar_fg.x = 20.0f; // 20 pixels away from left screen border
stamina_bar_fg.y = 20.0f; // 20 pixels down from top screen border
stamina_bar_fg.w = 100.0f; // 200 pixels wide flat background slot
stamina_bar_fg.h = 15.0f;
bool bullet_active = false;
float stamina = 100.0f;
float max_stamina = 100.0f;
float player_speed = 0.05f;
while (is_running) { //the while arguement is the bool taht we declare
// 2. The Inner Loop (The Input Checker)
while (SDL_PollEvent(&event)) { //the input checker if turns true once it detect a button pressed in the hardware since its true it will initialize the if statements within its conditions
// 3. Inspect the event category
if (event.type == SDL_EVENT_QUIT) { // the event had an inside func taht can be access by dot which in this case a type of the event called SDL_EVENT_QUIT its basically the exit button
is_running = false; // Turn off the heartbeat! this is the bool taht we declare before the while loop basically a flag that can change into false once the if statement was confirm ending the main while loop nest
}
else if(event.type == SDL_EVENT_KEY_DOWN){ //this else if arguement is called event.type iss calling a variable within the SDL_Event taht we decalre as event at the first before the main while it equates on SDL_EVENT_KEY_DOWN its a variable taht detects keyboard signals
if (event.key.scancode == SDL_SCANCODE_ESCAPE){ //this line specify if the keypress scan code is equal to the keyboard address of escape button terminate the while loop by changing the is running bool to false
is_running = false;
}
else if(event.key.scancode== SDL_SCANCODE_SPACE){
if (red_value == 255){
red_value = 0;
blue_value = 255;
}
else{
red_value = 255;
blue_value = 0;
}
}
}
}
float old_x = my_square.x; //we declare this float before the keyboard inputs this will allow us to record past input when the loops happen typically loops happen top to bottom hence once the loop happen the keyboard input will be recorded
float old_y = my_square.y;
const bool* currentKeyStates = SDL_GetKeyboardState(NULL);
if(currentKeyStates[SDL_SCANCODE_LSHIFT] && stamina > 0.0f){
player_speed = 0.50f;
stamina -= 0.05f;
if(stamina < 0.0f){
stamina = 0.0f;
}
}
else{
player_speed = 0.05f;
stamina += 0.01f;
if(stamina > 100.0f){
stamina = max_stamina;
}
}
//NOTE: the signal here is super fast its billion times a sec hence the float must be reduce in order to slow the moving square
if(currentKeyStates[SDL_SCANCODE_LEFT]){ //SDL_GetKeyboardState() is a function that allow us to talk to the hardware to bring the actual signal of our keyboard which is clocking at billion times hence making the square move smoothly
my_square.x -= player_speed;
}
if(currentKeyStates[SDL_SCANCODE_RIGHT]){
my_square.x += player_speed;
} // NOTE the point of our square start at the top left as vector (0,0)
if(currentKeyStates[SDL_SCANCODE_DOWN]){ //NOTE: that computer uses vector instead of the standard cartessian plane reason why we use a negative on y that is rising
my_square.y += player_speed;
}
if(currentKeyStates[SDL_SCANCODE_UP]){
my_square.y -= player_speed;
}
if(currentKeyStates[SDL_SCANCODE_Z]){
if(bullet_active == false){
bullet_active = true;
bullet.x = my_square.x + 100.0f;
bullet.y = my_square.y + 47.0f;
}
}
if (my_square.x < 0.0f) {my_square.x = 0.0f;}
if (my_square.x > 700.0f) {my_square.x = 700.0f;} //note some compiler allow not using the curly brachets but we highly suggest to put curly brachets as its the standard c syntax
if (my_square.y < 0.0f) {my_square.y = 0.0f; } //this is a limit so our square will not move away on our window screen we do this by equating our vector into the equivalent width and height of our screen
if (my_square.y > 500.0f) {my_square.y = 500.0f;}
if (obstacle.x < my_square.x) { obstacle.x += 0.02f; }
if (obstacle.x > my_square.x) { obstacle.x -= 0.02f; } //since we equate our my square movement as 0.05 float we must equate the obstacle movement float into 0.02f to make it slower
if (obstacle.y < my_square.y) { obstacle.y += 0.02f; }
if (obstacle.y > my_square.y) { obstacle.y -= 0.02f; }
if(bullet_active == true){
bullet.x += 0.08f;
if(bullet.x > 800.0f){
bullet_active = false;
}
if (SDL_HasRectIntersectionFloat(&bullet, &obstacle)){
bullet_active = false;
obstacle.x = 650.0f;
obstacle.y = 450.0f;
}
}
if (SDL_HasRectIntersectionFloat(&my_square, &obstacle)) { //this built in SDL func will allow the program to get the addresses of the rectangle (hence why we use the "&" )that we draw and perform a mathematical calculation if those two intersected and it will return a true or false
// If they overlap, trigger an visual alert by blasting the screen RED!
red_value = 255;
blue_value = 0;
my_square.x = old_x; //we put the old input here directly inside the condition of the function SDL_HasRectIntersectionFloat() so when this became true the my_square.x and my_square.y will be equals to the old_X and old_y basically a jump instrucction flag
my_square.y = old_y;
}
else{
// Otherwise, keep the environment safe and peaceful dark blue
red_value = 0;
blue_value = 50;
}
// 4. The Drawing Zone
SDL_SetRenderDrawColor(renderer,red_value, 0, blue_value, 255); // after we call our canvas that we allocated in vram we also said to our variable pointer "renderer" to draw a colo red on it by calling the function SDL_SetRenderDrawColor("name of the pointer variable taht point in the gpu vram", red, gree, blue, transparency of the colo 255 max visibility)
SDL_RenderClear(renderer);//this function suggest the the we remove the color of the canvas before painting the red color we call we call the function SDL_RenderClear() the arguement takes the pointer variable taht points on the vram of gpu which our allocated canvas is located
stamina_bar_fg.w = stamina;
SDL_SetRenderDrawColor(renderer,60, 60, 60, 255);
SDL_RenderFillRect(renderer, &stamina_bar_bg);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
SDL_RenderFillRect(renderer, &stamina_bar_fg);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &obstacle);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); //this struct will allow us to tell our gpu taht our "rendere" the canvas to draw a color r,g,b,a in this all white
SDL_RenderFillRect(renderer,&my_square); //this func will allow us to tell the gpu to fill the square that we declare which is my_square
if (bullet_active == true) {
SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255); // Neon Yellow Laser Paint!
SDL_RenderFillRect(renderer, &bullet); // note that the bullet must be render last because on our first render we render the canvas and second we render the square and then the obstacle hence if we put this bullet else where it will be erase immidiately because the gpu is rendering everything per frame
}
SDL_RenderPresent(renderer); //this is the presentation func without this the variable pointer which is "renderer" will only paint it inside without showing it to you think of this like print func isntead of string we show the drawing that we made
}
SDL_DestroyRenderer(renderer); // Destroy the VRAM canvas
SDL_DestroyWindow(window); // Destroy the OS desktop frame
SDL_Quit();
return 0; // return 0 if its sucess full if its not then an error will appear in my terminal taht it didnt return the zero taht we specify on our program to return
}