I've been trying to get this to build for hours, I have no idea what's wrong. Any help is appreciated, thank you.
Here's the code:

main.cpp

#include "SDL/SDL.h"
#include "Core.h"
#include "GameStates.h"
#include "globals.h"

int main(int argc, char** args) 
{
    if(core.Initilization(640, 480, 32, SDL_SWSURFACE) == -1)
    {
        SDL_Quit();
    }

    while(core.desiredstate != core.quit)
    {
        ::currentstate->EventHandling();
        ::currentstate->Logic();
        core.ChangeState();
        ::currentstate->Render();
        ::currentstate->Update();
    }

    SDL_FreeSurface(core.screen);
    SDL_Quit();
}

Core.h:

#ifndef CORE_H
#define CORE_H
#include "SDL/SDL.h"
#include <string>

class Core
{
    public:
        SDL_Surface* Load(std::string filename);
        SDL_Surface* screen;

        bool Initilization(int SCREEN_WIDTH, int SCREEN_HEIGHT, int SCREEN_BPP, int FLAGS);

        void ApplySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination);
        void SetState(int newstate);
        void ChangeState();

        enum state { intro, state_null, quit };

        int desiredstate, stateID;
} core;

#endif

Core.cpp

#include "Core.h"
#include "GameStates.h"
#include "SDL/SDL.h"
#include "Intro.h"
#include "globals.h"
#include <string>

/* Starts SDL subsystems and sets screen attributes */
bool Core::Initilization(int SCREEN_WIDTH, int SCREEN_HEIGHT, int SCREEN_BPP, int FLAGS) 
{
    //starts SDL subsystems, returns false upon error
    if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
    {
        return false;
    }

    //The screen
    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, FLAGS);
    //Returns false if there was an error
    if(screen == NULL)
    {
        return false;
    }

    SDL_WM_SetCaption("Game", NULL);

    return true;
}

/* Loads an image and optimizes it */
SDL_Surface* Core::Load(std::string filename)
{
    //original loaded image
    SDL_Surface* original = SDL_LoadBMP(filename.c_str());
    SDL_Surface* optimized = NULL;

    if(original != NULL)
    {
        //Sets optimized to optimized version of original
        optimized = SDL_DisplayFormat(original);

        SDL_FreeSurface(original);
    }

    return optimized;
}

/* Blits surfaces */
void Core::ApplySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination) 
{
    //holds the x y coordinates
    SDL_Rect location;
    location.x = x;
    location.y = y;

    if(destination != NULL) 
    {
        SDL_BlitSurface(source, NULL, destination, &location);
    }
}

Intro.h

#ifndef INTRO_H
#define INTRO_H
#include "SDL/SDL.h"
#include "GameStates.h"

class Intro : public GameStates
{
    private:
        SDL_Surface* test;
    public:
        Intro();
        void EventHandling();
        void Logic();
        void Render();
        void Update();
        ~Intro();
};

#endif

/* Sets desiredstate to be used in ChangeState(); */
void Core::SetState(int newstate) 
{
    if(desiredstate != state_null && desiredstate != quit)
    {
        desiredstate = newstate;
    }
}

/* Changes the game state */
void Core::ChangeState()
{
    if(desiredstate != state_null && desiredstate != quit)
    {
        //frees old state memory
        delete ::currentstate;

        switch(desiredstate)
        {
            case intro:
                //allocates new state memory
                ::currentstate = new Intro();
            break;
        }

        stateID = desiredstate;
        desiredstate = state_null;
    }
}

GameStates.h

#ifndef GAMESTATES_H
#define GAMESTATES_H

class GameStates 
{
    public:
        virtual void EventHandling() = 0;
        virtual void Logic() = 0;
        virtual void Render() = 0;
        virtual void Update() = 0;
};

#endif

Intro.cpp

#include "Intro.h"
#include "GameStates.h"
#include "Core.h"
#include "SDL/SDL.h"

Intro::Intro()
{
    test = core.Load("test.bmp");
}

void Intro::EventHandling()
{
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_QUIT:
                core.SetState(core.quit);
            break;
        }
    }
}


void Intro::Logic()
{
    //to be coded when it finally builds...
}
void Intro::Render()
{
    core.ApplySurface(30, 30, test, core.screen);
}

void Intro::Update()
{
    SDL_Flip(core.screen);
}

Intro::~Intro()
{
    SDL_FreeSurface(test);
}

globals.h

#ifndef GLOBALS_H
#define GLOBALS_H
#include "GameStates.h"
#include "SDL/SDL.h"

extern GameStates* currentstate;

#endif;

globals.cpp

#include "globals.h"
#include "GameStates.h"

currentstate = NULL;

And finally, the error:

/home/lincoln/Desktop/test/src/Intro.cpp:6: multiple definition of core' main.o:/home/lincoln/Desktop/test/src/main.cpp:7: first defined here Core.o: In functionCore::Initilization(int, int, int, int)':
/home/lincoln/Desktop/test/src/Core.cpp:10: multiple definition of core' main.o:/home/lincoln/Desktop/test/src/main.cpp:7: first defined here main.o: In functionmain':
main.cpp:(.text+0x49): undefined reference to currentstate' main.cpp:(.text+0x56): undefined reference tocurrentstate'
main.cpp:(.text+0x62): undefined reference to currentstate' main.cpp:(.text+0x73): undefined reference tocurrentstate'
main.cpp:(.text+0x89): undefined reference to currentstate' main.o:main.cpp:(.text+0x9a): more undefined references tocurrentstate' follow
collect2: ld returned 1 exit status
make: *** [game] Error 1

Thanks for all of your help!

Edited 4 Years Ago by linc186

One problem is in Core.h:

class Core
{
    ...
} core;

Every time you include Core.h, it defines a variable core--that's where the 'multiple definition' errors are coming from.

Assuming what you want is a single global instance of your Core class, you can do it the following way instead.

In Core.h:

class Core
{
    ...
};

extern Core core;

Somewhere in Core.cpp:

Core core;

This way, everything including Core.h gets the extern declaration, which tells them that there's a variable called core defined somewhere, but the only place it actually gets defined is once, in Core.cpp.

I see you've used extern elsewhere in your code--does this makes sense?

Is the code beginning on line 21 of Intro.h really in intro.h or is that just a posting mistake? It should be in a file named intro.cpp. If you really have it in intro.h then that is a problem, remove it and put it in intro.cpp.

As for the undefined errors, that means the linker can't find the named symbol(s), check for spelling and/or capitalization errors.

Edited 4 Years Ago by Ancient Dragon

I noticed some other issues... what compiler are you using? GCC complains about these things; are you getting warnings when you build?

In globals.h, you have #endif;--the semicolon shouldn't be there; just use #endif.

In globals.cpp, currentstate = NULL; should be GameStates* currentstate = NULL;--you need to reiterate the type in the definition.

There is no need to include GameStates.h again here, because it is already included in globals.h.

In Intro.h, you have a variety of function implementations for your Core class--these should be in Core.cpp, not in an unrelated header. Or is that a copy/paste error in the post?

This article has been dead for over six months. Start a new discussion instead.