我编写了一个“游戏”,其中一个球被发送到墙上反弹。 在伤害墙壁之前,y上的行为是一个春天动画。当它伤到墙壁时,球应该反弹并且有一个线性运动。
我的问题是我无法阻止初始行为。 我试过几种方法: - 禁用行为,但正在进行的运动继续 - 停止SpringAnimation:我有错误:“QML SpringAnimation:setRunning()不能在非根动画节点上使用。”
这是代码
Rectangle {
id: ball
property bool enableMoving: false
function newMousePos(mX,mY){
if(enableMoving){
ball.x = mX - ball.width/2
ball.y = mY - ball.height/2
}
}
Behavior on x {enabled: true;id: behavX; SpringAnimation {id:spX; spring: 0.8; damping: 0.9; mass: 10; } }
Behavior on y {enabled: true;id: behavY; SpringAnimation {id:spY; spring: 0.8; damping: 0.9; mass: 10 ; } }
onXChanged: {
if(ball.x>main.width-ball.size) {
console.log("wall 2 ")
spX.stop(); spY.stop()
}
if(ball.x<0) {
...
}
}
onYChanged: {
...
}
Timer{
id:timerDisableMoving
interval: 500; running:true
onTriggered: enableMoving=false
} }
我不明白为什么我无法阻止这种行为。是否有可能在状态上定义行为以解决问题?
感谢您的帮助
答案 0 :(得分:0)
当球击中墙壁时,将此代码置于信号上:
behavX.enabled = false
这将禁用行为(我已在我的项目中测试过它)。
如果您只想禁用特定动画,请按以下方式执行:
spX.running = false //ignore this, it is equivalent to spX.stop()
我只是认为你可能会推出这样的代码:
function disableBehavior()
{
behavX.enabled = false
//...
behavX.enabled = true
}
如果是这种情况,那么它将无法正常工作因为在执行期间动画不会发生。 相反,你应该进行异步调用,例如:
function disableBehavior()
{
behavX.enabled = false
//...
myTimer.start()
}
//...
Timer
{
id: myTimer
interval: 1
running: false
onTriggered:
{
behavX.enabled = true
stop()
}
}
但是,我认为你需要在“线性行为”完成后调用“行为启动器”(而不是创建新的计时器)。
答案 1 :(得分:0)
我认为,我也有类似的问题。我有一些行为,可以改变某些属性。而且我希望能够在中间尚未完成的情况下将其停止。
它没有用。顺便说一句,QML还在控制台中抱怨我试图在非root动画上使用某种方法。
简短答案: 行为似乎不支持将其停止在中间。
但是,可以通过为属性设置新值来中断它。这将重新启动动画以定位新值。当我意识到这一点时,就实现了这样的“停止”功能:
function stopAnimation() {
// disable animation for the next value change
moveBehavior.enabled = false
// Change value of the property of interest.
// This stops currently running animation
y += 1
// Restore initial value of the property
y -= 1
// Enable animation for subsequent property changes
moveBehavior.enabled = true
}
因此,我禁用了该行为以使属性更改立即生效。然后,将目标属性更改为非常接近当前值的值(我相信我不能使用相同的值,因为这样一来,将不会发出“ onChange”信号)。此时,应停止运行动画。然后,我将属性重置为其原始值。然后再次启用动画以处理进一步的属性更改。
看起来不太好,但是它对我的行为有帮助...
经过更多思考后,我得出结论,我可能不应该使用行为。然后,我刚刚创建了PropertyAnimation {},将它直接关联到需要移动的对象中我感兴趣的属性。然后,我只是动态分配目标值和持续时间,现在“ start()”和“ stop()”可以按预期工作。
完整的解决方案如下所示(它可以做什么,您可能会发现):
Item {
id: root
focus: true
Rectangle {
id: racket
height: 40
width: 10
x: 20
y: 20
color: "blue"
property int maxY: 460
// ...
PropertyAnimation {
id: moveDownAnimation
target: racket
property: "y"
to: racket.maxY
// if you want constant velocity, you need
// to calculate duration dynamically based
// on desired velocity and distance
duration: 1000
}
function moveUp () { // just return racket to the initial position
y = 50
}
function moveDown() {
moveDownAnimation.start()
}
function stopAnimation() {
moveDownAnimation.stop()
}
}
Keys.onPressed: {
if (event.isAutoRepeat) {
return
}
if (event.key === Qt.Key_Q) {
racket.moveUp() // return to initial position
} else if (event.key === Qt.Key_A) {
racket.moveDown()
}
}
Keys.onReleased: {
if (event.isAutoRepeat) {
return
}
if (event.key === Qt.Key_A) {
racket.stopAnimation()
}
}
}