View Full Version : Porting 1.0 to 2.0
rombust
09-21-2009, 02:21 PM
I have run into the following problem
CL_Zip_Archive zip(skin);
CL_ResourceManager gfx_pieces("pieces.xml", &zip, false);
How can we do this on ClanLib 2.0 ?
sphair
09-21-2009, 02:25 PM
Maybe we can use this thread for other issues with porting, and general tips on how to do it.
CL_Error --> CL_Exception.
CL_Surface --> CL_Image.
and window->get_graphic_context() everywhere :)
rombust
09-21-2009, 02:46 PM
I believe:
CL_Zip_Archive zip(skin);
CL_ResourceManager gfx_pieces("pieces.xml", &zip, false);
Becomes...
CL_VirtualFileSystem vfs(skin, true);
CL_VirtualDirectory vd(vfs, "./");
CL_ResourceManager gfx_pieces("pieces.xml", vd);
rombust
09-24-2009, 11:26 AM
ClanLib 1.0 to ClanLib 2.0 Migration
Code Design
If your old code creates objects as follows:
CL_Sprite *mysprite = new CL_Sprite(...);
...
delete mysprite;
Consider using
CL_Sprite mysprite;
mysprite = CL_Sprite(...);
...
This will help prevent objects not being destroyed when exceptions are thrown.
Most ClanLib's objects use shared pointers for the implemention:
CL_Sprite mysprite(...);
CL_Sprite mysprite2 = mysprite;
So, mysprite and mysprite2 both relate to the same objects. The overhead is only setting up a new shared pointer
If you do require a real copy of the object, a few clanLib objects support the "clone" function
CL_Sprite mysprite3(gc); <-- note CL_Sprite mysprite3; will not work
mysprite3.clone(mysprite2);
Graphic Contexts
Since ClanLib 2.0 directly supports multiple windows. All graphic functions require a CL_GraphicContext
This is obtained from the display window ( CL_DisplayWindow::get_gc() );
For example:
CL_GraphicContext gc = window.get_gc();
mysprite.draw(gc, 100, 200);
This usually means that you should pass the graphic context to every drawing function.
Note, passing by reference is faster than passing by object. For example:
void Player::draw(CL_GraphicContext &gc) { mysprite.draw(gc, 100, 200); }
CL_ClanApplication
ClanLib 1.0:
class Application : public CL_ClanApplication
{
public:
virtual int main(int argc, char **argv)
}
ClanLib 2.0:
class Program
{
public:
static int main(const std::vector<CL_String> &args)
{
CL_SetupCore setup_core;
// Start the Application
Application app;
int retval = app.start(args);
return retval;
}
};
CL_ClanApplication app(&Program::main);
(See the Basic2D example for an extended version of this example)
You don't have to use 2 classes, but it enforces CL_SetupCore is always called first before any other clanlib objects.
Target Setup
ClanLib 1.0:
CL_SetupCore::init();
CL_SetupDisplay::init();
..
CL_SetupCore::deinit();
CL_SetupDisplay::deinit();
ClanLib 2.0:
CL_SetupCore setup_core;
CL_SetupDisplay setup_display;
Core must be initialised before Display.
Display must be initialised before GL (or other display targets)
If you use multiple target targets, you can do the following:
CL_SetupGL target_gl2;
CL_SetupGL1 target_gl1;
CL_SetupGDI target_gdi;
CL_SetupSDL target_sdl;
target_gdi.set_current();
Exceptions
ClanLib 1.0:
catch (CL_Error err)
{
// Display the error message
std::cout << err.message.c_str() << std::endl;
}
ClanLib 2.0:
catch(CL_Exception& exception)
{
CL_ConsoleWindow console("Console", 80, 160);
CL_Console::write_line("Exception caught:");
CL_Console::write_line(exception.message);
console.display_close_message();
}
See the Basic2D example to display the call stack.
Window Creation
Fullscreen mode on ClanLib 2.0 does not change the screen resolution, unlike ClanLib 1.0
If your ClanLib 1.0 window size fixed (eg 800x600), the following option is ideal in most situations:
CL_DisplayWindowDescription desc;
desc.set_title("mygame");
desc.set_size(CL_Size(800,600), true);
if(fullscreen)
{
desc.set_fullscreen(true);
desc.set_decorations(false);
}
else
{
desc.set_allow_resize(true);
}
main_window = CL_DisplayWindow(desc);
And in the main loop, use:
CL_GraphicContext gc = main_window.get_gc();
CL_Mat4f matrix = CL_Mat4f::scale( (float) gc.get_width() / 800.0f, (float) gc.get_height() / 600.0f, 1.0f);
gc.set_modelview(matrix);
So you can resize the window in windowed mode and fill the entire screen in full screen mode.
CL_FramerateCounter
This class has been removed.
If you require it. Copy the source from ClanLib 1.0. and modify these lines:
From: class CL_API_DISPLAY CL_FramerateCounter : public CL_KeepAlive
To: class CL_API_DISPLAY CL_FramerateCounter
And call "framerate_counter.keep_alive();" in the main loop
Keep Alive!
ClanLib 1.0:
CL_System::keep_alive();
ClanLib 2.0:
CL_KeepAlive::process();
Display Flipping
ClanLib 1.0: CL_Display::flip(x)
ClanLib 2.0: window.flip(x)
It has been reported on ClanLib 0.8 release, that updating to ClanLib 1.0 has resulted in the application running at 60hz
At some point CL_Display::flip() API changed. To fix - change CL_Display::flip() to CL_Display::flip(0)
CL_Surface
ClanLib 1.0: CL_Surface
ClanLib 2.0: CL_Image
In the resource file,
From:
<surface name = "logo" file = "misc/logo.png"/>
To:
<image name = "logo">
<image-file file = "misc/logo.png"/>
</image>
Clear Screen
ClanLib 1.0: CL_Display::clear(CL_Color(0, 0, 0));
ClanLib 2.0: gc.clear(CL_Colorf(0.0f, 0.0f, 0.0f));
Keyboard
ClanLib 1.0:
CL_Keyboard::get_keycode(key);
ClanLib 2.0:
CL_InputDevice &keyboard = window->get_ic().get_keyboard();
keyboard.get_keycode(key);
File I/O
ClanLib 1.0: CL_InputSource_File file(options_file);
ClanLib 2.0: CL_File file(options_file);
ClanLib 1.0: CL_OutputSource_File file(options_file);
ClanLib 2.0: CL_File file(options_file, CL_File::create_always, CL_File::access_write);
ClanLib 1.0: file.tell();
ClanLib 2.0: file.get_position();
ClanLib 1.0: file.size();
ClanLib 2.0: file.get_size();
ClanLib 1.0: file.read_string();
ClanLib 2.0: file.read_string_a();
Resource Loading From ZipArchive
ClanLib 1.0:
CL_Zip_Archive zip(skin);
CL_ResourceManager gfx("menu_skins.xml", &zip, false);
ClanLib 2.0:
CL_VirtualFileSystem vfs(skin, true);
CL_VirtualDirectory vd(vfs, "./");
CL_ResourceManager gfx("menu_skins.xml", vd);
falsinfab
01-20-2010, 02:03 PM
Hi,
I'm trying to porting my project based to ClanLib 1.0 to 2.0 but the major problem is how to "substitute" the CL:surface object. Looking into the firum I found this port suggesting the association CL_Surface --> CL_Image but checking the documentation I saw the CL_Image doesn't contain methods like:
set_angle
set_angle_pitch
set_angle_yaw
rotate
rotate_pitch
rotate_yaw
that I use in my code. How can I replace these features of the old CL_Surface object?
Thank you
sphair
01-20-2010, 02:33 PM
Use CL_Sprite, it is more similar to CL_Surface than CL_Image.
Turzt
10-01-2010, 01:32 PM
Buffered keyboard event signals? I don't remember which version I used to use but
I used to make a CL_InputBuffer and add keyboard to it. then after each iteration of my application, process key events like that:
CL_InputEvent event;
while (inputbuffer.keys_left() > 0)
{
event = inputbuffer.pop_key();
if (event.type == CL_InputEvent::pressed)
{
/* some key is pressed */
switch(event.id) {
case CL_KEY_LEFT:
// move left
break;
case CL_KEY_UP:
// move up
break;
case CL_KEY_a:
// toggle weapon
break;
default:
break;
}
} // button pressed
}
Now it does not work anymore. How do I implement similar behaviour?
I mean, to do something "once per keypress" like switching weapon etc, instead of something happening "as long as key is pressed" like one would want in non-tiled realtime games where you move constantly with arrow keys.
sphair
10-01-2010, 02:26 PM
You use signals for it -
keyboard.sig_key_up().connect(...); or keyboard.sig_key_down().connect(...)
See the last section at http://clanlib.org/wiki/MainDocs:User_Input
Turzt
10-01-2010, 05:01 PM
Callback function is one way to do it. It is just that I would not necessarily want to process the keyboard event immediately. The keypress might for moving the player character and there can be, at the time keypress occurs, simulation step going on, which can cause data inconsistency if player position is changed in the middle of calculation. Or maybe not a problem, it depends how this all is implemented.
Is there any kind of "signal buffer" available where the keypresses would go, which can be polled and processed when its designated time occurs like there was inputbuffer before. My "game loop" would be like this:
while(!quit) {
process_keyboard_events();
simulate_world_one_timestep();
redraw_screen();
sleep_if_needed_for_realtime();
}
sphair
10-01-2010, 07:21 PM
The keyboard callback will happen during the KeepAlive call, so unless you are doing your logic processing in a separate thread, there will not be a conflict.
Polling using keyboard.get_keycode and signals are the only two ways of getting input.
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.