Scroll / Orx and C++, a survey for all orx users

2»

Comments

  • edited May 2012
    I think I might actually use this. I started a new project in C++ using vanilla orx but that object binding thing and the map editor sound good enough to give it a try.
  • edited May 2012
    Just reading this, it may be useful to make an ini editor in general of sorts, where you can determine and see in real time the original image and animations, then it just poops out ini files...

    I may try this after i've ported B0UNCE.
  • edited May 2012
    My first two Scroll tutorials are now available on the wiki:

    http://orx-project.org/wiki/en/orx/tutorials/community/acksys
  • edited June 2012
    Never mind.

    [Iarwain edit - The question was: where could one find the latest version of Scroll?]
  • edited August 2012
    In case others have the same question, here's the link to the bitbucket repo which will always have the latest version of Scroll: https://bitbucket.org/orx/scroll
  • edited September 2012
    Dear nice Orx community!

    (Note: The following is not a criticism of Orx itself at all, but rather a discussion of the limitations of C. I'm actually amazed (again and again) by how iarwain managed to build such a nice architecture on top of pure C!)

    I would also want to express my deep interest in Scroll. I naturally wrap every C function with a C++ mindset before I use them. I feel like cleaning a toilet with bare hands whenever I type cast a void pointer, or check an "int" property against a set of "int" constants (instead of using enumerations, which eliminates the risk of comparing apples and oranges). There's also the whole story of having to remember to undo something at the end of a function that you've done in the beginning (push/pop section f.x.), so anything that's already in Scroll is less code (and less checking documentation) for me.

    I hope one day we get to wrap all of Orx in Scroll. I really like how ScrollObject works, and I wish we had similar wrappers for everything.

    I'm sure C++ lovers like myself are already doing a lot of wrapping on top of Scroll and it'd be great if we shared the effort. This way, we'll have less bugs, less boilerplate code and more portability.

    Cheers!
  • edited September 2012
    Hi enobayram,

    I was playing around with Scroll and Orx quite a bit and I really liked the ideas behind the engine and how you could bind config types to custom objects with Scroll. I didn't like the need to fallback to plain C often though so after fighting myself for some time I couldn't take it and wrote my own version of orx from scratch and in modern c++. It's opensource and though still in development it provides quite a bit of tools (basics, xml-based configuration, box2d physics, lua/luabind integration and object scripting, events and listeners, zones/contexts and triggers, animation system, fonts, prototypes, etc.). I really love orx but I just can't live with a constant need to fallback to plain C code in a nice C++ environment (hi Iarwain).
    At the moment I'm crosscompiling my stuff to android (already have basic physics/lua demo working on my htc). If you want to check it out (you too, Iarwain ;) ) feel free to visit the outdated doc (http://x2d.7bit.co) or the github project (https://github.com/godexsoft/x2d).

    Cheers!
    Alex
  • edited September 2012
    This is blasphemy!!!

    :) Just kidding obviously. That's an amazing undertaking. I'm really curious as to why you've gone as far as developing orx from scratch. Did you try wrapping it first? What was the problem with wrapping it(I'm asking because that what I would/will do and would like to know the problems ahead).

    I'm looking forward to taking a look at what you have there, as soon as I have the time, but I must say I'm a bit skeptical about just throwing away all that's built around orx (and orx itself).

    Cheers!
    Enis
  • edited September 2012
    Oh I'm not suggesting to throw away orx and use my engine! Orx is great and if you already got it working then you definitely should stick to it :)

    As for my effort and decision there are several things I had in mind when starting x2d late january:
    1) Orx didn't work right for me. It gave me tops 30fps on an iPhone4 with a very simple game mockup (20 sprites on the screen). Me and Iarwain were looking into it and both couldn't find why it was happening. As I understand now it had to do with retina support and downscaling to older iPhone screen size (320x480) using the retina screen size as the physical one. Basically, I guess that orx was doing what should be done by iOS itself and was doing it wrong somehow.
    2) I really like to gain deep understanding of everything I try to learn. Writing my own engine was the best way to understand how stuff works in orx. For the same reason I wrote my own cross-platform boost::asio several years ago :)
    3) No fear. Its been ~8 months since I started x2d and most of the time I was busy with my daily work in my startup. Unfortunately we don't develop games and don't develop game engines in my startup.. however my real passion is in gamedev.

    And I didn't really try to wrap orx myself. I used Scroll from the start and I simply didn't like some stuff in it and how it's done. I don't say my engine is better though.. just it's mine and I know exactly where, what and how is happening. Also my memory management is based on boost::shared_ptr and RAII where possible.. i can't live without it :)

    No matter if you like or hate x2d, C+C is really welcome! :)
    Thanks in advance.
    Alex
  • edited September 2012
    And sorry, I forgot to mention. Obviously it's been a long while since january and I can't remember everything but here are some key differences:

    1) Config system is XML vs. INI. This allows nesting and hierarchy. Apart from nesting x2d provides namespaces in XML configs.
    2) x2d uses a virtual filesystem (zip with 0 compression) and all resources live inside one or more archives which you mount to a path: lvp_man.mount("resources.zip", "res") for example will open a 'filesystem' archive and mount onto a virtual 'res' drive. in the config system you can access stuff like this: path = "res/graphics/spritesheet.png" etc. This allows for really easy skin/theme support oob. as you can mount and unmount in runtime :)
    3) A plugin system (WIP) allows you to extend configurations (xml) with custom stuff. Note that these are compile time plugins, not shared libraries. For example there is a (mockup) plugin called x2d_ui which adds labels, buttons etc. into the mix.

    There is probably more but I can't remember :)
    Cheers
  • edited September 2012
    x2d looks/sounds really nice, you've got me even more interested. As a side note, I'm also experiencing performance issues on Android with Orx, but until now, I've assumed that it's something wrong that I'm doing. I'm curious whether the iphone performance issue is solved on Orx in the last 9 months since you've tried, or whether what I'm experiencing on Android is the same. Do you plan to ever support PC with x2d?
  • edited September 2012
    At the very begining of x2d i had xcode compiling and running stuff on my desktop mac but i guess you meant windows by pc. For windows support i think i would need to implement a directx driver and use proxies everywhere. I'm sure orx does a great job there.
    Originally i wanted to support multitouch input at the core of the engine and thats what i have now. So instead of simulating multitouch thru mouse input i can emailate/support mouse input thru the multitouch core:)
    I'm mainly interested in mobile gamedev though so unless someone will help me to build the pc framework i doubt i will spend time on that..
    Obviously orx is much more mature and i suggest you stick with it unless you really want to target mobile only with the benefit of modern c++ all around the place:)
    I guess i should open a forum for x2d where people could post their ideas and suggestions...:)

    Cheers!
    Alex
  • edited September 2012
    enobayram wrote:
    I would also want to express my deep interest in Scroll. I naturally wrap every C function with a C++ mindset before I use them.

    That's an interesting topic! To me, most of the time, a pure 1:1 wrapping only implies syntactic differences, ie.
    orxObject_GetName(MyObject);
    
    vs
    MyObject->GetName();
    

    The C++ one has the advantage to be shorter, while the C one has the advantage to explicitly reference the interface. I guess it boils down to a matter of preference in this case.

    However I wrote Scroll in C++ for a couple of very simple reasons:
    - I needed template meta-programming as macros where not powerful enough to embed the editor in any game with the ability to run the game from inside the editor.
    - Needed templates for managing objects via the factory in a cleaner way than C would have allowed me to.
    - I needed inheritance for objects as handling events is definitely verbose and annoying, while still keeping the overhead as small as possible.

    That's about it.
    I feel like cleaning a toilet with bare hands whenever I type cast a void pointer
    .

    Well, hopefully you don't have to do that often, if at all, beside event payloads. :)
    , or check an "int" property against a set of "int" constants (instead of using enumerations, which eliminates the risk of comparing apples and oranges).

    That's not a C/C++ issue there, enum are present in C as well. They're actually extensively used in orx except for flags which is probably the cases you reference, isn't it?
    The issue with enums is that their definition in C/C++ can't be partial. That means if you want to keep a set of flags private and a set of flags public, you can't do it cleanly.
    Hence the use of plain old un-typed numerical values.
    There's also the whole story of having to remember to undo something at the end of a function that you've done in the beginning (push/pop section f.x.), so anything that's already in Scroll is less code (and less checking documentation) for me.

    Well, Scroll does it behind the scene. It's more convenient but it's also more costly as you might not have needed to push/pop a config section in the first place.
    But even in a wider context, such as C++ RAII, symmetry is most of the time a good practice, and symmetric code is much less prone to any memory leakage, for example.
    I hope one day we get to wrap all of Orx in Scroll. I really like how ScrollObject works, and I wish we had similar wrappers for everything.

    This is going to be a daunting task, I think, but why not! :)
    I'm sure C++ lovers like myself are already doing a lot of wrapping on top of Scroll and it'd be great if we shared the effort. This way, we'll have less bugs, less boilerplate code and more portability.

    I'm curious about the portability statement here, I can understand the first two, but this one eludes me.

    And now a quick reason why I think wrapping is a good idea but rewriting isn't. C++ has many many more caveats than C, and some of them are pretty subtle (scope resolution not using mangled symbol name, sneaky operator overloads can lead to disastrous results (operator->, operator(), operator[], operator,, operator!, operator~, ...), virtual methods called from within a ctor or dtor are not going to yield the expected result, they'll crash for pure virtual methods but not for regular virtual ones, which is very sneaky and hard to track, variables declared in a for statement has a different scope depending on which C++ standard you're using, ...).

    Bugs created by such issues are usually very hard to track and I think that's a big reason why a lot of low level libraries/middleware are still sticking with C.

    All those are probably fine when you work by yourself, but for a project where you expect other developers from different level of knowledge of C++ to contribute, this can be very time consuming and aggravating (speaking of 11 years of experience in the video game industry with C++ there).
    Cheers!

    Cheers! :)
  • edited September 2012
    godexsoft wrote:
    Hi enobayram,

    I was playing around with Scroll and Orx quite a bit and I really liked the ideas behind the engine and how you could bind config types to custom objects with Scroll. I didn't like the need to fallback to plain C often though so after fighting myself for some time I couldn't take it and wrote my own version of orx from scratch and in modern c++. It's opensource and though still in development it provides quite a bit of tools (basics, xml-based configuration, box2d physics, lua/luabind integration and object scripting, events and listeners, zones/contexts and triggers, animation system, fonts, prototypes, etc.). I really love orx but I just can't live with a constant need to fallback to plain C code in a nice C++ environment (hi Iarwain).
    At the moment I'm crosscompiling my stuff to android (already have basic physics/lua demo working on my htc). If you want to check it out (you too, Iarwain ;) ) feel free to visit the outdated doc (http://x2d.7bit.co) or the github project (https://github.com/godexsoft/x2d).

    Cheers!
    Alex

    Hey Alex, long time no see! :)

    Congrats for x2d and best of luck with that. It's definitely the best way of learning than doing things oneself.

    I checked it out a bit, I'm no big fan of the syntax choices (or the lack of consistency in some cases), but beside that that looks fine.

    I'd advise using a component approach instead of aggregating things in your object as you're currently doing.
    A Data-Oriented Design (DOD) usually yields much better performances and a pure traditional Object-Oriented (OO) one.
    There are countless articles online on the matter and I think you can find some on http://www.altdevblogaday.com.

    There still a long road to go to get to a mature state but I'm sure you have the motivation so that shouldn't be a problem! I sure will check your work from time to time.

    Cheers!
  • edited September 2012
    godexsoft wrote:
    2) x2d uses a virtual filesystem (zip with 0 compression) and all resources live inside one or more archives which you mount to a path: lvp_man.mount("resources.zip", "res") for example will open a 'filesystem' archive and mount onto a virtual 'res' drive. in the config system you can access stuff like this: path = "res/graphics/spritesheet.png" etc. This allows for really easy skin/theme support oob. as you can mount and unmount in runtime :)

    Mmh, I never heard of lvp_man before. How does it compare to PhysicsFS?

    I considered integrating PhysicsFS a long time ago but in the current state it's not really worth it as it's very easy to handle it on the game-side (or even better by using encrypted archives) and spoon-feeding orx when it needs resources as they can now all be created at runtime from memory accesses (or memory-mapped files).
  • edited September 2012
    enobayram wrote:
    x2d looks/sounds really nice, you've got me even more interested. As a side note, I'm also experiencing performance issues on Android with Orx, but until now, I've assumed that it's something wrong that I'm doing. I'm curious whether the iphone performance issue is solved on Orx in the last 9 months since you've tried, or whether what I'm experiencing on Android is the same. Do you plan to ever support PC with x2d?

    Alex's issue are explained in this thread: https://forum.orx-project.org/discussion/3235

    Which still puzzles me as of today. I've never experienced it myself and I since then have had access to retina devices.
    I never was able to reproduce that issue, but, to be honest, the code might have changed quite a lot since January, including native orientation support on iOS (both portrait and landscape, no more double camera trick needed there).

    To be a bit more precise, using glOrtho for the transformation or pre-multiplying the coordinates yields the exact results/UVs, one simply does the multiply on the CPU side and I'm pretty sure that 20 multiplications is not going to make any difference within a frame (especially knowing that when having a straight 1:1 ratio is still using the same number of multiplies, except using 1 as an operand).

    Considering your performances issues on Android, have you tried the profiler to try to narrowing down the sources?
    Most of the time on handheld PowerVR-based devices, 2D performances are mostly affected by the use of alpha-blended pixels (alpha-tested is even worse).
    The more of them you have, the worst the performances are. Drastically.
    That being said, in your case, it might be different and the profiler is there to help you finding the root of the issue.
    Don't hesitate to open a thread if you need help on that topic! :)
  • edited September 2012
    Hi Iarwain!

    Thanks for your comments. I sure will read more on DOD and think what I can do. The object is currently a massive collection of "components" which are mostly flagged by a boolean or wrapped with a shared_ptr so it's almost free to check whether we are using one of them or not. also most of it happens at parse time (only once). However I really need to split up the code quite a bit coz currently object.cpp is an ugly monster :D

    lvp_man stands for liverpool manager which is a manager class built on top of the liverpool library. The liverpool library itself is a very simple wrapper for uncompressed zip files. It can read a directory structure and access individual files from it. The liverpool lib was written by me long time before x2d so I doubt you could have met it before :) I don't remember wether I looked into PhysicsFS but I definitely researched a little before implementing my own. I think most of these libs provide read/write access which i don't need. Supporting compressed zip archives, however, is a good idea. Even better - supporting encrypted zip archives.

    Why zip format was chosen? It's simple for designers to work with.. they can use their archiver tool to create it and they don't have to worry about custom tools. Especially helpful when you can easily separate your assets from your configurations (res -> resources.zip (only sprites, music, etc.), cfg -> configuration.zip).

    Cheers!
    Alex
  • edited September 2012
    Hi iarwain, thanks for your long and insightful comments! I finally have the time to reply appropriately.
    To me, most of the time, a pure 1:1 wrapping only implies syntactic differences, ie.

    I agree, percentage-of-code wise most differences are as shallow as this. However, some features of C++ can not be reproduced with C code without changing the code structure significantly. I'm not really armed for an all-out C versus C++ flamewar :) but I can try to give some examples. As godexsoft already mentioned, smart pointers are a very important feature. I've noticed that you're already reference counting all orxSTRUCTUREs, but that's not evident when you look at an orxOBJECT *. Further, without checking the documentation, (and note that, the orxOBJECT documentation has no mention of this, so you need to check the documentation exhaustively to notice the relevant section of orxSTRUCTURE!), I wouldn't know how to properly handle an orxOBJECT * appropriately. In a modern C++ library, you'd never have to worry about such low-level concerns. Everywhere that you see an orxOBJECT *, you'd see a shared_ptr<orxOBJECT>. This isn't important only when you're receiving something BTW. As we've discussed before, when I see orxDisplay_SetBitmapData, I can't know (without asking) whether this function copies my data, takes ownership of it or just references it, leaving the lifetime management to me entirely. Imagine that, before using ANY function that takes or returns a raw pointer, you have to ask about its memory management...

    This example actually brings us to another issue. Even though orxObject_GetName(MyObject); vs. MyObject->GetName(); seems trivial, if orxObject inherits from orxStructure in C++, you'd be able to say MyObject->IncreaseCounter(); -assuming you'd even need to know about the implementation of the shared semantics- and your IDE's content assist would probably inform you about this when you pressed ctrl+space.
    Well, hopefully you don't have to do that often, if at all, beside event payloads. :)

    Well, you can find void * in many many more places. Going back to the orxStructure_IncreaseCounter example, that function accepts a void *. Now, looking at just this, can you tell what exactly it expects? Does it expect my orxOBJECT pointer? or will I have to extract an internal pointer of my orxOBJECT using a macro?
    That's not a C/C++ issue there, enum are present in C as well.

    Well, my problem with C enums is that they allow comparing apples and oranges, though what I missed is that C++ allows that as well. My mind was at Java enums (Oh my god I'm about to say something good about java) which do not allow comparing enums of different types. Now in C++11 you have strongly typed enums that bring the same functionality.
    Symmetry is most of the time a good practice, and symmetric code is much less prone to any memory leakage.

    Symmetry is not the answer to all problems, even if you have the discipline to follow it. For example, what happens if someone else does not realize the symmetry in your code, and returns in the middle? Even worse, what if an exception is thrown? (I know using exceptions is a personal preference) I feel much more safe, when I can look at a small segment of code, and tell that it's not doing something wrong. In C, you often have to remember to clean-up very far away from where you start doing the dirty thing.

    But I really don't want to start a flamewar :), if you like C, I'm sure you're using it in a way that eliminates the problems I encounter using it. Just like I'm using C++ in a way that I never run into the problems that C++ haters love to mention. So, the important point is, we all have strong personal reasons to choose our programming environments.

    I would like to mention again, that even though I don't like using C libraries, I don't mind wrapping them. Especially in the case of Orx, which is very well designed around an OOP architecture. You just check the documentation once, wrap what you need to use before you use it, and sleep tight at night. So, even though I seem to have strong opinions against C, I really (Really) like Orx. There's so much good in it that makes the task of wrapping stuff insignificant.

    This brings us back to our real topic, let's do the wrapping as a collective effort! :)
    I'm curious about the portability statement here, I can understand the first two, but this one eludes me.

    Well, C++ compilers don't play along well with each other. Especially when you start doing advanced things like template-metaprogramming, there are certain cases where you need to go as far as writing preprocessor ifs for each compiler. I have some C++ programs compiled successfully with GCC on both Linux and Windows (MinGW), but I get a 100 distinct compiler errors when I try to compile it with MSVC. Have you noticed how far the boost people have gone to make sure that you can use boost on those supported compilers...
    All those are probably fine when you work by yourself

    You're right about this in both directions. It IS fine when you work by yourself and I believe you when you say it isn't when you collaborate with C++ programmers of various skill. Though I would still prefer to set-up the architecture in C++, and let the others program purely C-like. As a small example, imagine using smart pointers all around Orx, but keeping everything else the same otherwise.

    About the performance issues, I haven't done anything about them yet. They're most probably about alpha-blended pixels as you've said, because I've been using them ad-libitum :) I was planning to start a topic about it once I focus on the performance aspect.
    Cheers! :)
    Cheers! :) :)
  • edited September 2012
    godexsoft wrote:
    I guess you meant windows by pc.
    I actually meant the significant three (Linux, Windows, Mac). The reason why I asked it as "PC" is that in the github project page, you state
    Currently supported platforms:

    - iOS only :D

    BTW, why wouldn't you use OpenGL on windows as well? Valve people say in this blog that OpenGL is even faster on Windows as well.

    I'd love to collaborate with you on x2d, but I'm really overloaded these days. When I'm more free in a few months time, I'll try to see if/how I can help. The forum is still a good idea though :)

    Cheers!
  • edited September 2012
    I plusone enobayram. Your understanding of the C vs. C++ problem is very similar to mine :)
    Furthermore, I can't agree with Iarwain that hardcore C++ is only good when you work alone and/or don't have other developers of "various skill". I think there is a good reason people invented lead developers, senior developers and other names which usually represent the length of someone's dick in software companies :) In my opinion the core/engine of any application can be any level of hardcore meta-programming as long as it exposes a simple, intuitive, yet well-documented interface for "various skill" developers to use.
    Also, i never give jobs to people who i interview if they don't meet a certain level of expected knowledge. Many developers with _years_ of experience in C++ (some over 10 years in Symbian for example) don't know the basics. I wrote a blog post on this matter a while ago.

    Enobayram, thanks for your interest and will to help :) I will create a forum and post back here. Thanks!

    Cheers guys! :)
    Alex
  • edited September 2012
    Hey guys, the new x2d forum is up here: http://forum.x2d.7bit.co/
    Sorry for off-topic :) I suggest we stop discussing x2d in this thread and if anyone is interested - visit the x2d forums.

    Cheers!
    Alex
  • edited September 2012
    enobayram wrote:
    Further, without checking the documentation, (and note that, the orxOBJECT documentation has no mention of this, so you need to check the documentation exhaustively to notice the relevant section of orxSTRUCTURE!), I wouldn't know how to properly handle an orxOBJECT * appropriately.

    I completely agree that there's no doc about orx internals, they're currently all focused on using orx.
    Traditional use of orx doesn't require any knowledge of orxSTRUCTURE or other orx internals.
    orxOBJECTs should be handled in 99% of the cases via the orxObject interface. You'll never ever have to call orxStructure_IncreaseCounter yourself for example, it's strictly for internal uses only.

    The only part that I should probably improve and extract from the orxStructure interface is the functions for traversing the collections. I guess I could wrap them in all the specific modules but I think it is time consuming and rather counter productive. I instead chose of allowing a much easier access to collections via Scroll.
    Beside those functions, you really should never use the orxStructure interface.
    Now you can end up having orxSTRUCTURE pointers that you'll need to pass around. In that case there are conversion macro which really are based on a cheap C RTTI knock-off. :) It's not the best syntax but unfortunately C doesn't have support for this out of the box.
    In a modern C++ library, you'd never have to worry about such low-level concerns. Everywhere that you see an orxOBJECT *, you'd see a shared_ptr<orxOBJECT>. This isn't important only when you're receiving something BTW. As we've discussed before, when I see orxDisplay_SetBitmapData, I can't know (without asking) whether this function copies my data, takes ownership of it or just references it, leaving the lifetime management to me entirely. Imagine that, before using ANY function that takes or returns a raw pointer, you have to ask about its memory management...

    That is also some missing documentation here. Ownership in orx is never transmitted. The code responsible for creating something is also the owner and responsible for deleting it. That rule is enforced through the entire code base.
    If it weren't the case, it'd be hard to keep one's sanity as you'd have to remember all the special cases, that itself is already really bad. :)

    Memory management is extremely simple so as to make it as efficient as possible. You probably already have noticed that there aren't any extraneous copies of anything made behind the scene. If you want a result that doesn't fit in the machine word, you'll have to provide the memory for it yourself.

    As ownership is never transmitted, the use of smart pointers gets less obvious and the overall philosophy is that if something isn't required then don't do it.
    This example actually brings us to another issue. Even though orxObject_GetName(MyObject); vs. MyObject->GetName(); seems trivial, if orxObject inherits from orxStructure in C++, you'd be able to say MyObject->IncreaseCounter(); -assuming you'd even need to know about the implementation of the shared semantics- and your IDE's content assist would probably inform you about this when you pressed ctrl+space.

    There's a way to do that in C too (C99 to be precise) but it's rather ugly and, again, the use of functions such as orxStructure_IncreaseCounter are strictly for orx internals, not for external use. That separation isn't obvious unfortunately, and I should try to work on that.
    Well, you can find void * in many many more places. Going back to the orxStructure_IncreaseCounter example, that function accepts a void *. Now, looking at just this, can you tell what exactly it expects? Does it expect my orxOBJECT pointer? or will I have to extract an internal pointer of my orxOBJECT using a macro?

    The orxStructure interface required a void * as using orxSTRUCTURE * would require the use of explicit conversion everywhere. That's actually how it used to be if you go back in the svn log history. :) As those functions are internals, I chose to use a void * to prevent all the explicit conversions in all the calling places. That's the only place where such a call was made though. :)

    And for info, it'll use the cheap RTTI-like system making sure you're actually passing an orxSTRUCTURE to it and no some random piece of data, asserting otherwise.
    Well, my problem with C enums is that they allow comparing apples and oranges, though what I missed is that C++ allows that as well. My mind was at Java enums (Oh my god I'm about to say something good about java) which do not allow comparing enums of different types. Now in C++11 you have strongly typed enums that bring the same functionality.

    Yep, strongly typed enums are good, but that doesn't solve the fact you can't split their declaration. I remember either C# or Obj-C actually allows that and I found it great, too bad other languages didn't take example on this.
    Symmetry is not the answer to all problems, even if you have the discipline to follow it. For example, what happens if someone else does not realize the symmetry in your code, and returns in the middle? Even worse, what if an exception is thrown? (I know using exceptions is a personal preference) I feel much more safe, when I can look at a small segment of code, and tell that it's not doing something wrong. In C, you often have to remember to clean-up very far away from where you start doing the dirty thing.

    Well, let's put everything back in context then. :)
    I'm not really speaking of symmetry inside a function, but symmetry of logic. If you create something, then you're in charge of destroying it, etc... This is a very simple precept and that makes code a lot more robust, but it does require a certain discipline from the programmer.
    As for exceptions, well it's only valid in C++, there's no exception module in C (though I've seen some emulating them using setjmp/longjmp or similar).
    I've been working for 5 different console game developpers in the last 12 years. None of them has ever been using exceptions (or RTTI outside of debug builds for that matter). I recognize their merit, but I don't think I want to pay any overhead (both in memory or cycles) for what they bring, not for game development.

    Also exceptions tend to crash rockets, I'd be careful with those! ;)
    But I really don't want to start a flamewar :), if you like C, I'm sure you're using it in a way that eliminates the problems I encounter using it. Just like I'm using C++ in a way that I never run into the problems that C++ haters love to mention. So, the important point is, we all have strong personal reasons to choose our programming environments.

    Heh no flamewar, I like exchanging points of view. :)

    I don't really dislike C++ that to be honest, (or I'd be maso to write Scroll in C++ in the first place), I'm just very cautious in this very specific context of open source game engine.
    Over the last 15 years, 80 to 90% of all the code I've written has been in C++ as it's what I do 40-50h a week during my day job.
    I've seen so many horrors, once even forcing me to hex-edit binaries of precompiled libraries to patch some method calls, that for my own personal projects I'd rather use a much simpler language where people are less likely to make huge mistakes.
    I would like to mention again, that even though I don't like using C libraries, I don't mind wrapping them. Especially in the case of Orx, which is very well designed around an OOP architecture. You just check the documentation once, wrap what you need to use before you use it, and sleep tight at night. So, even though I seem to have strong opinions against C, I really (Really) like Orx. There's so much good in it that makes the task of wrapping stuff insignificant.

    I'm really glad you like orx and I'm sure a C++ wrapper would be beneficiary to it and will probably make a lot of potential users very happy. :)
    This brings us back to our real topic, let's do the wrapping as a collective effort! :)

    I believe Alastriona started a similar task when he started wrapping orx for .NET. Unfortunately that was a long time ago and things have changed a lot since.
    Well, C++ compilers don't play along well with each other. Especially when you start doing advanced things like template-metaprogramming, there are certain cases where you need to go as far as writing preprocessor ifs for each compiler. I have some C++ programs compiled successfully with GCC on both Linux and Windows (MinGW), but I get a 100 distinct compiler errors when I try to compile it with MSVC. Have you noticed how far the boost people have gone to make sure that you can use boost on those supported compilers...

    Heh, you don't have to go that far for C++ portability issues: name mangling is defined per-compiler. So a simple function might not even be found by another C++ compiler. :)
    You're right about this in both directions. It IS fine when you work by yourself and I believe you when you say it isn't when you collaborate with C++ programmers of various skill. Though I would still prefer to set-up the architecture in C++, and let the others program purely C-like. As a small example, imagine using smart pointers all around Orx, but keeping everything else the same otherwise.

    I see what you mean, though I wouldn't use smart pointers all over the place as they come with an overhead I don't want if I don't have the need for it. :)
    About the performance issues, I haven't done anything about them yet. They're most probably about alpha-blended pixels as you've said, because I've been using them ad-libitum :) I was planning to start a topic about it once I focus on the performance aspect.

    Well don't hesitate to let us know if you don't see any obvious cause, we'll be happy to help! :)
    Cheers! :) :)

    Cheers! :)
  • edited September 2012
    godexsoft wrote:
    Furthermore, I can't agree with Iarwain that hardcore C++ is only good when you work alone and/or don't have other developers of "various skill". I think there is a good reason people invented lead developers, senior developers and other names which usually represent the length of someone's dick in software companies :) In my opinion the core/engine of any application can be any level of hardcore meta-programming as long as it exposes a simple, intuitive, yet well-documented interface for "various skill" developers to use.

    In the very specific context of high performance game programming, I disagree. You cannot expect the lead and seniors to review all the code written by everybody to make sure it's up to a given standard. It will never happen, mostly by lack of time.
    Unfortunately, that means the codebase is of varying quality and it's hard to keep track of what should be rewritten.
    I ran Source Navigator where I currently work about 2 years ago, the active codebase (currently running on PS Vita, PS3 and Direct11) is about 8M lines of code and the quality really isn't consistent.
    Even on Splinter Cell Conviction and its 5M lines of code, the problem of code quality across the codebase was huge, due to the 100+ engineers that have been coding in it over the years.

    That's even worse in the case of open source projects where you don't hire people but where you'll have to integrate contributions. It's not the case of orx as the community is pretty small, but who knows if it grows much more one day...
    Also, i never give jobs to people who i interview if they don't meet a certain level of expected knowledge. Many developers with _years_ of experience in C++ (some over 10 years in Symbian for example) don't know the basics. I wrote a blog post on this matter a while ago.

    No matter what your level of knowledge is, there are caveats you probably don't know. And that's the case for all C++ programmers that I know, no matter how good they are.
    C being more simple is less prone to this, but of course not bullet proof.

    Also, in the context of open source development, you cannot difficultly enforce a certain level of proficiency among the contributors, and that's what we talking about here. :)

    Cheers!

    PS: As a side note, I don't think "modern C++" means the exact same thing for you and me, but I think we already covered that topic to some extent. :)
    For me it's a reference to the Modern C++ Design book of Alexandrescu. Based on that criteria, Boost sure is written in modern C++, but most (if not all?) of other open source C++ work isn't.
  • edited September 2012
    Hi iarwain, thanks again for your comprehensive reply

    iarwain wrote:
    the use of functions such as orxStructure_IncreaseCounter are strictly for orx internals, not for external use.

    What is the proper way of sharing ownership of a structure in Orx? Or am I doing something wrong by needing it? I can give an example of when I needed this. In the game that I'm currently working on, the arrangement of objects on the screen aren't the same as their arrangement in the game world. This is basically because the view is not perpendicular to the game world. In summary, I need to keep my own data structure for arranging the game objects in the world, so I need to keep orxOBJECT references. The problem with simply keeping pointers is that the object that they point to can silently die. Isn't it natural at this point to wrap this pointer in my smart pointer that uses the increase/decrease reference count?
    I've seen so many horrors, once even forcing me to hex-edit binaries of precompiled libraries to patch some method calls

    I feel for you...
    I wouldn't use smart pointers all over the place as they come with an overhead

    It's funny how one moment you find yourself talking to someone saying that C++ lacks the advanced features of modern higher level languages, just for the sake of performance (well, people write 3D games in scripting languages nowadays), and the next moment you're told that smart pointers are bad for performance and somebody would rather not use them :) I guess everybody has a threshold for how much performance they can sacrifice for fancy features :)

    The lesson I got from this entire discussion is that I should probably stop struggling with orx, and do things the orx way as much as possible.

    Cheers!
  • edited September 2012
    enobayram wrote:
    Hi iarwain, thanks again for your comprehensive reply

    Hey enobayram, don't mention it, it's an interesting discussion. :)
    What is the proper way of sharing ownership of a structure in Orx?

    Well the philosophy is that you own what you create, no more, no less. If something's created by orx, you're not the owner, if you create something, you're the owner.

    The only real exception to that rule (otherwise it wouldn't be a full-fledged rule ;)) is when using orxObject_SetOwner(), which is tempering with ownership, but that sounds pretty obvious I think (similar one with spawners). ;)
    And it's only for one aspect, object destruction, that it really matters, ie. an object being deleted will also call for the deletion all owned objects, that's about it.
    Or am I doing something wrong by needing it? I can give an example of when I needed this. In the game that I'm currently working on, the arrangement of objects on the screen aren't the same as their arrangement in the game world. This is basically because the view is not perpendicular to the game world. In summary, I need to keep my own data structure for arranging the game objects in the world, so I need to keep orxOBJECT references. The problem with simply keeping pointers is that the object that they point to can silently die. Isn't it natural at this point to wrap this pointer in my smart pointer that uses the increase/decrease reference count?

    Mmh, not really, cause increasing the reference counter will prevent it from being destructed when the rightful owner is trying to do so and will be leaked, which means you'll have to handle his fate later yourself.

    Now the real question is why your orxOBJECT is getting silently deleted? That should never happen unless you've originated it from the user side (either with a direct call or via properties such as LifeTime).

    If you need to have external data to the orxOBJECT, you should link them to it via the orxObject_SetUserData.
    Unless you're using Scroll that actually already does that behind the scene and let you create C++ classes and bind them to config sections instead.

    Now if you ever need to get a reference to an orxSTRUCTURE without taking the ownership, you should use its Global Unique IDentifier (GUID) instead of using C pointer.
    If the object associated with that GUID has been deleted, you won't find it and you can react accordingly.
    Scroll also wraps the concept of GUIDs for ScrollObject, making it easier to access without having to go through the orxStructure interface. :)

    GUIDs actually pack all the data that make any orxSTRUCTURE instance unique + the reference counter for memory tightness/alignment sake. That is the type of structure, its ID within the bank that holds those structures in memory and an ID counter that makes sure one doesn't get a different object re-allocated in the same place in memory as your old object.

    They're also used for executing orxCOMMANDS either via code, via the newly added console or via timelines. When/if there's network support one day, they should be able to help synchronizing objects over the wires too. :)

    Let me know if this is unclear as I don't think there's any tutorial or clear doc about this in the wiki yet.
    I feel for you...

    That was actually pretty interesting and fun to do. Definitely not productive though. ;)
    It's funny how one moment you find yourself talking to someone saying that C++ lacks the advanced features of modern higher level languages, just for the sake of performance (well, people write 3D games in scripting languages nowadays), and the next moment you're told that smart pointers are bad for performance and somebody would rather not use them :) I guess everybody has a threshold for how much performance they can sacrifice for fancy features :)

    It's all a matter of context, isn't it? :)
    If I'm to make a simple puzzle game with not much performance requirement or very few objects to handle, I'll definitely use higher concept and tools.
    But as a coder of a low level game engine that could virtually be used on big/ambitious games or on very limited platforms, I'd always try to go for the most efficient, if possible. Did I mention orx used to run on GBA at some point? Probably some of the recent modules wouldn't work there anymore but it's easy not to use or even compile them if needed. :)
    The lesson I got from this entire discussion is that I should probably stop struggling with orx, and do things the orx way as much as possible.

    Cheers!

    Well as long as you still feel somewhat comfortable, that should be good. We tried to design the engine to be as open/generic as possible, while finding a good compromise for efficiency. You can use it as a low level library if needed or as a higher feature-rich engine. Of course, all choices come with limitations but we tried our best to go in that direction.

    A C++ wrapper would be welcomed by a lot of people I guess, Scroll could be a base for it or not, hard to say, it's impossible to please everybody and we all have our preferences.

    Someone wrote a FreeBasic wrapper a few years ago, unfortunately it was never really finished. It's too bad as I think the FreeBasic community is pretty strong and having them on-board would be great.

    That's what I really like about the current motivation around building a community-driven editor, it's made by people having different needs than mine and to suit their needs, I'm all for that even though I don't think I'll be using it a lot as I like my config files and I dislike "modern" UIs. :)

    Cheers! :)
Sign In or Register to comment.