[Racer-svn] SF.net SVN: racer:[130] trunk/racer
Status: Alpha
Brought to you by:
jlegg
From: <jl...@us...> - 2009-12-12 03:31:33
|
Revision: 130 http://racer.svn.sourceforge.net/racer/?rev=130&view=rev Author: jlegg Date: 2009-12-12 03:31:26 +0000 (Sat, 12 Dec 2009) Log Message: ----------- Use editor created tracks in the game. No textures yet. Breaks replay. Modified Paths: -------------- trunk/racer/Engine/GameObjects/Car.cpp trunk/racer/Engine/GameObjects/Car.h trunk/racer/Engine/GameScene.cpp trunk/racer/Engine/GameScene.h trunk/racer/Engine/Makefile.am trunk/racer/Engine/ReplayReader.cpp trunk/racer/Engine/ReplayReader.h trunk/racer/MainLoop.cpp trunk/racer/MainLoop.h trunk/racer/RacerApp.cpp trunk/racer/RacerApp.h trunk/racer/UI/GameStartMenuItem.cpp trunk/racer/UI/GameStartMenuItem.h trunk/racer/UI/ReplayStartMenuItem.cpp trunk/racer/UI/TitleScene.cpp Added Paths: ----------- trunk/racer/Engine/LoadScene.h Modified: trunk/racer/Engine/GameObjects/Car.cpp =================================================================== --- trunk/racer/Engine/GameObjects/Car.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/GameObjects/Car.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -82,7 +82,7 @@ typedef ResourceHandler<Graphics::Texture, int, std::string> TextureStore; typedef ResourceHandler<Graphics::Mesh, int, Graphics::Mesh::ConstructionInformation> MeshStore; -Car::Car(Physics::World & world, float height, InputDevice * input_device, +Car::Car(Physics::World & world, btTransform start, InputDevice * input_device, unsigned int car_model) : world(world), input_device(input_device), @@ -122,8 +122,7 @@ btVector3 inertia(0,0,0); shape->calculateLocalInertia(mass, inertia); btDefaultMotionState* motion_state = - new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1), - btVector3(height * 1.8 - 20.0, 0.0, 3.0))); + new btDefaultMotionState(start); btRigidBody::btRigidBodyConstructionInfo rigid_body_CI(mass, motion_state, Modified: trunk/racer/Engine/GameObjects/Car.h =================================================================== --- trunk/racer/Engine/GameObjects/Car.h 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/GameObjects/Car.h 2009-12-12 03:31:26 UTC (rev 130) @@ -37,12 +37,12 @@ public: /** Construct the car and place it into the game. * @param world The Physics world of the game. - * @param height A parameter that picks the starting position. + * @param start The transformation for the starting position. * @todo Get a proper starting position. * @param input_device The input device to bind the car to. * @param car_model The mesh and texture of the car. Must be 0 or 1. */ - Car(Physics::World & world, float height, InputDevice * input_device, + Car(Physics::World & world, btTransform start, InputDevice * input_device, unsigned int car_model); virtual ~Car(); virtual void draw(OcclusionTester & occlusion_tester); Modified: trunk/racer/Engine/GameScene.cpp =================================================================== --- trunk/racer/Engine/GameScene.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/GameScene.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -22,40 +22,40 @@ { GameScene::GameScene(std::vector<std::size_t> input_device_indices, - unsigned int stage) - : sky(stage ? "data/theme4/sky.png" : "data/theme2/sky/sky_box.png") - , floor(stage ? "data/playground2.png" : "data/playground1.png") - , playground_graphics(stage ? "data/playground2" : "data/playground1", - Graphics::Mesh::genererator_graphic_bit) - , playground_physics(stage? "data/playground2_phys_sub" : "data/playground1_phys", - Graphics::Mesh::genererator_triangle_mesh_bit - ) - , stage(stage) + const Track::Track & track) + /// @todo support this: sky(track.get_theme().get_skybox()) + : sky("data/theme4/sky.png") + , track(track) , save_replay(true) { + /** @todo take starting positions set in the editor.*/ + // For now we place cars along any edge. + const Track::Path::Graph & graph = track.get_path().graph; + const Track::PathEdge & edge = graph[*(boost::edges(graph).first)]; const std::size_t number_of_cars = input_device_indices.size(); cars.reserve(number_of_cars); car_cameras.reserve(number_of_cars); for(unsigned int i = 0; i< number_of_cars; i++) { + btScalar position = btScalar(i) / btScalar(number_of_cars); + btTransform transform = edge.get_transform(position); + transform.setOrigin(transform(btVector3(0.0, 0.0, 1.0))); cars.push_back(new GameObjects::Car(world, - i, + transform, InputHandler::get_instance()[input_device_indices[i]], i%2)); car_cameras.push_back(new CarCamera(*cars[i], world)); } btDefaultMotionState motion_state(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 0, 0))); - btCollisionShape * shape = playground_physics.get_triangle_shape(); - //shape->setMargin(btScalar(0.01)); + track_shape = track.get_collision_shape(); btRigidBody::btRigidBodyConstructionInfo rigid_body_CI(btScalar(0), &motion_state, - shape, + &(*track_shape), btVector3(0, 0, 0)); - playground_body = new btRigidBody(rigid_body_CI); - world.get_dynamics_world().addRigidBody(playground_body); - //world.get_course_collision_world().addCollisionObject(playground_body); + track_body = new btRigidBody(rigid_body_CI); + world.get_dynamics_world().addRigidBody(track_body); } GameScene::~GameScene() @@ -65,13 +65,14 @@ { std::ofstream out("last replay"); // Write metadata identifing the scene and cars - out << stage << " "; + /// @todo write track filename. + // out << stage << " "; // Write the input device events that occured during the game. world.write_replay_events(out); } - delete playground_body; - // delete the car's cameras + delete track_body; + // delete the cars' cameras for (std::vector<CarCamera *>::iterator i = car_cameras.begin(); i != car_cameras.end(); i++) { @@ -223,10 +224,45 @@ car_cameras[player]->full_transform(); glEnable(GL_DEPTH_TEST); - // draw ground plane - floor.bind(); + + // + // draw scene + // + const Track::Path & path = track.get_path(); + // edges glEnable(GL_CULL_FACE); - playground_graphics.draw(); + glClear(GL_DEPTH_BUFFER_BIT); + typedef boost::graph_traits<Track::Path::Graph>::edge_iterator EdgeIterator; + std::pair<EdgeIterator, EdgeIterator> edge_range; + for (edge_range = boost::edges(path.graph); + edge_range.first != edge_range.second; + edge_range.first++) + { + const Track::PathEdge & edge = path.graph[*(edge_range.first)]; + unsigned int count = edge.get_number_of_repetions(); + for (unsigned int i = 0; i < count; i++) + { + edge.get_graphics_mesh(i)->draw(); + } + } + // vertices. + typedef boost::graph_traits<Track::Path::Graph>::vertex_iterator VertexIterator; + std::pair<VertexIterator, VertexIterator> vertex_range; + for (vertex_range = boost::vertices(path.graph); + vertex_range.first != vertex_range.second; + vertex_range.first++) + { + const Track::PathVertex & vertex = path.graph[*(vertex_range.first)]; + // Draw mesh at vertex. + glPushMatrix(); + btScalar mat[16]; + mat[15] = 1.0; + btTransform(vertex.get_angle(), vertex.get_position()).getOpenGLMatrix(mat); + glMultMatrixf(mat); + vertex.get_segment()->get_graphics_mesh().get_faces().draw(); + glPopMatrix(); + } + // cars for (unsigned int i = 0; i < cars.size(); i++) { cars[i]->draw(occlusion_tester); Modified: trunk/racer/Engine/GameScene.h =================================================================== --- trunk/racer/Engine/GameScene.h 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/GameScene.h 2009-12-12 03:31:26 UTC (rev 130) @@ -19,6 +19,8 @@ #include "OcclusionTester.h" #include "CarCamera.h" +#include <libtrack/Track.h> + namespace Engine { @@ -28,12 +30,10 @@ /** Create a game where the players use specified input devices. * @param input_device_indices The indices of the devices in InputHandler to * use for players. The ordering is important. - * @param stage which stage to use. Must be 0 or 1. - * @todo Load stages as created by the level editor, rather than using - * large meshes exported from Blender. + * @param track The track to play on. */ GameScene(std::vector<std::size_t> input_device_indices, - unsigned int stage); + const Track::Track & track); virtual ~GameScene(); @@ -69,17 +69,15 @@ void set_save_replay(bool value = true); private: Graphics::SkyBox sky; - Graphics::Texture floor; - Graphics::Mesh playground_graphics; - Graphics::Mesh playground_physics; Physics::World world; OcclusionTester occlusion_tester; std::vector<GameObjects::Car *> cars; std::vector<CarCamera *> car_cameras; - btRigidBody * playground_body; + btRigidBody * track_body; + boost::shared_ptr<btCollisionShape> track_shape; - /// An identifier for the course being played. - unsigned int stage; + /// The course to play on + const Track::Track & track; /// Save replays when the scene is destroyed? bool save_replay; Added: trunk/racer/Engine/LoadScene.h =================================================================== --- trunk/racer/Engine/LoadScene.h (rev 0) +++ trunk/racer/Engine/LoadScene.h 2009-12-12 03:31:26 UTC (rev 130) @@ -0,0 +1,143 @@ +/** @file racer/Engine/LoadScene.h + * @brief Declare the Engine::LoadScene class. + * @author James Legg + */ +/* Copyright © 2009 James Legg. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. +*/ +#ifndef RACER_ENGINE_LOAD_SCENE_H +#define RACER_ENGINE_LOAD_SCENE_H + +#include "GameScene.h" +#include "../MainLoop.h" + +#include <libtrack/Track.h> + +#include <GL/gl.h> + +#include <boost/shared_ptr.hpp> + +#include <vector> +#include <string> +#include <fstream> + +namespace Engine +{ + +template <class T> +class daft_function_object +{ +public: + void operator()(T * in) {}; +}; + +/** Load a game. + * @tparam class of scene to create. Must be an Engine::Scene constuctable + * with a std::vector<std::size_t> picking the input devices and a + * Track::Track for the track. + */ +template <class T = GameScene, class Q = daft_function_object<T> > +class LoadScene : public Engine::Scene +{ +public: + /** Load a game where the players use specified input devices. + * @param input_device_indices The indices of the devices in InputHandler to + * use for players. The ordering is important. + * @param track The filename of the track. + */ + LoadScene(std::vector<std::size_t> input_device_indices, + std::string filename) + : blanked(false) + , track_filename(filename) + , input_device_indices(input_device_indices) + , main_loop(0) + , function_object(0) + { + } + + virtual ~LoadScene() + { + } + + virtual void take_input(InputReport & report) + { + // ignore input. + } + + virtual void update_logic(unsigned int milliseconds_elapsed) + { + // wait until the screen has been blanked before trying any long + // operations. + if (!blanked) return; + // load the track and its theme. + track_file = boost::shared_ptr<std::ifstream>(new std::ifstream(track_filename.c_str())); + std::getline(*track_file, theme_filename); + theme_file = boost::shared_ptr<std::ifstream>(new std::ifstream(theme_filename.c_str())); + theme = boost::shared_ptr<Track::Theme>(new Track::Theme(*theme_file)); + track = boost::shared_ptr<Track::Track>(new Track::Track(*track_file, *theme)); + // create the game scene + game_scene = boost::shared_ptr<T>(new T(input_device_indices, *track)); + if (main_loop) + { + main_loop->set_scene(*game_scene); + } + if (function_object) + { + (*function_object)(&(*game_scene)); + } + // How will the loaded scene ever be used without being assigned a + // main_loop or passed to something else? + assert((main_loop != 0) | (function_object != 0)); + } + + virtual void draw() + { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + blanked = true; + } + + virtual void do_sound() + { + } + + /// Set the main loop so that it can be switched when the game loads + void set_main_loop(MainLoop & main_loop_in) + { + main_loop = &main_loop_in; + } + + /// Give a function object the a reference to the scene when it's ready. + void set_done_notifier(Q * function_object_in) + { + function_object = function_object_in; + } +private: + bool blanked; + /// The filename of the track. + std::string track_filename; + boost::shared_ptr<std::ifstream> track_file; + /// The filename of the theme the track uses + std::string theme_filename; + boost::shared_ptr<std::ifstream> theme_file; + /// Theme the track uses + boost::shared_ptr<Track::Theme> theme; + /// The course to play on + boost::shared_ptr<Track::Track> track; + + boost::shared_ptr<T> game_scene; + + std::vector<std::size_t> input_device_indices; + + /// loop to use for new scene + MainLoop * main_loop; + /// object to send new scene to. + Q * function_object; +}; + +} // namespace Engine + +#endif // RACER_ENGINE_LOAD_SCENE_H Modified: trunk/racer/Engine/Makefile.am =================================================================== --- trunk/racer/Engine/Makefile.am 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/Makefile.am 2009-12-12 03:31:26 UTC (rev 130) @@ -1,6 +1,6 @@ SUBDIRS = GameObjects Physics noinst_LIBRARIES = libengine.a -libengine_a_SOURCES = CarCamera.cpp Drawable.h InputDevice.cpp InputDeviceJoystick.cpp InputDeviceJoystick.h InputDeviceKeyboard.h InputDeviceReplay.cpp InputDeviceReplay.h InputReport.cpp OcclusionTester.h Scene.h CarCamera.h GameScene.cpp InputDevice.h InputHandler.cpp InputReport.h ResourceHandler.h Drawable.cpp GameScene.h InputDeviceKeyboard.cpp InputHandler.h OcclusionTester.cpp ReplayReader.cpp ReplayReader.h Scene.cpp +libengine_a_SOURCES = CarCamera.cpp Drawable.h InputDevice.cpp InputDeviceJoystick.cpp InputDeviceJoystick.h InputDeviceKeyboard.h InputDeviceReplay.cpp InputDeviceReplay.h InputReport.cpp LoadScene.h OcclusionTester.h Scene.h CarCamera.h GameScene.cpp InputDevice.h InputHandler.cpp InputReport.h ResourceHandler.h Drawable.cpp GameScene.h InputDeviceKeyboard.cpp InputHandler.h OcclusionTester.cpp ReplayReader.cpp ReplayReader.h Scene.cpp libengine_a_CPPFLAGS = $(racer_CFLAGS) -I@top_srcdir@ libengine_a_LIBADD = GameObjects/libgameobjects.a Physics/libphysics.a #we need a flattened archive rather than a nested one, so gameobjects and physics libraries work. Modified: trunk/racer/Engine/ReplayReader.cpp =================================================================== --- trunk/racer/Engine/ReplayReader.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/ReplayReader.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -20,8 +20,8 @@ : ticks(0) { // Read metadata - unsigned int stage; - data >> stage; + std::string stage; + std::getline(data, stage); /// @todo read metadata about players std::vector<std::size_t> input_devices; @@ -37,8 +37,14 @@ input_devices[index] = index + input_devices_start; } - // create scene - scene = new Engine::GameScene(input_devices, stage); + // create scene to load game. + load_scene = new Engine::LoadScene<Engine::GameScene, ReplayReader>(input_devices, stage); + load_scene->set_done_notifier(this); +} + +void ReplayReader::operator()(GameScene * scene_in) +{ + scene = scene_in; // monitor ticks so that we can submit events at the right time. scene->get_world().add_tick_observer(this); // we don't want to save a replay of the replay. Modified: trunk/racer/Engine/ReplayReader.h =================================================================== --- trunk/racer/Engine/ReplayReader.h 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/Engine/ReplayReader.h 2009-12-12 03:31:26 UTC (rev 130) @@ -19,6 +19,7 @@ #include "InputReport.h" #include "InputDeviceReplay.h" #include "GameScene.h" +#include "LoadScene.h" namespace Engine { @@ -62,6 +63,9 @@ /// Process any events that happen next tick. virtual void posttick(); + + /// Called by LoadScene when it has finished loading. + void operator ()(GameScene *); protected: struct ReplayEvent { @@ -86,7 +90,9 @@ /// Input devices to relay the events through. There is one per player. std::vector<InputDeviceReplay *> devices; - // The scene the replay takes place in. + /// The scene used to load the track. + LoadScene<GameScene, ReplayReader> * load_scene; + /// The scene the replay takes place in. GameScene * scene; }; Modified: trunk/racer/MainLoop.cpp =================================================================== --- trunk/racer/MainLoop.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/MainLoop.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -25,6 +25,14 @@ DEBUG_MESSAGE("Starting Main loop"); scene.attach_main_loop(*this); Engine::InputHandler::get_instance().set_scene(scene); +} + +MainLoop::~MainLoop() +{ +} + +void MainLoop::run() +{ while (!quit) { process_events(); @@ -34,10 +42,6 @@ } } -MainLoop::~MainLoop() -{ -} - void MainLoop::exit() { DEBUG_MESSAGE("Internal quit request: Will quit next frame."); Modified: trunk/racer/MainLoop.h =================================================================== --- trunk/racer/MainLoop.h 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/MainLoop.h 2009-12-12 03:31:26 UTC (rev 130) @@ -13,8 +13,9 @@ #include "Engine/Scene.h" -/** When created, this class runs the main loop. It attaches to a scene which - * it asks to do processing until a quit message is received. +/** Runs the main loop. It attaches to a scene which + * it asks to do processing until a quit message is received. After creation, + * start the loop with run(). */ class MainLoop { @@ -25,6 +26,8 @@ void exit(); /// Change the active scene to a different one. void set_scene(Engine::Scene & scene); + /// Run the main loop. Returns when ready to quit. + void run(); private: // Record input void process_events(); Modified: trunk/racer/RacerApp.cpp =================================================================== --- trunk/racer/RacerApp.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/RacerApp.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -47,6 +47,7 @@ } main_loop = new MainLoop(*title_scene); + main_loop->run(); // shutdown SDL_Quit(); } @@ -94,16 +95,10 @@ } else { - if (argc == 2 && (argv[1][0] == '1' || argv[1][0] == '0')) + if (argc == 2) { // use a game scene - unsigned int track; - if (argv[1][0] == '1') - { - track = 1; - } else { - track = 0; - } + std::string track = argv[1]; // create a player for each controller. DEBUG_MESSAGE("Using one player per avaliable controller."); std::vector<std::size_t> input_devices; @@ -114,17 +109,25 @@ input_devices[index] = index; } /// @todo allow disused controllers by commandline arguments. - title_scene = new Engine::GameScene(input_devices, track); + /// @todo give it a main_loop or callback. + Engine::LoadScene<Engine::GameScene, RacerApp> * scene; + scene = new Engine::LoadScene<Engine::GameScene, RacerApp>(input_devices, track); + scene->set_done_notifier(this); + title_scene = scene; } } } +void RacerApp::operator ()(Engine::GameScene * new_scene) +{ + main_loop->set_scene(*new_scene); +} + void RacerApp::show_usage() { std::cout << "Usage:" << std::endl << "racer start the game showing the menu." << std::endl - << "racer 0 play track 0 multiplayer using all avaliable controllers." << std::endl - << "racer 1 play track 1 multiplayer using all avaliable controllers" << std::endl + << "racer track play track multiplayer using all avaliable controllers." << std::endl << "racer r file Show the replay saved in file." << std::endl << "racer r Show replay passed in by standard input." << std::endl << "racer --help Show this help and exit." << std::endl Modified: trunk/racer/RacerApp.h =================================================================== --- trunk/racer/RacerApp.h 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/RacerApp.h 2009-12-12 03:31:26 UTC (rev 130) @@ -15,6 +15,7 @@ #include "MainLoop.h" #include "Engine/Scene.h" #include "Engine/ReplayReader.h" +#include "Engine/GameScene.h" #include <vector> /* Class to handle command line arguments and start the game. @@ -30,6 +31,9 @@ RacerApp(int argc, char ** argv); /// Destuctor: do some final clearing up. ~RacerApp(); + + /// Set the scene. + void operator ()(Engine::GameScene * new_scene); private: void parse_arguments(int argc, char ** argv); void show_usage(); Modified: trunk/racer/UI/GameStartMenuItem.cpp =================================================================== --- trunk/racer/UI/GameStartMenuItem.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/UI/GameStartMenuItem.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -11,7 +11,9 @@ #include "GameStartMenuItem.h" -#include "../Engine/GameScene.h" +#include <fstream> + +#include "../Engine/LoadScene.h" #include "../Engine/InputHandler.h" #include <Debug.h> @@ -19,9 +21,9 @@ { GameStartMenuItem::GameStartMenuItem(std::wstring label, - unsigned int scene_number) + std::string filename) : MenuItem(label) - , scene_number(scene_number) + , filename(filename) , main_loop(0) , scene(0) { @@ -44,9 +46,11 @@ input_devices[index] = index; } /// @todo allow disused controllers by a graphical user interface. - scene = new Engine::GameScene(input_devices, scene_number); + scene = new Engine::LoadScene<>(input_devices, filename); + scene->set_main_loop(*main_loop); main_loop->set_scene(*scene); - /// @todo create some method to free the scene when returning to the menu. + /** @todo create some method to free the scene when returning to the menu. + */ } void GameStartMenuItem::set_main_loop(MainLoop & main_loop_in) Modified: trunk/racer/UI/GameStartMenuItem.h =================================================================== --- trunk/racer/UI/GameStartMenuItem.h 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/UI/GameStartMenuItem.h 2009-12-12 03:31:26 UTC (rev 130) @@ -16,7 +16,7 @@ #include "MenuItem.h" #include "../MainLoop.h" -#include "../Engine/Scene.h" +#include "../Engine/LoadScene.h" namespace UI { @@ -30,7 +30,7 @@ * @param label The caption displayed on the menu item. * @param scene_number The track identifier used to create the GameScene. */ - GameStartMenuItem(std::wstring label, unsigned int scene_number); + GameStartMenuItem(std::wstring label, std::string filename); virtual ~GameStartMenuItem(); @@ -45,9 +45,9 @@ */ void set_main_loop(MainLoop & main_loop); protected: - unsigned int scene_number; + std::string filename; MainLoop * main_loop; - Engine::Scene * scene; + Engine::LoadScene<> * scene; }; } Modified: trunk/racer/UI/ReplayStartMenuItem.cpp =================================================================== --- trunk/racer/UI/ReplayStartMenuItem.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/UI/ReplayStartMenuItem.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -20,7 +20,7 @@ { ReplayStartMenuItem::ReplayStartMenuItem(std::wstring label) - : GameStartMenuItem(label, 0) + : GameStartMenuItem(label, "") , replay(0) { } Modified: trunk/racer/UI/TitleScene.cpp =================================================================== --- trunk/racer/UI/TitleScene.cpp 2009-12-12 02:42:35 UTC (rev 129) +++ trunk/racer/UI/TitleScene.cpp 2009-12-12 03:31:26 UTC (rev 130) @@ -38,8 +38,8 @@ mi_sp_time_trial(L"Time Trial"), mi_sp_practice(L"Practice"), // multiplayer submenu items - mi_mp_c1(L"Track 0", 0), - mi_mp_c2(L"Track 1", 1) + mi_mp_c1(L"Track 0", "data/tracks/0"), + mi_mp_c2(L"Track 1", "data/tracks/1") { // add items to the main menu //main_menu->insert_item(&mi_single_player); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |