Scroll and Config Code Questions

edited April 2017 in Help request
Hello everyone. I'm currently working on a project, a top down RPG, and I've made it about as far as I could just by delving into the documentation and lurking on the forums here for answers, and I've hit sort of an issue.

I'm coding this in C++, and I've been looking at Scroll and it seems to be what I need, but there's not much documentation about it besides 2 or 3 tutorials. My current setup creates new objects by passing in arguments which are then used in initializer lists (I read that this is faster than assigning members in the constructor). I'm wondering whether it's possible to pass in arguments to a constructor when using Scroll, or whether I just need to use the OnCreate() function.

I'm also wondering what the best method is to go about linking a database to it. I'm pretty sure I want to use a SQLite database for distribution and because I'm familiar with it. I want to use this database to store all the stats for enemies, items, etc. and possibly graphics information. I've seen examples here that show in the config files sections like:
Key = Code "<c code here>"
Would I use this sort of setup for obtaining graphic information from a database?

Comments

  • edited April 2017
    krypto42 wrote:
    Hello everyone. I'm currently working on a project, a top down RPG, and I've made it about as far as I could just by delving into the documentation and lurking on the forums here for answers, and I've hit sort of an issue.

    Nice, sounds like an ambitious project, looking forward to learning more about it. Don't hesitate to create a thread in the project section if you feel like it.
    I'm coding this in C++, and I've been looking at Scroll and it seems to be what I need, but there's not much documentation about it besides 2 or 3 tutorials. My current setup creates new objects by passing in arguments which are then used in initializer lists (I read that this is faster than assigning members in the constructor). I'm wondering whether it's possible to pass in arguments to a constructor when using Scroll, or whether I just need to use the OnCreate() function.

    The performance difference is true in some cases: you'd need to be dealing with non-POD (aka Plain Old Data) members, ie. that have non trivial constructors. Initialization lists would skip the call to the constructor without any argument.
    In the case of Scroll, you can't do that and you'll have to use the OnCreate() method for your initialization purposes. However you have some guarantees Scroll is giving you:

    - when OnCreate() is called, the binding with the underlying orxOBJECT has already been made, no matter how your ScrollObject has been created (ie. spawned from an orxSPAWNER, created with a call to Scroll::CreateObject() or a call to orxObject_CreateFromConfig())

    - when OnCreate() is called, its config section is currently pushed, ie. you don't need to call orxConfig_PushSection()/ScrollObject->PushConfigSection() and you can directly fetch your data with calls to orxConfig_Get*()
    I'm also wondering what the best method is to go about linking a database to it. I'm pretty sure I want to use a SQLite database for distribution and because I'm familiar with it. I want to use this database to store all the stats for enemies, items, etc. and possibly graphics information. I've seen examples here that show in the config files sections like:
    Key = Code "<c code here>"
    Would I use this sort of setup for obtaining graphic information from a database?

    Regarding the Code = "" config property, it's actually to define fragment (pixel) shaders that will be compiled and executed instead of the default shader defined by orx. It's not C code but GLSL (GL Shading Language) code, which does look quite similar.

    If you want to use a database, there are a few ways to approach this, but it'll depends more on the specifics. What would you like to store in the DB? Here are a couple of potential approaches:

    - wrap Scroll::CreateObject() into a wrapper that would first push the corresponding config section, fetch the properties you'd need to retrieve the data from the DB (probably executing a JOIN based on those properties), retrieve whichever data you want from the DB, let's use a texture for this example, set the graphic property of the object in config (orxConfig_SetString("Graphic", "@) to set the section as its own graphic + orxConfig_SetString(Texture", TextureFetchedFromDB)), then call Scroll::CreateObject() on it. And you now get your object with its graphic dynamically set from the DB

    - do it post-creation instead of pre-creation: inside OnCreate(), fetch the config properties as done above, write your SQL query using them, retrieve your graphic, creates it with orxGraphic_CreateFromConfig(), link it to the object with orxObject_LinkStructure() and make sure you unlink + delete the graphic inside OnDelete(), otherwise it'll leak: given you created it, you're the owner, not orx, so you need to delete it yourself.

    I prefer the first approach as I don't have to do any bookkeeping, but that's just me. =)

    Another option would be to not use a DB at all, or, best of both worlds (?) import the DB inside orx's config system either when loading the game or offline when exporting the assets and creating the build.
    You wouldn't be able to make JOIN queries, but in most cases you might not need those. Again, it really depends on the specifics of your gameplay, so I can't help much more than that on this topic.

    Hope this helps and best of luck with your project! =)
    Don't hesitate to ask any questions you have here or on https://gitter.im/orx/orx for faster/smaller answers.
  • edited April 2017
    Nice, sounds like an ambitious project, looking forward to learning more about it. Don't hesitate to create a thread in the project section if you feel like it.

    It is, it's basically a game inspired by Crono Trigger. Ideally it would have lots of time travel and timeline branching. I don't really have that much of it down right now besides some character concepts, some features I would like to have, and an overarching idea for the plot.

    Right now I'm working on the bones of the project: things like handling transitions from one map to another, depth sorting, screen resizing, etc.
    The performance difference is true in some cases: you'd need to be dealing with non-POD (aka Plain Old Data) members, ie. that have non trivial constructors. Initialization lists would skip the call to the constructor without any argument.
    In the case of Scroll, you can't do that and you'll have to use the OnCreate() method for your initialization purposes. However you have some guarantees Scroll is giving you:

    - when OnCreate() is called, the binding with the underlying orxOBJECT has already been made, no matter how your ScrollObject has been created (ie. spawned from an orxSPAWNER, created with a call to Scroll::CreateObject() or a call to orxObject_CreateFromConfig())

    Yeah, I figured that would be the case. The idea with using that was that things like stats would be looked up from the database and used in the initialization list.
    - when OnCreate() is called, its config section is currently pushed, ie. you don't need to call orxConfig_PushSection()/ScrollObject->PushConfigSection() and you can directly fetch your data with calls to orxConfig_Get*()

    I haven't used that functionality of orx yet. What exactly would that allow?
    Regarding the Code = "" config property, it's actually to define fragment (pixel) shaders that will be compiled and executed instead of the default shader defined by orx. It's not C code but GLSL (GL Shading Language) code, which does look quite similar.

    Ah, ok. I was thinking I could use that to make queries to retrieve info for keys, that doesn't exactly make as much sense now.
    - wrap Scroll::CreateObject() into a wrapper that would first push the corresponding config section, fetch the properties you'd need to retrieve the data from the DB (probably executing a JOIN based on those properties), retrieve whichever data you want from the DB, let's use a texture for this example, set the graphic property of the object in config (orxConfig_SetString("Graphic", "@) to set the section as its own graphic + orxConfig_SetString(Texture", TextureFetchedFromDB)), then call Scroll::CreateObject() on it. And you now get your object with its graphic dynamically set from the DB

    - do it post-creation instead of pre-creation: inside OnCreate(), fetch the config properties as done above, write your SQL query using them, retrieve your graphic, creates it with orxGraphic_CreateFromConfig(), link it to the object with orxObject_LinkStructure() and make sure you unlink + delete the graphic inside OnDelete(), otherwise it'll leak: given you created it, you're the owner, not orx, so you need to delete it yourself.

    I don't exactly have experience writing wrappers, but I have some bad habits when it comes to cleaning up potential memory leaks, so let's just say the less leaks the better.
    Another option would be to not use a DB at all, or, best of both worlds (?) import the DB inside orx's config system either when loading the game or offline when exporting the assets and creating the build.
    You wouldn't be able to make JOIN queries, but in most cases you might not need those. Again, it really depends on the specifics of your gameplay, so I can't help much more than that on this topic.

    My thoughts for using the DB would primarily be a centralized area for modifying basic game stats, mostly for in dev reasons but also for modding. I have mock ups of how combat works, but I don't want to hard code stuff into the binary since I want to make it as fast as possible, and being an RPG means a variety of enemies and items. The DB would only really be used for a centralized way of keeping track of all that stuff, plus things like the path to the texture used, and probably sound paths. I likely wouldn't be storing any large data files into the DB.

    I know I want modding to be a primary feature of the game, it's one of the reasons I chose orx to begin with. I don't really know how I would load the DB inside orx though. I haven't actually linked a DB to a program before, I've seen code examples of it though.
  • edited April 2017
    krypto42 wrote:
    It is, it's basically a game inspired by Crono Trigger. Ideally it would have lots of time travel and timeline branching. I don't really have that much of it down right now besides some character concepts, some features I would like to have, and an overarching idea for the plot.

    Right now I'm working on the bones of the project: things like handling transitions from one map to another, depth sorting, screen resizing, etc.

    There's definitely a lot to be done. Regarding map transitions, depth sorting and screen resizing, all those could easily be handled by orx itself, to a certain extent.

    Regarding map loading, what I like to do is simply create an object which is the map. This object in turn has many children (like buildings, characters, etc) which in turn can also have children, etc etc.
    This makes it really easy to load a map (simply create the object) and unload it (simply delete the object, all children will be removed as well).

    Regarding depth sorting, there are two things to consider when using orx:

    - object groups, you can assign a group to any object (it's just a string literal you pick, like "Background" or "UI", etc). Then you can assign a list of groups to cameras. They'll render all the groups in the order they were assigned to the camera. Let's say one has:
    [MyCamera]
    GroupList = Background # Game # Foreground # UI # Cursor
    

    When a viewport that is linked to this camera gets rendered, all the objects from the group Background will be rendered first, then all objects from the group Game, and so on and so forth...

    - The Z position is used for depth sorting withing a single group. Smaller Z values get rendered on top (ie. after) larger Z values. They still have to be within the camera's frustum Z bracket defined by FrustumNear/FrustumFar values. FrustumNear is excluded while FrustumFar is included.
    Yeah, I figured that would be the case. The idea with using that was that things like stats would be looked up from the database and used in the initialization list.

    Another thing that is worth mentioning is that resource can be hotloaded in orx, which is very handy during development. Ie. all your textures, sounds, config files will be reloaded as soon as they're saved on disk if you so desire. That means all the values you get from the config can be modified while the game is running without having to restart.
    - when OnCreate() is called, its config section is currently pushed, ie. you don't need to call orxConfig_PushSection()/ScrollObject->PushConfigSection() and you can directly fetch your data with calls to orxConfig_Get*()

    I haven't used that functionality of orx yet. What exactly would that allow?

    It means you can define any property for your objects that you'll retrieve easily upon creation.

    Let's take a weapon as example, with some basic properties. If you bind your class MyWeapon to the config section Weapon by calling
    ScrollBindObject<MyWeapon>("Weapon");
    
    inside the method BindObjects(), you can then have:
    [Sword@Weapon]
    Type = sword
    Attacks = slice # thrust
    
    [BasicSword@Sword]
    Damage = 50
    Durability = 90
    TwoHanded = false
    
    [ZweiHander@Sword]
    Damage = 120
    Durability = 150
    TwoHanded = true
    

    In code:
    void MyWeapon::OnCreate()
    {
      damage = orxConfig_GetS32("Damage");
      durability = orxConfig_GetS32("Durability");
      isTwoHanded = orxConfig_GetBool("TwoHanded");
      for(orxU32 i = 0, iCount = orxConfig_GetListCounter("Attacks");
          i < iCount;
          i++)
      {
        const orxSTRING attack = orxConfig_GetListString("Attacks", i);
        // Do something with this info ...
      }
    }
    

    When you call Scroll::CreateObject("ZweiHander"), you know you'll get a MyWeapon object in return which will be initialized with all the data you defined in config. That's because ZweiHander inherits in config from Sword which inherits from Weapon which is bound to MyWeapon.
    Of course you can override the binding if you wanted to have separate classes for Swords and Axes, for example. Hopefully that illustrates a bit more what I previously wrote.
    Regarding the Code = "" config property, it's actually to define fragment (pixel) shaders that will be compiled and executed instead of the default shader defined by orx. It's not C code but GLSL (GL Shading Language) code, which does look quite similar.

    Ah, ok. I was thinking I could use that to make queries to retrieve info for keys, that doesn't exactly make as much sense now.

    Unfortunately no, it'll be handy to have nice visual effects though. :)
    I don't exactly have experience writing wrappers, but I have some bad habits when it comes to cleaning up potential memory leaks, so let's just say the less leaks the better.

    I guess leak was a bit strong as you'd still be able to retrieve it by calling some orx functions (internally orx keeps bookmarks on everything that has been allocated through it, to make sure things don't leak), it'll just be a temporary waste of resources.
    My thoughts for using the DB would primarily be a centralized area for modifying basic game stats, mostly for in dev reasons but also for modding. I have mock ups of how combat works, but I don't want to hard code stuff into the binary since I want to make it as fast as possible, and being an RPG means a variety of enemies and items. The DB would only really be used for a centralized way of keeping track of all that stuff, plus things like the path to the texture used, and probably sound paths. I likely wouldn't be storing any large data files into the DB.

    I know I want modding to be a primary feature of the game, it's one of the reasons I chose orx to begin with. I don't really know how I would load the DB inside orx though. I haven't actually linked a DB to a program before, I've seen code examples of it though.

    If you do not plan on using SQL queries joining tables and such, I'd recommand using orx's config system. It's very versatile, in addition to providing orx with all the properties required for it to run, you can also define your own, as seen above, use inheritance for partial or complete overrides (which is very handy for modding, while still keeping under control what you want to be moddable or not), and can be either loaded from disk (with optional hot-reload) or even modified at runtime programmatically (all the orxConfig_Set*() functions).

    There's also commands you can use to have somewhat scripted behaviours. Orx comes which a bunch of commands (like Object.Create or Input.IsActive, for example) and one can add their own as well.
    Commands can be called from within the interactive console (Quake-style, you can get it by pressing backtick "`", it supports history and auto-completion), directly from config (when a config file is loaded commands can be executed directly to dynamically modify the config values, for example) or, and that's the most frequent use case: from timelines. If you haven't stumbled upon them yet, I believe Sausage wrote a couple of tutorials about them on the wiki.
  • edited April 2017
    Regarding depth sorting, there are two things to consider when using orx:

    - object groups, you can assign a group to any object (it's just a string literal you pick, like "Background" or "UI", etc). Then you can assign a list of groups to cameras. They'll render all the groups in the order they were assigned to the camera. Let's say one has:

    Code:

    [MyCamera]
    GroupList = Background # Game # Foreground # UI # Cursor


    When a viewport that is linked to this camera gets rendered, all the objects from the group Background will be rendered first, then all objects from the group Game, and so on and so forth...

    - The Z position is used for depth sorting withing a single group. Smaller Z values get rendered on top (ie. after) larger Z values. They still have to be within the camera's frustum Z bracket defined by FrustumNear/FrustumFar values. FrustumNear is excluded while FrustumFar is included.

    Wow, I didn't really know what groups did. That's very useful, so far I've just been modifying every object's Z value depending on their lowest pixel (for a semi-3D effect) and trying to mark UI objects with a 'ui' collision tag, which would then be ignored by the depth sorter. That's way simpler, thanks!
    It means you can define any property for your objects that you'll retrieve easily upon creation.

    Let's take a weapon as example, with some basic properties. If you bind your class MyWeapon to the config section Weapon by calling
    Code:
    ScrollBindObject<MyWeapon>("Weapon");
    inside the method BindObjects(), you can then have:

    Code:

    [Sword@Weapon]
    Type = sword
    Attacks = slice # thrust

    [BasicSword@Sword]
    Damage = 50
    Durability = 90
    TwoHanded = false

    [ZweiHander@Sword]
    Damage = 120
    Durability = 150
    TwoHanded = true


    In code:

    Code:

    void MyWeapon::OnCreate()
    {
    damage = orxConfig_GetS32("Damage");
    durability = orxConfig_GetS32("Durability");
    isTwoHanded = orxConfig_GetBool("TwoHanded");
    for(orxU32 i = 0, iCount = orxConfig_GetListCounter("Attacks");
    i < iCount;
    i++)
    {
    const orxSTRING attack = orxConfig_GetListString("Attacks", i);
    // Do something with this info ...
    }
    }


    When you call Scroll::CreateObject("ZweiHander"), you know you'll get a MyWeapon object in return which will be initialized with all the data you defined in config. That's because ZweiHander inherits in config from Sword which inherits from Weapon which is bound to MyWeapon.
    Of course you can override the binding if you wanted to have separate classes for Swords and Axes, for example. Hopefully that illustrates a bit more what I previously wrote.

    Hmm. I saw an example of this somewhere on here not too long ago. I was meaning the calls to orxConfig_PushSection(). Scroll looks like it helps with that too.
    If you do not plan on using SQL queries joining tables and such, I'd recommand using orx's config system. It's very versatile, in addition to providing orx with all the properties required for it to run, you can also define your own, as seen above, use inheritance for partial or complete overrides (which is very handy for modding, while still keeping under control what you want to be moddable or not), and can be either loaded from disk (with optional hot-reload) or even modified at runtime programmatically (all the orxConfig_Set*() functions).

    My main worry was that I'd just lose track of files. A full fledged DB is probably more trouble than it's worth if I don't make use of everything, now that I think about it.

    So regarding inheritance, I think I saw something about Scroll bindings also inheriting. So would something like this bind GameEnemy to the Soldier object?
    [Enemy]
    Graphic = @
    Texture = generic-enemy.png
    Damage = 20
    
    [Soldier@Enemy]
    Texture = soldier.png
    Damage = 45
    
    Using a GameEnemy class
    void OrxScroll::BindObjects ()
    {
        ScrollBindObject<GameEnemy> ("Enemy");
    }
    
    There's also commands you can use to have somewhat scripted behaviours. Orx comes which a bunch of commands (like Object.Create or Input.IsActive, for example) and one can add their own as well.
    Commands can be called from within the interactive console (Quake-style, you can get it by pressing backtick "`", it supports history and auto-completion), directly from config (when a config file is loaded commands can be executed directly to dynamically modify the config values, for example) or, and that's the most frequent use case: from timelines. If you haven't stumbled upon them yet, I believe Sausage wrote a couple of tutorials about them on the wiki.

    I've looked at the command module and tried it out, the syntax takes some getting used to for me. Most of the time I've just used it to double check FPS and the like, some things early on were being weird.

    I think you've convinced me to refactor my code to use Scroll though. So far I've been using the examples in some of Sausage's tutorials, making orx objects members of C++ classes. I have quite a bit of refactoring that I need to do now, my initial class system wasn't exactly well designed, just an initial mock up to get some structuring out of my head.

    I'm in the process of updating to orx 1.8 from 1.7 now, some initial weirdness happened there, something about the version of Box2d in the LiquidFun part of your workspace not liking something in my config (I tracked it down to hiding an entry point node by scaling it down to be invisible). I'm also trying to target Windows, OS X and Linux, building from Linux, and there's been some weirdness with missing dlls when testing on Windows using the precompiled builds (I think libgcc, libgomp, and winpthreads, it's been awhile). In the past I've had to just compile the dlls myself when the new version has been released.
  • edited April 2017
    krypto42 wrote:
    Wow, I didn't really know what groups did. That's very useful, so far I've just been modifying every object's Z value depending on their lowest pixel (for a semi-3D effect) and trying to mark UI objects with a 'ui' collision tag, which would then be ignored by the depth sorter. That's way simpler, thanks!

    My pleasure. Groups can also be used for picking (orxObject_Pick/orxObject_BoxPick take an optional GroupID parameter).
    Hmm. I saw an example of this somewhere on here not too long ago. I was meaning the calls to orxConfig_PushSection(). Scroll looks like it helps with that too.

    It wraps a few things at the object level, its main advantage remains the config<->code binding and the level editor (which might be broken by now, I haven't used it in years!).
    My main worry was that I'd just lose track of files. A full fledged DB is probably more trouble than it's worth if I don't make use of everything, now that I think about it.

    Makes sense. Though it's versatile, you can separate the files as you see fit, all the way from everything within a single config file to files scattered in many directories. As you probably already know, you can include config files as much as you want using the syntax
    @MyIncludeFile.ini@
    

    Lastly, regarding resource location, the resource module should help you with that. It allows one to define layers of storages where to look for resource files. Orx defines three resource groups (Texture, Sound and Config), but users can define as many as they want for their own purposes. In addition to that, it's easy to add "transports", called types. By default, simple on-disk files is the only type supported by orx (except on Android where a second resource type exist to load resources from inside .apk files). It's easy to add new types to load resources from inside an archive or from a remote location, for example. I've posted examples of those on the orx-dev mailing list (orxArchive.c that allows one to load resources from within ZIP files, and orxRemote.c that allows accessing resources from a web server).
    So regarding inheritance, I think I saw something about Scroll bindings also inheriting. So would something like this bind GameEnemy to the Soldier object?
    [Enemy]
    Graphic = @
    Texture = generic-enemy.png
    Damage = 20
    
    [Soldier@Enemy]
    Texture = soldier.png
    Damage = 45
    
    Using a GameEnemy class
    void OrxScroll::BindObjects ()
    {
        ScrollBindObject<GameEnemy> ("Enemy");
    }
    

    This example looks very similar to the one I posted above. Here the binding says that any config section that inherits from Enemy will be associated to a GameEnemy instance. So in your case, calling Scroll::CreateObject("Soldier") will return an instance of GameEnemy.

    Having a section [EliteSoldier@Soldier] would also result in a GameEnemy as EliteSoldier inherits from Soldier which in turn inherits from Enemy.
    If you wanted to have your own GameSoldier section bound to Soldier, you'd need to add the following binding:
    void OrxScroll::BindObjects ()
    {
        ScrollBindObject<GameEnemy> ("Enemy");
        ScrollBindObject<GameSoldier> ("Soldier");
    }
    
    I've looked at the command module and tried it out, the syntax takes some getting used to for me. Most of the time I've just used it to double check FPS and the like, some things early on were being weird.

    Yes the syntax is stack-based and very simplistic. There's some proposal to make it nicer, I'll probably tackle this at some point before next release.
    I think you've convinced me to refactor my code to use Scroll though. So far I've been using the examples in some of Sausage's tutorials, making orx objects members of C++ classes. I have quite a bit of refactoring that I need to do now, my initial class system wasn't exactly well designed, just an initial mock up to get some structuring out of my head.

    I know Sausage hasn't really gone with Scroll yet, but I think it helps quite a bit for people who want to use C++ instead of plain C.
    I'm in the process of updating to orx 1.8 from 1.7 now, some initial weirdness happened there, something about the version of Box2d in the LiquidFun part of your workspace not liking something in my config (I tracked it down to hiding an entry point node by scaling it down to be invisible). I'm also trying to target Windows, OS X and Linux, building from Linux, and there's been some weirdness with missing dlls when testing on Windows using the precompiled builds (I think libgcc, libgomp, and winpthreads, it's been awhile). In the past I've had to just compile the dlls myself when the new version has been released.

    I'd recommend going all the way with the repository instead of using the binary packages. Orx compiles out of the box after running the setup script (only once, it'll get called automatically with subsequent pulls). I try to keep the default/master branch as stable as possible and most new features are first deployed via branches.
    Regarding LiquidFun/Box2D, I know they don't have the same threshold about what they consider a surface too small to use as a physics shape, which might be the source of your issue. If you want to scale things down to disappear, I'd consider unlinking the body from the object (if it's orx that created the body, it'll delete it as well when the unlinking call is issued) at some point before it gets too small. Or at least remove the shapes from the body.

    Regarding cross-compiling from linux to osx/windows, I haven't done that myself. Unfortunately orx has one C++ dependency (Box2D/LiquidFun), and it's ABI isn't stable between gcc/MinGW releases. If you can't use a VM to build on windows, try to match gcc 5.3.0 to cross-compile as it's the current one deployed with MinGW (and the one I used to compile the latest binaries of the dependencies).

    In any case, if you find a reliable way to do so, I'm sure a lot of people would appreciate a tutorial in the wiki. ;)
  • edited April 2017
    So I've been trying to build orx 1.8 using only the cross toolchains. The native linux toolchain works like a charm, but I've hit a brick wall with windows. I'm using the mingw-w64 repository package (Mint 18 if it matters), and in linking I've come across the errors undefined reference to `_Unwind_Resume' and [block]undefined reference to `__gxx_personality_v0'

    I've narrowed the culprit down to at least one of the dependencies, LiquidFun, to using dwarf2 exception handling, where the i686-w64-gcc binary uses sjlj exception handling. Unfortunately, my distro doesn't seem to provide a version with dwarf2 EH, so I really have two options:
    1. recompile the dependencies using my current toolchain
    2. build a new mingw that uses dwarf2

    I could also attempt to compile on Windows, but that may just push the issue further back when I attempt to build my project.

    Or it occurs to me I could take the really easy/lazy option and pull the dwarf2 dll and any other dependencies and just package them with the Windows install. It's kind of hacky, but it might work.

    Thoughts?
  • edited April 2017
    I'm actually surprised you didn't encounter more issues as orx's dependencies aren't compiled with mingw-w64 at the moment, which is a separate project from mingw32 (which is the one used by orx).

    I'd recommend going with #1 as it seems to be the more robust path.

    Building the dependencies is a bit annoying as they don't all use the same build system (premake, cmake, hand-made makefiles, etc), but there aren't that many of those.

    I guess I could maintain separate branches in the repository for mingw32 and mingw-w64, but given you're not using the repositories in the first place, that wouldn't help you much at the moment.

    Good luck!
  • edited April 2017
    Oh, I did encounter other issues, it's just they were easier to solve :)
    In the past I just hopped over to windows and built there, then used the libraries when building my project with mingw-w64, which worked fine for previous builds.

    Yeah, that is probably the better route. It may allow for a 64-bit build using mingw, which I've noticed is absent in the release. I'll be recording what steps I take for a future tutorial, which can hopefully save others headaches in the future.

    I'm using the repository now, but only a checkout of 1.8 I want to get it working with a known stable release first before trying it with the latest build. Do you have any tips for managing the dependencies?
  • edited April 2017
    Yep, a 64bit version with MinGW-w64 would be nice. I remember trying it in the past but I don't remember why I didn't proceed with it.

    I do not have any tips unfortunately, one of the things I'd eventually like to do is to write an automated build process for them as it's really annoying to recompile all the versions manually when doing updates, but so far I always ended up spending my time adding features to the engine itself instead. Were I ever able to do that full time one day, I'll definitely change that.
  • edited April 2017
    First of all, Happy Easter everyone :)


    Secondly, I've run into some issues cross building the dependencies. I have Freetype and GLFW building, but I've gotten hung up on libsndfile. The build seems to fail in the linking stage with libFLAC and libvorbisenc. I used MXE to get those packages and linked them to the /include and /lib directories via symlink, but it's still failing. The output log mentions it can link to shared versions of these libraries, but I thought it linked statically.
    The strange thing is the maintainer of libsndfile builds using the same cross compiler because they couldn't stand Windows native tools.

    How does your build system link libsndfile to these libraries iarwain?


    Edit: Nevermind, solved my own problem!
  • edited April 2017
    Ah good, just for the sake of completeness, the answer is that we don't link those libraries to libsndfile. :)

    We don't support FLAC and we use stb_vorbis for ogg/vorbis.
  • edited April 2017
    Regarding the author of libsndfile vs windows, he does have a pretty strong position with which I don't agree.
    Strong enough that libsndfile will not compile natively with Visual Studio and I had to make quite a few changes to it because of that.

    That's also the reason I haven't updated that library in years, given there wasn't any public repository for it back then (maybe that has changed?). The license is also problematic for platforms like iOS (on which I'm using yet another audio decoder library).

    In the end, I think people only use it for .wav files, so if you know of any other portable library with a more permissive license, please let me know. :)
  • edited April 2017
    Ok, I was able to get it to build both with and without linking those libraries. I'll probably include it in the instructions just for completeness. Speaking of which, I'm working on a build script to automate all of this. It won't build for any other platforms, and it will only build the dependencies, but it should work for cross building.

    Regarding something with a a more permissive license, I'd start with ffmpeg. It's LGPL, which I checked libsndfile and it seems like it uses that too, but if that doesn't do the trick here's the license file for ffmpeg. It details that full GPL can be enabled and which libraries those are, and mentions it uses some libraries with other licenses. It may not be what you're looking for, but it might at least point in the right direction.

    Also, are any other libraries included with the other dependencies? I'm on libwebp now, next is LiquidFun and openal. That should be it right?
  • edited April 2017
    It's too bad it won't work with other platforms, but that's already better than what we have. :)

    ffmpeg sounds rather overkill as we only need to decode audio files into PCM but if it would have helped license-wise, I'd have considered it.
    In any case, it's using the LGPL license which is the problematic one in our case, as it's also the one used by libsndfile.
    It prevents static linking of a library inside a commercial/closed source application.
    "Plain" GPL is even worse and would completely prevent orx from being used for commercial applications.

    The dependencies you need to pre-compile for orx are:
    - glfw
    - libsndfile
    - libwebp
    - liquidfun
    - openal-soft (windows-only)
    - freetype (for orxfontgen, not orx itself)
    - Tremolo (only for Android)

    The dependencies that are compiled at the same time as orx (and hence that do not require any binaries compiled ahead of time) are:
    - dlmalloc
    - stb_image
    - stb_vorbis
  • edited April 2017
    It's too bad it won't work with other platforms, but that's already better than what we have. :)
    I was meaning it won't run on Windows, since it's a shell script. I might run on OS X though, and modifying it to build the linux libraries shouldn't be too difficult. The only issue I can imagine existing for it would be install locations, depending on whether or not certain dependencies need other dependencies built, such as libwebp seems to need.
    ffmpeg sounds rather overkill as we only need to decode audio files into PCM but if it would have helped license-wise, I'd have considered it.
    In any case, it's using the LGPL license which is the problematic one in our case, as it's also the one used by libsndfile.
    It prevents static linking of a library inside a commercial/closed source application.
    "Plain" GPL is even worse and would completely prevent orx from being used for commercial applications.
    Yeah, I wanted to avoid GPL when choosing a game engine, part of the reason I'm here. :)
    I did some digging though, and came across this. From that thread, the most promising options seem to be libsoundio (MIT), PortAudio (MIT), Cinder (BSD), and SDL 2.0 (zlib). Maybe one of these could work, although SDL is probably overkill on overkill.

    I've already got freetype, glfw, and libsndfile building, libwep is next. Using the configure script and getting some of it's dependencies, I have this output:
    WebP Configuration Summary
    --------------------------
    
    Shared libraries: yes
    Static libraries: yes
    Threading support: yes
    libwebp: yes
    libwebpdecoder: no
    libwebpdemux: no
    libwebpmux: no
    libwebpextras: no
    
    Tools:
    cwebp : yes
      Input format support
      ====================
      JPEG : yes
      PNG  : no
      TIFF : yes
      WIC  : yes
    dwebp : yes
      Output format support
      =====================
      PNG  : no
      WIC  : yes
    GIF support : yes
    anim_diff   : no
    gif2webp    : no
    webpmux     : no
    vwebp       : no
    

    I assume I need png, but do I need anif_diff, gif2webp, webpmux and vwebp? As in, what is it used for in orx? I'm just wondering if the only dependency that shouldn't be built using other dependencies is libsndfile with ogg and vorbis.
  • edited April 2017
    Ah thanks for those references, I'll check them out (back with SDL 1.2, audio decoding was done by an external library, which was a bit annoying, hopefully they've changed it).

    Regarding libwebp, I forgot that there were so many options with that library. Actually we don't need the full library, only the static versions of libwebpdecoder (as we use it to decode webp images and we have stb_image for the other formats already).

    Sorry I didn't mention it earlier, I completely forgot it wasn't as straightforward as I remembered it!
  • edited April 2017
    After a quick check, unless I'm mistaken, both libsoundio and portaudio do not have file decoding features (they're used for playing the sound, but we already use openal/openal-soft for this).
    Cinder seems a bit overkill (it's a full framework after all) and I'll have to check SDL 2 to see if they support decoding without any external dependency (which could be nice as I was thinking of updating the SDL-based plugins as well, to see how they compare with GLFW nowadays).

    There's also SoLoud I've been wanting to try it for quite a while (to replace both openal and libsndfile at the same time), but it looks like Jari hasn't worked on it for a few months now. I'll poke him to see if it's just a pause or if he has abandoned it.
  • edited April 2017
    So just the decoder part, don't worry about png and co.? What about the encoding part, mux/demux, anim_diff, etc.?

    It's unfortunate those won't work as decoders. :huh:
  • edited April 2017
    Yep, just libwebpdecoder, nothing more. We only use it to load textures as WEBP isn't handled by stb_image itself.

    In addition to reading WEBP, orx also supports reading BMP, TGA, PNG, JPG, GIF, PIC & PNM and writing to BMP, TGA and PNG. Those cover most cases for game development. Are there some other formats you'd like to see supported?
  • edited April 2017
    Aside from maybe SVG I can't really think of anything.

    I've got LiquidFun building now, after a huge paradigm shift from autoconfig to cmake, and after having some fun with the combination of -Werror and -fPIC breaking the build. I've noticed there are two libraries, a regular and a debug. Did you have to manually append the d to the debug library, or did it build like that automatically? I assume not to worry about building freeglut?
  • edited April 2017
    SVG could be interesting, I've used nanoSVG in the past but I could probably integrate it to orx at some point.

    Regarding LiquidFun, I don't remember if I had to modify the project to have the -d suffix or if it came like that, sorry. And yes, no need to build the tests and/or freeglut.
  • edited April 2017
    So I'm on the last dependency now, openal. When configuring in cmake it's telling me it cannot find PortAudio, PulseAudio, JACK, and SDL2. It also says it couldn't execute qmake. Should I worry about any of these or are they not necessary?

    Edit: it builds as is, just curious. Also wondering if libcommon.a does anything and if libOpenAL32.a should just be renamed to libopenal32.a (is it just an arbitrary name, or is it a different build configuration)? I just like to double check with this sort of thing, make sure it's all correct.
  • edited April 2017
    This is going to be the interesting one. It'll need to find the dsound (directsound) backend, but it looks like it's trying to find the Linux backends instead.
    If it doesn't find the dsound backend, you'll have n audio.
    Not sure about qmake though.
    It shouldn't need renaming given that Windows is case insensitive, I'm not sure what case is currently used as I'm not on a computer.
  • edited April 2017
    As a side note, you'll also need ranlib to pack a few dependent libraries inside the glfw and openal ones. I'll have the details when I get on my computer later.
  • edited April 2017
    Well, it seems to have found directsound:
    -- Building OpenAL with support for the following backends:
    -- WinMM, DirectSound, MMDevApi, WaveFile, Null
    --
    -- Building with support for CPU extensions:
    -- Default, SSE, SSE2, SSE3, SSE4.1
    Maybe it just searches for any sound headers it can? I know it's looking in the correct directory because it's finding windows.h and not finding the ALSA includes which are in my linux includes but not mingw's.
    As a side note, you'll also need ranlib to pack a few dependent libraries inside the glfw and openal ones.
    How does that work exactly? Does it happen at compile time or is this just adding more things to the archive?
  • edited April 2017
    Well, then you're all set. Regarding the deps, here are the two little scripts I manually run after compiling:

    glfw.sh:
    ar xv libopengl32.a | cut -f3 -d ' ' | xargs ar rvs libglfw.a && rm *.o && echo 'done'
    

    openal.sh:
    ar xv libole32.a | cut -f3 -d ' ' | xargs ar rvs libopenal32.a && rm *.o && echo 'done'
    ar xv libcommon.a | cut -f3 -d ' ' | xargs ar rvs libopenal32.a && rm *.o && echo 'done'
    
  • edited April 2017
    So why exactly is ranlib needed for library injection?
  • edited April 2017
    Ok, here's the build script. I added two additional makefiles for glfw, but when I get the chance I'll change that to a "sed" command to temporarily modify an existing one. The zip mimics the structure of the orx directory, so all that's needed is to unzip and merge it with the orx build directory and run it. It should build everything correctly. My build machine is Linux Mint 18, so it assumes a Debian based system, I'm not sure if it will work on Fedora or some other distro. You may need to install some dependencies, like mingw-w64 in order to get it to work. Let me know if everything's configured properly, it seems to build both 32 and 64 bit dlls just fine, but so far that's untested.

    The other thing is I'm not sure if Freetype is building correctly anymore, since I added the external MXE libraries to the includes it's failed. I'll need to know if any other dependencies are necessary for that.

    PS. I had to modify your library injection commands a bit. https://forum.orx-project.org/uploads/legacy/fbfiles/files/orx-ab8cc8ba31ea5dc96e793b9209d79dc4.zip
  • edited April 2017
    krypto42 wrote:
    So why exactly is ranlib needed for library injection?

    To regenerate the archive indices (it's not part of the scripts I pasted, I usually run it on Windows manually whereas I use the scripts on Linux).
    Orx wouldn't build for me otherwise.
  • edited April 2017
    Ah I see. I added that to the script, and I ran a diff afterward, both with the generated libraries and the outputs given from using nm -s, but there was no difference. I'll keep it in there if it's different on other machines though.

    I also added parallelization to the make commands, so it'll build everything a bit faster. I've been looking into running each dependency's build commands in parallel (1 job for glfw, 1 for libsndfile, etc.) but I'm not quite sure how to do that yet while preserving the output. I've attached the updated script, let me know what you think.

    Should I keep the usage of the cmake toolchain files, or should I aim to get rid of them and make the build script itself the only file?

    Finally for completeness, even though I know it's not necessary for building orx itself, I have this when building freetype:
    Library configuration:
    external zlib: yes (pkg-config)
    bzip2: no
    libpng: yes (libpng-config)
    harfbuzz: no
    However, building fails due to something wrong with linking libpng. In any case, which ones are necessary for building freetype? https://forum.orx-project.org/uploads/legacy/fbfiles/files/build_deps.zip
  • edited May 2017
    Sorry for the delay, I completely missed your last post.
    Regarding CMake, it's really up to you. Which way do you feel would be the most maintainable?

    Regarding FreeType, I haven't compiled it in a very long time and I don't remember which deps I've used last time. I'm pretty sure libpng and harfbuzz wouldn't be needed for what we use it.
    I'll try to check it over the week.
  • edited May 2017
    It's ok. I had quite a bit of a delay myself due to life stuff that happened/still is happening.
    Well, having toolchain files is easier at the moment, although a single file for cross compiling would be ideal, just to minimize the number of files.
  • edited May 2017
    I agree with you, the less files, the simpler it usually gets.

    Good luck with your life events in any case!
  • edited August 2017
    Hello again!

    Life events are pretty much over now, and I'm slowly getting back into the swing of this.
    I've updated the build script again, so that it works without the 2 additional scripts.

    So far, orx builds for 32 and 64 bit versions of mingw when using an edited version of the generated windows codeblocks project. I'm currently trying to figure out a way to get premake4 to autogen gmake projects with the correct libraries and compiler options. I'm currently editing orx/code/build/premake4.lua for this, but I'm not all that familiar with modifying premake or writing lua scripts, so any help in that area would be appreciated.
  • edited August 2017
    Welcome back!

    I'm no expert in writing lua/premake files either however, if you could tell me what the final changes to the edited code::blocks project were, I could maybe help you figure out how to alter the premake files.
  • edited August 2017
    I managed to figure out how to get premake to work with it actually. The biggest problem was figuring out how to get a non standard compiler name to be generated in the compiler, since premake doesn't have very good cross compilation functionality yet, I handled it with a flag.

    I've attached the updated scripts, there's the dependencies one, then one for orx and finally the modified premake lua. Also, just to note this for future reference so I don't forget once everything's said and done, malloc.c requires redefining __forceinline specifically for mingw-w64, the reason being that it's original definition uses extern, which doesn't work with static, but changing it at the source causes other problems where the compiler thinks functions are getting defined multiple times on the same line of the same file. Apparently, this is a known workaround, see here. It's a little weird, but it works.

    The problem I'm seeing now though is that if the build script is run multiple times and you save the results and run a diff, the files differ. I'm wondering if it has something to do with premake generating make files :huh: https://forum.orx-project.org/uploads/legacy/fbfiles/files/build_scripts.zip
  • edited September 2017
    Hi krypto42, sorry for the late reply, I recently came back from vacation and only picked up orx yesterday.
    I'll have a look at what you posted over next weekend.
Sign In or Register to comment.