0
\$\begingroup\$

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

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
  • 2
    \$\begingroup\$ I just wanted to mention that turning on warnings in your compiler might be a good idea (and perhaps even treating the warnings as errors), as this error could have been easily detected if warnings were enabled. \$\endgroup\$ – Tyyppi_77 Nov 29 '18 at 16:08
  • \$\begingroup\$ warnings are already turned on but just didn't get any. I know they're turned on because when I change some stuff around I get a warning. \$\endgroup\$ – Yvalson Dronkers Nov 29 '18 at 16:52
  • \$\begingroup\$ thank you @DMGregory I knew about scopes I already but forgot about the declaring the variable again part which is pretty dumb because I'm fairly competent using Unityscript and GML just slipped my mind. anyway thank you it fixed my problem. but did create another \$\endgroup\$ – Yvalson Dronkers Nov 29 '18 at 16:55
  • \$\begingroup\$ everything is now completely fixed thanks for the support \$\endgroup\$ – Yvalson Dronkers Nov 29 '18 at 18:25

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.