[SOLVED] Set Nametag from random line in text file

edited November 2011 in Help request
I've been having relative success with Orx. Things have been actually super satisfying when it works! :3

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

  • edited November 2011
    Somewhere during my 2a haze last night, I came up with a potential solution but can't actually implement it right now because of work. HOWEVER, let me know if I'm getting along in the right direction:

    - 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.
  • edited November 2011
    So for the enemy tag, if you have a list of random names, you can do it from config, otherwise you'll have to hook your code via an event listener.

    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.
  • edited November 2011
    So for the enemy tag, if you have a list of random names, you can do it from config, otherwise you'll have to hook your code via an event listener.
    Oh really? This all sounds very intesting! I assumed random values only worked for number-y things such as positioning.
    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:
    [Spawner]
    Object = Enemy
    WaveSize = 1
    WaveDelay = 1
    ObjectSpeed = (-200, 0, 0)
    CleanOnDelete = True
    
    [EnemySpawner]
    Spawner = Spawner
    
    ...
    
    [Enemy]
    ChildList = zeEnemy#Word
    Position = (223, -179, 0) ~ (200, 50, 0)
    
    ...
    
    [Word]
    Graphic = WordWord
    Position = (50, 75, 0)
    Body = WordBody
    
    [WordWord]
    Text = WordString
    Color = (0, 0, 0)
    Pivot = center
    
    [WordString]
    String = rarrr!
    

    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.
  • edited November 2011
    rebthegreat wrote:
    Oh really? This all sounds very intesting! I assumed random values only worked for number-y things such as positioning.

    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:
    [MySpawner]
    Object = Enemy1 # Enemy2 # Enemy3
    
    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:
    [MyObject]
    Rotation = 0 ~ 180; <= MyObject will be created with any angle A with 0 <= A <= 180
    Rotation = 0 # 90 # 180; <= MyObject will be created with a random angle of 0, 90 or 180
    

    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.
    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:
    [Spawner]
    Object = Enemy
    WaveSize = 1
    WaveDelay = 1
    ObjectSpeed = (-200, 0, 0)
    CleanOnDelete = True
    
    [EnemySpawner]
    Spawner = Spawner
    
    ...
    
    [Enemy]
    ChildList = zeEnemy#Word
    Position = (223, -179, 0) ~ (200, 50, 0)
    
    ...
    
    [Word]
    Graphic = WordWord
    Position = (50, 75, 0)
    Body = WordBody
    
    [WordWord]
    Text = WordString
    Color = (0, 0, 0)
    Pivot = center
    
    [WordString]
    String = rarrr!
    

    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.

    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:
    [WordString]
    String = Rarr # rowrr # ra-cough cough # and so on!
    

    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:
    Config:
    [Names]
    FirstNames = Tom # Bob # Laurentius
    LastNames = Smith # Wesson # Quelaag
    
    Code:
    
    orxSTATUS orxFASTCALL MyEventHandler(const orxEVENT *_pstEvent)
    {
      if(_pstEvent->eType == orxEVENT_TYPE_OBJECT && _pstEvent->eID == orxOBJECT_EVENT_CREATE)
      {
        // Do a string compare to check if that's the object we want or push its section to check a boolean or any other way you have to see what kind of object it is
        if(...)
        {
          orxCHAR zFullName[128]; // Or whichever size you need
          orxConfig_PushSection("Names");
          orxString_Print(zFullName, "%s %s", orxConfig_GetString("FirstNames"), orxConfig_GetString("LastNames"));
          orxObject_SetTextString(orxOBJECT(_pstEvent->hSender), zFullName);
          orxConfig_PopSection();
        }
      }
      return orxSTATUS_SUCCESS;
    }
    

    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!
  • edited November 2011
    Also, note that all the config data doesn't have to be entered manually in a config file. It can be created and/or modified programmatically at runtime. That's especially useful when you need to have very repetitive config data entries that you could initialize more easily in code at the start of your game. You do so by using the orxConfig_Set* accessors.

    It's actually how I implement savegames in my own games or how orx stores customized inputs with orxInput_Save().
  • edited November 2011
    Ah, I understand. Yes, you definitely answered my question! The random list is super useful especially with 65k entries possible which is way more than enough.

    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.
  • edited November 2011
    rebthegreat wrote:
    I think this ought to be my last question:

    Keep them coming, I actually enjoy helping people around here. =)
    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?

    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.
    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.

    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?
  • edited November 2011
    [quote]Keep them coming, I actually enjoy helping people around here. =)[/quote]
    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
  • edited November 2011
    rebthegreat wrote:
    Oh, phew, good! I really like the framework and definitely want to keep using it so there'll be many more in the future.

    Yeah, I'd rather have people asking instead of getting frustrated and ultimately rage quitting as orx as a few unusual features.
    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.

    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.
    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?
    All keys unfortunately :

    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?
  • edited November 2011
    Would I have to initialize the keyboard to register a clock to it? There is "void orxFASTCALL orxKeyboard_Setup ()" and "orxSTATUS orxFASTCALL orxKeyboard_Init()". What is the difference between them?
    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:
    orxSTATUS orxFASTCALL StandAlone::Init() 
    {
    ...
    orxConfig_Load("Interaction.ini"); // load interactive bits
    orxInput_Load(orxSTRING_EMPTY); // reset input on level load
    ...
    orxEvent_AddHandler(orxEVENT_TYPE_INPUT, StandAlone::EventHandler);
    orxEvent_AddHandler(orxEVENT_TYPE_PHYSICS, StandAlone::EventHandler);
    orxEvent_AddHandler(orxEVENT_TYPE_OBJECT, StandAlone::EventHandler);
    ...
    orxCLOCK* ListeningClock = orxClock_Create( 0.2f, orxCLOCK_TYPE_USER );
    orxOBJECT* EnemyCat = GetObjectByName("Enemy");
    
    if( EnemyCat != orxNULL ){
    	orxClock_Register( ListeningClock, Update, EnemyCat, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);}
    
    return orxSTATUS_SUCCESS;
    }
    
    
    // nothing happened here
    orxSTATUS orxFASTCALL StandAlone::EventHandler(const orxEVENT* currentEvent)
    {
    	switch(currentEvent->eType) {
    	case orxEVENT_TYPE_INPUT:
    	{
    		orxINPUT_EVENT_PAYLOAD* EventPayload = (orxINPUT_EVENT_PAYLOAD*)currentEvent->pstPayload;	
    		const orxCHAR* EventAct;
    	
    		switch( currentEvent->eID )
    		{
    			case orxINPUT_EVENT_ON: EventAct = "pressed down"; break;
    			case orxINPUT_EVENT_OFF: EventAct = "released"; break;
    			default: return orxSTATUS_SUCCESS; // Remember to 'early return' here, as there are more than just the two events we've specifically handled right now.
    		}
    	
    		orxLOG("Input <%s> has been %s!", EventPayload->zInputName, EventAct );
    		break;
    	}
    	...
    	}
    }
    
    
    // nothing happened here
    void orxFASTCALL StandAlone::Update(const orxCLOCK_INFO* clockInfo, void* context)
    {
    	orxOBJECT* Object = orxOBJECT( context );
     
    	if( Object != orxNULL )
    	{
    		std::string ObjectName = orxObject_GetName( Object );
     
    		if( ObjectName.compare( "Enemy" ) == 0 )
    		{	
    			if( orxInput_IsActive( "ItemClear" ) ) {
    				std::cout << "INPUT HANDLED IN UPDATE" << std::endl;}
    		}
    	}
    }
    
  • edited November 2011
    rebthegreat wrote:
    Would I have to initialize the keyboard to register a clock to it? There is "void orxFASTCALL orxKeyboard_Setup ()" and "orxSTATUS orxFASTCALL orxKeyboard_Init()". What is the difference between them?

    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:
    void orxFASTCALL MyUpdate(const orxCLOCK_INFO *_pstInfo, void *_pContext)
    {
      orxKEYBOARD_KEY eKey;
    
      eKey = orxKeyboard_Read();
    
      if(eKey != orxKEYBOARD_KEY_NONE)
      {
        // Handles your key press here
      }
    }
    
    // And in your init function:
    
    orxClock_Register(orxClock_FindFirst(orx2F(-1.0f), orxCLOCK_TYPE_CORE), MyUpdate, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);
    
    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

    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. :)
    orxConfig_Load("Interaction.ini"); // load interactive bits
    orxInput_Load(orxSTRING_EMPTY); // reset input on level load
    

    @Interaction.ini@@) ? This way those two lines will get obsolete.
    orxCLOCK* ListeningClock = orxClock_Create( 0.2f, orxCLOCK_TYPE_USER );
    orxOBJECT* EnemyCat = GetObjectByName("Enemy");
    
    if( EnemyCat != orxNULL ){
    	orxClock_Register( ListeningClock, Update, EnemyCat, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);}
    

    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.
    // nothing happened here
    orxSTATUS orxFASTCALL StandAlone::EventHandler(const orxEVENT* currentEvent)
    {
    	switch(currentEvent->eType) {
    	case orxEVENT_TYPE_INPUT:
    	{
    		orxINPUT_EVENT_PAYLOAD* EventPayload = (orxINPUT_EVENT_PAYLOAD*)currentEvent->pstPayload;	
    		const orxCHAR* EventAct;
    	
    		switch( currentEvent->eID )
    		{
    			case orxINPUT_EVENT_ON: EventAct = "pressed down"; break;
    			case orxINPUT_EVENT_OFF: EventAct = "released"; break;
    			default: return orxSTATUS_SUCCESS; // Remember to 'early return' here, as there are more than just the two events we've specifically handled right now.
    		}
    	
    		orxLOG("Input <%s> has been %s!", EventPayload->zInputName, EventAct );
    		break;
    	}
    	...
    	}
    }
    
    
    // nothing happened here
    void orxFASTCALL StandAlone::Update(const orxCLOCK_INFO* clockInfo, void* context)
    {
    	orxOBJECT* Object = orxOBJECT( context );
     
    	if( Object != orxNULL )
    	{
    		std::string ObjectName = orxObject_GetName( Object );
     
    		if( ObjectName.compare( "Enemy" ) == 0 )
    		{	
    			if( orxInput_IsActive( "ItemClear" ) ) {
    				std::cout << "INPUT HANDLED IN UPDATE" << std::endl;}
    		}
    	}
    }
    

    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?
  • edited November 2011
    Wait your Update function isn't called either? Did it get registered correctly?
  • edited November 2011
    Oh, right, forgot to include those details
    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 :
    orxSTATUS orxFASTCALL StandAlone::Init()
    {
    	...
    	
    	orxEvent_AddHandler(orxEVENT_TYPE_INPUT, StandAlone::EventHandler);
    	orxEvent_AddHandler(orxEVENT_TYPE_PHYSICS, StandAlone::EventHandler);
    	orxEvent_AddHandler(orxEVENT_TYPE_OBJECT, StandAlone::EventHandler);
    	
    	orxCLOCK* ListeningClock = orxClock_Create(0.2f, orxCLOCK_TYPE_USER); 
    	orxClock_Register(ListeningClock, Update, orxNULL, orxMODULE_ID_MAIN, orxCLOCK_PRIORITY_NORMAL);
    	...
    	
    	return orxSTATUS_SUCCESS;
    }
    
    void orxFASTCALL StandAlone::Update(const orxCLOCK_INFO* clockInfo, void* context)
    {
    	// this doesn't get called
    	if(orxInput_IsActive("ItemClear"))	{
    		std::cout << "INPUT HANDLED IN UPDATE" << std::endl;}
    		
    	// this gets called
    	std::cout << "HEY! LISTEN! HEY! HEY! LISTEN!" << std::endl
    }
    
    // nothing happened here
    orxSTATUS orxFASTCALL StandAlone::EventHandler(const orxEVENT* currentEvent)
    {
    switch(currentEvent->eType) {
    case orxEVENT_TYPE_INPUT:
    {
    orxINPUT_EVENT_PAYLOAD* EventPayload = (orxINPUT_EVENT_PAYLOAD*)currentEvent->pstPayload;
    const orxCHAR* EventAct;
    
    switch( currentEvent->eID )
    {
    case orxINPUT_EVENT_ON: EventAct = "pressed down"; break;
    case orxINPUT_EVENT_OFF: EventAct = "released"; break;
    default: return orxSTATUS_SUCCESS; // Remember to 'early return' here, as there are more than just the two events we've specifically handled right now.
    }
    
    orxLOG("Input <%s> has been %s!", EventPayload->zInputName, EventAct );
    break;
    }
    ...
    }
    }
    

    I'm holding my breath for it to be something super silly on my end.
  • edited November 2011
    Mmh, yeah, if nothing's working, it's probably something very simple we're overlooking. I tested with snow leopard last night and all the keys were working fine for me, and so were clock updates.
    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. :)
  • edited November 2011
    I sped up my clock because 0.1f was running way to slow to pick up on super fast typing. The downside to that was that it would keep reading from the buffer so it was as if I pressed 'e' five times. So then at the end of my update function I put a orxKeyboard_ClearBuffer() the whole program just crashes. Am I using this function incorrectly?

    Maybe I'm just going about reading/listening for keyboard input all awkwardly:
    void orxFASTCALL StandAlone::Update(const orxCLOCK_INFO* clockInfo, void* context)
    {
    	orxKEYBOARD_KEY eKey = orxKeyboard_Read();
    
    	switch(eKey)
    	{
    		case orxKEYBOARD_KEY_A:
    		case orxKEYBOARD_KEY_B:
    		case orxKEYBOARD_KEY_C:
    		case orxKEYBOARD_KEY_D:
    		case orxKEYBOARD_KEY_E:
    		case orxKEYBOARD_KEY_F:
    		case orxKEYBOARD_KEY_G:
    		case orxKEYBOARD_KEY_H:
    		case orxKEYBOARD_KEY_I:
    		case orxKEYBOARD_KEY_J:
    		case orxKEYBOARD_KEY_K:
    		case orxKEYBOARD_KEY_L:
    		case orxKEYBOARD_KEY_M:
    		case orxKEYBOARD_KEY_N:
    		case orxKEYBOARD_KEY_O:
    		case orxKEYBOARD_KEY_P:
    		case orxKEYBOARD_KEY_Q:
    		case orxKEYBOARD_KEY_R:
    		case orxKEYBOARD_KEY_S:
    		case orxKEYBOARD_KEY_T:
    		case orxKEYBOARD_KEY_U:
    		case orxKEYBOARD_KEY_V:
    		case orxKEYBOARD_KEY_W:
    		case orxKEYBOARD_KEY_X:
    		case orxKEYBOARD_KEY_Y:
    		case orxKEYBOARD_KEY_Z:
    			lastKeyPressed = eKey;
    		break;
    	}
    
    	// emulates if(keyReleased), but it skips input read sometimes
    	if(lastKeyPressed != orxKEYBOARD_KEY_NONE)
    	{
    		if(!orxKeyboard_IsKeyPressed(lastKeyPressed))
    		{		
    			const orxSTRING stringEKey = orxKeyboard_GetKeyName(lastKeyPressed);
    			std::string theTypedKey = stringEKey;
    			theTypedKey.replace(0, 4, "none");
    			theTypedKey = UpToLow(theTypedKey);
    			typedTextOnScreen.append(theTypedKey);
    			
    			for(orxOBJECT *pstObj = orxOBJECT(orxStructure_GetFirst(orxSTRUCTURE_ID_OBJECT)); pstObj != orxNULL; pstObj = orxOBJECT(orxStructure_GetNext(pstObj)))
    			{
    				std::string ObjectName = orxObject_GetName(pstObj);
    
    				// update the typing area portion
    				else if(ObjectName.compare("Typing") == 0)
    				{
    					orxSTRING textToShow = (orxCHAR*)typedTextOnScreen.c_str();			
    					orxConfig_PushSection("TypingText");
    					orxObject_SetTextString(pstObj,textToShow);
    					orxConfig_PopSection();
    				}
    			}
    
    			lastKeyPressed = orxKEYBOARD_KEY_NONE;
    		}
    	}
    }
    
  • edited November 2011
    Ah, my questions are never-ending. I'm trying to get the Enemy's word stored in the config file via
    for(orxOBJECT *pstObj = orxOBJECT(orxStructure_GetFirst(orxSTRUCTURE_ID_OBJECT)); pstObj != orxNULL; pstObj = orxOBJECT(orxStructure_GetNext(pstObj)))
    {
    	if(ObjectName.compare("Enemy"))
    	{	
    		const orxSTRING enemyStoredWord;
    		orxConfig_PushSection("WordWord"); 
    		enemyStoredWord = orxConfig_GetString("WordWord"); 
    		std::cout << enemyStoredWord << std::endl;
    		orxConfig_PopSection(); 
    	}
    }
    


    ): 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
  • edited November 2011
    The last one is an easy one. There's no config entry 'WordWord' in the section 'WordWord'. :)
    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:
    orxGRAPHIC *pstGraphic = orxOBJECT_GET_STRUCTURE(pstNametagObject, GRAPHIC);
    orxTEXT *pstText = orxTEXT(orxGraphic_GetData(pstGraphic));
    const orxSTRING zEnemyTag = orxText_GetString(pstText);
    

    If that's the random list of words at the end of your config, it'll be:
    orxConfig_PushSection("WordString");
    const orxSTRING zEnemyWord = orxConfig_GetString("String");
    orxConfig_PopSection();
    
  • edited November 2011
    rebthegreat wrote:
    I sped up my clock because 0.1f was running way to slow to pick up on super fast typing. The downside to that was that it would keep reading from the buffer so it was as if I pressed 'e' five times. So then at the end of my update function I put a orxKeyboard_ClearBuffer() the whole program just crashes. Am I using this function incorrectly?

    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.
    	switch(eKey)
    	{
    		case orxKEYBOARD_KEY_A:
    		case orxKEYBOARD_KEY_B:
    		case orxKEYBOARD_KEY_C:
    		case orxKEYBOARD_KEY_D:
    		case orxKEYBOARD_KEY_E:
    		case orxKEYBOARD_KEY_F:
    		case orxKEYBOARD_KEY_G:
    		case orxKEYBOARD_KEY_H:
    		case orxKEYBOARD_KEY_I:
    		case orxKEYBOARD_KEY_J:
    		case orxKEYBOARD_KEY_K:
    		case orxKEYBOARD_KEY_L:
    		case orxKEYBOARD_KEY_M:
    		case orxKEYBOARD_KEY_N:
    		case orxKEYBOARD_KEY_O:
    		case orxKEYBOARD_KEY_P:
    		case orxKEYBOARD_KEY_Q:
    		case orxKEYBOARD_KEY_R:
    		case orxKEYBOARD_KEY_S:
    		case orxKEYBOARD_KEY_T:
    		case orxKEYBOARD_KEY_U:
    		case orxKEYBOARD_KEY_V:
    		case orxKEYBOARD_KEY_W:
    		case orxKEYBOARD_KEY_X:
    		case orxKEYBOARD_KEY_Y:
    		case orxKEYBOARD_KEY_Z:
    			lastKeyPressed = eKey;
    		break;
    	}
    

    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.
  • edited November 2011
    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.

    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!
  • edited November 2011
    Glad that worked!

    Are you still using the release or did you decide to switch to the svn version?
  • edited November 2011
    We're all systems go with the SVN version!
Sign In or Register to comment.