|Nov 15, 2012, 03:13 PM||#1|
XCode 4.2 and referencing external files
Hello MacRumors! I'm finally taking the dive and trying to learn how to port my C++ game to Mac via XCode. With sfml and opengl, that hasn't been too hard - but I use a custom file type that I read in with ifstream (although I've been told I should switch to fopen eventually) and while I have it working when I click Run in XCode, the OS X App itself does not know how to read in these files. More details below, but, any thoughts?
I am importing this project into XCode essentially, so I took a working SFML framework, added my files, swapped out the main and hit run. Amazingly, all the core stuff worked! The maps (external files in question) did not load though, and it ended up being due to the location of the working directory. Going into XCode's scheme and changing it to be the working dir I use for my old project itself, the maps began loading just fine (since all the map addresses are relative, ie "./maps/world1.map") when I clicked the Run button from inside XCode. Great! But I want to share the file with friends.
Going into the Derived Data path, where ultimately under Derived Data/Project Folder/Build/Products/Debug I found myGame.app, a 75MB Intel App (so it appears to be sucking up all the music and sound effect files, since the example sfml project before would only make an 8MB app). Trying to run this file by double clicking though makes the project open, but no sound, music, maps, or images load (so none of the external files that were referenced in the working directory). Moving the app into the working directory does not fix this problem either.
So far I have been unable to find a way to build the app directly into the working directory, and am only able to influence its placement by changing Derived Data in Preferences for all of XCode. So, any tips on how to get my final product seeing files the same way that the one run out of XCode sees?
EDIT: And I was wrong! The game does not work flawlessly from XCode, only the first level (the one loaded when building the game) loads properly, every level after that fails to load. I'm guessing that's since after that point, the game is running from the dir where it was built to rather than the one it was built from.
Last edited by BlinksTale; Nov 15, 2012 at 03:28 PM.
|Nov 16, 2012, 01:04 PM||#2|
Your game's map, sound, and image files are in the app bundle's Resources folder. The app bundle looks like a single file, the application, but it contains a bunch of directories. You can examine your game's app bundle by selecting it in the Finder, right-clicking, and choosing Show Package Contents.
To load the files you're going to have to do one of two things. First, you can try setting the game's working directory to the app bundle's Resources folder. I have not used SFML so I'm not sure if this is possible in SFML, but SDL's source code has a method to change the working directory. You'll have to look at SFML's source to see if they have a method to set the working directory.
Second, you can use Cocoa's NSBundle class or Core Foundation's CFBundle data structures and functions to access the app bundle and load files from the bundle. Since you're using C++, I recommend CFBundle over NSBundle.
|Nov 29, 2012, 04:34 PM||#3|
The resources folder was exactly what I needed, and the show contents instructions helped a lot. The game now fully runs out of XCode! Victory!
But the war is not won. xD Now I am trying to run the .app as a standalone, and though everything is in the resources folder, it does not load anything in the initial startup of the game. Since I am porting into XCode, I have my repo for the game, and my folders for the XCode project. If I point to the code repo as my working dir, everything works in XCode, but no luck with standalone (although everything AFTER the initial load works, so the second/third/fourth/etc levels all load). If I point the working dir to the .app's resource folder, it does not load the initial content either in XCode or as a standalone.
I'm pretty sure it's not a problem that has to do with SFML, since loading levels (no SFML involved, just fstream or something, I forget what I've used) will not load the initial level, but loads everything after that. Even without using Cocoa or Core Foundation, the later levels load - so I'm wondering why the first doesn't (and all the music/sfx/images that I load at the same time) in the standalone only. I'm tempted to just not load anything until the Window is up and running and the user hits enter or something...
And thanks for the help szymczyk! Much further now than I was two weeks ago because of your post, sorry for the late reply! (limited Mac access)
|Nov 29, 2012, 06:55 PM||#4|
NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; [[NSFileManager defaultManager] changeCurrentDirectoryPath:resourcePath];
You should also take a look at the following SFML tutorial, which includes a file named ResourcePath.mm that simplifies accessing the app bundle's Resources folder:
Tutorial - Getting started - SFML and Xcode (Mac OS X)
|Nov 30, 2012, 03:51 AM||#5|
Responding to my posts from two forums at once? Talk about above and beyond!
I set my working directory from XCode, it's under Product > Edit Scheme, then under "Run MyGame.app (Release)" in the Options tab, there is a setting there: "Working Directory: Use Custom Working Directory" and then a field to input your own path.
What's strangest yet though, none of this impacts anything after the data that is loaded when the game first starts. I just disabled using that working directory, and levels 2 through the end all load fine (they all copy over in their folders since XCode has been told that they are necessary files) - it's only that initial batch that has trouble loading. I imagine the rest succeed in accessing the Resources folder inside the app... so why would the first batch not be able to do this, or rely so heavily on the working dir?
So it really seems like I can get this without diving into Objective C. The latter levels are already loaded seamlessly from the Resources folder, so if I loaded everything with the second level, I would bet it all works. I just can't figure out why that would be right now. So it already can reference Resources on its own (I just make calls to "./map/level002.map" and it finds "~/myGame.app/Contents/Resources/map/level002.map" all on its own) but only after the program is already running. Any idea why its reference point would change between when it was starting and when it was actually running?
|Nov 30, 2012, 12:54 PM||#6|
You shouldn't have to dive into Objective-C. SFML has done most of the work for you. If you read the tutorial I linked to in the past post, SFML has Xcode project templates. The project templates have the files ResourcePath.mm and ResourcePath.hpp that contain the code to get to the app bundle's Resources folder. Create a SFML Application project, copy the ResourcePath.mm and ResourcePath.hpp files to your game's Xcode project folder, and add those files to your game's Xcode project.
Alternatively, you could use CFBundle to access the app bundle's Resources folder. CFBundle is a C API, not Objective-C. But I would start with SFML's ResourcePath files and see if that works before doing anything with CFBundle.
As to why the first level has problems loading, my guess is that the first level loads before the working directory changes to the app bundle's Resources folder. Make sure your code sets the working directory to the app bundle's Resources folder before loading any files.
|Thread Tools||Search this Thread|
|thread||Thread Starter||Forum||Replies||Last Post|
|Xcode gets the wrong path when adding files||printz||Mac Programming||1||Mar 6, 2014 04:01 AM|
|Where are files downloaded by Xcode being stored?||MacMan988||OS X 10.8 Mountain Lion||1||Jan 26, 2013 09:35 AM|
|How to ignore project files with xcode git ?||mikezang||iPhone/iPad Programming||1||Jan 7, 2013 04:14 AM|
|Input/Output with files in XCode||crisro996||Mac Programming||2||Jul 21, 2012 12:20 PM|
|Referencing Controls within / from sub views||CylonGlitch||Mac Programming||14||Jun 25, 2012 08:06 PM|
All times are GMT -5. The time now is 02:40 AM.