[Define to path of game asset directory.])
-CONFIGFILES="\$HOME/.yoinkrc:/etc/yoinkrc"
+CONFIGFILES="/etc/yoinkrc:\$HOME/.yoinkrc"
AC_DEFINE_UNQUOTED([YOINK_CONFIGFILES], ["$CONFIGFILES"],
[Define to colon-delimited configuration file paths.])
-/* C-style comments are allowed. */
-{
- "engine.timestep": 0.01,
- "input.grab": false,
- "video.colorbuffers": [8, 8, 8, 8],
- "video.cursor": true,
- "video.doublebuffer": true,
- "video.fullscreen": false,
- "video.maxfps": 45,
- "video.mode": [800, 600],
- "video.multisamplebuffers": 6,
- "video.multisamplesamples": 6,
- "video.resizable": true,
- //"video.printfps": true,
- "video.swapcontrol": true
-}
+
+-- Example Yoink Configuration File
+-- vim: ft=lua
+
+print "loading yoinkrc..."
+
+
+-- Set the level of detail to use when drawing scenes. This can be 1, 2 or
+-- 3, where 1 shows the least amount of detail and 3 draws the scene with
+-- the most detail.
+
+detail = 3
+
+-- Set the amount of time in seconds between each update of the physics
+-- state. A value of 0.01 or lower is ideal for accurate physics
+-- approximations. Values that are much higher cause the CPU to do less
+-- work, but accuracy will suffer. Errors could be introduced in the game
+-- with extremely high values.
+
+timestep = 0.01
+
+-- Set the maximum number of frames that can be drawn per second. A value
+-- of 50 is pretty good. If your computer is really old, you can get away
+-- with decreasing this value and still have reasonably smooth animation.
+-- You can set this to a very high number to effectively render as many
+-- frames as is possible, but the actual rate could be limited by vertical
+-- display synchronization, depending on the X11 driver and settings used.
+-- You should not set this option higher than the point where the vertical
+-- synchronization effectively limits the draw rate or else the game may
+-- not be able to update the physics on schedule which could actually
+-- significantly lower the quality of the animation.
+
+maxfps = 45
+
+-- Set whether or not to print the current actual framerate to the console.
+
+printfps = false
+
+-- Set whether or not the game will run in full-screen mode. If false, the
+-- game will run in a window.
+
+fullscreen = false
+
+-- If the game is running in a window, set whether or not the window will
+-- be resizable.
+
+resizable = true
+
+-- Set the resolution or size of the window. The value is an array with
+-- three number elements representing the width, height, and bits per pixel
+-- that make up the video mode. A typical value is 800,600 for a size of
+-- 800x600 pixels with millions of colors (the third number is optional).
+
+videomode = {1024, 786}
+
+-- Set whether or not the cursor will be visible when you mouse over the
+-- display of the game.
+
+showcursor = true
+
+-- Set whether or not the drawing should use two buffers. This results in
+-- a higher quality animation. You should usually leave this as true.
+
+doublebuffer = true
+
+-- Set whether or not to sync with the display in order to reduce
+-- distortion.
+
+swapcontrol = true
+
action. Basic arguments include:
.TP
.B -h, --help
-display this help and exit
+Display this help and exit.
.br
.SH TIPS
.PP
.PP
There are a plethora of options available for tweaking various aspects of the
game. All options can be set either from a configuration file or by passing
-them as arguments. Some of the more common options can be set from within the
-game.
+them as arguments.
.PP
A
.B yoink
-configuration file ("yoinkrc") consists of key-value pairs organized in a
-logical hierarchy. The format of the file is human-readable, so you can get in
-there with your favorite text editor if you like to work under the hood.
+configuration file ("yoinkrc") consists of key-value pairs. The format is not
+unlike that of other configuration files you are already familiar with. The
+syntax used is lua.
.B yoink
-looks for configuration files and loads them in this order, with the options in
-prior configuration files taking precedence over the same options if they exist
-in multiple configuration files:
+looks for configuration files and loads them in this order, the options from
+each subsequent configuration files taking precedence over the same options from
+previous files.
.TP
-1. $YOINKRC
-This is an optional environment variable you can set to point to a configuration
-file.
-.TP
-2. $HOME/.yoinkrc
-This is a specific user's personal configuration file.
+1. @DATADIR@/yoinkrc
+This is the base configuration file which should be considered read-only. Look
+to this file as an example of the format used for configuration files.
.TP
-3. /etc/yoinkrc
+2. /etc/yoinkrc
This is the system-wide configuration file. Not available on Windows.
.TP
-4. @DATADIR@/yoinkrc
-This is the base configuration file which should be considered read-only. Look
-to this file as an example of the format used for configuration files.
+3. $HOME/.yoinkrc
+This is your own personal configuration file.
+.TP
+4. $YOINKRC
+This is an optional environment variable you can set to point to a configuration
+file.
.PP
Options that are passed as arguments take precedence over options loaded from
the configuration file(s). This mechanism is good for running the game with a
-temporary setting which you do not intend to retain. Keep in mind that if you
-edit and save options in-game, any options you have passed as arguments during
-the invocation of the game will be saved to the
-.I $HOME/.yoinkrc
-configuration file. If this is not what you intended, you may have to go into
-that file and remove any options you didn't intend to set. When passing options
-as arguments, you must use the fully qualified name of the option if it exists
-in a subgroup. For example:
+temporary setting which you do not intend to retain. Examples:
.PP
.TP
-yoink video.fullscreen=true
-Set the option
-.I video.fullscreen
-to true. This will run the game in full-screen mode.
+yoink fullscreen=true
+Run Yoink with the option
+.I fullscreen
+as true. This will run the game in full-screen mode.
.TP
-yoink video.maxfps=60
-Set the option
-.I video.maxfps
-to 60. This will cap the display rate at 60Hz.
+yoink maxfps=60
+Run Yoink with the option
+.I maxfps
+as 60. This will cap the display rate at 60Hz.
.PP
You can also set options with array values. Arrays can be passed on the command
-line by surrounding all the parts with square brackets and separating each part
-by a comma. For example:
+line by surrounding all the parts with curly brackets and separating each part
+by a comma. You may also have to quote the brackets so your shell doesn't parse
+them. For example:
.TP
-yoink video.mode=[1024,768]
-Set the option
-.I video.mode
-to an array with numbers 1024 and 768. The video size will be 1024x768.
+yoink videomode=\\{1024,768\\}
+Run Yoink with the top
+.I videomode
+as the numbers 1024 and 768. The video size will be 1024x768.
.PP
Here is a list of some of the options available:
.TP
-.B engine.rngseed
-The number value used as a seed for the random number generator. Set this to
-make the game more predictable. This is typically only useful for debugging.
-.TP
-.B engine.timestep
-The amount of time in seconds between each update of the physics state. A value
-of 0.01 or lower is ideal for accurate physics approximations. Values that are
-much higher cause the CPU to do less work, but accuracy will suffer. Errors
-could be introduced in the game with extremely high values.
-.TP
-.B game.detail
+.B detail
The level of detail. Possible values are high, medium, and low. This effects
the number of objects drawn to the screen. A high level of detail will draw
everything but could cause poor frame rates if the graphics driver can't keep up
playing the game with the benefit of higher frame rates. See the Notes for more
ways to get good performance.
.TP
-.B input.grab
-Takes a boolean (true or false). If true, the cursor pointer will be "stuck"
-within the area of the window, and many key combinations which would otherwise
-be handled by the window manager will instead be dropped. This is a low-level
-option of limited usefulness.
-.TP
-.B video.colorbuffers
-This takes an array of four number values which represent the number of bits to
-use for red, green, blue, and the alpha channel. This is a low-level option of
-limited usefulness. The default value is almost always preferable.
-.TP
-.B video.showcursor
-This option effects the visibility of the cursor while it is "hovering" over the
-window. If the value is true, the cursor will be visible. Otherwise, the
-cursor will be hidden.
-.TP
-.B video.doublebuffer
+.B doublebuffer
If true, double-buffering will be used to render animations with minimal
distortions. Otherwise, a single buffer will be used. The recommended value is
true.
.TP
-.B video.fullscreen
+.B fullscreen
If true, the window will capture the display and render the game in full screen
splendor. A value of false means the game will run in a window.
.TP
-.B video.maxfps
+.B maxfps
The maximum number of frames to be drawn per second. A value of 50 is pretty
good. If your computer is pretty old, can get away with decreasing this value
and still have reasonably smooth animation. You can set this to a very high
game may not be able to update the physics on schedule which could actually
significantly lower the quality of the animation.
.TP
-.B video.mode
-The resolution or size of the window. The value is an array with three number
-elements representing the width, height, and bits per pixel that make up the
-video mode. A typical value is [800,600] for a size of 800x600 pixels with
-millions of colors (the third number is optional).
-.TP
-.B video.multisamplebuffers
-The number of multisample buffers used.
-.TP
-.B video.multisamplesamples
-The number of multisample samples used.
-.TP
-.B video.printfps
+.B printfps
If true, the current number of frames being draw per second will be printed to
the console. This is usually off by default, but you can set this to true if
you're interested in the draw rate you're actually getting.
.TP
-.B video.resizable
+.B resizable
If true, the window will be resizable by the window manager. This option is
meaningless if the game is drawing to the full screen.
.TP
-.B video.swapcontrol
-If true, drawing will take place at a time which will minimize distortion caused
-by the vertical refreshing of displays. The recommended value is true.
+.B showcursor
+This option effects the visibility of the cursor while it is "hovering" over the
+window. If the value is true, the cursor will be visible. Otherwise, the
+cursor will be hidden.
+.TP
+.B timestep
+The amount of time in seconds between each update of the physics state. A value
+of 0.01 or lower is ideal for accurate physics approximations. Values that are
+much higher cause the CPU to do less work, but accuracy will suffer. Errors
+could be introduced in the game with extremely high values.
+.TP
+.B videomode
+The resolution or size of the window. The value is an array with three number
+elements representing the width, height, and bits per pixel that make up the
+video mode. A typical value is {800,600} for a size of 800x600 pixels with
+millions of colors (the third number is optional).
+.PP
+This is only a list of the more useful options. You'll have to use the source
+to find out about the more esoteric options, but you probably won't need to.
.br
.SH ENVIRONMENT
.PP
If set to a path of a valid configuration file,
.B yoink
will load the options from that file, and those options will take precedence
-over options loaded from other configuration files. Any in-game saving will
-cause this file to be over-written by the new options rather than the
-.I $HOME/.yoinkrc
-config file.
+over options loaded from other configuration files.
.br
.SH NOTES
.PP
is. Yoink is really not all that heavy on graphics, but it doesn't take much to
overload a software implementation. If you're stuck without hardware
acceleration, there are some things you can do to get better frame rates:
-.PP
-1. Decrease the resolution with the
-.I video.mode
-option. Due to the nature of the graphics in the game, you can go as low as
-320x240 and not notice a large reduction in image quality. You can take
-advantage of this by decreasing the resolution and running full-screen (so the
-window is not so itty bitty on your monitor). This will help out a lot. Try
-this:
.TP
-yoink video.mode=[320,240] video.fullscreen=true
-.PP
-2. Decrease the level of detail with the
-.I game.detail
-option.
+1. Decrease the resolution.
+Use the
+.I videomode
+option. This speeds up software renderers considerably.
+.TP
+2. Decrease the level of rendering detail.
+Use the
+.I detail
+option. The game world may look sparse or incomplete, but that may be better
+than choppy animation.
.PP
On the other hand, if you already get high frame rates, you may also want to cap
the rate so that your computer doesn't do more work than it really needs to.
-This may be useful when you run
-.B yoink
-on your production server at work. You can get reasonably smooth animation at
-around 30fps, but you can probably tell a difference between that and a higher
-rate like 50fps. The latter will look noticeably smoother and nice, while the
-former is just "acceptable." See the
-.I video.maxfps
+You can get reasonably smooth animation at around 30fps, but you can probably
+tell a difference between that and a higher rate like 50fps. The latter will
+look noticeably smoother and nice, while the former is just "okay." See
+the
+.I maxfps
option.
.br
.SH BUGS
Impl(int argc, char* argv[], const std::string& configFile,
const std::string& name, const std::string& iconFile,
Engine* outer) :
- interface(outer)
+ interface(outer),
+ timestep(0.01),
+ printFps(false)
{
#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__)
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
alutInit(&argc, argv);
Settings& settings = Settings::getInstance();
- settings.parseArgs(argc, argv);
settings.loadFromFile(configFile);
+ settings.parseArgs(argc, argv);
long randomSeed;
- if (settings.get("engine.rngseed", randomSeed)) setSeed(randomSeed);
+ if (settings.get("rngseed", randomSeed)) setSeed(randomSeed);
else setSeed();
- double ts = 0.01;
- settings.get("engine.timestep", ts);
- timestep = Scalar(ts);
+ settings.get("timestep", timestep);
long maxFps = 40;
- settings.getNumber("video.maxfps", maxFps);
+ settings.get("maxfps", maxFps);
drawRate = 1.0 / Scalar(maxFps);
- printFps = false;
- settings.get("video.printfps", printFps);
+ settings.get("printfps", printFps);
video = Video::alloc(name, iconFile);
video->makeActive();
if (printFps)
{
- logInfo("framerate: %d fps", fps);
+ logInfo("%d fps", fps);
}
}
#include <cstring> // strcpy
#include "Log.hh"
+#include "Script.hh"
namespace Mf {
case LOG_WARNING:
fprintf(stderr, "warning: ");
break;
+ case LOG_SCRIPT:
+ fprintf(stderr, " script: ");
+ break;
case LOG_INFO:
fprintf(stderr, " info: ");
break;
va_end(args);
}
+static void logScript(const char* fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ printLog_(LOG_SCRIPT, fmt, args);
+
+ va_end(args);
+}
+
+int logScript(Script& script)
+{
+ Script::Value param = script[1];
+
+ while (!param.isNone())
+ {
+ if (param.isString())
+ {
+ std::string str;
+ param.get(str);
+ logScript("%s", str.c_str());
+ }
+ else if (param.isBoolean())
+ {
+ if (param) logScript("true");
+ else logScript("false");
+
+ }
+ else if (param.isNil())
+ {
+ logScript("nil");
+ }
+ else
+ {
+ logScript("%s (%X)", param.getTypeName().c_str(),
+ param.getIdentifier());
+ }
+
+ param.index++;
+ }
+
+ return 0;
+}
+
+
+void importLogScript(Script& script)
+{
+ script.importFunction("print", (int (*)(Script&))logScript);
+}
+
} // namespace Mf
LOG_NONE = -1, ///< Disable all logging.
LOG_ERROR = 1, ///< Log only errors.
LOG_WARNING = 2, ///< Log warnings and errors.
- LOG_INFO = 3, ///< Log info, warnings, errors.
- LOG_DEBUG = 4 ///< Log all messages.
+ LOG_SCRIPT = 3, ///< Log messages from Lua, too.
+ LOG_INFO = 4, ///< Log info, warnings, errors.
+ LOG_DEBUG = 5, ///< Log all messages.
};
void logDebug(const char* fmt, ...);
+class Script;
+int logScript(Script& script);
+void importLogScript(Script& script);
+
} // namespace Mf
};
-static int luaPrint(Script& script)
-{
- Script::Value param = script[1];
-
- while (!param.isNone())
- {
- if (param.isString())
- {
- std::string str;
- param.get(str);
- logInfo("lua: %s", str.c_str());
- }
- else if (param.isBoolean())
- {
- if (param) logInfo("lua: true");
- else logInfo("lua: false");
-
- }
- else if (param.isNil())
- {
- logInfo("lua: nil");
- }
- else
- {
- logInfo("lua: %s (%X)", param.getTypeName().c_str(),
- param.getIdentifier());
- }
-
- param.index++;
- }
-
- return 0;
-}
-
static void importScriptBindings(Script& script, Meh& scene)
{
script.importFunction("SetPlayfieldBounds",
boost::bind(&Meh::makeTilemap, &scene, _1));
script.importFunction("MakeBillboard",
boost::bind(&Meh::makeBillboard, &scene, _1));
- script.importFunction("print", luaPrint);
}
{
std::string filePath = getPath(name);
+ Meh cool;
+
Script script;
script.importStandardLibraries();
-
- Meh cool;
+ importLogScript(script);
importScriptBindings(script, cool);
long detail = 3;
- Settings::getInstance().getNumber("game.detail", detail);
+ Settings::getInstance().get("detail", detail);
script.push(detail);
script.set("detail");
*/
#include <list>
+#include <map>
#include <string>
+#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <lua.hpp>
#include <Moof/Exception.hh>
+#include <Moof/Log.hh>
namespace Mf {
* Value will be invalid even if index is manually changed to a valid
* index. You have to index the script itself to get a valid Value.
*/
- Value() :
- index(0),
- state(0) {}
-
- Value(lua_State* s, int i) :
+ Value(lua_State* s = 0, int i = 0) :
index(i),
state(s) {}
return std::string(lua_typename(state, (int)getType()));
}
+
+ /**
+ * Get the length of the value according to the definition given by Lua.
+ */
+
+ size_t getLength() const
+ {
+ return lua_objlen(state, index);
+ }
+
+ int getRealIndex() const
+ {
+ if (index < 0) return lua_gettop(state) + 1 + index;
+ else return index;
+ }
+
+
/**
* Get a pointer value (for userdata, tables, threads, and functions).
*/
}
- /**
- * Get the length of the value according to the definition given by Lua.
- */
-
- size_t getLength() const
- {
- return lua_objlen(state, index);
- }
-
-
/**
* Convert the underlying value to a C++ type.
*/
template <typename T>
- void get(T& value) const
+ bool get(T& value) const
{
- value = (T)lua_tointeger(state, index);
+ if (isNumber())
+ {
+ value = (T)lua_tointeger(state, index);
+ return true;
+ }
+ return false;
}
- void get(bool& value) const
+ bool get(float& value) const
{
- value = (bool)lua_toboolean(state, index);
+ if (isNumber())
+ {
+ value = (float)lua_tonumber(state, index);
+ return true;
+ }
+ return false;
}
-
- void get(float& value) const
+ bool get(double& value) const
{
- value = (float)lua_tonumber(state, index);
+ if (isNumber())
+ {
+ value = (double)lua_tonumber(state, index);
+ return true;
+ }
+ return false;
}
- void get(double& value) const
+
+ bool get(bool& value) const
{
- value = (double)lua_tonumber(state, index);
+ if (isBoolean())
+ {
+ value = (bool)lua_toboolean(state, index);
+ return true;
+ }
+ return false;
}
- void get(std::string& value) const
+ bool get(std::string& value) const
{
- size_t size;
- const char* str = lua_tolstring(state, index, &size);
- value.assign(str, size);
+ if (isString())
+ {
+ size_t size;
+ const char* str = lua_tolstring(state, index, &size);
+ value.assign(str, size);
+ return true;
+ }
+ return false;
}
+ template <typename T>
+ bool get(std::vector<T>& array) const
+ {
+ if (!isTable()) return false;
+
+ array.clear();
- void set(std::string& value)
+ Value value(state, -1);
+ int realIndex = getRealIndex();
+
+ bool done = false;
+ for (int i = 1; !done; ++i)
+ {
+ lua_rawgeti(state, realIndex, i);
+
+ T v;
+ if (value.get(v)) array.push_back(v);
+ else done = true;
+
+ lua_pop(state, 1);
+ }
+
+ return true;
+ }
+
+ template <typename T>
+ bool get(std::map<std::string,T>& dictionary) const
{
+ if (!isTable()) return false;
+
+ dictionary.clear();
+
+ Value key(state, -2);
+ Value value(state, -1);
+ int realIndex = getRealIndex();
+
+ lua_pushnil(state);
+ while (lua_next(state, realIndex) != 0)
+ {
+ std::string k;
+ if (!key.isNumber() && key.get(k))
+ {
+ T v;
+ if (value.get(v)) dictionary[k] = v;
+ }
+ lua_pop(state, 1);
+ }
+ lua_pop(state, 1);
+
+ return true;
}
- //template <typename T>
- //void get(const std::string& field, T& value) const
- //{
- ////lua_getfield(state_, field.c_str());
- //pushField(field);
- //get(-1, value);
- //lua_pop(state_, 1);
- //}
-
+
/**
* Copy the value and push the copy to the stack.
* Pops n values from the top of the stack.
*/
- void pop(int n)
+ void pop(int n = 1)
{
lua_pop(state_, n);
}
#include <sstream>
#include <cstdlib> // getenv
-#include <cstring> // strchr
-#include <boost/algorithm/string.hpp>
-
-#include "Log.hh"
#include "Settings.hh"
namespace Mf {
-Settings::Settings(int argc, char* argv[])
-{
- parseArgs(argc, argv);
-}
-
-
Settings& Settings::getInstance()
{
static Settings settings;
{
for (int i = 1; i < argc; ++i)
{
- char* where = strchr(argv[i], (int)'=');
-
- if (where)
- {
- std::string key(argv[i], (size_t)(where - argv[i]));
- std::string stringValue(where + 1);
-
- std::stringstream stream;
- stream << stringValue << std::endl;
-
- Deserializer deserializer(stream);
-
- try
- {
- SerializableP value(deserializer.deserialize());
- map_[key] = value;
- }
- catch (std::exception e)
- {
- // it doesn't deserialize to anything we know, so just store it
- // as a string
- map_[key] = SerializableP(new SerializableBasic<Serializable::String>(stringValue));
- }
- }
+ script_.doString(argv[i]);
}
}
-void Settings::loadFromFile(const std::string& filePath, bool precedence)
+void Settings::loadFromFile(const std::string& filePath)
{
std::vector<std::string> paths;
boost::split(paths, filePath, boost::is_any_of(":"));
- loadFromFiles(paths, precedence);
+ loadFromFiles(paths);
}
-void Settings::loadFromFiles(const std::vector<std::string>& filePaths,
- bool precedence)
+void Settings::loadFromFiles(const std::vector<std::string>& filePaths)
{
std::vector<std::string>::const_iterator it;
boost::replace_all(path, "$HOME", home);
}
- try
- {
- Deserializer deserializer(*it, true);
-
- SerializableP obj = deserializer.deserialize();
- Serializable::Map map;
-
- if (obj && obj->get(map))
- {
- if (!precedence)
- {
- map_.insert(map.begin(), map.end());
- }
- else
- {
- map.insert(map_.begin(), map_.end());
- map_ = map;
- }
- }
- }
- catch (Deserializer::Exception e)
+ if (script_.doFile(path) != Script::SUCCESS)
{
- logWarning("cannot load settings from %s because an exception was"
- "thrown: %s", (*it).c_str(), e.what());
+ std::string str;
+ script_[-1].get(str);
+ logWarning("running config file: %s", str.c_str());
+ script_.clear();
}
}
}
* Load, store, save program settings.
*/
-#include <map>
#include <string>
+#include <vector>
-#include <Moof/Serializable.hh>
+#include <boost/algorithm/string.hpp>
+
+#include <Moof/Log.hh>
+#include <Moof/Script.hh>
namespace Mf {
class Settings
{
public:
- Settings() {}
- Settings(int argc, char* argv[]);
+ Settings() :
+ globals_(script_.getGlobalTable()),
+ top_(script_[-1])
+ {
+ importLogScript(script_);
+ }
// get global instance
static Settings& getInstance();
void parseArgs(int argc, char* argv[]);
- void loadFromFile(const std::string& filePath, bool precedence = false);
- void loadFromFiles(const std::vector<std::string>& filePaths,
- bool precedence = false);
+ void loadFromFile(const std::string& filePath);
+ void loadFromFiles(const std::vector<std::string>& filePaths);
template <typename T>
bool get(const std::string& key, T& value);
- template <typename T>
- bool getNumber(const std::string& key, T& value);
private:
- Serializable::Map map_;
+ Script script_;
+ Script::Value globals_, top_;
};
template <typename T>
bool Settings::get(const std::string& key, T& value)
{
- Serializable::Map::const_iterator it = map_.find(key);
+ std::vector<std::string> fields;
+ boost::split(fields, key, boost::is_any_of("."));
- if (it != map_.end())
- {
- SerializableP obj = (*it).second;
- return obj->get(value);
- }
- else
- {
- return false;
- }
-}
-
-template <typename T>
-bool Settings::getNumber(const std::string& key, T& value)
-{
- Serializable::Map::const_iterator it = map_.find(key);
+ globals_.pushCopy();
- if (it != map_.end())
+ std::vector<std::string>::iterator it;
+ for (it = fields.begin(); it != fields.end(); ++it)
{
- SerializableP obj = (*it).second;
- return obj->getNumber(value);
- }
- else
- {
- return false;
+ if (top_.isTable())
+ {
+ top_.pushField(*it);
+ }
+ else
+ {
+ script_.clear();
+ return false;
+ }
}
+
+ bool got = top_.get(value);
+ script_.clear();
+ return got;
}
return impl_->isPlaying();
}
-void Sound::setPosition(Vector3 position)
+void Sound::setPosition(const Vector3& position)
{
float p[3] = {position[0], position[1], position[2]};
alSourcefv(impl_->source_, AL_POSITION, p);
}
-void Sound::setVelocity(Vector3 velocity)
+void Sound::setVelocity(const Vector3& velocity)
{
float v[3] = {velocity[0], velocity[1], velocity[2]};
alSourcefv(impl_->source_, AL_VELOCITY, v);
}
+void Sound::setListenerPosition(const Vector3& position)
+{
+ alListener3f(AL_POSITION, float(position[0]), float(position[1]),
+ float(position[2]));
+}
+
+void Sound::setListenerVelocity(const Vector3& velocity)
+{
+ alListener3f(AL_VELOCITY, float(velocity[0]), float(velocity[1]),
+ float(velocity[2]));
+}
+
+void Sound::setListenerOrientation(const Vector3& forward, const Vector3& up)
+{
+ float vec[6];
+ vec[0] = float(forward[0]);
+ vec[1] = float(forward[1]);
+ vec[2] = float(forward[2]);
+ vec[3] = float(up[0]);
+ vec[4] = float(up[1]);
+ vec[5] = float(up[2]);
+ alListenerfv(AL_ORIENTATION, vec);
+}
+
+
std::string Sound::getPath(const std::string& name)
{
std::string path = Resource::getPath("sounds/" + name + ".ogg");
bool isPlaying() const;
- void setPosition(Vector3 position);
- void setVelocity(Vector3 velocity);
+ void setPosition(const Vector3& position);
+ void setVelocity(const Vector3& velocity);
void setGain(Scalar gain);
void setPitch(Scalar pitch);
void setLooping(bool looping);
+ static void setListenerPosition(const Vector3& position);
+ static void setListenerVelocity(const Vector3& velocity);
+ static void setListenerOrientation(const Vector3& forward,
+ const Vector3& up);
+
static std::string getPath(const std::string& name);
#include "Dispatcher.hh"
#include "Log.hh"
-#include "Serializable.hh"
#include "Settings.hh"
#include "Video.hh"
Settings& settings = Settings::getInstance();
- Serializable::Array colors;
- settings.get("video.colorbuffers", colors);
- if (colors.size() > 0) colors[0]->get(colorBuffer[0]);
- if (colors.size() > 1) colors[1]->get(colorBuffer[1]);
- if (colors.size() > 2) colors[2]->get(colorBuffer[2]);
- if (colors.size() > 3) colors[3]->get(colorBuffer[3]);
-
- settings.get("video.framebuffer", frameBuffer);
- settings.get("video.doublebuffer", doubleBuffer);
- settings.get("video.depthbuffer", depthBuffer);
- settings.get("video.stencilbuffer", stencilBuffer);
-
- Serializable::Array accum;
- settings.get("video.accumbuffers", accum);
- if (accum.size() > 0) accum[0]->get(accumBuffer[0]);
- if (accum.size() > 1) accum[1]->get(accumBuffer[1]);
- if (accum.size() > 2) accum[2]->get(accumBuffer[2]);
- if (accum.size() > 3) accum[3]->get(accumBuffer[3]);
-
- settings.get("video.stereo", stereo);
- settings.get("video.multiesamplebuffers", multisampleBuffers);
- settings.get("video.multiesamplesamples", multisampleSamples);
- settings.get("video.swapcontrol", swapControl);
- settings.get("video.hardwareonly", hardwareonly);
-
- if (!settings.get("video.caption", caption))
+ std::vector<long> colors;
+ settings.get("colorbuffers", colors);
+ if (colors.size() > 0) colorBuffer[0] = colors[0];
+ if (colors.size() > 1) colorBuffer[1] = colors[1];
+ if (colors.size() > 2) colorBuffer[2] = colors[2];
+ if (colors.size() > 3) colorBuffer[3] = colors[3];
+
+ settings.get("framebuffer", frameBuffer);
+ settings.get("doublebuffer", doubleBuffer);
+ settings.get("depthbuffer", depthBuffer);
+ settings.get("stencilbuffer", stencilBuffer);
+
+ std::vector<long> accum;
+ settings.get("accumbuffers", accum);
+ if (accum.size() > 0) accumBuffer[0] = accum[0];
+ if (accum.size() > 1) accumBuffer[1] = accum[1];
+ if (accum.size() > 2) accumBuffer[2] = accum[2];
+ if (accum.size() > 3) accumBuffer[3] = accum[3];
+
+ settings.get("stereo", stereo);
+ settings.get("multiesamplebuffers", multisampleBuffers);
+ settings.get("multiesamplesamples", multisampleSamples);
+ settings.get("swapcontrol", swapControl);
+ settings.get("hardwareonly", hardwareonly);
+
+ if (!settings.get("caption", caption))
{
caption = "Untitled";
}
- settings.get("video.icon", icon);
-
- Serializable::Array dimensions;
- settings.get("video.mode", dimensions);
- if (dimensions.size() > 0) dimensions[0]->get(mode[0]);
- if (dimensions.size() > 1) dimensions[1]->get(mode[1]);
- if (dimensions.size() > 2) dimensions[2]->get(mode[2]);
-
- settings.get("video.fullscreen", fullscreen);
- settings.get("video.resizable", resizable);
- settings.get("video.showcursor", cursorVisible);
- settings.get("input.grab", cursorGrab);
+ settings.get("icon", icon);
+
+ std::vector<long> dimensions;
+ settings.get("videomode", dimensions);
+ if (dimensions.size() > 1)
+ {
+ mode[0] = dimensions[0];
+ mode[1] = dimensions[1];
+ }
+ if (dimensions.size() > 2) mode[2] = dimensions[2];
+
+ settings.get("fullscreen", fullscreen);
+ settings.get("resizable", resizable);
+ settings.get("showcursor", cursorVisible);
+ settings.get("grab", cursorGrab);
}
*******************************************************************************/
#include <cstdlib> // getenv
+#include <cstring>
#include <iostream>
#include <string>
{
std::string files;
- char* configFile = getenv("YOINKRC");
+ // look in the configured data directory last of all
char* dataDir = getenv("YOINK_DATADIR");
-
- if (configFile)
- {
- // if a config file from the environment variable is specified, we want
- // to load it first so it has precedence
- files += configFile;
- files += ":";
- }
+ files += (dataDir ? dataDir : YOINK_DATADIR);
+ files += "/yoinkrc";
// add the colon-delimited paths from configure
+ files += ":";
files += YOINK_CONFIGFILES;
- if (dataDir)
+ char* configFile = getenv("YOINKRC");
+ if (configFile)
{
- // if another data directory is set in the environment, look for a
- // config file there
+ // if a config file from the environment variable is specified, we want
+ // to load it first so it has precedence
files += ":";
- files += dataDir;
- files += "/yoinkrc";
+ files += configFile;
}
- // look in the configured data directory last of all
- files += ":";
- files += (dataDir ? dataDir : YOINK_DATADIR);
- files += "/yoinkrc";
-
return files;
}
camera.setPosition(Mf::Vector3(-heroine->current.position[0],
-heroine->current.position[1], -256));
+ Mf::Vector3 heroinePosition;
+ Mf::promoteVector(heroinePosition, heroine->current.position);
+ Mf::Sound::setListenerPosition(heroinePosition);
+
interp.update(dt);
hud.setBar1Progress(interp.getState(dt));
hud.setBar2Progress(1.0 - interp.getState(dt));
}
+void printUsage()
+{
+ std::cout << "Usage: "PACKAGE" [-h|--help] [OPTION=VALUE]..." << std::endl
+ << "The alien-smashing action game." << std::endl
+ << std::endl
+ << "Options:" << std::endl
+ << " -h, --help" << std::endl
+ << " show this help and exit" << std::endl
+ << " detail=1|2|3" << std::endl
+ << " the level of detail of game scenes" << std::endl
+ << " fullscreen=true|false" << std::endl
+ << " if true, uses the entire display" << std::endl
+ << " maxfps=num" << std::endl
+ << " the maximum number of frames per second" << std::endl
+ << std::endl
+ << "See documentation for more options." << std::endl;
+}
int main(int argc, char* argv[])
{
+ if (argc > 1 &&
+ (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0))
+ {
+ printUsage();
+ return 0;
+ }
+
std::cout << std::endl << PACKAGE_STRING << std::endl
<< "Compiled " << __TIME__ " " __DATE__ << std::endl
<< "Send patches and bug reports to <"
#elif YOINK_LOGLEVEL >= 3
Mf::setLogLevel(Mf::LOG_INFO);
#elif YOINK_LOGLEVEL >= 2
- Mf::setLogLevel(Mf::LOG_WARNING);
+ Mf::setLogLevel(Mf::LOG_SCRIPT);
#elif YOINK_LOGLEVEL >= 1
Mf::setLogLevel(Mf::LOG_ERROR);
#elif YOINK_LOGLEVEL