Pages

Saturday, August 27, 2011

Code::Blocks(16) RPG 4 - Game Menus






The game has two different menus, the start menu and in-game menu, the differences are the available options and what will happen when we choose them as seen here:

Start Menu:
  • NEW > Goto player creation
  • LOAD > Goto load game, Start game (Disabled)
  • EXIT > Quit game
Game Menu:
  • CONTINUE > Return to game
  • SAVE > Goto Save Game, Return Game (Disabled)
  • EXIT > Quit Game
For the menus I have created two images more:

Ball selector:



Menu Item:



I have used Gimp again to draw them, to draw the ball i just made a new, square shaped image, filled it with color FF,00FF (Pink) so i can apply later the colorkey, then i selected a circle and used the blend tool with orange and yellow colors.

Drawing the button was quite easy: Gimp > File > Create > Button > Simple beveled button, the only thing I made was to left the text empty so I can use the same button for all the menu items.

The logic for the menu is simple:
  • Define an "Option" variable, it will be which menu option is chosen.
  • Check the keyboard, and if we have pressed the following keys:
  1. Key up > decrease option 
  2. Key down > increase option
  3. Enter > execute action associated to the button (Change game state)
Now draw the menu:
  1. Fill with a color (grey)
  2. Draw menu tittle
  3. Draw menu buttons
  4. Draw the text into the menu buttons
  5. Draw the ball selector
Repeat until we press the enter key

      <"Game.cpp", Code for MenuStart:>
      void Game::MenuStart()    //Start menu
      {
      //MenuTittle ="START MENU";
      
      SDL_Surface* Button; //The menu buttons
      SDL_Surface* Ball; //The ball selector
      Button = IMG_Load("images/button.png");
      Ball = IMG_Load("images/ball.png");
      
      //The ball uses colorkey to display correctly
      SDL_SetColorKey(Ball,SDL_SRCCOLORKEY |SDL_RLEACCEL,SDL_MapRGB(Ball-> format, 255, 0, 255));
      
      
      SDL_Rect ButtonPosition ,BallPosition;
      int i; //An iterator for the loop
      int Option=1;//To select items
      
      //startx, starty Used to display images
      int startx = ((myengine.ScreenX / 2) - (Button->w/2) );
      int starty = (myengine.ScreenY / 2) ;
      
      
      bool done = false;
          while (!done) // will loop infinite times until we set done = true
          {
       SDL_Event event;
              while (SDL_PollEvent(&event))//Check new events
              {
                  // check for messages
                  switch (event.type)
                  {
                             // exit if the window is closed
                  case SDL_QUIT:
                      done = true;
                      break;
      
                      // check for keypresses
                  case SDL_KEYDOWN:
      
      
              // Down key
              if (event.key.keysym.sym == SDLK_DOWN)
              {
                 Option++; //Move down ball selector
                  if(Option>3)Option=1;
                  break;
              }
      
      
             //Up key
             if (event.key.keysym.sym == SDLK_UP)
             {
                   Option--;//Move up ball selector
                  if(Option<1)Option=3;
                  break;
             }
      
             //Return pressed
               if (event.key.keysym.sym == SDLK_RETURN)
             {
                 switch (Option)
                 {
                     case 1://NEW
                     myGameState=CREATEPLAYER;
                     break;
      
                     case 2://LOAD
                     myGameState=LOAD;
                     break;
      
                     case 3://EXIT
                     myGameState=OUTRO;
                     break;
      
                 }//switch option
                 done = true;
                 break;
             }//if
      
             //Exit game
             if (event.key.keysym.sym == SDLK_ESCAPE)
             {
                 done = true;
                 break;
             }
                  }//switch
              }//while
      
      myengine.FillColour(100,100,100);//Fill with grey
      
      myengine.SetTextColor( 0, 0, 255 );//Blue color
      myengine.TextOut(startx -50 ,100,"START MENU",3);//Menu tittle
      
      for (i=1;i<4;i++) // draw 3 buttons
      {
      ButtonPosition.x = startx; // X
      ButtonPosition.y = starty + (i*40); // Y
      ButtonPosition.w = Button->w;
      ButtonPosition.h = Button->h;
      
      SDL_BlitSurface(Button, NULL, myengine.screen, &ButtonPosition);//Draw button
      }//for
      
      BallPosition.x=startx -Ball->w;
      BallPosition.y=starty + (Option*40);
      BallPosition.w=Ball->w;
      BallPosition.h=Ball->h;
      
      SDL_BlitSurface(Ball, NULL, myengine.screen, &BallPosition);//Draw ball selector
      
      //Draw text for the options
      myengine.TextOut(startx + 10,starty + 50,"NEW",1);
      myengine.TextOut(startx + 10,starty + 90,"LOAD",1);
      myengine.TextOut(startx + 10,starty + 130,"EXIT",1);
      myengine.Flip();
      
      myengine.Wait(1);
        }//End while done loop
      
      //Free surfaces Before finishing
      SDL_FreeSurface(Button);
      SDL_FreeSurface(Ball);
      }
      

      <"Game.cpp", Code for MenuGame:>
      void Game::MenuGame()    //In-Game menu
      {
      
      SDL_Surface* Button; //The menu buttons
      SDL_Surface* Ball; //The ball selector
      Button = IMG_Load("images/button.png");
      Ball = IMG_Load("images/ball.png");
      
      //The ball uses colorkey to display correctly
      SDL_SetColorKey(Ball,SDL_SRCCOLORKEY |SDL_RLEACCEL,SDL_MapRGB(Ball-> format, 255, 0, 255));
      
      
      SDL_Rect ButtonPosition ,BallPosition;
      int i; //An iterator for the loop
      int Option=1;//To select items
      
      //startx, starty Used to display images
      int startx = ((myengine.ScreenX / 2) - (Button->w/2) );
      int starty = (myengine.ScreenY / 2) ;
      
      
      bool done = false;
          while (!done) // will loop infinite times until we set done = true
          {
       SDL_Event event;
              while (SDL_PollEvent(&event))//Check new events
              {
                  // check for messages
                  switch (event.type)
                  {
                             // exit if the window is closed
                  case SDL_QUIT:
                      done = true;
                      break;
      
                      // check for keypresses
                  case SDL_KEYDOWN:
      
      
              // Down key
              if (event.key.keysym.sym == SDLK_DOWN)
              {
                 Option++; //Move down ball selector
                  if(Option>3)Option=1;
                  break;
              }
      
      
             //Up key
             if (event.key.keysym.sym == SDLK_UP)
             {
                   Option--;//Move up ball selector
                  if(Option<1)Option=3;
                  break;
             }
      
             //Return pressed
               if (event.key.keysym.sym == SDLK_RETURN)
             {
                 switch (Option)
                 {
                     case 1://CONTINUE
      myGameState=MAINLOOP;
                     break;
      
                     case 2://SAVE
                     myGameState=SAVE;
                     break;
      
                     case 3://EXIT
                     myGameState=OUTRO;
                     break;
      
                 }//switch option
                 done = true;
                 break;
             }//if
      
             //Exit game
             if (event.key.keysym.sym == SDLK_ESCAPE)
             {
                 done = true;
                 break;
             }
                  }//switch
              }//while
      
      myengine.FillColour(100,100,100);//Fill with grey
      
      myengine.SetTextColor( 0, 0, 255 );//Blue color
      myengine.TextOut(startx -50 ,100,"GAME MENU",3);//Menu tittle
      
      for (i=1;i<4;i++) // draw 3 buttons
      {
      ButtonPosition.x = startx; // X
      ButtonPosition.y = starty + (i*40); // Y
      ButtonPosition.w = Button->w;
      ButtonPosition.h = Button->h;
      
      SDL_BlitSurface(Button, NULL, myengine.screen, &ButtonPosition);//Draw button
      }//for
      
      BallPosition.x=startx -Ball->w;
      BallPosition.y=starty + (Option*40);
      BallPosition.w=Ball->w;
      BallPosition.h=Ball->h;
      
      SDL_BlitSurface(Ball, NULL, myengine.screen, &BallPosition);//Draw ball selector
      
      //Draw text for the options
      myengine.TextOut(startx + 10,starty + 50,"CONTINUE",1);
      myengine.TextOut(startx + 10,starty + 90,"SAVE",1);
      myengine.TextOut(startx + 10,starty + 130,"EXIT",1);
      myengine.Flip();
      
      myengine.Wait(1);
        }//End while done loop
      
      //Free surfaces Before finishing
      SDL_FreeSurface(Button);
      SDL_FreeSurface(Ball);
      }
      
      

      <Now the game is starting to have what we would expect to find in a game, intros, menus.. in the next post the main game loop> 

      Monday, August 22, 2011

      Code::Blocks(15) RPG 4 - An intro screen



      <I will show how I did two things: the intro / splash screen and the outro, before starting I have to say that an intro screen is very important because it is like a business card: The sign from your game, obviously I'm not going to expend a week to make a 3D- synthesized intro but I will include it into the game so anybody can make their own, feel free to play with it>

      <My intro probably is the easier one you can do, I just made an Image with the gimp "File" > "Create" > "Logo" > then I chosen a marble texture, replaced the text and voilá!:>

      <Intro image, saved as "tittle.png">


      <Then what I did was to make the background to fade in from black to white while I was showing the tittle image, to do so I just made a for loop with an integer variable "i" and filled the background with that value from {0,0,0} to {255,255,255}, finally I added a small delay (10ms) every frame to make it a little slower>

      <"SplashScreen" method:>

      void Game::SplashScreen() //Splash /Intro Screen
      {
      
      SDL_Surface* Tittle; //A surface to load intro image
      Tittle = IMG_Load("images/tittle.png");
      int i;
      for (i=0;i<255;i++)
      {
      myengine.FillColour(i,i,i); //Will fill the background from color {0,0,0} (black) to {255.255.255} (white)
      SDL_Rect end; //To set the intro image position
      end.x = (myengine.ScreenX / 2) - (Tittle->w/2); // X
      end.y = (myengine.ScreenY / 2) - (Tittle->h/2); // Y
      end.w = Tittle->w;
      end.h = Tittle->h;
      
      SDL_BlitSurface(Tittle, NULL, myengine.screen, &end);//Blit the intro image
      
      myengine.Flip();
      SDL_Delay(10); // slow down the process so we will actually se something on screen
      
      }//For
      
      SDL_FreeSurface(Tittle);//Clean memory
      
      myGameState = MENUSTART; //Go to start menu
      }
      

      <for the outro I just swapped the colour order from (0 to 255) in the intro to (255 to 0)  in the outro so it faded from white to black>

      <"OutroScreen" method:>

      void Game::OutroScreen()//Splash Screen
      {
      
      SDL_Surface* Tittle; //A surface to load outro image
      Tittle = IMG_Load("images/tittle.png");
      int i;
      for (i=255;i>1;i--)//Will fill the background from color {255.255.255} (white) to {0,0,0} (black)
      {
      myengine.FillColour(i,i,i);
      SDL_Rect end;
      end.x = (myengine.ScreenX / 2) - (Tittle->w/2); // X
      end.y = (myengine.ScreenY / 2) - (Tittle->h/2); // Y
      end.w = Tittle->w;
      end.h = Tittle->h;
      
      SDL_BlitSurface(Tittle, NULL, myengine.screen, &end);
      myengine.Flip();
      SDL_Delay(10);// slow down the process so we will actually se something on screen
      
      }//For
      
      SDL_FreeSurface(Tittle);//Clean memory
      
      myGameState = END; // It does not needs an explanation, right?
      }
      

      <In the next post: Game menus..>

      Thursday, August 18, 2011

      Code::Blocks(14) RPG 4 - More classes , Game states and a few tweaks more



      <In this post I'm going to create the basic structure of the game, until now I had almost all the code included in the "rpg.cpp" file, but it was starting to get too big. I knew i needed to do a few things:>
      1. Clean up code, separate it into smaller parts.
      2. Create a Game State structure
      3. Use the new tileset!(see picture above)
      4. Create a folder to store images, move all references to the images to the new folder.
      <Before starting with the updates to the code I'm going to explain what the game states are and what i expect to do with them>

      <The best way to understand it is to look at this diagram:>
       <We have many "Screens" that represent different game states, in every game state the game acts in a different way (different input, output and logic), what we need is to have a way to store where the game is, so we can launch the code that will handle that particular state>

      <At the moment that's the project structure:>





      <To create the game states and to divide the code into smaller parts, we are going to change the project structure to:>

      <Now the "main" function include all the code,  how i made the changes? First I created a file "gamestates.h" that is basically an enum to know in what state the game is:>

      <File "gamestates.h">

      enum GameState { //Enumerates the game states
          INTRO = 1,
          MENUSTART = 2,
          LOAD = 3,
          CREATEPLAYER = 4,
          MAINLOOP = 5,
          MENUGAME = 6,
          SAVE = 7,
          OUTRO = 8 ,
          END = 99};
      
      

      <File rpg.cpp has been totally rewritten:>

      #include  //SDL library
      #include  //+SDL_image library (I use it for loading .png files)
      
      #include "game.h" //Core game class
      
      int main ( int argc, char** argv ) //when you use a SDL c++ app you have to initialize main that way
      {
      
      Game mygame; //Create an Instance of Game, Loads default values
      
      mygame.myGameState = INTRO; //We start with the intro screen
      
      bool done = false;
      while (!done) //Loop infinite times until done
      {
      
      switch (mygame.myGameState)
      {
      case INTRO: //Intro screen
      {
          mygame.SplashScreen(); //Shows an intro Splash Screen
          break;
      }
      
      case MENUSTART: //The first menu (new game, load...)
      {
          mygame.MenuStart();
          break;
      }
      
      case CREATEPLAYER: //Player creation process
      {
          mygame.CreatePlayer(); //Player Creation Process
          break;
      }
      
      case MAINLOOP: //Game main loop
      {
          mygame.MainLoop();//The main game loop
          break;
      }
      
      case MENUGAME: //In game menu (save game...)
      {
          mygame.MenuGame();
          break;
      }
      
      case OUTRO: //Outro screen
      {
          mygame.OutroScreen();//The main game loop
          break;
      }
      
      case SAVE: //Save game
      {
          mygame.SaveGame();
          break;
      }
      
      case LOAD: //Load Game
      {
          mygame.LoadGame();
          break;
      }
      
      case END: //End game
      {
          done = true;
          break; //exit switch , end game
      }
      
      } //switch
      } //while
      
      return 0; //Everything is ok
      
      }//End main
      
      

      <Now it just contains a game class instance and a simple switch to select the game state and execute the right code (clean and neat), the game class is declared here:>

      <File "game.h":>

      #ifndef GAME_H
      #define GAME_H
      
      #include  //SDL library
      #include  //+SDL_image library (I use it for loading .png files)
      
      #include "engine.h" // The simple engine class
      #include "cplayer.h" //The player class
      #include "cmap.h" // The Map class
      #include "gamestates.h" //The Game states Enum
      #include 
      
      #include  // I use it to work with text streams
      
      using namespace std;
      
      //Class Game, i have moved everything
      class Game
      {
          public:
      
      
      
      GameState myGameState ; //used to know what we should do at any moment
      Engine myengine; //Create a object from the type "Engine"
      std::stringstream text; //Variable used to display text
      Uint8 x,y; //variables used to travel across the map array
      cmap mymap; // Our map class
      cplayer Hero; //Our player class
      //cmenu mymenu; //Our Menu Class
      Uint8 *keys;
      SDL_Rect Camera;
      
       char* MenuTittle; //The menu tittle
       vector MenuItems; //The menu items
      
              Game();
              virtual ~Game();
              void SplashScreen();
              void OutroScreen();
              void MenuStart();
              void MenuGame();
              void CreatePlayer();
              void MainLoop();
              void SaveGame();
              void LoadGame();
      
          protected:
          private:
      };
      
      #endif // GAME_H
      
      

      <Notice I moved all the variables as properties into the new class, and functions now are methods, notice too we have achieved two objectives: clean the code and split it into smaller parts, it is easier to understand and implement too, next objective is to code game.cpp >

      The first function, the class initializer is this:
      file "game.cpp"

      Game::Game()//Initialize Game class instance
      {
      myengine.SetVga(800,600,32,true); //Start graphics mode
      myengine.LoadTileset("images/tileset3.png"); //Load the image tileset to a SDLSurface
      
      
      //Set starting position and speed for the player
      Hero.SetX(110);
      Hero.SetY(310);
      Hero.SetSpeed(10);
      
      //Set default values for the players
      Hero.SetName("Conan");
      Hero.Defaults();
      Hero.CalculateVitMag();
      Hero.MaximumAttributes();
      
      //Ser camera starting offset
      Camera.x=1;
      Camera.y=1;
      Camera.w = myengine.ScreenX;
      Camera.h = myengine.ScreenY;
      }
      

      In the next posts I will show all the other methods.

      Tuesday, August 16, 2011

      Creating an RPG player




      <We've got a player and we can move the player around a tile-map but we need the most important thing in a RPG game,  the player creation process>

      <There are hundreds of methods to create RPGames , but i have chosen to use a percentile method because it's quite easy to implement and it fullfills all my game needs>

      These are the rules for my game:

      SKILLS:
      • In this method the skills are a value from 0 % to 100 % (can get higher, but that would take ages for the player to achieve and it does not give an actual advantage) that represents the chance to successfully use a skill.
      • Every skill is linked to an attribute.  
      • Skills grow when you use them or when using skill points.
      • When a skill reaches 70%(Expert) and 90%(Master) the player earns two skill point.
      • Skill points are special, player start with skill points and get new ones when using skills.
      • Skill points can be used to increase a skill (Every point expend increases a skill 10% up to 50% maximum) or to learn a new skill to a 25% level (To do so player needs to find an NPC with the desired skill with a level of 90% or higher, and usually pay a fee that will depend on the skill).
      • A skill can have from zero to two parent skills, those are skills player MUST already know before learning the skill, most of the skills will finish forming a kind of skill tree, but a few ones are free to anybody.
      • When there is a skill check there are 4 possible results (As an example I will use a warrior with melee at 70% attacking an Orc):
      1. Skill has failed: When player rolls a skill and gets a value higher than it's skill (example: 83 > higher than 70%) this means player has failed to hit the Orc.
      2. Critical failure: When player rolls a skill and gets a value from 96 to 100 , that will happen even if the player has a skill level higher than 95 (for example 135%), so there is always a small (5%) possibility to fail a skill, there are not guaranteed skills in the game except event-driven ones (special events)
      3. Skill has worked: When a player rolls a skill and gets a value equal or lower than his/her skill (warrior rolls 43, lower than 70% > Orc has been hit)
      4. Critical success: When a player rolls a skill and gets a value equal or lower than his/her skill divided by 10 (in the example, the warrior has 70% melee, divided by 10 > 7% critical chance so if it rolls 1-7 the Orc is going to get a critical hit...) , when a critical success, the effect of the skill is doubled , for a melee skill for example, double damage .
      • Every skill has an upgrade level, the upgrade level is an integer value starting at 0 that grows by one very time a player successfully uses a skill.
      • When the upgrade level gets higher than the current skill level, the skill level increases by one, and the upgrade level goes again to 0, in the example the warrior has a melee skill at 70% with an upgrade level 70, the warrior uses the melee skill again an rolls 35 (success) so upgrade level goes to 71, it is greater than melee skill so melee skill goes to 71% and upgrade level to 0.
        ATTRIBUTES:
        • The attributes of the player come in a value from 5 to 15 (To prevent too high/ too low values).
        • All attributes start at 10, that is the "medium" attribute value, if you've got an higher or lower value, the chances to use skills based in that attribute will be greater/lower.
        • The player can remove points from one attribute to increase another, but it will never be higher than 15 or lower than 5.
        • When finishing the player creation process, every attribute is doubled and stored, that is the maximum value a player can get an attribute ever, so it is very important to choose how to distribute the attribute points at the start of the game thinking of what kind of player you want to be.
        • All players have these attributes:
        1. Strength:The brute force, increases the damage made using melee weapons.
        2. Dexterity:It is both the agility and how fast the player is.
        3. Endurance:The endurance, pain and venom resistance
        4. Size:Physical size, modifies life points and armour prices
        5. Intellect:Mind power, basically modifies all mind related skills starting from literacy (write/read) to magic skills
        6. Power:The player's soul strength, it increases resistance to special magic attacks (disintegrate like spells) and versus negative plane creatures (such as undeads (zombies, ghosts), daemons , daemonic weapons (items)), it modifies to the amount of followers a player can have (NOTE: Followers are bound undeads / daemons / beasts)
        • There are some special stats that depend on the attributes:
        1. Life / Vitality points: It is based in Size*2 + Endurance
        2. Magic points:It is based in Power*2 + Intellect
        3. Carry capacity: It is based in strength + size
        GENDER:

        In the game gender affects attributes:
        • Male players: Strength +1
        • Female players: Dexterity +1
        <Before anybody complains about it, the gender rule is set to make the game more fun, not to discriminate anybody in anyway so it has nothing to do with sex rights, it is just a game!>

         RACES:

        Players can choose to play with the following races:

        • Humans: Good in almost everything, they have no special modifiers <Humans were the stronger civilization in my game, they became so powerful that they tough were gods, opened doors to distant planes, made dark pacts with even darker gods but finally the doors were left open, when the negative plane creatures started to get into the world it was too late to try to close it..., nowadays humans just fight to survive>
        • Midgets: Small sized humans, they are quite small and notably faster too (Size -2, Dexterity +2), <some people say they are the thieves nation, but nobody ever has proven it>
        • Mountain humans: Rude, strong but not very intelligent (Strength +2 , Intellect -2) <It is said that when the first humans had their first encounter with the Mountain giants the natural selection started to play again, after centuries they have become a stronger race>
        • Forest nation:  Fast, very intelligent humans, but very weak (Dexterity +1, Intellect +2, Strength -3) <Nobody knows when those humans started to live in the deepest, forgotten forests, but everybody knows what they do: Look for arcane knowledge and dark secrets...>
        • Half giants: Pure muscle, very big, slow and definitively dumb (Strength + 3, size +3, dexterity -3, intellect -3)<somebody will tell they are Huge Mountain Humans, others will tell they are small giants, either way they are the most unbalanced race to play>.
        <Note about the races: Notice that if you add all the modifiers from a race, it will always become 0, even Half giants!, it is the only way to try to balance it, another important thing is that after modifying the attributes, the gender and race selection, the maximum and minimum attributes you can get is 19 and 2, attributes very high can make a warrior / wizard very strong (only in the super-attributes based skills), but they will have a few attributes so low that it will be almost impossible later in the game to use anything else, humans are not the stronger, faster or more intelligent , but they can use both swords and books >

        <In the next post, i will iexplain the player creation process in the game>