Jump to content

  • Log In with Google      Sign In   
  • Create Account

Squared'D's Journal



Project B - New Project

Posted by , in Project B 30 June 2013 - - - - - - · 804 views
game, game project
Project B

Hello all. I've been working hard on putting the graphics-less game together and I'm going to continue to work on it, but work will go a little slower as I'm starting to work on a new game project. I've already developed a 3D multi-player game engine that was used for my last IGF entry shown here (Genesis SEED), but these days I've been doing some major improvements and updating the rendering system. The project was in limbo so I started doing other things. Now with this new project, I need to quickly get my improvements up and running. Basically, the old system was DX 9 only, but I've been building a new system that I hope will give me multi-platform capabilities in the future. Currently it supports DX 9 and DX 11. Here's a list of the things that I need to finish by August. While I the old project was in limbo, I also started building a new GUI system. I want to finish it and use it with this new game. I'll try to provide regular updates here, maybe even some videos that detail my progress.

Here's my task list:

Posted Image

I picked up the color-coded system back when I was working for the USDA. I use to do contract management and IT security while I was there. The project managers for the database systems would use a similar color-coded system. I like it because it easily lets me see what I need to do. And I hate seeing red. That motivates me to work faster. Right now, there is too much red.

I will update this blog weekly. I'd like to submit this game to IGF so I'll probably post some test framework code for the public to try out.


Direct X 11 Problems on Windows 8 Laptop

Posted by , 22 June 2013 - - - - - - · 1,260 views
DX11, D3D, Intel HD Graphics 4000 and 1 more...
Direct X 11 Problems on Windows 8 Laptop
(Edit: Took out the major from the title. I think it was too bold)
Other's may disagree with this, but I think one of the worst feeling in the world for a programmer is to work hard on something, debug it and test it out thoroughly just for it to fail on someone else's computer. This is what happened to me a few days ago. I'd been working on my new game framework which I hope will give me multi-platform capabilities in the future. My new post-processing framework was working well with some nice new effects and I had been testing out some new GUI elements. So it all works well on my computer, or so I thought actually.

Laptop
OS: Windows 7
CPU: Intel® Core™ i5-2410M
Display Adapters: (0) NVidia GeForce GT 540M
(1) Intel HD Graphics 3000


The Problem
So my friend and gamedev partner tried it out on his two computers:

System 1 Desktop (Windows 7)
CPU: Intel Core i5-2500K 3.3ghz 16GB ram
Display Adapter: GPU AMD Radeon HD 6800 series
SUCCESS

System 2 Laptop( Windows 8)
CPU: Intel i7-3632 2.2GHZ
Display Adapters: (0) GPU AMD Radeon HD 7730M
(1) Intel HD Graphics 4000
FAILURE


And it was strange because everything started up well, but then I stopped. When spent about 2 days on this with me sending out various builds and slowly disabling more and more things before I realized that it was crashing way at the beginning when the Direct X device was being created. I didn't expect this because a message was supposed to have popped up in this case, but I guess now it doesn't matter.

The Solution
After searching around on the internet, I came to believe his configuration was the problem. I got a lot of information from this old Gamedev post: http://www.gamedev.net/topic/617965-directx-11-cant-find-all-of-my-graphics-adapters/

From that post, I realized that on laptops, it's common for the system to default the integrated graphics card and not use the high performance one. This was happening on my computer as well. By why was the program crashing on his computer. Look at all of these references:

http://forums.heroesofnewerth.com/showthread.php?346005-D3D-CreateDevice-fail
http://www.bleepingcomputer.com/forums/t/490819/games-fail-to-launch-directx-11-error-direct3d-failure/
https://community.playhawken.com/topic/17979-failed-to-create-d3d9-device-error-on-surface-pro/
http://www.tomshardware.com/forum/115848-13-failed-creating-device-version-adapter-intel-graphi
http://www.bleepingcomputer.com/forums/t/490819/games-fail-to-launch-directx-11-error-direct3d-failure/
http://battlelog.battlefield.com/bf3/forum/threadview/2832654347765284506/
http://en.community.dell.com/support-forums/laptop/f/3519/p/19470967/20205166.aspx
http://support.futuremark.com/futuremark/topics/directx_fail
http://forums.autodesk.com/t5/Autodesk-Inventor/Windows-8-Graphics-Issue-Inventor-2013/td-p/3757109


There seems to have been a bug in the HD Graphics 4000 drivers. Intel says that it's fixed it now so if you have any users having problems on Windows 8 laptops with HD Graphics 4000, have them update their drivers. Also, if they have another graphics card, tell them to look into their display adapters configuration settings and make sure it uses the high performance card for your game. The configurations change can be made in a utility that's installed with the drivers and not via device manager. I'm not sure how it works on Windows 8.

I'm adding this here because I'm sure someone else will have this problem and I want to help them find the answer.


A Complete Graphics-less Game #5 - World Map Part 2

Posted by , in A Complete Graphics-less Game 16 June 2013 - - - - - - · 648 views
text, text based, game and 2 more...
It's been a while since I've had a chance to update this. I've started working on another project with an old friend of mine and 3 others so I haven't had the time to really focus on this project, but I'll try to keep it up. I think this is a good project for me. As I dive deeper into it, I feel that I'll be able to explore some interesting concepts. So what have I been working on?

World Map Part 2
You don't have to be a genius to see that the game is very limited. I thought this was as good a time as any to try to load the world map from a file. In all of my recent programs, I haven't been using C++ streams to do any file loading. It's been years since I've done anything with it. Honestly, even using "std::cout" feel like weird to me. I grew up on printf and all it's derivatives, but I will try my best to use streams now. Remember, I'm making this program as a learning experience. I want to show that programmers don't have to jump into graphics programming from the beginning. They can instead test basic concepts and refine their skills using console applications.

Long story short, I'm going to build a loader to load the world map. As I said before, towns and the world map will use the same basic system as everything is really just locations connected by links. That's why do code uses the name AreaMap and not WorldMap. Here's a sample of the world map. I'm using text files for now as they are easy by hand.
"Washington"   1 3
"Frederick"    0 2 3 
"Pittsburgh"   1 4
"Baltimore"    0 1 4 5
"Philadelphia" 2 3 5
"Camden"       3 4 6
"Newark"       5 7
"New York"     6 8
"Boston"       7
I think this format is simple enough. It's merely the name of the location followed by a list of the links. The loader will perform minimal error checking so the file should be in the proper format.

Input File Streams in C++
Input file streams in C++ are quite simple. Just include the <fstream> header. I'll use the std::ifstream type because this is only for input. There are two ways to open the file: specifying the file in the object constructor or by using the open() method. Here's an example:
std::ifstream m_file_stream;
m_file_stream.open("test.txt", std::ios::in);

// or

std::ifstream m_file_stream("test.txt", std::ios::in);
After opening a basic text file, you can use it just like std::cin.

Loading the Area Map
For this loader, I decided to create a loader class that will handle loading the file. I decided to make it a class because to load the file in a clean way, I needed to use multiple function calls. Putting it in a single class made everything fit nicely. I also had to make some changes to the CAreaMap class so I can add links to a location after the location in the map has been created.

Here's the class definition:
// forward declaration of for the CAreaMap class
class CAreaMap;

/// \brief return values for the loader
enum LoaderResult
{
    LOAD_OK		= 0,
    LOAD_EOF	= 1,
    LOAD_FAIL	= 2
};

/// \brief Class for loading an area map
/// An Area map can represent all the places in a town or it can be used as a
/// higher level world map.
class CAreaMapLoader
{
    public:
        /// \brief Loads the Area Map from a file
        /// @param szFile the file name
        /// @param the_area_map the area map to load the data to
        /// @return the result of the load
        LoaderResult LoadFromFile(const char *szFile, CAreaMap &the_area_map);

    private:
        // Helper function to parse a line
        LoaderResult ReadLine(CAreaMap &the_area_map);

        // Helper function to search a string for a quoted sub-string
        LoaderResult GetNextStringToken(const std::string &inputline, size_t start, std::string &out, size_t &next);

        // Helper funtion to search a string for an int
        LoaderResult GetNextIntToken(const std::string &inputline, size_t start, int &out, size_t &next);

        // Helper funtion to search for the next numeric character
        size_t findNum(const std::string &in, size_t start);

        std::ifstream m_file_stream;
};
I made some helper functions to help me parse the file. Here's the code from LoadFromFile() and ReadLine():
LoaderResult CAreaMapLoader::LoadFromFile(const char *szFile, CAreaMap &the_area_map)
{
    // create the stream and open the file
    m_file_stream.open(szFile, std::ios::in);

    // check for success
    if(m_file_stream.fail()) return LOAD_FAIL;

    // read the lines
    LoaderResult result;
    do
    {
        result = ReadLine(the_area_map);
    } while(result == LOAD_OK);

    if(result == LOAD_EOF)
    {
        // this isn't failue, we just processed all of the data
        result = LOAD_OK;
    }

    // close the file
    m_file_stream.close();

    return result;
}

LoaderResult CAreaMapLoader::ReadLine(CAreaMap &the_area_map)
{
    // read the first line, it should be the number of places
    std::string file_line;

    // check for eof before getting the line otherwise if the last line ends with eof, it won't be processed
    if(m_file_stream.eof()) return LOAD_EOF;

    // get the next line
    std::getline(m_file_stream, file_line);

    // check for blank lines
    if(file_line.size() < 1) return LOAD_OK;

    if(m_file_stream.fail()) return LOAD_FAIL;
    if(m_file_stream.bad()) return LOAD_FAIL;

    size_t cursor = 0;
    std::string location_name;

    // get the location name
    GetNextStringToken(file_line, cursor, location_name, cursor);

    // create the location without any links
    LocationIndex loc_index = the_area_map.AddLocation(location_name, 0);

    // get the links
    LoaderResult link_result = LOAD_OK;
    int link;
    do
    {
        link_result = GetNextIntToken(file_line, cursor, link, cursor);
        if(link_result == LOAD_FAIL) return LOAD_FAIL;
        else if (link_result == LOAD_OK)
        {
            // add the links
            the_area_map.AddLocationLink(loc_index, link);
        }
    } while(link_result == LOAD_OK);

    return LOAD_OK;
}
The code is very simple. I read an entire line from the string and then scan the line for the information that I need. Since I broke the code up into smaller sections, it's not some big convoluted mess.

Loading the map is as simple as this:
CAreaMapLoader map_loader;
map_loader.LoadFromFile("testmap.txt", m_WorldMap);
That's it. You can check the full source to see it working and as always, let me know if you have any problems compiling it.

Attached Files




A Complete Graphics-less Game #4 - World Map Test

Posted by , in A Complete Graphics-less Game 02 June 2013 - - - - - - · 808 views

Beginning on the World Map

I had hoped to release this earlier, but other projects have held me up a bit. Also when I had first envisioned writing this, I thought that I would be able to write about my thought process while I was actively making decisions. That turned out to be too difficult as I change my mind a lot. So I decided that it would be better to make all of the decisions, code something up, and then document my findings here.

Lessons Learned from the last prototype
I learned a lot working on that prototype. I know, it wasn't anything special, but at least I have something working that I can test out. As I said in my last entry, the prototype was written using a more C-style and not C++. Why? I don't know. I guess even though I've been using C++ for years, I'm still more comfortable using C-style functions. So what did I learn from the prototype? If you take a look at the code, I'm sure you'll see a lot of redundancy. Also, as you move from place to place in the game, a new menu is always drawn. To me, I feel like I'm moving between pages. Each page has the following task:
  • draw a menu
  • wait for input
  • process input
Now, how will I implement this into a more robust world map system? In this game, the world map will be a collection of places connected by links. When I think about other aspects of the game, when the user enters towns, a similar system will be used. Because of this, I'll use more generic-style names to describe things.

The Area Map
First, I need to develop a way to story the area information. For this, I'll start by defining a location.
typedef unsigned int LocationIndex;

/// \brief Defines one location in an area and it's links
struct AreaLocation
{
	std::string name;			//!< The name of the location

	std::vector <LocationIndex> links;	//!< The links

	/// \brief Helper function to return the number of links in this location
	inline unsigned int GetNumLinks() const { return links.size(); }
};

I've defined the type LocationIndex because I feel it's clearer than sticking a bunch of "unsigned int"s everywhere. The AreaLocation struct is fairly simple. I contains the area name and a vector of the links. The helper function GetNumLinks() isn't needed, but it will help the code be clearer.

To hold all of this together, I made the CAreaMap class.
/// \brief Class for an area map
/// An Area map can represent all the places in a town or it can be used as a
/// higher level world map.
class CAreaMap
{
	public:
		/// \brief Constructor for CAreaMap
		/// This constructs a new CAreaMap taking the name as the argument
		/// param name[in] The name of the map
		CAreaMap(const std::string &name);

		// ~CAreaMap(void); // we don't need a destructor yet

		/// \brief Returns the name of the map
		const std::string &GetName() const { return m_area_name; }

		/// \brief Returns a location by index
		const AreaLocation &GetLocationByIndex(LocationIndex index) const
		{
			return m_locations[index]; // will crash on invalid index
		}

		/// \brief Returns the number of locations
		inline unsigned int GetNumLocations() const { return m_locations.size(); }

		/// \brief Adds a location to the map
		/// This will add a location to the map. The variable list is a list of ints,
		/// and are the indices for each location that this location links to.
		void AddLocation(std::string name, int num_links, ...);

	private:
		std::string m_area_name;
		std::vector <AreaLocation> m_locations;
};

So far, all of the type are simple so I don't feel that I have use for pointers at the moment. In general, I've been learning to avoid pointers and to use them only when necessary. I'm still in the beginning stages of this project so there's a big possibility for change later. Sometimes when working on projects alone, we want to code everything right the first time. But this isn't always possible. Without a strong framework, you may not even be able to test things properly. And if you make some code and wait for its dependencies to get coded or vice versa before testing, when you run into bugs, you may have a hard time figuring out where the bug is because you've waited so long to do any testing. That's why I'm a huge fan of making temporary code for testing.

Commands
Processing and distinguishing between user commands is very important. This will be a text based game and all commands will come in via a single keystroke. To do this, _getch() is a good function, but it has a problem. _getch() is a blocking function and won't return until the user presses a key. I never want to block the code waiting for a keystroke. Other things may need to be processes such as AI and AI agent should be able to move in and out of an area while you're thinking about your next action. The function _kbhit() can be used to check to see if a key is waiting in the queue. If _kbhit() returns true, then I can get the key using _getch().

I don't want to feed keystrokes directly into the system to be processed. I want them to be translated first. These are the enums and structs that I'll use to define commands.
/// \brief Enum of the possible user commands
enum UserCommandType
{
    Command_Null		= 0,
    Command_Invalid		= 1,
    Command_Move		= 2,
    Command_MoveLink		= 3,
    Command_Cancel		= 4,
    Command_Quit		= 5
};

/// \brief Enum detailing what kind of commands we're listening for
enum SubCommandMode
{
    Mode_Base	= 0,
    Mode_Moving	= 1
};

struct UserCommand
{
    UserCommandType cmd_type;
    int		    cmd_param;
};
The UserCommandType enum details the type of command the user has entered. I've also made the UserCommand struct because some commands need an extra parameter. But why the SubCommandMode enum? Remember before I said that I never want to block waiting for input. This enum will allow me to have sub-menus with different controls. For example, the user should press 'M' to move, but after that, the user should enter the link number or C to cancel. I don't want to block the program while the user thinks about his or her next location and I don't want to introduce another look so I'll use this enum so the program will know what kind of input the user is entering.

The World Map State
Even though this test project doesn't support multiple states yet, I'm going to start using this terminology now. Remember, I'm still in the early phases and don't want to introduce inheritance yet.
/// \brief Class for the world state
/// This class allows a user to be able to explore a world map as
/// defined in the CAreaMap class.
class CWorldMapState
{
    public:
        CWorldMapState(void);

        /// \brief Runs the main loop for this state
        void DoMainLoop();

    private:
        /// \brief Sets the world map to the default value
        void SetUpWorldMap();

        /// \brief Gets the next user command
        UserCommand GetNextUserCommand();

        /// \brief Show an error message on an invalid command
        void OnInvalidCommand();

        /// \brief process the current message
        /// \return true to redraw the current location
        bool OnProcessCommand(const UserCommand &user_cmd);

        /// \brief shows an area display on std::cout
        void DisplayAreaLocation(const AreaLocation &) const;

        /// \brief returns true if the world map is looking at a valid location
        bool isCurrentLocationValid() const;

        /// \brief returns the current location
        const AreaLocation &GetCurrentLocation() const;

        CAreaMap m_WorldMap;
        unsigned int m_CurLocation;

        SubCommandMode m_CommandMode;

};
Most of the methods are private, but may end up being protected after I add a state base class. The really class only has one public method and that is to run the main loop. The SetUpWorldMap() method is temporary and will be removed or changed drastically after I add loading the map from a file.

Here's the main loop. Sorry for the lack of comments:
void CWorldMapState::DoMainLoop()
{
    UserCommand user_cmd;

    if(isCurrentLocationValid())
    {
        // dislay the current location
        DisplayAreaLocation(GetCurrentLocation());

        do
        {
            // query for the next user command
            user_cmd = GetNextUserCommand();

            if(user_cmd.cmd_type != Command_Null)
            {
                // check for an invalid input message
                if(user_cmd.cmd_type == Command_Invalid)
                {
                    OnInvalidCommand();
                }
                else if (user_cmd.cmd_type != Command_Quit)
                {
                    if(OnProcessCommand(user_cmd))
                    {
                        DisplayAreaLocation(GetCurrentLocation());
                    }
                }
            }
        } while (user_cmd.cmd_type != Command_Quit);
    }
}
Every time through the loop the program queries for new input. If there's new input, it is sent to be processed.

The GetNextUserCommand() method checks to see if a key has been pressed and then turns that keystroke into a command.
UserCommand CWorldMapState::GetNextUserCommand()
{
    UserCommand new_command;
    new_command.cmd_type = Command_Invalid;

    if(_kbhit())
    {
        int key = _getch();
        if(m_CommandMode == Mode_Base)
        {
            switch(key)
            {
                case 'q':
                case 'Q':
                    new_command.cmd_type = Command_Quit;
                    break;
                case 'm':
                case 'M':
                    new_command.cmd_type = Command_Move;
                    break;
            }
        }
        else if(m_CommandMode == Mode_Moving)
        {
            if((key == 'c') || (key == 'C'))
            {
                // the user has pressed cancel
                new_command.cmd_type = Command_Cancel;
            }
            int max_link = (int)GetCurrentLocation().GetNumLinks();
            int link = key - '0'; // convert to an int
            if((link >= 0) && (link < max_link))
            {
                new_command.cmd_type = Command_MoveLink;
                // set the index as the param
                new_command.cmd_param = (int)GetCurrentLocation().links[link];
            }
        }
    }
    else
    {
        new_command.cmd_type = Command_Null;
    }

    return new_command;
}



I'll just show the two other important methods here just so you can take a look. You can download the source to see the complete project.
bool CWorldMapState::OnProcessCommand(const UserCommand &user_cmd)
{
    if(user_cmd.cmd_type == Command_Move)
    {
        std::cout << "Enter link (0 - " << GetCurrentLocation().GetNumLinks() - 1 << ") (C - Cancel)" << std::endl;

        // change the command mode so we'll process user commands as links
        m_CommandMode = Mode_Moving;
    }
    else if(user_cmd.cmd_type == Command_MoveLink)
    {
        m_CommandMode = Mode_Base;
        m_CurLocation = (unsigned int)user_cmd.cmd_param;
        std::cout << "Moving to " << GetCurrentLocation().name << std::endl;
        return true; // redraw the current location
    }
    else if(user_cmd.cmd_type == Command_Cancel)
    {
        m_CommandMode = Mode_Base;
        return true; // redraw the current location
    }

    // do not redraw the current location
    return false;
}

void CWorldMapState::DisplayAreaLocation(const AreaLocation &location) const
{
    std::cout << std::endl << "==========================================" << std::endl;
    std::cout << "==========================================" << std::endl;
    // write the name
    std::cout << "Now in " << location.name << std::endl;

    // write the links
    std::cout << std::endl << "Links:------------------------------------" << std::endl;
    for(unsigned int i = 0; i < location.GetNumLinks(); ++i)
    {
        unsigned int link_index = location.links[i];

        if(link_index < m_WorldMap.GetNumLocations()) // make sure the location is valid
        std::cout << i << ") " << m_WorldMap.GetLocationByIndex(link_index).name << std::endl;
    }

    // write the menu
    std::cout << std::endl << "Commands:---------------------------------" << std::endl;
    std::cout << "M) Move" << std::endl;
    std::cout << "Q) Quit" << std::endl;
    std::cout << "==========================================" << std::endl;
}

If you have any questions about this entry you can leave a comment.

Note about the source
I develop using Microsoft Visual Studio 2010 Professional so if you have any problems compiling the code on your system let me know.

Attached Files







Recent Comments

June 2013 »

S M T W T F S
      1
2345678
9101112131415
16171819202122
23242526272829
30      


PARTNERS