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

Forums

OverviewFelgo 1 Support › Dynamically changing the parent of a QML item

Viewing 13 posts - 1 through 13 (of 13 total)
  • Author
    Posts
  • #3997

    Christian
    Felgo Team

    Hi,

    in QML, it is possible to change the parent of an item.

    But with V-play and the cocos renderer, this doesn’t work the way I’m doing it, especially when it comes to the z-order of those items.

    What I’m doing is this:

    I have a level which has a grid of tiles, and some other elements.
    When I load another level, i want to reuse all the tiles in the grid, so i don’t have to destroy all the entities, and then re-create them.
    But when I do this, all the other items appear on top of the tiles that i have re-used. When I enable the QML renderer, everything’s displayed correctly.

    So my question is, is it intended to be possible to change the parent of an item in V-play, or do i have to find another way to do this?

    Here’s how I’m trying to to this:

    t.parent = level

    With t being the tile that is re-used, and level being the new level that is being loaded.

    Later in the code i call

     window.loadItemWithCocos(level)

    So that the cocos item gets loaded, but it still seems the tiles all are under their old parent.

    Thanks for all the support in advance,
    Chrisu

    #4077

    Christian
    Felgo Team

    Hi Chrisu,
    reparenting is currently not supported in Felgo.

    It seems like you could use the entity pooling concept for your use-case: if you derive your Tiles component from EntityBase and use the poolingEnabled property: http://doc.felgo.com/qml-components-vplay1-entitybase.html#poolingEnabled-prop

    Our games Squaby and Chicken Outbreak use this concept too.

    Does that help?

    Cheers,
    Chris

    #4078

    Christian
    Felgo Team

    EDIT: Didn’t see your post up there.

    OK I’ll have a look at the pooling, thanks.

    #4079

    Christian
    Felgo Team

    The problem is that the cocos representation was not created for this item when you call loadItemWithCocos().

    The much easier and cleaner road would be to use entity pooling as the entityManager would then take car of all these issues – is that not an option?

    #4081

    Christian
    Felgo Team

    Pooling seems to give it a good performance boost, but I’m getting some really weird results with z-ordering.

    Could it be that the sorting of the items isn’t invoked when using them from the pool?

    After loading some levels, it looks like this:

    So the tiles probably have their old z-index.

    #4083

    Christian
    Felgo Team

    PS: And with every time i re-load the level, it gets screwed up further. My guess is, that the items are re-used in a random order, and that the z-index doesn’t get sorted correctly (it is set correctly in QML).

    #4084

    Christian
    Felgo Team

    Do you set the new z order when you re-create the tiles for the new level? I.e. do you call something like

    createEntityFromUrlWithProperties(Qt.resolvedUrl("EntityUrl.qml"), { "z": newZValue})

    You could debug print the z order after the creation call if it displays the correct one with the following code:

    var entityId = createEntity...();
    var entity = entityManager.getEntityById(entityId);
    console.debug("new z value of created entity:", entity.z);

    You set the z value based on your row and column number right?

    #4085

    Christian
    Felgo Team

    Quote from Christian on January 3, 2013, 21:03
    Do you set the new z order when you re-create the tiles for the new level?

    The z value is a dynamic property with the formula

    z: row * 25 + level * 5 + priority

    So when I print the z values after loading a level, it’s correct:

    tile at 0/0.z: 5
    tile at 1/0.z: 0
    tile at 2/0.z: 0
    tile at 3/0.z: 0
    tile at 4/0.z: 0
    tile at 5/0.z: 0
    tile at 6/0.z: 0
    tile at 7/0.z: 0
    tile at 8/0.z: 0
    tile at 0/1.z: 30
    tile at 1/1.z: 25
    tile at 2/1.z: 25
    tile at 3/1.z: 25
    tile at 4/1.z: 25
    tile at 5/1.z: 25
    tile at 6/1.z: 25
    tile at 7/1.z: 25
    tile at 8/1.z: 25
    tile at 0/2.z: 55
    tile at 1/2.z: 50
    tile at 2/2.z: 50
    tile at 3/2.z: 50
    tile at 4/2.z: 50
    tile at 5/2.z: 50
    tile at 6/2.z: 50
    tile at 7/2.z: 50
    tile at 8/2.z: 50
    tile at 0/3.z: 80
    tile at 1/3.z: 75
    tile at 2/3.z: 75
    tile at 3/3.z: 75
    tile at 4/3.z: 75
    tile at 5/3.z: 75
    tile at 6/3.z: 75
    tile at 7/3.z: 75
    tile at 8/3.z: 75
    tile at 0/4.z: 105
    tile at 1/4.z: 105
    tile at 2/4.z: 105
    tile at 3/4.z: 100
    tile at 4/4.z: 105
    tile at 5/4.z: 105
    tile at 6/4.z: 105
    tile at 7/4.z: 105
    tile at 8/4.z: 105

    With the first index being the column, the second being the row.
    So every row has higher z values than the row above it, and if the item is at a higher level (which is the “3rd dimension” in my game), it’s also a bit higher.
    This is the same when using pooling, or when not using pooling (but without everything is displayed correctly)

    But it still looks like in the screenshot.

    #4088

    Christian
    Felgo Team

    Did you test if the row and column get modified correctly by adding this debug output for example:

    onZChanged: console.debug("new z value for tile at", column, "/", row, ".z:", z) 

    Could you post the source code for your dynamic level creation, and how you remove it?

    #4090

    Christian
    Felgo Team

    Quote from Christian on January 3, 2013, 21:21
    Did you test if the row and column get modified correctly by adding this debug output for example:

    onZChanged: console.debug("new z value for tile at", column, "/", row, ".z:", z) 

    Yes that’s exactly what produced my output that I posted earlier.

    console.debug( "tile at " + t.col + "/" + t.row + ".z: " + t.z)

    I think what the problem is, that the items that get loaded from pool don’t get assigned the new parent item correctly, and now they are behind all the other items.

    I remove the level items with entity manager:

    entityManager.removeEntitiesByFilter(["game_item", "base_tile"])

    Where “base_tile” is the entityType of the grid of tiles that should always be there, and “game_item” are items that can be placed on top of the tiles, like the player and the block you see in the screenshot.

    Then i create a new level via

     function doLoadFromFile() {
            comp = Qt.createComponent(fileName);
            if (comp.status == Component.Ready)
                finishCreation();
            else
                comp.statusChanged.connect(finishCreation);
        }
    
        function finishCreation() {
            if (comp.status == Component.Ready) {
                item = comp.createObject(loader.parent, {});
                if (item == null) {
                    console.log("Error creating object:", comp.errorString());
                } else {
                    isLoaded = true
                    loaded()
                }
            } else if (comp.status == Component.Error) {
                console.log("Error loading component:", comp.errorString());
            }
        }
    

    And then in the loaded() signal handler i call a function which loads the tiles into the level:

        function load() {
            var test = ""
            for(var j = 0; j < rows; j++) {
                for(var i = 0; i < columns; i++) {
                    var ind =i + j * columns
                    var c = 0
                    if(ind < tz.length && tz[ind] != ' ') {
                        c = tz[ind]
                    }
                    var  t = entityManager.getEntityById(
                                    entityManager.createEntityFromComponentWithProperties(
                                        tileC, {index: ind, itemHeight: c, level: c, entityId: "tile" + ind}))
                        test += "tile at " + t.col + "/" + t.row + ".z: " + t.z + "\n"
                }
            }
    }

    The component to load tiles looks like this:

        Component {
            id: tileC
    
            Tile {
                property int base_tile: 0
                property int index: 0
                entityType: "base_tile"
                id: tile
                col: game.level ? index % game.level.columns : 0
                row: game.level ? (index - col) / game.level.columns : 0
                level: 0
            }
        }

    Where tile is derived from GameItem, which is derived from EntityBase.

    The QML for the levels that get loaded with the dynamic component looks something like this:

    BaseLevel {
        tz: "100000000100000000100000000100000000111011111"
        Player{ col:0; row: 0; level:2; itemHeight: 1}
        Gem{ col:8; row: 4; level:1; itemHeight: 0}
        Gem{ type: 2; col:0; row: 4; level:1; itemHeight: 0}
        Block{ col:3; row: 0; level:1; itemHeight: 1}
       // Rock{col:3; row: 4; level:1; itemHeight: 1}
    
    }
    

    With tz being the data which levels the tiles should have, and the children are all items that are derived from GameItem, that are placed into the level on top of the tiles.
    BaseLevel is the base type for the levels which has some properties like rows and columns for the size of the level, and more.

    #4093

    Christian
    Felgo Team

    I’m not sure what you are doing in the level loading with these calls:
    1. comp = Qt.createComponent(fileName);
    2. item = comp.createObject(loader.parent, {});

    How do you load the dynamic levels – with the Loader element?

    Also, which entitContainer did you set for the EntityManager? All the entities get placed as child of this element and you should not remove it. So instead of replacing the entityContainer, use the same one.

    You could additionally use the onZChanged slot for debuggin the z changes, as it indicates when the game.level item might get changed.

    #4094

    Christian
    Felgo Team

    Quote from Christian on January 3, 2013, 22:41
    I’m not sure what you are doing in the level loading with these calls:
    1. comp = Qt.createComponent(fileName);
    2. item = comp.createObject(loader.parent, {});
    .

    I made a LevelLoader element which loads the levels like this. It’s from a QT tutorial on how to create dynamic items.
    http://doc.qt.digia.com/qt/qdeclarativedynamicobjects.html

    Quote from Christian on January 3, 2013, 22:41
    How do you load the dynamic levels – with the Loader element?
    All the entities get placed as child of this element and you should not remove it. So instead of replacing the entityContainer, use the same one.
    .

    Ah so that could be the problem – i always delete the entityContainer and make a new one.
    Then i should probably try to avoid this?

    #4095

    Christian
    Felgo Team

    Yes please.. Also have a look at Squaby please, which has level loading of qml files and also by using the storing feature of the EntityManager for user-generated levels.

Viewing 13 posts - 1 through 13 (of 13 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