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?
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.
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*()
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.
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.
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.
I haven't used that functionality of orx yet. What exactly would that allow?
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.
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.
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.
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:
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.
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.
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 inside the method BindObjects(), you can then have:
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.
Unfortunately no, it'll be handy to have nice visual effects though.
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.
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.
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!
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.
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? Using a GameEnemy class
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.
My pleasure. Groups can also be used for picking (orxObject_Pick/orxObject_BoxPick take an optional GroupID parameter).
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!).
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
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).
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 [[email protected]] 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:
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 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'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.
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:
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.
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.
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?
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.
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!
We don't support FLAC and we use stb_vorbis for ogg/vorbis.
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.
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?
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:
- 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:
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:
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.
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!
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.
It's unfortunate those won't work as decoders. :huh:
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?
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?
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.
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.
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.
How does that work exactly? Does it happen at compile time or is this just adding more things to the archive?
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
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.