Dear Felgoteam,
I implemented a Dog-entity, which is moving via KI by using PathMovement for a game and it worked (mostly) correct.
But since we integrated it into the main project, which contains all the other entities and game logic it isn’t working anymore at all.
Here are the errors which occur constantly in a loop:
file:///C:/VPlayWorkspace/Try03/qml/entities/Dog.qml:51:5: QML PathMovement: Binding loop detected for property “waypoints”
file:///C:/VPlayWorkspace/Try03/qml/levels/Level1.qml:14:5: QML Dog: Binding loop detected for property “actualPosX”
The first error refers to the PathMovement of the Dog-Entity and the second error refers to this line of the code: Dog { id: dog; row: 0; column: 0;} in Level1.qml.
But I have no idea, where the binding loop could actually be comming into beginning.
Here is the code of the relevant entities:
Dog.qml (Code worked in a different project)
import QtQuick 1.1
import VPlay 1.0
EntityBaseDraggable {
id: dog1
entityType: "dog"
property real gridSize: gameScene.fieldsize
x: column * gridSize + gridSize/2
y: row * gridSize + gridSize/2
width: gridSize
height: gridSize
property int column
property int row
property int randomNumber
property bool upWay;
property bool rightWay;
property bool downWay;
property bool leftWay;
property int xPoint: 1
property int yPoint: 0
property int actualPosX: column * gridSize
property int actualPosY: row * gridSize
property bool done: false
property int wayCame: 0
// these properties must be set for EntityBaseDraggable
selectionMouseArea.anchors.fill: dogImg
selectionMouseArea.onPressAndHold: removeEntity()
MultiResolutionImage {
id: dogImg
width: parent.width
height: parent.height
rotation: 90
source: "../img/dog/dog1_straighttail-hd.png"
x: -gridSize/2
y: -gridSize/2
}
BoxCollider {
id: collider
width: parent.width
height: parent.height
bodyType: Body.Static
x: -gridSize/2
y: -gridSize/2
}
PathMovement {
velocity: 100
rotationAnimationDuration: 200
waypoints: [
{ x: actualPosX + gridSize/2, y: actualPosY + gridSize/2},
{ x: xPoint*gridSize + gridSize/2, y: yPoint*gridSize + gridSize/2}
]
onWaypointReached: {
column = xPoint
row = yPoint
console.debug("DEBUG: xPoint: " + xPoint + " yPoint: " + yPoint)
chooseDirection()
move()
}
onPathCompleted: {
start()
}
}
function chooseDirection() {
leftWay = true
rightWay = true
upWay = true
downWay = true
// checking for border
if (column === 0) {
leftWay = false
console.debug("DEBUG: Border is left")
}
if (column === 12) {
rightWay = false
console.debug("DEBUG: Border is right")
}
if (row === 0) {
upWay = false
console.debug("DEBUG: Border is up")
}
if (row === 8) {
downWay = false
console.debug("DEBUG: Border is down")
}
// checking for border of joystick
if ((row > 5) && (column === 9)) {
rightWay = false
console.debug("DEBUG: Border is right - joystick")
}
if ((row === 5) && (column > 9)) {
downWay = false
console.debug("DEBUG: Border is down - joystick")
}
// checking which way the dog came and blocking it
switch (wayCame) {
case 1: // came from up
upWay = false
console.debug("DEBUG: Way came is up")
break
case 2: // came from right
rightWay = false
console.debug("DEBUG: Way came is right")
break
case 3: // came from down
downWay = false
console.debug("DEBUG: Way came is down")
break
case 4: // came from left
leftWay = false
console.debug("DEBUG: Way came is left")
break
}
// checking for tree (wall)
var selectedBody
var entity
selectedBody = physicsWorld.bodyAt(Qt.point((xPoint-1)*gridSize + gridSize/2, yPoint*gridSize + gridSize/2))
console.debug("DEBUG: checked position for wall - xPoint: " + (xPoint-1) + " yPoint: " + yPoint)
if (selectedBody) {
entity = selectedBody.parent.parent//.parent.parent
console.debug("DEBUG: There is a entity at the dog's LEFT and it's a " + entity.entityType)
if (entity.entityType === "wall") {
leftWay = false
console.debug("DEBUG: There is a tree at the dog's LEFT")
}
}
selectedBody = physicsWorld.bodyAt(Qt.point((xPoint+1)*gridSize + gridSize/2, yPoint*gridSize + gridSize/2))
console.debug("DEBUG: checked position for wall - xPoint: " + (xPoint+1) + " yPoint: " + yPoint)
if (selectedBody) {
entity = selectedBody.parent.parent//.parent.parent
console.debug("DEBUG: There is a entity at the dog's RIGHT and it's a " + entity.entityType)
if (entity.entityType === "wall") {
rightWay = false
console.debug("DEBUG: There is a tree at the dog's RIGHT")
}
}
selectedBody = physicsWorld.bodyAt(Qt.point(xPoint*gridSize + gridSize/2, (yPoint-1)*gridSize + gridSize/2))
console.debug("DEBUG: checked position for wall - xPoint: " + xPoint + " yPoint: " + (yPoint-1))
if (selectedBody) {
entity = selectedBody.parent.parent//.parent.parent
console.debug("DEBUG: There is a entity at the dog's UP and it's a " + entity.entityType)
if (entity.entityType === "wall") {
upWay = false
console.debug("DEBUG: There is a tree at the dog's UP")
}
}
selectedBody = physicsWorld.bodyAt(Qt.point(xPoint*gridSize + gridSize/2, (yPoint+1)*gridSize + gridSize/2))
console.debug("DEBUG: checked position for wall - xPoint: " + xPoint + " yPoint: " + (yPoint+1))
if (selectedBody) {
entity = selectedBody.parent.parent//.parent.parent
console.debug("DEBUG: There is a entity at the dog's DOWN and it's a " + entity.entityType)
if (entity.entityType === "wall") {
downWay = false
console.debug("DEBUG: There is a tree at the dog's DOWN")
}
}
// freeing the direction the dog came from if it's the only way left to go
if (!upWay && !rightWay && !downWay && !leftWay) {
switch (wayCame) {
case 1: // came from up
upWay = true
console.debug("DEBUG: freeing the way up")
break
case 2: // came from right
rightWay = true
console.debug("DEBUG: freeing the way right")
break
case 3: // came from down
downWay = true
console.debug("DEBUG: freeing the way down")
break
case 4: // came from left
leftWay = true
console.debug("DEBUG: freeing the way left")
break
}
}
}
function move() {
while (done === false) {
randomNumber = utils.generateRandomValueBetween(1, 4)
console.debug("Random number created: " + randomNumber)
switch (randomNumber) {
case 1: // go up
if (upWay) {
yPoint--
wayCame = 3 // is comming from down the next field
done = true
}
break
case 2: // go right
if (rightWay) {
xPoint++;
wayCame = 4 // is comming from left the next field
done = true
}
break
case 3: // go down
if (downWay) {
yPoint++
wayCame = 1 // is comming from up the next field
done = true
}
break
case 4: // go left
if (leftWay) {
xPoint--
wayCame = 2 // is comming from right the next field
done = true
}
break
}
}
done = false
}
}
Level1.qml
import QtQuick 1.1
import VPlay 1.0
import "../entities"
Item {
id: level1
property string levelName: "Level1"
property alias startfield: startfield
property alias fox: fox
property int pawPrintSum: 11
property int wallSum: 14
property alias dog: dog
Dog { id: dog; row: 0; column: 0;}
Fox { id: fox; row: startfield.row; column: startfield.column }
Startfield { id: startfield; row: 6; column: 6 }
Wall { row: 1; column: 1 }
Wall { row: 2; column: 1 }
Wall { row: 5; column: 1 }
Wall { row: 1; column: 2 }
Wall { row: 5; column: 2 }
Wall { row: 6; column: 2 }
Wall { row: 1; column: 3 }
Wall { row: 3; column: 3 }
Wall { row: 6; column: 3 }
Wall { row: 7; column: 3 }
Wall { row: 2; column: 4 }
Wall { row: 3; column: 4 }
Wall { row: 6; column: 4 }
Wall { row: 7; column: 4 }
Way { row: 6; column: 1 }
Way { row: 7; column: 1 }
Way { row: 8; column: 1 }
Way { row: 2; column: 2 }
Way { row: 3; column: 2 }
Way { row: 4; column: 2 }
Way { row: 8; column: 2 }
Way { row: 5; column: 3 }
Way { row: 8; column: 3 }
Way { row: 1; column: 4 }
Way { row: 1; column: 5 }
}
and the GameScene.qml, where the level is loaded:
import VPlay 1.0
import QtQuick 1.1
import "entities"
SceneBase {
id:gameScene
height: 640
width: height/9*13
anchors.centerIn : window.center
focus: true
Keys.forwardTo: twoAxisController
property int fieldsize: gameScene.height/9 //gridSize
property int wallsize: fieldsize/20
// the name of the current level gets stored here
property string activeLevelString
// the current level gets stored here
property variant activeLevel
property int respawnColumn
property int respawnRow
property int pawPrintSum
property int wallSum
property variant fox
property variant dog
property alias controller: controller
BackgroundImage {
source: "img/forestground.png"
anchors.fill: parent
}
EntityBase {
TwoAxisController {
id: twoAxisController
}
// BoxCollider {
// width: 60
// height: 40
// force: Qt.point(twoAxisController.yAxis*8000, 0)
// torque: twoAxisController.xAxis*2000
// }
}
PhysicsWorld {
gravity.x: 0
gravity.y: 0
}
// Dog {
// column: 5
// row: 3
// xPoint: 6
// yPoint: 3
// }
Border {
// bottom wall
height: fieldsize
y: gameScene.height
anchors.left: gameScene.left
anchors.right: gameScene.right
}
Border {
// left wall
x: -fieldsize
width: fieldsize
height: gameScene.height
}
Border {
// right wall
x: gameScene.width
width: fieldsize
height: gameScene.height
}
Border {
// top wall
y: -fieldsize
height: fieldsize
width: gameScene.width
}
Border {
// joystick top wall
height: fieldsize
width: fieldsize * 3
x: fieldsize * 10
y: fieldsize * 6
}
Border {
// joystick left wall
width: fieldsize
height: fieldsize * 3
x: fieldsize * 10
y: fieldsize * 6
}
JoystickControllerHUD {
id: controller
anchors.bottom: parent.bottom
anchors.right: parent.right
width: gameScene.height/3; height: gameScene.height/3
joystickRadius: gameScene.height/7
z: 1
// do not show the HUD when in release build on desktop
visible: !(!system.debugBuild && system.desktopPlatform)
source: "img/joystick_background.png"
thumbSource: "img/joystick_thumb.png"
onControllerXPositionChanged: { }
onControllerYPositionChanged: { }
}
// state: "levelEditing" enables dragging and clicking of obstacles
// change the state in the next line to start in levelEditing mode:
state: "playing" //state: "levelEditing"
onStateChanged: {
if(state === "levelEditing") {
//stopGame()
}
}
function stopGame() { //needs to be modified in actual game ^^
// remove all entities of type "tree", but not the walls
entityManager.removeEntitiesByFilter(["wall"]);
}
LevelEditor {
id: levelEditor
toRemoveEntityTypes: [ "wall" ]
toStoreEntityTypes: [ "wall" ]
}
Column {
anchors.right: parent.right
spacing: 5
SimpleButton {
text: gameScene.state === "playing" ? "Level Mode" : "Game Mode"
onClicked: {
if (text === "Level Mode") {
gameScene.state = "levelEditing"
} else {
gameScene.state = "playing"
}
}
anchors.right: parent.right
}
BuildEntityButton {
visible: gameScene.state === "levelEditing"
toCreateEntityType: "entities/Wall.qml"
width: 50
height: 50
anchors.right: parent.right
// the obstacle is just a grey entity, we can customize the look of the button here
Rectangle {
color: "purple"
anchors.fill: parent
}
}
}
// load levels at runtime
Loader {
id: loader
source: "levels/" + gameScene.activeLevelString + ".qml"
onLoaded: {
// do not forget to call loadItemWithCocos or the item might not be displayed!
loadItemWithCocos(item)
activeLevel = item
item.width = gameScene.width
item.height = gameScene.height
respawnColumn = activeLevel.startfield.column
respawnRow = activeLevel.startfield.row
pawPrintSum = activeLevel.pawPrintSum
wallSum = activeLevel.wallSum
fox = activeLevel.fox
dog = activeLevel.dog
findCorrectImagesWayWall()
}
}
function findCorrectImagesWayWall() {
var array = entityManager.getEntityArrayByType("way")
var i
for (i = 0; i < pawPrintSum; i++) {
array[i].findImages()
}
array = entityManager.getEntityArrayByType("wall")
for (i = 0; i < wallSum; i++) {
array[i].findImages()
}
}
// set the name of the current level, this will cause the Loader to load the corresponding level
function setLevel(level) {
activeLevelString = level
}
function countPawPrint() {
pawPrintSum--
// console.debug(pawPrintSum)
}
}
I hope you can help me with my issue and I thank you in advance for a quick response (it’s an urgent matter).
Best regards,
PanflamCutie