瀏覽代碼

Implement basic loading of games through shared object libreries

Daniele Bartolini 12 年之前
父節點
當前提交
3afc3ef6a9
共有 8 個文件被更改,包括 173 次插入41 次删除
  1. 2 0
      CMakeLists.txt
  2. 47 0
      game/Game.h
  3. 3 3
      samples/CMakeLists.txt
  4. 24 28
      samples/terrain/terrain.cpp
  5. 27 0
      src/Device.cpp
  6. 5 0
      src/Device.h
  7. 26 10
      src/os/OS.h
  8. 39 0
      src/os/linux/LinuxOS.cpp

+ 2 - 0
CMakeLists.txt

@@ -30,6 +30,8 @@ set (INCLUDES
 	${CMAKE_SOURCE_DIR}/src/input
 	${CMAKE_SOURCE_DIR}/src/renderers
 	${CMAKE_SOURCE_DIR}/src/network
+
+	${CMAKE_SOURCE_DIR}/game
 )
 
 include_directories(${INCLUDES})

+ 47 - 0
game/Game.h

@@ -0,0 +1,47 @@
+/*
+Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#pragma once
+
+namespace crown
+{
+
+class Game
+{
+public:
+
+					Game() {}
+	virtual			~Game() {}
+
+	virtual void	init() = 0;
+	virtual void	shutdown() = 0;
+	virtual void	update() = 0;
+};
+
+typedef Game* create_game_t();
+typedef void destroy_game_t(Game* game);
+
+} // namespace crown
+

+ 3 - 3
samples/CMakeLists.txt

@@ -5,19 +5,19 @@ project(crown-samples)
 link_directories(${CROWN_BINARY_DIR})
 
 link_libraries(GLU pthread)
-add_executable(terrain terrain/terrain.cpp)
+add_library(game SHARED terrain/terrain.cpp)
 #add_executable(texturing texturing/texturing.cpp)
 #add_executable(textrenderer textrenderer/textrenderer.cpp)
 #add_executable(collision collision/collision.cpp)
 add_executable(json json/json.cpp)
 
-target_link_libraries(terrain crown)
+target_link_libraries(game crown)
 #target_link_libraries(texturing crown)
 #target_link_libraries(textrenderer crown)
 #target_link_libraries(collision crown)
 target_link_libraries(json crown)
 
-#install (TARGETS terrain DESTINATION bin)
+install (TARGETS game DESTINATION bin)
 #install (TARGETS texturing DESTINATION bin)
 #install (TARGETS textrenderer DESTINATION bin)
 #install (TARGETS collision DESTINATION bin)

+ 24 - 28
samples/terrain/terrain.cpp

@@ -1,6 +1,7 @@
 #include "Crown.h"
 #include "Terrain.h"
 #include "FPSSystem.h"
+#include "Game.h"
 
 using namespace crown;
 
@@ -22,8 +23,6 @@ public:
 	}
 };
 
-void DrawCircle(const Vec3& pos, float radius);
-
 class MainScene: public KeyboardListener, public MouseListener
 {
 
@@ -121,7 +120,7 @@ public:
 		wheel -= event.wheel * 0.25;
 	}
 		
-	void OnLoad()
+	void on_load()
 	{
 		crown::Renderer* renderer = crown::device()->renderer();
 
@@ -165,7 +164,7 @@ public:
 		terrain.UpdateVertexBuffer(true);
 	}
 
-	void RenderScene()
+	void render()
 	{
 		Renderer* renderer = device()->renderer();
 		
@@ -248,40 +247,37 @@ private:
 	Ray ray;
 };
 
-int main(int argc, char** argv)
+class TerrainGame : public Game
 {
-	os::init_os();
-	os::create_render_window(0, 0, 1000, 625, false);
-	os::init_input();
-
-	Device* engine = device();
+public:
 
-	if (!engine->init(argc, argv))
+	void init()
 	{
-		return 0;
+		m_scene.on_load();
 	}
 
-	WndCtrl ctrl;
-	MainScene mainScene;
-	mainScene.OnLoad();
-
-	while (engine->is_running())
+	void shutdown()
 	{
-		os::event_loop();
-
-		device()->input_manager()->event_loop();
-
-		engine->renderer()->begin_frame();
-			mainScene.RenderScene();
-		engine->renderer()->end_frame();
+	}
 
-		os::swap_buffers();
+	void update()
+	{
+		m_scene.render();
 	}
 
-	engine->shutdown();
+private:
 
-	os::destroy_render_window();
+	MainScene m_scene;
+	WndCtrl m_ctrl;
+};
 
-	return 0;
+extern "C" Game* create_game()
+{
+	return new TerrainGame;
+}
+
+extern "C" void destroy_game(Game* game)
+{
+	delete game;
 }
 

+ 27 - 0
src/Device.cpp

@@ -33,6 +33,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "Types.h"
 #include "String.h"
 #include "Args.h"
+#include "Game.h"
 #include <cstdlib>
 
 #include "renderers/gl/GLRenderer.h"
@@ -99,6 +100,22 @@ bool Device::init(int argc, char** argv)
 
 	Log::I("Crown Engine initialized.");
 
+	Log::I("Initializing Game...");
+	// FIXME Should we maintain a fixed name library?
+	m_game_library = os::open_library("libgame.so");
+
+	if (m_game_library == NULL)
+	{
+		Log::E("Error while loading game library.");
+		return false;
+	}
+
+	create_game_t* create_game = (create_game_t*)os::lookup_symbol(m_game_library, "create_game");
+
+	m_game = create_game();
+
+	m_game->init();
+
 	return true;
 }
 
@@ -111,6 +128,13 @@ void Device::shutdown()
 		return;
 	}
 
+	m_game->shutdown();
+
+	destroy_game_t* destroy_game = (destroy_game_t*)os::lookup_symbol(m_game_library, "destroy_game");
+
+	destroy_game(m_game);
+	m_game = NULL;
+
 	if (m_input_manager)
 	{
 		delete m_input_manager;
@@ -180,6 +204,9 @@ void Device::frame()
 	m_input_manager->event_loop();
 
 	m_renderer->begin_frame();
+
+	m_game->update();
+
 	m_renderer->end_frame();
 }
 

+ 5 - 0
src/Device.h

@@ -33,6 +33,7 @@ namespace crown
 
 class Renderer;
 class InputManager;
+class Game;
 
 /// The Engine.
 class Device
@@ -78,6 +79,10 @@ private:
 	InputManager*			m_input_manager;
 	Renderer*				m_renderer;
 
+	// The game currently running
+	Game*					m_game;
+	void*					m_game_library;
+
 private:
 
 	// Disable copying

+ 26 - 10
src/os/OS.h

@@ -37,9 +37,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 namespace crown
 {
 
-/**
-	OS-specific functions and parameters.
-*/
+/// OS-specific functions and parameters.
 namespace os
 {
 
@@ -75,6 +73,8 @@ const size_t	MAX_THREADS = 16;
 const size_t	MAX_MUTEXES = 16;
 #endif
 
+//-----------------------------------------------------------------------------
+// Print and log functions
 //-----------------------------------------------------------------------------
 void			printf(const char* string, ...);				//!< Printf wrapper
 void			vprintf(const char* string, va_list arg);		//!< VPrintf wrapper
@@ -84,6 +84,9 @@ void			log_error(const char* string, va_list arg);		//!< Print error message
 void			log_warning(const char* string, va_list arg);	//!< Print warning message
 void			log_info(const char* string, va_list arg);		//!< Print info message
 
+//-----------------------------------------------------------------------------
+// File management
+//-----------------------------------------------------------------------------
 bool			exists(const char* path);		//!< Returns whether the path is a file or directory on the disk
 
 bool			is_dir(const char* path);		//!< Returns whether the path is a directory. (May not resolve symlinks.)
@@ -94,12 +97,17 @@ bool			unlink(const char* path);		//! Deletes a regular file. Returns true if su
 bool			mkdir(const char* path);		//! Creates a directory. Returns true if success, false if not
 bool			rmdir(const char* path);		//! Deletes a directory. Returns true if success, false if not
 
+//-----------------------------------------------------------------------------
+// OS ambient variables
+//-----------------------------------------------------------------------------
 const char*		get_cwd();						//! Fills ret with the path of the current working directory. Returns true if success, false if not 
 const char*		get_home();						//! Fills ret with the path of the user home directory
 const char*		get_env(const char* env);		//! Returns the content of the 'env' environment variable or the empty string
 
 //bool			ls(const char* path, List<Str>& fileList);	//! Returns the list of filenames in a directory.
 
+//-----------------------------------------------------------------------------
+// Render window and input management
 //-----------------------------------------------------------------------------
 void			init_os();
 
@@ -117,10 +125,14 @@ void			set_cursor_xy(int32_t x, int32_t y);
 void			hide_cursor();
 void			show_cursor();
 
+//-----------------------------------------------------------------------------
+// Timing
 //-----------------------------------------------------------------------------
 uint64_t		milliseconds();
 uint64_t		microseconds();
 
+//-----------------------------------------------------------------------------
+// Events
 //-----------------------------------------------------------------------------
 enum OSEventType
 {
@@ -153,17 +165,23 @@ struct OSEvent
 	OSEventParameter	data_d;
 };
 
-//! Pushes @a event into @a event_queue
+/// Pushes the event @type along with its parameters into the os' event queue.
 void			push_event(OSEventType type, OSEventParameter data_a, OSEventParameter data_b, OSEventParameter data_c, OSEventParameter data_d);
 
 
-//! Returns the event on top of the event_queue	
+/// Returns and pops the first event in the os' event queue.
 OSEvent&		pop_event();
 
 //-----------------------------------------------------------------------------
-// Threads
+// Dynamic libraries
 //-----------------------------------------------------------------------------
+void*			open_library(const char* path);
+void			close_library(void* library);
+void*			lookup_symbol(void* library, const char* name);
 
+//-----------------------------------------------------------------------------
+// Threads
+//-----------------------------------------------------------------------------
 typedef			void* (*ThreadFunction)(void*);
 
 void			thread_create(ThreadFunction f, void* params, OSThread& thread, const char* name);
@@ -176,9 +194,8 @@ void			mutex_lock(OSMutex mutex);
 void			mutex_unlock(OSMutex mutex);
 
 //-----------------------------------------------------------------------------
-//		Networking
+// Networking
 //-----------------------------------------------------------------------------
-
 struct NetAddress
 {
 	uint8_t 	address[4];
@@ -259,7 +276,6 @@ struct NetAddress
 };
 
 //-----------------------------------------------------------------------------
-
 class UDPSocket
 {
 public:
@@ -283,8 +299,8 @@ private:
 				// Socket descriptor
 	int32_t 	m_socket;
 };
-//-----------------------------------------------------------------------------
 
+//-----------------------------------------------------------------------------
 class TCPSocket
 {
 public:

+ 39 - 0
src/os/linux/LinuxOS.cpp

@@ -35,6 +35,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include <sys/time.h>
 #include <time.h>
 #include <pthread.h>
+#include <dlfcn.h>
 
 namespace crown
 {
@@ -230,6 +231,44 @@ uint64_t microseconds()
 	return (tmp.tv_sec - base_time.tv_sec) * 1000000 + (tmp.tv_nsec - base_time.tv_nsec) / 1000;
 }
 
+//-----------------------------------------------------------------------------
+void* open_library(const char* path)
+{
+	void* library = dlopen(path, RTLD_NOW);
+
+	if (library == NULL)
+	{
+		os::printf("OS: ERROR: Unable to load library '%s' with error: %s\n", path, dlerror());
+		return NULL;
+	}
+
+	return library;
+}
+
+//-----------------------------------------------------------------------------
+void close_library(void* library)
+{
+	assert(dlclose(library) == 0);
+}
+
+//-----------------------------------------------------------------------------
+void* lookup_symbol(void* library, const char* name)
+{
+	dlerror();
+
+	void* symbol = dlsym(library, name);
+
+	const char* error = dlerror();
+
+	if (error)
+	{
+		os::printf("OS: ERROR: Unable to lookup symbol '%s' with error: %s\n", name, error);
+		return NULL;
+	}
+
+	return symbol;
+}
+
 //-----------------------------------------------------------------------------
 void thread_create(ThreadFunction f, void* params, OSThread& thread, const char* name)
 {