help removing all objects

Hello, I setup orx this weekend and am really enjoying it....everything works as advertised so far.

My basic questions is - what is the recommended way to iterate through all orxOJBECTS and remove them (for exiting a level of game play, for example). More context below:

I've setup a simple system to allow navigation between various "levels" - for example, a main menu with ability to quit or proceed to Level 1. My Level 1 is a simple Space Invaders style game. While this level is in play, I want the user to be able to hit Esc to return to the main menu. This works fine, but I'm having trouble getting rid of all of the objects used in level1 before switching to the main menu. So a couple of questions:

To remove objects, I'm using orxObject_SetLifeTime(MyObject, 0);

It works well for removing objects I have references to, but I'm curious if that is the orx-like way to do it, or if there another recommendation.

To remove children of a parent object (my enemy fleet is composed of a single object with a bunch of children enemy objects), I've found how to iterate through the children and set their lifetimes to 0, so that works well to remove my enemies when the user returns from level 1 to the menu.

The problem is with my player's missiles...they are setup with a simple spawner that activates when the spacebar is pressed (pretty much the same as in the Beginner's guide). If I launch a bunch of missiles then return to the menu, I'm not sure how to find those objects and remove them since I don't have references to them.

Sorry for the long-winded message. I assume there must be a master list of objects that can be iterated for this purpose, but I haven't found it in the short amount of time I've spent looking around.

Thanks!

Comments

  • edited November 2019

    Hi Funemaker, welcome to using orx!

    Yes you are correct, that using setlifetime is the recommended safe way to remove objects.

    And for your spawned child objects, it is possible to set the spawner to remove all objects when itself is destroyed with the CleanOnDelete property: https://wiki.orx-project.org/en/orx/config/settings_structure/orxspawner

  • edited November 2019

    Hi @funemaker and welcome here!

    As @sausage mentioned, you want to look at CleanOnDelete for auto-cleanup of spawned objects upon spawner's deletion. That being said, objects are also deleted by their owner, so if you're using the ChildList property, it'll set both the parenting and the ownership, which means deleting the parent will automatically delete all the children (then you shouldn't have to do it yourself).

    The recommended way for cleaning up batches of objects is definitely to use that property (the ownership). As an example, in Little Cells, I clean all the spawned particles by simply having them set as "owned" by a container, then during the game over phase, I simply delete that single container and all remaining particles (whose spawners were already gone), are cleaned instantly.

    Regarding level handling, we're in the process of making a new sample video on that topic. The video isn't ready yet but you can already check the project itself: https://github.com/orx/SceneSwap

    You'll notice that all the scenes are a single object and their transition is also handled by another object. It might not fit your needs but it might give you some ideas of handling it mostly on the data side.

  • Great, thanks very much guys. The ownership property sounds like a very simple way to go! I'll look forward to seeing how you handle the SceneSwap...my current method is code driven, ie, I've got a SceneBase class and the levels inherit from that. The main orx update loop simply passes control to the current scene object's update function and then checks if that scene has requested a change to another scene. It works well for me but I'm always open to other approaches!

    thanks again!

  • edited November 2019
    As long as you find a way that works for you, that's the important part. I tend to go for the data driven approach as I like the runtime flexibility it brings, especially if I want to experiment new things or add some debug stuff without having to rebuild. Or if I'm just feeling lazy and I want the artists/designers to be able to work without having to rely on me. :)
  • Thanks @iarwain. I'm interested in using the orx approach, but it isn't always clear how to go about doing certain things. As an example, I've got a parachute that drops every now and then from a spawner, works fine. I'd like to add a very simple rotation to it, back and forth so it looks sort of like floating. (not talking about anything fancy, super simple rotate a few degrees clockwise, rotate back the other way, repeat). In looking over the examples, I think I could maybe do this with an FX slot and perhaps use a looping timeline? I feel like given what I've seen there must be a way to set that up. If you have a suggestion or can point me to a similar example it would be great. This is one of those things I can do in code, would be nice to use the orx approach. Thanks!

  • edited November 2019

    Hi @funemaker,

    Sure, a FX would do a great job for that effect. Let's try something. Start a new orx project using the command init parachute. Build it with your favorite IDE. If you run it, you should just get a plain orx logo with some color effect.
    Now go to parachute/data/config and replace the content of parachute.ini with:

    [Display]
    Title           = parachute
    FullScreen      = false
    Decoration      = false
    Smoothing       = true
    VSync           = true
    
    [Resource]
    Texture         = ../data/texture
    Sound           = ../data/sound
    
    [Input]
    SetList         = MainInput
    
    [MainInput]
    KEY_ESCAPE      = Quit
    
    [Viewport]
    Camera          = Camera
    
    [Camera]
    FrustumWidth    = 1280
    FrustumHeight   = 720
    FrustumFar      = 2
    FrustumNear     = 0
    Position        = (0, 0, -1) ; Objects with -1 <= Z <= 1 will be visible
    
    [Object]
    TrackList       = CursorTrack
    Spawner         = @
    Object          = Parachute
    WaveSize        = 1
    WaveDelay       = 1
    
    [CursorTrack]
    0               = > Mouse.GetPosition, > Render.GetWorldPosition <, Object.SetPosition ^ <
    Loop            = True
    ; Moving Object under the mouse cursor
    
    [Parachute]
    Pivot           = center top
    Graphic         = @
    Texture         = logo.png
    HSL             = (0.33, 0.9, 0.8) ~ (0.66, 0.9, 0.8)
    Scale           = 0.2
    Rotation        = -30
    Speed           = (0, 50)
    LifeTime        = 15
    FXList          = Reel
    
    [Reel]
    Loop            = true
    SlotList        = @ ; Single slot FX
    Type            = rotation
    Curve           = sine
    StartTime       = 0
    EndTime         = 2
    StartValue      = 0
    EndValue        = % > Get Parachute Rotation, * < -2
    ; We're dynamically getting `-2 * Parachute.Rotation`, which makes it easier to tweak the effect in a single place
    

    Restart the executable and you should now (hopefully) get something close to what you expected. Every second, a "parachute" will spawn from the cursor's position.

    From there, we can tweak a lot of things, like de-syncing the parachute movements, etc... but I won't get into those unless you're asking for it. ;)

    Hope this helped and don't hesitate if you have any other questions!

  • Wow @iarwain , thanks so much for this! I don't have time to look at it yet, but will do soon. I'll let you know how it goes.

  • Just tried it...very nice. This is indeed very elegant and powerful. I need to look over the ini entries and see if I can understand how this works.

    thanks again, very much!

  • My pleasure, hope it'll help.
    Don't hesitate if you have any questions regarding the config data above. The last two sections being the most interesting ones in your case.
  • So the only fuzziness for me is the last line that sets the end value of the fx.

    Is there documentation for the syntax? It isn't familiar to me. I find that if I use a value of 60 for the end, I get pretty much the same effect. I think I understand how that works assuming the rotation is in degrees, but not sure about what the the original line is doing.

    ;EndValue = % > Get Parachute Rotation, * < -2
    EndValue = 60

    thanks

  • edited November 2019

    Yes, you can use 60 directly by hand. It's only a convenience to help you tweak in a single place.
    Let's say you want a smaller angle of 20, instead of having to set Rotation to -20 on Parachute and the EndValue to 40 on the FX, you would simply have to change the object Rotation to -20.

    You might have stumbled upon commands in orx. Those can be typed in the interactive console (quake-style) or by using timeline tracks on objects (which is a time sequencer that can run commands, among other things).

    Well, commands can also be used directly from config. There's a little section at the top of CreationTemplate.ini about it:

    ; Commands can be used in order to get more dynamic contents, they'll be prefixed by `%`.
    ; A sequence of multiple commands can be expressed by separating them with `,`.
    ; There are two ways to define embedded commands:
    ; - Commands evaluated at load time, not tied to any specific property. These will be evaluated once, when the file is loaded. Example:
    ;   % > Get OtherSection BaseValue, + < 1, Set NewSection ValuePlusOne <
    ; - Commands that are lazily evaluated every time the value of a property is retrieved. Example:
    ;   Key = % MyOwnCommand 42
    ; In this second case, when more than a single command is defined, the property's value will be the result returned by the last one.
    ; Example:
    ; MyOtherKey = % log "Fetching dynamic content of MyOtherKey", * 21 2; Fetching MyOtherKey will return 42
    ; Lazy commands can also be embedded inside lists.
    ; Example:
    ; Key = 1 # % + 2 3 # 10; Fetching Key will return either 1, 5 or 10
    

    In our case, it's the second kind we're using: a lazily evaluated sequence of commands (using % as the first character on the value side). It contains two commands:

    • > Get Parachute Rotation, which retrieves the value of the key Rotation in the section Parachute, and pushes its result on the stack (>)
    • * < -2, which multiplies (*) the top value popped from the results stack (<) by -2, in our case -30 * -2 = 60

    If this seems too complex, you can stick with simply using a hardcoded numeric value for now, until commands feel more familiar. But know that, in addition to all the commands already defined by orx, you can also define your own commands and have them called directly by the config system, making the whole system very flexible and powerful.

  • Ah yes, you can get a list of all the commands by opening the console at runtime by pressing the backtick/tilde key and running Commands.ListCommands and the aliases with Commands.ListAliases.
    Then for any command, you can get their prototype with help <command_name> or ? <command_name>
    More details can be found on the wiki.

  • @iarwain Great, thanks. It makes sense and so easy to tweak the angle if needed with that line instead of the hard coded 60 vs -30. I applied the effect to my actual parachute very easily and it looks good. I'll try the console ListCommands sometime to see what I can learn.

  • My pleasure, I'm glad it was helpful!

  • I'm really enjoying using orx so far. Hopefully this is an easy one - I've set my Display to fullscreen. I then set my camera Frustum width and height based on that. I'd like to be able to set the position of objects relative to those dimensions...for example, to place a blocking pillar at the right edge of the screen. For now I've hard coded positions to look ok on my laptop.

    The various ways I've tried to specify this in the Position= line of an object don't seem to work. Assuming this can be done in the ini file, how would you set an object position's x value at the screenwidth - 100 (for example)

    thanks again for all the help!

  • I'll have a solution that should work perfectly in your case, however do you think you could post this question as a separate thread instead? That'd make it easier for people with similar questions to find their answer later on and that improves global searchability.
  • Absolutely, I'll do it now.

  • Thanks a lot! I'll reply a bit later when I'm back in front of a computer. :)
Sign In or Register to comment.