Week 2

Published October 06, 2014
Advertisement
Hey all,
Technically, this is more like week 3 or 4, but it's my second journal entry so I'm going to run with it tongue.png
I've been sick all week, and still had to go to work, so I figured it would be a good week to simply fix some things I'd been procrastinating.

Taking a few steps back:
Up until this week, I had been postponing learning how to save to and read from a file. I've been programming for about 9 months now, and there's really no excuse, other than I was a little intimidated by the process for whatever reasons. In the early months, I learned the basic cin/cout things, and had used fstream in a limited capacity, but that was really about it as far as the c++ IO functions went.

I've never been much of a "eat my vegetables first" type person, and one of the hazards of learning on your own is habitually avoiding the things you should learn, but don't really want to tongue.png So, this week, I buckled down and implemented a save/load game feature.

On that note, I want to thank the people here on gamedev.net. Seriously, regardless of my question, the same handful of people always seem to be there to offer helpful advice, week after week, and have helped me through some roadblocks. It's truly appreciated smile.png

Anyhow, I spent the early part of the week reading about the different IO functions in c++, and settled on JSON rather than XML and the JsonCPP library to parse it. I learned that I'm terrible at reading documentation. After some help on these forums, player information was relatively easy to sort out and save/load. The world information was slightly more difficult as it consists of a number of vectors of different classes, each with their own attributes. I ended up simply saving a number of arrays in Json. I.e. one array for tree locations, another array for ints that represent the location of the tree image in the texture array, etc, etc.

context and code for this implementation is

here

. It's not very elegant (but it's functional, and seemingly bug-free, so...yay

smile.png

, I'll hopefully go through it later this week and clean things up a little.

[code=:0]#include "FileManager.h"FileManager::FileManager(){ //ctor}FileManager::~FileManager(){ //dtor}void FileManager::SaveGame(std::vector &entityVec, TerrainManager &TerrainManager1){ try { //create json object for all values//// Json::Value playerInfo(Json::objectValue); //save player information//// //create vector of json values//// std::vector jPlayerLocVec; //set name and value for entity attributes------------------------------------------------------------- for(int i = 0; i < entityVec.size(); i++) { //see CommonCommands.h std::string tempI = NumberToString(i); playerInfo["plhealth"+tempI] = entityVec.health; playerInfo["plmana"+tempI] = entityVec.mana; playerInfo["plaffinity"+tempI] = entityVec.affinity; //for vec size, emplace a new array object and set its values//// jPlayerLocVec.emplace_back(Json::arrayValue); jPlayerLocVec.append(entityVec.location.x); jPlayerLocVec.append(entityVec.location.y); jPlayerLocVec.append(entityVec.location.z); //save info to json value//// playerInfo["plLoc"+tempI] = jPlayerLocVec; } //save mountains//// //create vector of JsonValues//// std::vector jMountLocVec; for(int i = 0; i < TerrainManager1.MountainVec.size(); i++) { std::string tempI = NumberToString(i); jMountLocVec.emplace_back(Json::arrayValue); jMountLocVec.append(TerrainManager1.MountainVec.location.x); jMountLocVec.append(TerrainManager1.MountainVec.location.y); jMountLocVec.append(TerrainManager1.MountainVec.location.z); //write info to json value//// playerInfo["mountloc"+tempI] = jMountLocVec; } //save ground tile types//// for(int i = 0; i < TerrainManager1.ForestFloorVec.size(); i++) { std::string tempI = NumberToString(i); playerInfo["floortype"+tempI] = TerrainManager1.ForestFloorVec.itileType; } //save forest objects//// SaveForest(TerrainManager1.ForestVec, 0, std::string("forestLoc"), playerInfo); SaveForest(TerrainManager1.ForestVec2, 2, std::string("forestLoc2"), playerInfo); SaveForest(TerrainManager1.ForestVec3, 3, std::string("forestLoc3"), playerInfo); SaveForest(TerrainManager1.ForestVec4, 4, std::string("forestLoc4"), playerInfo); SaveForest(TerrainManager1.ForestVec5, 5, std::string("forestLoc5"), playerInfo); SaveForest(TerrainManager1.GoodForestVec, 6, std::string("forestLoc6"), playerInfo); SaveForest(TerrainManager1.GoodForestVec2, 7, std::string("forestLoc7"), playerInfo); //create integer for size of various vectors (used when loading) int entVecSize = entityVec.size(); playerInfo["entVecSize"] = entVecSize; //open datafile std::ofstream DATAFILE; DATAFILE.open("Save1.json", std::ios::out); //stream json values to it DATAFILE<< playerInfo; //close file. DATAFILE.close(); std::cout<<"Game Saved"< &entityVec, EntityManager &EntityManager1, TerrainManager &TerrainManager1){ try { ////open json file//// std::ifstream DATAFILE; DATAFILE.open("Save1.json", std::ios::in); //create root and reader Json::Value root; Json::Reader reader; //parse json file bool parsedSuccess = reader.parse(DATAFILE, root, false); if(not parsedSuccess) { std::cout<<"failed, damnit"< jPlayerLocVec; for(int i =0; i < entityVecSize; i++) { std::string tempI = NumberToString(i); jPlayerLocVec.emplace_back(root["plLoc"+tempI]); } //set player location and attributes std::cout<<"vec size"<.location = glm::vec3(jPlayerLocVec[0].asFloat(), jPlayerLocVec[1].asFloat(), jPlayerLocVec[2].asFloat()); //make temp json values const Json::Value tempHealth(root["plhealth"+tempI]); const Json::Value tempMana(root["plmana"+tempI]); const Json::Value tempAffinity(root["plaffinity"+tempI]); //set entity values to json values entityVec.health = tempHealth.asInt(); entityVec.mana = tempMana.asInt(); entityVec.affinity = tempAffinity.asInt(); } else { std::string tempI = NumberToString(i); //create minion EntityManager1.CreateMinion(EntityManager1.getEntityTurn(), glm::vec3(0,0,0), TerrainManager1.ForestFloorVec[TerrainManager1.selectedTile].itileType); //set location entityVec.location = glm::vec3(jPlayerLocVec[0].asFloat(), jPlayerLocVec[1].asFloat(),jPlayerLocVec[2].asFloat()); //create temporary json values const Json::Value tempHealth(root["plhealth"+tempI]); const Json::Value tempMana(root["plmana"+tempI]); const Json::Value tempAffinity(root["plaffinity"+tempI]); //set entity values to json values entityVec.health = tempHealth.asInt(); entityVec.mana = tempMana.asInt(); entityVec.affinity = tempAffinity.asInt(); } } //make vector of json values std::vector jMountLocVec; //set mountain locations for(int i = 0; i < TerrainManager1.MountainVec.size();i++) { std::string tempI = NumberToString(i); jMountLocVec.emplace_back(root["mountloc"+tempI]); TerrainManager1.MountainVec.location = glm::vec3(jMountLocVec[0].asFloat(), jMountLocVec[1].asFloat(),jMountLocVec[2].asFloat()); } //load forests LoadForest(0, std::string("forestLoc"), TerrainManager1.ForestVec, root, TerrainManager1, glm::vec3(0,100,0), TerrainManager1.ForestVertices, TerrainManager1.ForestUvs2, TerrainManager1.ForestNormals); LoadForest(2, std::string("forestLoc2"), TerrainManager1.ForestVec2, root, TerrainManager1, glm::vec3(0,100,0), TerrainManager1.ForestVertices2, TerrainManager1.ForestUvs2, TerrainManager1.ForestNormals2); LoadForest(3, std::string("forestLoc3"), TerrainManager1.ForestVec3, root, TerrainManager1, glm::vec3(0,100,0), TerrainManager1.ForestVertices3, TerrainManager1.ForestUvs3, TerrainManager1.ForestNormals3 ); LoadForest(4, std::string("forestLoc4"), TerrainManager1.ForestVec4, root, TerrainManager1, glm::vec3(0,100,0), TerrainManager1.ForestVertices4, TerrainManager1.ForestUvs4, TerrainManager1.ForestNormals4); LoadForest(5, std::string("forestLoc5"), TerrainManager1.ForestVec5, root, TerrainManager1, glm::vec3(0,100,0), TerrainManager1.ForestVertices, TerrainManager1.ForestUvs5, TerrainManager1.ForestNormals5 ); LoadForest(6, std::string("forestLoc6"), TerrainManager1.GoodForestVec, root, TerrainManager1, glm::vec3(0,600,200), TerrainManager1.GoodForestVertices, TerrainManager1.GoodForestUvs, TerrainManager1.GoodForestNormals); LoadForest(7, std::string("forestLoc7"), TerrainManager1.GoodForestVec2, root, TerrainManager1, glm::vec3(0,600,200), TerrainManager1.GoodForestVertices2, TerrainManager1.GoodForestUvs2, TerrainManager1.GoodForestNormals2 ); //set floor tile types//// for(int i = 0; i < TerrainManager1.ForestFloorVec.size(); i++) { std::string tempI = NumberToString(i); const Json::Value tempFloorType(root["floortype"+tempI]); TerrainManager1.ForestFloorVec.itileType = tempFloorType.asInt(); } DATAFILE.close(); std::cout<<"Game Loaded"< &ForestVec, int forestNumber, std::string jsonForestName, Json::Value &playerInfo){ std::vector Forest1Vec; for(int i = 0; i < ForestVec.size(); i++) { std::string tempI = NumberToString(i); Forest1Vec.emplace_back(Json::arrayValue); Forest1Vec.append(ForestVec.location.x); Forest1Vec.append(ForestVec.location.y); Forest1Vec.append(ForestVec.location.z); playerInfo[tempI+jsonForestName] = Forest1Vec; } std::string tempI = NumberToString(forestNumber); //create integer for size of various vectors (used when loading) int forest1VecSize = ForestVec.size(); playerInfo[tempI+"forestVecSize"] = forest1VecSize;}void FileManager::LoadForest(int forestNumber, std::string ForestName, std::vector&ForestVec, Json::Value &root1, TerrainManager &TerrainManager1, glm::vec3 lightPos, std::vector< glm::vec3 > &verticesIn, std::vector< glm::vec2 > &uvsIn, std::vector< glm::vec3 > &normalsIn){ //create forest 1------------------------------------------------------------------------------ std::vectorForestVector; std::string strForestNum = NumberToString(forestNumber); //load size of forest Json::Value jforestVecSize; jforestVecSize= Json::Value(root1[strForestNum+"forestVecSize"]); int forestVecSize = jforestVecSize.asInt(); //reallocate forest object locations for(int i = 0; i < forestVecSize; i++) { if(i < ForestVec.size()) { std::string tempI = NumberToString(i); ForestVector.emplace_back(root1[tempI+ForestName]); ForestVec.location = glm::vec3(ForestVector[0].asFloat(), ForestVector[1].asFloat(), ForestVector[2].asFloat()); ForestVec.lightPos = ForestVec.location + lightPos; } else//if new forest object needs to be created { std::string tempI = NumberToString(i); ForestVector.emplace_back(root1[tempI+ForestName]); ForestVec.emplace_back(TerrainManager1.ForestShader, glm::vec3(ForestVector[0].asFloat(), ForestVector[1].asFloat(), ForestVector[2].asFloat()), ForestVec[0].imageNumber, glm::vec3(0,0,0), verticesIn, uvsIn, normalsIn); ForestVec.location = glm::vec3(ForestVector[0].asFloat(), ForestVector[1].asFloat(), ForestVector[2].asFloat()); ForestVec.lightPos = ForestVec.location + lightPos; } } //clean up any extra trees//// if(ForestVec.size() > forestVecSize) { for(int i = 0; i < ForestVec.size(); i++) { if(i > forestVecSize) ForestVec.erase(ForestVec.begin()+i, ForestVec.end()); } }}
The second thing I had been putting off is utilizing accessor functions for my classes. I'm in a terrible habit of throwing absolutely everything into "public." Which seems to be fine when coding small programs by myself, but is probably a horrible habit to get into. So, I started the slow process of moving everything into protected/private and using accessor functions to retrieve/write them. I've only done a class or two, but it hasn't been as painful as I feared. It's rather slow, but overall not that bad.

Actual game changes:
Not much, sadly on this front as I mentioned I've been sick and working a lot. I've only had a couple hours in the evening each night to do much of anything. However, I did implement the "affinity" attribute for characters. It's a variable that will add bonuses to attack/defense/movement/etc that is dependent upon the day/night cycle, the tile the character stands on (i.e. if a good character is in a good forest, they get a bonus to this trait), and proximity to other like-aligned characters (this last part isn't implemented yet).

Additionally, I threw the character attributes into the UI as they had just been half implemented before. I question spending time doing this, as it's a half-measure really. The UI I got from opengameart.org, and plan on redoing it myself at some point, but for the moment it works. However, I end up spending twice the time as my workflow tends to go something like "placeholder art"->"temporary-but-slightly-better-placeholderart"->"finished artwork". I really ought to just use placeholders, finish the game, then do the artwork, but I find I get really discouraged if the game looks incredibly shoddy, so I end up doing things this way, which really takes a lot longer, with extra work, but looks slightly better along the way.

For Next week:
I'm torn between working more on game mechanics or adding more artwork. The game mechanics kind of require at least some placeholder work. I'm planning on adding more minion types for the players (right now it consists of the evil player's spiders).
For game mechanics, the most pressing things are:
Player upgrades: buildings, skill tree, minions, player-levels/xp
Player creations: power fonts, fortresses, etc
NPC villages, AI

I still need to really implement more UI functions, clickable skill casting, character selection by mouse select, rather than tabbing, etc. Just generally clean up the playability of everything.

Those seem like a good foundation before moving on to anything more complicated, and should get the game up to a playable state. We'll see what I actually manager to get done tongue.png

Lastly:
I've been using github to host the code, but I've decided to use the github pages (their website hosting....thingy) to update things. Right now it's just blank, but it seems pretty snazzy, customizable, and it's free, so for the time being, that will be where I update development progress (other than this journal). Additionally, it's linked to my github account, and hosts the game files that are easily downloadable from the website. http://hobogames.github.io/Eviiil-Empiiire-Extremely-Alpha/

Screenshots, other than the UI, are pretty much like last week. You can't see in the picture, but I've loaded a saved game tongue.png)
skybox and UI credit here and here.
Full game code here:
Feel free to leave thoughts, criticism, comments, encouragement, or even discouragement, it's much appreciated smile.png
Cheers all!
Previous Entry Ending and Beginning
Next Entry Week 3:
3 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement

Latest Entries

Week 4

1812 views

Week 3:

1997 views

Week 2

2253 views
Advertisement