I've been having relative success with Orx. Things have been actually super satisfying when it works!
I'm at the point in my game where when an enemy spawns I want to give it a random name tag from any line in a text file. I'm not quite sure where to actually start on this. Can the enemy.ini file read from a function in my StandAlone.cpp? The other way I was thinking about it was on enemy creation the objecthandler assigns it a name.
Thanks for all your help!
Comments
- Set up an orxEVENT_TYPE_SPANWER event handler listening for orxOBJECT_EVENT_CREATE
- Read file, get nametag
- Set the text with orxObject_SetTextString()
- Have a beer
I was reading in the forums that the hSender is an orxSPAWNER and not orxOBJECT, correct?
----
Lastly, if I wanted to keep track of these enemies with randomly assigned nametags that I could access and compare later what would be the best way to go about this? I was thinking an array of pointers but there might be something better that's built into Orx.
You're right about the hSender of spawner events: it's an orxSPAWNER. Be careful not to mix up events: orxEVENT_TYPE_SPAWNER events will always begin by orxSPAWNER_EVENT_. and not by orxOBJECT_EVENT_. In this case you either want to listen to the spawner event orxSPAWNER_EVENT_SPAWN or simply on the object event (orxEVENT_TYPE_OBJECT) orxOBJECT_EVENT_CREATE. This one has the orxOBJECT in hSender.
If you use the macro helpers for casting (ie. orxOBJECT(hSender) / orxSPAWNER(hSender)) they'll return orxNULL if the type's wrong.
So my advice is to do exactly what you listed except you want to listen for orxEVENT_TYPE_OBJECT and not orxEVENT_TYPE_SPAWNER.
If you want to keep a list of ennemies, there are many ways to do so. Array of pointer would work, so would an orxHASHTABLE (using the pointer as both key and value). Also you can go through all the created objects by calling orxStructure_GetFirst(orxSTRUCTURE_TYPE_OBJECT)/_GetNext). But that will be every object, not just your enemies so you might want to put a boolean to recognize them either in your own enemy structure/class that you attach to the orxOBJECT (orxObject_SetUserData()) or in a config section that has this random name.
In that case, on creation you'd do orxConfig_PushSection(MyRandomName) / orxConfig_SetBool("IsEnemy", orxTRUE) / orxConfig_PopSection(). And when going through the collection of orxOBJECTs, you'd push the config section from the name tag and test if the boolean is set. Unless you have thousands of enemies at once, I think this shouldn't have any noticeable performance impact.
Last option would be to volunteer to test Scroll (beta). There's a thread in the forum about Scroll: it's a thin C++ layer written on top of orx that brings nice features like automated C++ class binding to objects, an embedded level editor, the concept of levels plus a few shortcuts (some events are wrapped in virtual functions, etc...). Scroll is under zlib too but as it's still beta (and changing regularly) and I didn't get the chance to write a proper doc, I haven't released it publicly. It's only a thin layer though, so no precompiled stuff.
Cool, I'd love to after finishing this demo (on a tight deadline)!
Hm, I was reading on the forums about updating text objects and I think I succeeded in only confusing myself. Am probably missing out on a simple concept. I have an enemy config file such as:
I'm not quite sure how to iterate through the containers to get the Text portion in order to set it during the event handler.
Well there are two types of random values in config: random list and random range.
Random range is define with Value1 ~ Value2 and can take any value inside that range. This, as you mentioned, only works with numerical values.
Lists, on the other hand, are defined this way Item1 # Item2 # ...
If the property expects an explicit list, no random will take place (like ChildList, for example). In orx, all the properties expecting a list have the suffix List, so no surprise there.
However, if the property expects only a single value, then the item will be chosen randomly in the list. Ex: Every time that spawner is triggered it'll either spawn an Enemy1, Enemy2 or Enemy3 object.
It's also a way to control numerical randomness. Ex:
Now, for your own config needs, you can explicitly get a value in a list with orxConfig_GetListFloat("MyValue", iIndex), for example. Whereas if you call orxConfig_GetFloat("MyValue") on a property that is defined as a list, you'll randomly get one element from that list.
If all your nametags can be defined in a config list (remember that a config list can have a maximum of 65535 items in it, which should be more than enough for everybody needs, but I'd prefer pointing it out, just in case), you'd define:
If you want to create names on the fly, by, let's say, combining a random first name and a random last name, here's what you'd do:
As I wrote that code in the forum editor, it might not compile but you get the idea.
Now that I reread your question, I wonder if that's the answer you were expecting. If not, just let me know!
It's actually how I implement savegames in my own games or how orx stores customized inputs with orxInput_Save().
I think this ought to be my last question:
I want to always be listening for alphanumeric keyboard input. User types 'a', A is handled, buffer cleared. User types Q, Q is handled and so forth. Since there's a limit of only 4 key-bindings per set how would I go about setting up a keyboard object/listener/frankenstein-beast.
I noticed OrxKeyboard in the API. Would I couple it with the input-listener if orxInput_IsActive() returns false?
---
Also, side-note: while compiling & running the project in osx the keys don't seem activate to while in Windows it's just fine. KEY_RSHIFT = ItemClear does nothing.
Keep them coming, I actually enjoy helping people around here.
Mmh, it really depends what you want to achieve. Can you give us more details?
If you want to handle text input, for example, you should access the keyboard API directly instead of going through the input module. The orxKeyboard_Hit()/Read()/ClearBuffer() should be what you need in that case. No event though, you'll have to poll them in a clock update function, for example.
Mmh, troubling. Does it happen with other keys too? I'll try it on my side either tonight or tomorrow. Which version of orx are you using?
Oh, phew, good! I really like the framework and definitely want to keep using it so there'll be many more in the future.
[quote]Mmh, it really depends what you want to achieve. Can you give us more details?[/quote]
Oh, silly me! I totally forgot to explain what I was trying to accomplish. My objective is to make a typing game (ex: Mavis Beacon, Mario Teaches Typing, etc) so you start typing and then it finds the enemy with the word in it.
I'm thinking that in the Update function (which i had completely forgotten about) always poll orxKeyboard_Hit(), read it, find the enemy object with the matching nametag then assigned it as the target.
[quote]Mmh, troubling. Does it happen with other keys too? I'll try it on my side either tonight or tomorrow. Which version of orx are you using? [/quote]
All keys unfortunately :","BBCode
Yeah, I'd rather have people asking instead of getting frustrated and ultimately rage quitting as orx as a few unusual features.
Ah I see. Yes, in that case you might want to poll the keyboard module directly. You can have as many Update function as you want by registering them to a clock (clocks can have any tick size and can also do time stretching). I'd recommend not doing any game code in the Run() function you register to orx's init though, as this one hasn't a consolidated DT and that can result in unwanted side effects.
You don't need to call orxKeyboard_Hit(), simply call the other one and check the return code.
Ah, that's weird. I know at least the keys I use in orx's bounce demo are working on my macbook. Which version of orx and osx are you using?
I looked at it further and it seems input isn't being handled whatsoever in osx even mouse clicks. Tested on my macbook and an imac at work. My ini file is pretty simple:
[Input]
SetList = TypingInput
[TypingInput]
KEY_ESCAPE = GamePause
KEY_LEFT = ItemClear
MOUSE_LEFT = ItemClear
KEY_SPACE = ItemClear
Maybe osx didn't like something in here and Windows does:
Ah yes, my bad, this asks for more details. So, those two functions are internal to orx. If you want the details, every module in orx has 3 functions: Setup, Init and Exit. Setup is where the dependencies are defined. Based on the dependency graph that we obtain in the end, we know which modules should be initialized in which order and this way we can call Init/Exit for all modules as needed (it also allows to run with only a subset of modules and do hotloading of modules, but that's another story ).
What I meant was to register an Update function of yours. If you don't have any timing needs and simply want to have your update function called once per frame, you can use orx's main core clock. Something like:
It is indeed simple. However I'd really like to know what version of orx you are using (svn? release package?) and which version of osx.
@Interaction.ini@@) ? This way those two lines will get obsolete.
Ah I see you already know how to create/handle clocks, so ignore the beginning of my post then.
However, you can have the clock created automatically from config by using the Clock property on the object and then retrieve your clock by its name to register whichever function you want on it.
Mmh, that'd mean that your input aren't correctly loaded maybe? What text encoding did you use for your config file, just in case?
orx release version: 1.3rc0
osx version: Tested with Leopard and Snow Leopard
windows version: Latest Windows (I lost track of the name)
I double checked with simpler code and still no dice :
I'm holding my breath for it to be something super silly on my end.
Is your init function called correctly? What does the orxClock_Register() function return? Are you using the orx_Execute() function helper or are you using your own main loop? Is your Run callback called? What's your favorite color?
That should be enough questions for now.
Maybe I'm just going about reading/listening for keyboard input all awkwardly:
): nothing comes out. Config:
[Word]
Graphic = WordWord
Position = (50, 75, 0)
Body = WordBody
[WordWord]
Text = WordString
Color = (0, 0, 0)
Pivot = Center
[WordString]
String = some # list # of # words
Font = SilomFontBig
What do you actually want to retrieve from the config?
If it's your nametag, you can get it from the object itself. I didn't wrap the get accessor for it in the object module, so you'll have to retrieve it manually like this:
If that's the random list of words at the end of your config, it'll be:
Do you have the log of the crash? It's definitely not supposed to crash when you call that function. However you're using a version of orx that's really getting outdated and I'd advise syncing the SVN version. There are many bugfixes and improvements made since the latest release and it compiles out of the box as long as you sync the full /trunk folder.
That long switch statement can be replaced by a eKey >= orxKEYBOARD_KEY_A && eKey <= orxKEYBOARD_KEY_Z, btw.
If you only care about those characters actually and you want the key release, you might as well disregard my last recommendation and actually use the input module. If you create one input per key (you can either do it in config or programmatically when your game loads), you can simply listen for the orxINPUT_EVENT_OFF which would be your key release and then check for the input name and tadaa, you have your key press. If you want to register it when it gets pressed instead of released, simply listen to the _ON event instead. You can also poll the status of your inputs in a loop but you'll have to loop through all the inputs which can be a bit more tedious than simply listening to an event.
Also by doing so, you get a bonus feature: you can have a tutorial or a bot playing by activating the inputs in code (orxInput_SetValue() function) and the same listening code will handle it exactly as if the physical keys have been pressed on the keyboard.
Oh! I thought I had already tried that and for some reason it didn't work so that's why I was going through the whole business of clocks listening for typing. Probably because I was assigning them all the same "input name" or some other. This solution works great!
Are you still using the release or did you decide to switch to the svn version?