Sunday, October 23, 2011

SmashPC is Started!

So, I've decided specifically what type of game I'll be making.  It'll be a top-down Alien Swarm type game (for those old guys, think SmashTV).  In fact, I've named it SmashPC.

What I've done for this initial code drop is implement the basics as far as SFML window, simple sprite drawing, playing Sounds, and Input and input configuration.

You can get the full source code and project here:
(Link Removed, get newer version)

First, we need to create a project.  So, using Code::Blocks, I made a project, and pointed at all the libraries I would need.

Here's my settings for the Compiler and Linker:



(Check out the links for sfml, tinyxml, and chipmunk-physics in the 1st blog entry to get those libraries.  I use sfml2.0, but 1.6 should work fine).

Next, I add the main source code (in SmashPc.cpp), and a simple main loop.  Here's what I have so far:

int main(int argc, char *argv[])
{
    sf::Event Event;
    BOOL bFullScreen;

    GameSound::Init("SmashPcSounds.xml");
    Utilities::LoadConfig("SmashPcCfg.xml");

    Utilities::ScreenResolutionGet(gu32GravScreenX, gu32GravScreenY, bFullScreen);

 sf::RenderWindow App(sf::VideoMode(gu32GravScreenX, gu32GravScreenY, 32), "SmashPC", (bFullScreen ? sf::Style::Fullscreen : sf::Style::Default));

    gpOurPlayer = new SmashPcPlayer(&App);

    srand(time(NULL));

    App.ShowMouseCursor(true);
    App.SetCursorPosition(gu32GravScreenX/2, gu32GravScreenX/2);

    // main game loop
    while (App.IsOpened())
    {
        float FrameTime;
        const sf::Input& Input = App.GetInput();

        while (App.PollEvent(Event))
        {
            // Window closed
            if (Event.Type == sf::Event::Closed)
            {
                App.Close();
                GameSound::Shutdown();
            }

            // Escape key pressed
            if (Event.Type == sf::Event::KeyPressed)
            {
                if (Event.Key.Code == sf::Key::Escape)
                {
                    App.Close();
                    GameSound::Shutdown();
                }
            }
        }

        gpOurPlayer->CheckInput();

        FrameTime = App.GetFrameTime();

        if (FrameTime > 1/60.0f)
        {
            //printf("Frametime %f expected %f\n", FrameTime, 1/60.0f);
        }
        else
        {
            Sleep((U32)((1/60.0f - FrameTime)*1000.0f));
            FrameTime = 1/60.0f;
        }

        /* clear screen and draw map */
        App.Clear();

        gpOurPlayer->Draw();

        App.Display();
    }

    return 0;
}

You see some simple SFML setup, but we're also calling the functions GameSound::Init() and Utilities::LoadConfig().  

Gamesound::Init loads the sounds stored in SmashPcSounds.xml.  Here's that function:

void GameSound::Init(char *pcFilename)
{
    if (bNeedsInit)
    {
        TiXmlDocument doc(pcFilename);

        // load and check if it was successful
        if (doc.LoadFile())
        {
            TiXmlElement *root = doc.RootElement();

            for(TiXmlElement* example = root->FirstChildElement(); example;
                example = example->NextSiblingElement())
            {
                char cFile[32];
                std::string SoundStr  = example->ValueStr();

                printf("Found SoundName %s .. ", SoundStr.c_str());

                SoundMap[SoundStr] = new sf::SoundBuffer();

                sprintf(cFile, "Sfx/%s", example->GetText());

                if (!SoundMap[SoundStr]->LoadFromFile(cFile))
                {
                    printf("Failed loading sound %s!\n", cFile);
                }
            }
        }
        else
        {
            printf("Failed opening GravithonSounds.xml\n");
        }

        bNeedsInit = FALSE;

    }

}

This is using tinyxml to parse the xml file, and it uses std::map to associated a string to a sfml sound buffer.  This way, you play a sound you'd just pass in the string to play, like GameSound::Play("PeaShooter");

The next piece you saw was the call to Utilities::LoadConfig().  This function loads the SmashPcCfg.xml file and setups the users prefrences with respect to controls, mouse sensitivty, and screen resolution.  Take a look at the Utilities.cpp and.h for more info on how it does that.

Finally, there's SmashPcPlayer class. Here's the constructor:

SmashPcPlayer::SmashPcPlayer(sf::RenderWindow *pApp) :
mpApp(pApp),
mu32Health(100),
mu32Armor(0),
mu32LastFire(0),
mu32LastSpecialFire(0)
{

    // Load the temp image for this player
    mpImage = Utilities::ImageGet("Gfx/Player.bmp");

    mpSprite = new sf::Sprite();
    mpSprite->SetImage(*mpImage);
    mpSprite->SetOrigin(mpImage->GetWidth()/2, mpImage->GetHeight()/2);

    // Set to middle of screen
    mpSprite->SetPosition(pApp->GetWidth()/2, pApp->GetHeight()/2);

    // Sound notifying a player has spawned
    GameSound::Play("PlayerSpawn");

}

We make a call to load the image (we use the Utilities function since we want to make sure we won't load the image more than once), and create a sprite from the image, set the sprite to the middle of the screen, and play a sound, noting the player has spawned in the world.

The SmashPcPlayer->Draw () currently just draws the sprite where the payer is.
And, SmashPcPlayer->CheckInput() simply moves the player around and plays a gunshot sound when you press the Fire button (configured as left mouse button).

Next time we'll add in chipmunk-physics 2d engine to handle all the big work for us as far as movement and collision detection.

No comments:

Post a Comment