{[ promptMessage ]}

Bookmark it

{[ promptMessage ]}

Step3 - CSE 335 Step 3 Files Time Animation and Visitors...

Info iconThis preview shows pages 1–8. Sign up to view the full content.

View Full Document Right Arrow Icon
Background image of page 1

Info iconThis preview has intentionally blurred sections. Sign up to view the full version.

View Full Document Right Arrow Icon
Background image of page 2
Background image of page 3

Info iconThis preview has intentionally blurred sections. Sign up to view the full version.

View Full Document Right Arrow Icon
Background image of page 4
Background image of page 5

Info iconThis preview has intentionally blurred sections. Sign up to view the full version.

View Full Document Right Arrow Icon
Background image of page 6
Background image of page 7

Info iconThis preview has intentionally blurred sections. Sign up to view the full version.

View Full Document Right Arrow Icon
Background image of page 8
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: CSE 335 Step 3: Files, Time, Animation, and Visitors This is CSE 335 Step 3. This assignment Will address three important topics Fil s e Savmg your city as an XMLfile and loading it back in. Time - Making your tiles change overtime and creating a simple animation. Visitors 7 Using a Visitor pattern for efficient operations on our tiles. The bulk ofthis step assignment is tutorial, but there are seVeraI programming tasks you Will need to complete and you haVe to create a UMLdiagram The programming elements ofthis assignment are due Thursday, September 23, 2010 at ll 55pm. WheneVer you see this icon you should be sure your program Will compile and run I have supplied a hints and suggestions page for this step. Before you Begin This assignment builds on Step 2 lfyou did not complete Step 2, please contact course staffto discuss alternatIVes to continue on this step. This step builds the foundation for Proyect l. You Will be responsible forthis step individually. Yourgroup Will selem one Step 3 solution ofthe members ofyour group to extend for ProjeCtl Please do not turn in a DijECE named Step2 for this assignment ln Eclipse, it is easy to copy a DfUlEfl Click on an open DijECE and select Edit/Copy. Then selettt Edit/‘Paste. It Will alloW you to give the copy a new name. I Would use Step3 You should then close Step2. In the Modes enum in CFrame, please change option 5 from Commune to Windmill. The enum should now be: enum Modes (Trash=0, Blank=1, Grass=2, Firestation=8 , University=9 , Residentia1=l4, Parkland=15 l ; Blacksmith=3, Coalmine=4, Windmill=5, Cricket=6, Port='7, Industryfleavy=10, lndustryLight=ll, Market=12, Tree=13, A Save As menu option Our city builder program is not much use ifyou have to rebuild the city eVery time you stait the program. So, we are going to add the ability to save and load the citydata to/from files First, We need to add a menu option Add a new menu option to the file menu called "SaVe &As.. lt should call the function CFrame::OnFileSaveAs(). lfyou don't recall how to create menu options, see the page 1: ea’ ‘ ’ You should be able to run your program and select the File/Save As menu option lt should notdo anything, yet The WxWidgets class to pop up a File SaVe Dialog box is waileDialog. Add this code to CFrame::OnFileSaveAs()to bring up thatdialog box amehti ‘ e's wxE'ileDialog dlgtthis, L"Save File", L"", L"", L"*.oity", waD_SAVE if(d1g.3hownoas1() != wxlD_OK) return; I waD_dVERW'RITE_PROM'—”T) 7 Feel free to peruse the documentation. You should be able to run your program and select the File/Save As menu option. The save dialog box should come up. 3 a to options in the documentation. The options l have selemed indicate this is a save dailog box and that I Want a Warning if l try to oVerwrite a file BTW, you can usually type a wxWidgets class name into Google and itWilI go straight to the We are going to have an extension of.city forthe files We save our city in. Unfortunately, ifyoujusttype in “file” as the filename, waileDialog Will give you that name and doesn‘t automatically add the extension. So, we Want to tack “ city“ onto the end of the filename ONLY if it is not already there, because it Will be there is we are overwriting an existing file // Get: the filename into a local string wstring filename = dlg.GetPath() .wc_str(); // If no suffix is supplied for the file, supply it here wstring suffix(L".city") ,' if ( ! equal (suffix. rbegin“ , l suffix.rend () , filename.rbegin () )) filename += suffix; l The function dlg.GetFatht) returns a watrihg, wxWidgets own string implementation. l prefer to use STL strings when posSIble, so l‘m converting the filehame to an STL string using its memberfunction WILSHO This returns a Wide charadter string in C format (null terminated) The folIoWing code is a bit oftrickery The STL function equal can be used to test to strings for equality By using rbegin and rend, I‘m testing from the end ofthe strings rather than the beginning lfthe suffix does not exist, l add it. Who should do the Work of savmg the city? lt seems logical that CCity should be responsible for that task. CFrame Was responsible for getting a filename. Now We‘ll let CCitydo the rest ofthe Work. Add this member function to CCity wxWidgels has its own class fol strings called Sti ing. it by default handles Unicode stlings However, I pretet to Lise the STL string functions in progtarns when possible to avoid much platform specific code Also, the plan is that watring Will be phased out inlhe fulule in favor of using the STL siting classes. You can conved a walling to a wstring using the .WtiiSIIO function on watring That returns a pointer to a null lenninaled const WCl‘lafJ * string We can put that into a wslring /x * Name CCity: :SaveO * Description Save the city as a .oity XML. file. */ void CCity::Save(oonst std: :wstring Efilename) l l Now add this code to the end of CFrame"OnFileSaveAs(lto save the city' mCity . Save (filename) F XML Set a breakpoint in CCity: Save(l and run You should be able to enter a filename and have the debugger stop in the routine This ensures you are getting to this point in execution okay If you don‘t knowwhat It! . Microsoft Office 2007 replaced the Office file formats With XMLfiIes (multiple files stored in a Zip archive) It is a very convenient and popularformat. This is what an XMLfile for our city Will look like when we are done. <?x.ml version="1 .0" encoding="utf-8"?> (city) <tile x.="341" y="248“ time="1264370381921" type-"grass"/> <tile x.="403" 279" tim '12643'70381941" grass"/> <tile x.=“279" y="279“ time=“1264370381941“ type=“graas"/> <tile x="465" y="310“ time=“126437035194l“ type="grass"/> <tile x="341" y="310" time="12643'70381941" type="windmill"/> <tile x="217" y="310" time="1264370382061“ type="grass"/> <tile x=“403" y="341“ time=“1264370382061“ type="grass"/> <tile x.="2'79" y="341" time="12643'70382061" type="grass"/> <tile x="341" y="372" time="1264370382061“ type="grass"/> <lcity> _ is, now is a good time to learn. XML is a standard way to encode documents. The vast mayority of new application that save files containing text data Will save it in XML and even applications With lots ofbinary data areiumping on the bandwagon. XML looks a lot like HTML It consists of tags, which start With < and end with >. There are three types oftags: start tags, end tags, and emptyrelementtags. In the example above, <city> is a staittag What follows is contained in that tag. We call the outer tag the root tag and only allow one. lnside We see other tags fortiles. These are empty element tags, since theydon‘t contain other content between the tag and an end tag Empty-element tags begin With < and end With f: Each tag has the name tile followed by attributes (called propenies in wxWidgets). An attribute consists ofa name and a value in quotation marks. The file contains only text. XML suppons many different character formats We‘ll use ufl-, which is a representation of Unicode as one to four bytes per character. We‘ll let the library deal With those details for us The XML version and encoding is indicated by the special <9me> tag that stans the document. Atag that encloses other tags Will have a start, as in <city> and an end, as in </city>, Atag that stands alone, like the tile tags above Wlll end With “/>“ You should be familiar With the format; you‘ll likely see it a lot. Fortunately, there are numerous libraries that support XML for us We'll use the library built into wxWidgets, since it is already there and is one ofthe easiest libraries l haVe found to use It also handles the encoding for us. Creating XML To write an XMLfile, We need to build an XML document in memory, then save it to disk Add this line of code to be beginning ofCCity"Save()' // Create an empty XML document wmelDocument xmlooe; To use the XML library, you need to add this line to CCity cpp it include "wx/ xml/ xml . )1" You'll need to add this in several places Ifyou get errors that it can notfind XMqunctions, then you need to add this header lfyou are using ‘ I recommend adding this line to prech and rebuilding it a Be sure this at least compiles so you know you have your headers right. We need to add a root node to the XML document. Add this code to create a root node named city // Create a root node wmelNode “root = new wxfinlNode(waCMI-_EIEMENT_NODE, L"city“); xmlDoc.SetRoat (root) ; Each tag is considered an XML node In the above example, each city and tile tag is a node when the document is in memory. The tile nodes are children ofthe city node The city node is the root node. Add this code to save the XML document // And save the file to disk xmlDoc . Save (filename . c_str ()3 ; E Run this and do a File/Save As... and proVIde some filename. Look at the file it created. It should look like this. <'?)un1 version=“1 .0" eneading="utf—B"?> <city/> This created an empty cityfile. We are notyet saving tiles, so the tag was empty. We‘re going to really take advantage of inhentanceto save our tiles. Add this public virtual function to CTile: wmelNude ‘C'l'ile: :XmlSave () l // Create a new node for the tile wxxmlNode *nade = new wmnlNodE(wm_EIMNT_NODE, L"tile“) ,' return node; l You'll need to include wxlxml/xml h in CTile h Be sure you make the function virtual. This is a function that creates an XML node With the name “tile” We‘ll ask each tile to create an XML node for us. We now have a funrition in CTile that Will create an XML node The nodes We create need to be children ofthe <city> node You do this by building a singly linked list of nodes We Will set the child of root to one node, then each node‘s next child Will be set to another node Add this code to CCity::Savel) al'terthe root node is created, but before we save the document: wmelNode *lastChild = NULL; for(list<C'l'ile *>: :const_iterator t=mTi1es.begin(); trmmilesendn; t++) t I] Create a node for the tile wmelNode *node = (*t)->Xm13ave(); II If we have a previous child, add this node after H the child. if(1astChi1d = NULL) { root->AddChi1d(node) 7 } else I lastChild—>SetNext (node) ,- } lastChild = node; Be sure you understand what this does and how it creates a linked list. Run this. Drag a few tiles to the city and do a File/Save As Then look at the generated cityfile It should look something like this: <?x.ml version="1.0" encoding="utf-8"?> (city) <tile/> <tile/> <ti1e/> <lcity> We created a <tilef> node for each tile Read the code above carefully, perhaps drawmg the nodes it is creating on paper The first node it creates as it iterates over the nodes is added as the child ofroot. Then lastChi/d is set to that node. The next node is added as SetNext for the preVious node and so on, creating a singlyelinked list of nodes. We want to set attributes on the tile nodes Whatdoes CTile know') It knows the x,y location forthe file. We‘ll add that information to the XML node. Add this code to CTile::XmlSaVel) alter the node is created node—>AddProperty (L'lx'l , waString' node->AddProperty (L"y" , wxstring ormat (L"%d" , mm) : ormat (L"%d" , mYH .' This sets two properties x and y XML is a text format We haveto convert any numbers to strings to save in the file There are many ways to convert a number to a string that XML can output In this case I have used the wxWidgets watring::Format fundion, which Works a lot like printl, only the output is a Unicode string. Vou may need to convert other numbers as well later on, so be sure you know what the code above is doing E Run this. Drag a few tiles to the city and do a File/Save As Then look at the generated city file lt should look something like this: <?.imil version="1.0” encoding="utf-B”?> (city) (tile x="279" y="217"/> <ti1e x="155" y=”248"/> (tile “"495” y="310“/> <fnity> The only thing we still need is to be able to tell what type oftile we have saved. Right now they all look the same In the file l can‘t tell a grass tile from a blacksmith shop tile. Add this public Virtual function to CTileBlank: /* * Name : C'l'ileBlank: :XmlSaven * Description : Create an XML node and save the information about * this tile into it. */ wmelNode *C'l'ileBlank: :Xmlsave () l wmelNode *node = CTile: :XmlSave”; return node 7 We diScussed this syntax in class. When the fundion XmlSaye is called on CTile where the underlying object is adually of type CTileBlank, this funflion will override the version in the base class But, the call to CTile::XmlSave() allows us to still call that function This is handy here, since we let CTile XmlSaveO do its work, then weJust add more stutfto the node. We need an indication of type, so add this code to CTileBlank XmISaveO (do you know where?): no de — >AddPrope rty (L " type " , L"b1 an): ") ,- n Run this. Drag a few tiles to the city including blank and grass tiles and do a File/Save As... Then look at the generated .city file. ll should look something like this: <?.imil version="1.0” enooding="utf-E”?> <city> (tile x.=“124" y="124“ type=“b1ank"/> <ti1e x="248" y=”217"/> (tile x.="310" y="24B"/> (tile x.=“124" Y="372“ type=“b1ank"/> <lcity> Note that we only got the type attribute for nodes that We did add ourselves Now, you are responsible for adding this capability to your other node types grass and blacksmith shop E Run this and be sure it is saying all tile types correctly A File Open menu option We are saying. Now we need to openthe files. Add a menu option. File/Open. and a handler CFrame..OnFileOpen. Add this function to the city for loading: y:- * Name : CCity::Load() * Description : Load the city from a .city XML file. */ void CCity::Load(const std: :wstring .ifilename) l l Now, add this code to CFrame OnFileOpenO wxE'ileDialog dlg (this , L"0pen File" , L”" , L"" , L"* . city" , waD_0PEN I waD_E'II-E_WJST_EXIS'I) ; if (dlg. Showflodal 0 != waD_0K) return; wstring filename = dlg.GetPath() .wc_str(); mCity.Load(fi1ename) ; RefreshU 7 This does the file dialog box, but parameterizes it for open instead of save. Then weJust call a Load function in the city. Note the Refresh to ensure Window is redrawn after we load new data E Run this and be sure the open file dialog box comes up and that you are reaching the CCity::Load() function This won‘t do anything, yet. A Clear procedure Whenever we load data into the city, we need to clear out the old data first. Because we also need to do this when we des1ruct, it makes sense to create a single fundionto clear the city. Add this public function to CCity: /:- * Name : CCity::Clear() * Description : Clear the city data. */ void CCity: :Clear() l ) I‘ll leave it up to you now to fill in the body of thisfunction. Vou should make the destruclor call this instead of duplicating the clear code here It's very cmmonfor applicators like ttiisttia'l load dalafrornfiles to have a Clearfunchon. I otten write one somewhat aiilmriatirally instead (if wnlJrig a desli'uclor, since I know [It otteri need it Opening the XML document Add this codeto CCity Load() HmelDocument :milDoc; if ( lamilDoc. Load (filename . c_str() )) l wstringstream str; str << L”Unab1e to open file ” << filenaine << ends; wxMessageBoxtstr.str() .c_str() , L"Error", waK | waCON_ERROR)7 return; // Clear our existing city Clear() ,' I put in code to error check that the load was successful. lt would be good practice to do so for the save as well, but l‘m not gorng to worry about all of these details in this assignment. You will need to #include <sstream> to use wstringstrearn. This code opens an XML document and loads the file into it, lfitfails, it pops up an error message box and returns, DtherWise, it clears the city, We are now ready to load the city data. Run this and be sure it is opening the file okay, We traverse the linked list of children oftne root usrng this code that you should put at the end of CCity::Load(): wmelNode *child = xmlDoc.GetRoot()->GetChi1dren() ,- while(child != NULL) t // Move to the next child child = child—>GetNext0 f- This should look familiar, ltgets a pointerto the first child node and then continues following the next pointers until we are done, Add this code to the interior ofthe traversal loop before the child : Cl’llldJGEtNEXfl) line // This is the tile we will create CTile *tile = NULL; // We have a tile. What type? watring type = child->GetPrana1(L"ty‘pe", L"")F if(type = L"blank") ( tile = new C'l'ileBlank(this)i' else iftty‘pe = L"blaclcsmith—shop") { tile = new C'l'ileBlacksmithShop(this); else if(ty'pe L"grass“) { tile = new C'l'ileGrass(this); } if(tile != NULL) ( m'l‘iles.push_back (tile) 7 } This allocates a node of the proper type depending on the value of the type attribute You get the value of an attribute using child»>GetPropVal(), The first parameter is the attribute you are looking for The second is a default value that Will be returned ifthe attribute does not exist mom have waves me pmpertyvalue mm a wsmng’ bm’ 5mm we are my damg em ‘mmemate campare’ lyust left it in a watring Vou are welcome to use watring ifyou like in your programs in this class The type determines what objectto create Be sure you know what this code does You‘ll need to add to rt later on We need to be sure the tiles are in sorted order when done, so add this line to the end ofCCity::Load() // When done, sort the files SortTiles U i' We are not yet done, This does create the tiles, but itdoesn‘t read the attributes associated With the tiles otherthan the type, Specifically, itdoes not yet read the x and y location for the tile, Where should that code go? You might want to put rt here, butdiliferenttiles may have different attributes. lt‘s betterto give that responsrbilityto the tiles themselves. Add this Virtual public member function to CTile: /: * Name : CTile::XmlLoad() * Description : Load the attributes for a tile nude. This is the * base class version that load the attributes common * to all tiles. Override this to load custom attributes * for specific tiles. */ void C'l'ile::XmlLaad(wmelNoi:‘le *node) t m}! = westel(node->GetPrepVal(L"x", L“0") , NULL, 10) ; mY = westol(node->GetPropVal(L"y", L"64") , NULL, 10) ,- } The property value is in a Unicode string of type watring We need to convert that to a number For this, l'm using wcstol, which is "wide strong to long“ The first argument is the string to convert The second argument can be set to a pointer to a pointer to allow scanning to continue from that point. We are just using NULL since we don‘t need that feature. Thethird option is the base. We‘re using base 10. To call this, add this line to CCity Loadt) right before the call to mTrles pushiback(tile) tile—>Xmanad (child) ,- At this time load and save should be fully functional I have not overwrittenthis tuncticn inthe base clam, since none O‘Hth have specific dale we needtd rad That willchange as you do your part dtthis assigrmerit rim.“ “ mg, Is this cool or what? l. Time lwould like for our city to have the concept of time and lthrhk it would be neat if it would keep track of time eVen aiter being closed and reopened We‘re going to keep track of time wrth a 64 bit number that ...
View Full Document

{[ snackBarMessage ]}