Saturday, January 19, 2019

c++ - OpenGL Textures not showing


So I'm currently working on a small C++ project for a school assessment and for some reason my Textures are not showing when I run the game. I don't get any compilation errors but they don't show up. I first used


int main()

only for my code but after reading up on functions I thought my code would be better if I used those. The game was working perfectly fine before I started using functions so my question is about the placement of a few parts of my code.


here is the entire code:


#include "raylib.h"


//Variable declaration
static int screenWidth = 800; // Set screen width.
static int screenHeight = 450; // Set Screen Height.
static int EnemyMove = 0;
static int Score = 0;
static int Lives = 5;
static int EnemySpeed = 6;

static Vector3 PlayerPosition = {336.0f, 361.0f, 0.0f}; //Define positions of all objects at the start of the game.
static Vector3 IceCreamPosition = {600.0f, 300.0f, 0.0f};

static Vector3 EnemyPosition = {75.0f, 25.0f, 0.0f};

static bool HasIce = true;
static bool IceShooting = false;
static bool HitEnemy = false;
static bool GameStarted = false;

Image Cone;
Image Ice;
Image Enemy;


Texture2D ConeText;
Texture2D IceText;
Texture2D EnemyText;

//local Function declaration
static void InitGame(void); // Initialize game
static void UpdateGame(void); // Update game (one frame)
static void DrawGame(void); // Draw game (one frame)
static void UpdateDrawFrame(void); // Update and Draw (one frame)


int main()
{
// Initialization
//--------------------------------------------------------------------------------------

InitWindow(screenWidth, screenHeight, "Icecream Eater");

InitGame();


//--------------------------------------------------------------------------------------

// Main game loop.
while (!WindowShouldClose()) // Detect window close button.
{

UpdateDrawFrame();
}

// De-Initialization

//--------------------------------------------------------------------------------------
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

return 0;
}

static void InitGame(void)
{
Image Cone = LoadImage("Images/Cone.png"); //load image into CPU memory.

Image Ice = LoadImage("Images/Ice.png");
Image Enemy = LoadImage("Images/Enemy.png");

Texture2D ConeText = LoadTextureFromImage(Cone); //Convert the image into a Texture; Put in vram.
Texture2D IceText = LoadTextureFromImage(Ice);
Texture2D EnemyText = LoadTextureFromImage(Enemy);

UnloadImage(Cone);
UnloadImage(Ice);
UnloadImage(Enemy);


SetTargetFPS(60); //define Target Frames per second.

}

static void UpdateGame(void)
{
if(!GameStarted && IsKeyPressed(KEY_ENTER)){
GameStarted = true;


}
if(GameStarted){
// Update
if(HasIce){ //If player has Ice the Ice will attach to the player.
IceCreamPosition.x = PlayerPosition.x + 12;
IceCreamPosition.y = PlayerPosition.y - 17;

if(IsKeyPressed(KEY_SPACE)){ //if the Space key is pressed the player goes to a shooting state.
IceShooting = true;
HasIce = false;

}
}

if(!HasIce && IceShooting){ //if the player doesn't have Ice and Is shooting check for collision with Enemy.
if(((EnemyPosition.x - IceCreamPosition.x < 10 && EnemyPosition.x - IceCreamPosition.x > - 40) && (EnemyPosition.y - IceCreamPosition.y > -64 && EnemyPosition.y - IceCreamPosition.y < 34))){
HasIce = true;
IceShooting = false;
Score ++;
EnemySpeed += 2;
EnemyPosition.x = 75;

EnemyMove = 0;
}

}

// Move player
if (IsKeyDown(KEY_RIGHT) && PlayerPosition.x < (screenWidth - 64)) PlayerPosition.x += 2.5f;
else if (IsKeyDown(KEY_LEFT) && PlayerPosition.x > 0) PlayerPosition.x -= 2.5f;
else if (IsKeyDown(KEY_DOWN) && PlayerPosition.y < (screenHeight - 64)) PlayerPosition.y += 2.5f;
else if (IsKeyDown(KEY_UP) && PlayerPosition.y > 325) PlayerPosition.y -= 2.5f;


if(IceShooting){ //Shoots ice
IceCreamPosition.y -= 5;
}

{ //enemy movement
if(EnemyMove <= 540){
EnemyPosition.x += EnemySpeed;
EnemyMove += EnemySpeed;


}
else if(EnemyMove >= 540 && EnemyMove <= 1080){
EnemyPosition.x -= EnemySpeed;
EnemyMove += EnemySpeed;

}
else if(EnemyMove == 1080){
EnemyMove = 0;

}

}

if(IceCreamPosition.y < 0 || HitEnemy){ //checks if icecream it the top
HasIce = true;
IceShooting = false;
Lives --;
EnemyPosition.y += 50;
}

if(Lives == 0){ // ends game if player has no lives left

CloseWindow();

}
}

}

static void DrawGame(void)
{
BeginDrawing();


ClearBackground(RAYWHITE);

if(GameStarted){
//draw all Textures for in game.
DrawTexture(EnemyText, EnemyPosition.x, EnemyPosition.y, WHITE);
DrawTexture(ConeText, PlayerPosition.x, PlayerPosition.y, WHITE);
DrawTexture(IceText, IceCreamPosition.x, IceCreamPosition.y, WHITE);

//draw all HUD elements.

DrawText(FormatText("Score: %i", Score), 10, 10, 20, LIGHTGRAY);
DrawText(FormatText("Turns: %i", Lives), 700, 10, 20, LIGHTGRAY);
}
else{
//draw starting menu.
DrawText("Stop the crazy woman", 200, 50, 20, LIGHTGRAY);
DrawText("from eating your icecream cone.", 200, 70, 20, LIGHTGRAY);
DrawText("Make sure she is full by", 200, 90, 20, LIGHTGRAY);
DrawText("Feeding her scoops of ice cream.", 200, 110, 20, LIGHTGRAY);
DrawText("Press ENTER to begin.", 200, 130, 20, LIGHTGRAY);

}

EndDrawing();

}

static void UpdateDrawFrame(void)
{
UpdateGame();
DrawGame();


}

my question is regarding this part of my code


Image Cone = LoadImage("Images/Cone.png"); //load image into CPU memory.
Image Ice = LoadImage("Images/Ice.png");
Image Enemy = LoadImage("Images/Enemy.png");

Texture2D ConeText = LoadTextureFromImage(Cone); //Convert the image into a Texture; Put in vram.
Texture2D IceText = LoadTextureFromImage(Ice);

Texture2D EnemyText = LoadTextureFromImage(Enemy);

UnloadImage(Cone);
UnloadImage(Ice);
UnloadImage(Enemy);

this is used to get the textures from the computer into ram and then into vram and then remove them from ram again. LoadImage cannot be used before the initialization of initWindow


does someone know why the images are not showing up?


Image Cone;


Image Ice; Image Enemy;


Texture2D ConeText; Texture2D IceText; Texture2D EnemyText;


I placed those in the variable declaration because otherwise I get an error telling me that those variables are not declared in scope.


if someone could help me that would be greatly appreciated



Answer



The reason for this is something called scope.


These two lines:




  • Texture2D ConeText; (at the top of your program)





  • Texture2D ConeText = LoadTextureFromImage(Cone); (inside your InitGame function)




each define a new Texture2D variable called ConeText.


The reason you don't get a compiler error about re-defining an identifier is that these sit in two different scopes.




  • the first is in Global Scope. Any code in your program can use ConeText to refer to this variable.





  • the second is in the InitGame function's Local Scope. That means any line of code inside InitGame that says ConeText will refer to this local version. This is called Variable Shadowing, and the local ConeText is said to mask the global version.


    Since this variable is local to InitGame, any value you put there will not be available to other code after InitGame returns. They'll just see the global ConeText which has still never been populated.




The fix is simple: if you don't want to declare a new variable, don't put the variable type before the name.


ConeText = LoadTextureFromImage(Cone);

This line says "take the exisiting variable ConeText and assign a value to it" rather than declaring a new local variable with the same name.



No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...