QML - 可翻转的矩形动画有一个bug

时间:2018-02-18 13:46:17

标签: qt animation qml

我使用此示例:QML Flipable Example。 我用GridLayout创建了矩形。我刚刚添加了我的新状态示例:

states: [
      State {
        name: 'back'
        PropertyChanges { target: rotation; angle: 180 }
        when: flipable.flipped
      },
      State {
        name: 'remove'
        PropertyChanges {
          target: card
          visible: false
        }
      }
    ]

我想要点击矩形,检查矩形,打开它们是否相同。我的算法算法:

property int card1: -1
property int card2: -1
property int remaining: 20

function cardClicked(index) {
  var card = repeater.itemAt(index); // Selected card
  if (!card.flipped) { // If selected card is not opened
    card.flipped = true; // Open card
    if (card1 === -1) {  // If card is first selected card
      card1 = index; // Set first selected card
    } else { // If selected card is not first card, I mean that is second card because first card is already selected
      card2 = index; // Set second card
      area.enabled = false; // Disabled GridLayout (area)
      delayTimer.start(); // Start `Timer` QML component
    }
  } else { // If card is opened so, close that card, because that card is opened and player clicked its
      card.flipped = false; // Close that card
      card1 = -1; // first card is not selected
  }
}

function validateCards() {
  var state = ''; // Default state: Close cards
  if (imageIndexes[card1] === imageIndexes[card2]) { // If first card and second card are equal, you found same cards :)
    state = 'remove'; // You found cards so, remove cards
    --remaining; // If this equals 0, you found all cards
  }
  // If cards are not same, close cards but if they are same remove them
  repeater.itemAt(card1).state = state; 
  repeater.itemAt(card2).state = state;
  card1 = -1; // first card is not selected
  card2 = -1; // second card is not selected
  area.enabled = true; // Enabled area (GridLayout)
  if (remaining === 0) { // If you found all cards, game over
    console.log('Game Over!');
  }
}

我将MouseArea添加到Rectangle s:

MouseArea {
  anchors.fill: parent
  onClicked: cardClicked(index) // This index belongs to my `Repeater`.
}

我为动画设置Timer以正常工作并检查卡片:

  Timer {
    id: delayTimer
    interval: 1000
    onTriggered: validateCards()
  }

此示例和动画运行良好但有时它们无法正常运行: qml_flip_animation_bug.gif
如何解决这个动画错误?

更新!
您可以在here上找到所有源代码。

1 个答案:

答案 0 :(得分:1)

我认为您通过使用计时器使应用程序变得复杂,因为您不知道项目是否已完成更改其位置,因此在完成翻转字母时执行该任务是合适的。

我在您的代码中看到的另一个错误是您正在分配state = ""

我修改了以下部分:

<强> GameArea.qml

GridLayout {
    [...]
    property variant imageIndexes: GameUtils.generateCardIndexes(
                                       imageCount, repeatCount)

    property int lastIndex : -1


    Repeater {
        id: repeater
        model: 40
        Card {
            id: card
            backImageSource: 'qrc:/images/img_' + area.imageIndexes[index] + '.jpg'
            onFinished: verify(index)
        }
    }

    function verify(index){
        if(lastIndex == -1){
            lastIndex = index
            return
        }
        area.enabled = false
        var lastItem = repeater.itemAt(lastIndex)
        var currentItem = repeater.itemAt(index)

        if(lastItem.backImageSource === currentItem.backImageSource){
            lastItem.state = "remove"
            currentItem.state = "remove"
        }
        else{
            lastItem.flipped = false
            currentItem.flipped = false
        }
        if(repeater.model === 0){
            console.log("Winning")
        }
        lastIndex = -1
        area.enabled = true
    }
}

<强> Card.qml

Item {
    [...]        
    property alias state: flipable.state
    signal finished()

    Flipable {
        [...]
        transitions: Transition {
            NumberAnimation { target: rotation; property: 'angle'; duration: 400 }
            onRunningChanged: {
                if ((state == "back") && (!running))
                    finished()
            }
        }

        MouseArea {
            anchors.fill: parent
            onClicked: card.flipped = true
        }
    }
}

可以在以下link

找到完整的代码