Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Forums

OverviewFelgo 3 Support (Qt 5) › How to access signals from dynamically created entities?

Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #8635

    Martin

    How do I specify a signal handler for a dynamically created entity?

    I am using this code (based on code from the examples):

                var newKeyProperties = {
                    x: keyEntryX,
                    y: keyEntryY,
                    velocity: Qt.point(0, 0)
                }
    
                console.log("adding key at x,y:", newKeyProperties['x'], newKeyProperties['y'])
                var new_key_id = entityManager.createEntityFromUrlWithProperties(
                            Qt.resolvedUrl("../entities/Key.qml"),
                            newKeyProperties);

     

    but I can’t see how to add a signal handler to the newKeyProperties: this is not syntactically correct:

                var newKeyProperties = {
                    x: keyEntryX,
                    y: keyEntryY,
                    velocity: Qt.point(0, 0),
                    onDropped: {
                        removeEntity()
                    }
                }

     

     

    • This topic was modified 9 years, 3 months ago by  GreenAsJade.
    #8643

    Christian
    Felgo Team

    Hi Martin,

    you cannot create signal handlers dynamically, instead implement the handler in our EntityBase, and you can toggle if it shall be used or not for example with a property that you define.

    Cheers, Chris

    #8644

    Martin

    How does this work if the signal to be handled

    • has to be handled differently in each level, and
    • the handling is to be done be logic within the level?

    The real example I face is that a Key (in this instance) knows when it has hit a Platform (both dynamically created instances).   This is detected in the Key’s collider’s onBeginContact.

    But the Key has no idea what is supposed to happen when it hits the Platform.   Only the level knows this.    One example of what might have to happen is a new Key drops in from the ceiling (this is in fact the case in the current level I am working on).

     

    • This reply was modified 9 years, 3 months ago by  GreenAsJade.
    • This reply was modified 9 years, 3 months ago by  GreenAsJade.
    #8653

    Martin

    I’ve readjusted my “game story” to not have to have level responses to dynamically created entity interaction, for now.

    I wonder if one workaround to get that interaction is to create the entities statically in QML with signal handlers as pooled entities, then remove them, so that later when they are grabbed from the pool on creation they have the handler?

    This brings up a “worrying” topic about pooled entities: it seems that their “state” is not reset upon reactivation.   For example, I had a pooled entitiy go to opacity 0 before removal … when it was “reused” it came back at opacity 0!

     

    #8663

    Alex
    Felgo Team

    Hi,

    the deactivation and reactivation needs to be handled in the onMovedToPool and onUsedFromPool signal handlers of the entity.

    Regarding your entities, I’m not quite sure how your exact game logic looks like, but maybe something like this could help you:

    As you said, the key detects the collision, so the key obviously knows all the actions that can happen to him, so what i like to do in this cases is having a distinct game logic object that can be accessed from the entities, with functions to handle those actions. This could look like this:

    GameLogic {
      function keyCollided(key,collidedWith) {
        // do something like this
        entityManager.removeEntityById(key.entityId)
      }
    }

     

    Scene {
      id: gameScene
    
      property alias gameLogic: gameLogic
      GameLogic {
        id: gameLogic
      }
    }

     

    EntitiyBase {
      id: entitiy
    
      // ...
    
      BoxCollider {
        // ...
        fixture.onBeginContact: {
          // actually physical bodies collide, to get the entity we have to navigate <body>.<fixture>.<collider>.<entity>
          var collidedEntity = other.parent.parent.owningEntity
          gameScene.gameLogic.keyCollided(entity,collidedEntity)
        }
      }
    }

    If the key collides with something, it tells the gameLogic that a collision happened, and passes a reference to himself and the collided entity. Now the gameLogic can access all items that participated in the action. If the actions are different in every level, consider moving the gameLogic to the different levels then.

    I hope this helps you 🙂

    Cheers,
    Alex

    #8813

    Martin

    Thanks for the suggestion – I made the problem “go away” for a while, so I only just got back to this.   I need to deal with it now.

    I hope you will understand what I mean when I observe that while this obviously works, its not “good” in the sense of “clean design”.

    signals exist to provide a clean interface between entities.   This solution breaks that: it requires that the scene instantiating the entity have a fixed name, and have a logic block with a fixed name as well.

    What if I need to use the entity in more than one “game scene”?   Maybe I want to make little display in my credits scene, for example?   Then the entity will not have a “gameScene” to refer to.

    I’ve worked out that I can actually achieve what I’m trying to do by using function-properties instead of signals:

    In my Grunt.qml:

    EntityBase {
        id: grunt
        entityType: "grunt"
    
        property var kickedNinja: function() {console.log("grunt kicked ninja - no further action")}
    
    
        
        fixture.onBeginContact: {
          # ... blah blah
    
         if (collidedEntityType == "ninja") {
                    var ninja = collidedEntity
                    if (ninja.kickState == "idle") {
                        console.log("Hah! (grunt kicks ninja)")
                        ninjaKicked.play()
                        kickedNinja()

     

     

    Where a change is needed statically (in QML) of a level:

        function highlightKickController() {
            jumpKickController.highlightKick = true;
        }
    
        Repeater {
            model: 3
            Grunt {
                x: blockPlatformLeft.x+blockPlatformLeft.width + width * index
                y: 0
                kickedNinja: highlightKickController
            }
        }

    And where it needs to be added to a dynamically created entity:

                    // make a new grunt
                    var newGruntProperties = {
                        y: gruntEntryY,
                        x: gruntEntryX,
                        kickedNinja: newKickedNinja
                    }
                    entityManager.createEntityFromUrlWithProperties(
                                Qt.resolvedUrl("../entities/Grunt.qml"),
                                newGruntProperties);

    where newKickedNinja is of course a function pointer passed into this routine by the level that wants to do something different.

    It’s kind of do-it-yourself signals ….

     

     

     

     

    • This reply was modified 9 years, 2 months ago by  GreenAsJade.
    • This reply was modified 9 years, 2 months ago by  GreenAsJade.
    #8831

    Alex
    Felgo Team

    Hi Martin,

    wow that’s an extremely nice workaround. I think this looks even cleaner than this approach: http://doc.qt.io/qt-5/qtqml-syntax-signals.html as you don’t even need the JavaScript code lines to connect, did you try that too?

    Especially the line
    relay.messageReceived.connect(sendToPost)
    could be what you needed.

    Cheers,
    Alex

    • This reply was modified 9 years, 2 months ago by  Alex.
Viewing 7 posts - 1 through 7 (of 7 total)

RSS feed for this thread

You must be logged in to reply to this topic.

Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded