How to gain the speed of a moving component



  • Hi all,

    In the simple QML program below we have a ball moving from left to the right side of the window. The goal is to know how fast the ball goes.

    For that I wrote the code below. We firstly get the time at which the ball starts to move, and then the time it hits the right side of the window. Then using the Newton's equation (x = vt) we try to gain the speed, but it doesn't show that speed! :(
    How to gain that purpose please?

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.5
    
    Window {
        id: window
        visible: true
        width: 1000; height: 800
        color: "royalblue"
        property real colTime_1: new Date().getTime()
        property real colTime_2
        property real speed
        
        Rectangle {
            id: ball
            x: window.x + 50; y: window.y + 50
            width: 18; height: 18
            color: "white"
            radius: width/2
        }
        
        onFrameSwapped: {
            ball.x += 5
            ball.y += 3
            if (test()) console.log("Speed = ", speed)
        }
        
        function test(){
            if(ball.x >= window.x + window.width) {
                colTime_2 = new Date().getTime()
                speed = window.width / (colTime_2 - colTime_1)
                return true
            }
            return false
        }
    }
    
    


  • @tomy Hey, I will suggest you to use "Timer" and "Animation" Component.
    Timer for :- How fast your ball should move.
    Animation:- for smooth moving from one point to other.



  • hi,
    @tomy said in How to gain the speed of a moving component:

    but it doesn't show that speed

     if(ball.x >= /* window.x  */ + window.width) {
    


  • @Bhushan_Sure
    hi, thanks for your suggestions.

    Timer for :- How fast your ball should move.

    We don't want to apply how fast the ball "should" move, but how fast the ball "is" moving! :)

    Animation:- for smooth moving from one point to other.

    It's indeed onFrameSwapped:'s body code which moves the ball. Of course we can alter the velocity of that movement when needed.

    The program needs to obtain the speed of a component, to use it for the velocity of another component.

    Think of a Pong game you play tomorrow for example. Why will sometimes the ball move slowly, and some other times move quickly? Because you hit it with different speed. I,e,. when you hit the ball with a bat at a higher speed, it goes faster, otherwise slower. Agree?
    Therefore, to give the ball the proper velocity, we need to know how fast it has been hit by the bat. We need that velocity of the bat to put the same to the ball. The faster hit the faster the ball moves and vice versa.
    Did you get my intention, please?
    In the real program we need the speed of the bats (when hitting the ball), but I put this simple program here which deals with the same matter (speed) so that it's more easily understood by the readers and on the other hand, since the answer is relevant to the other program, I can use it for that.
    So for the current program, if we can achieve the speed, it might be the exact solution for the other (bigger) program.

    To have a sense of the issue with the other program you can read this:
    For that other (bigger) program, I thought of a loop or something else to wait for a little while (about less than a second). We firstly save the y coordinate of the bat when collision occurs between the ball and that bat. (y1). Then we set another coordinate as y2 = y1 + 5. At this point we have the distance (y2 -y1). We also have the time of collision. (t1) But when also need the time when the bat reaches y2. For that we can make use of the "loop or something else" we mentioned above. If we can make the bat reaches that y2 point by such a loop, we then have distance (5), time (less than a second), and we can obtain the velocity of the bat to use it for the ball too.
    I hope it is comprehensible.

    I changed the code the following way to gain that speed, but it still doesn't work as expected. :(
    Also, I put the racket to be on the right hand side, but it's on the land side!! Why?

    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        id: window
        visible: true
        width: 1000; height: 800
        color: "royalblue"
        property real colTime_1: new Date().getTime()
        property real colTime_2
        property real speed
    
        Rectangle {
            id: ball
            x: window.x + 50; y: window.y + 50
            width: 18; height: 18
            color: "white"
            radius: width/2
        }
        Rectangle {
            id: bat
            width: 15; height: 40
            anchors.right: window.right
            anchors.rightMargin: 30
            y: window.width / 2
            color: "red"
        }
    
          // Move the ball
        onFrameSwapped: {
            ball.x += 5
            ball.y += 3
        }
    
        
        property real ballHitsWall: ball.x
        
          // catch the collsion
        onBallHitsWallChanged: {
            if (ball.x >= window.x + window.width) {
                colTime_2 = new Date().getTime()
                speed = window.width / (colTime_2 - colTime_1)
                console.log("Speed = ", speed)
            }
        }
    }
    


  • @LeLev
    Yes, thank you, it solved the issue. :)

    Below is the waiting loop I was talking about. Everything is fine seemingly. When the collision occurs, the while loop terminates and the function returns true but in reality it crashes, I don't know why! :(

    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        id: window
        visible: true
        width: 1000; height: 800
        color: "royalblue"
        property real colTime_1: new Date().getTime()
        property real colTime_2
        property real speed
        
        Rectangle {
            id: ball
            x: window.x + 50; y: window.y + 50
            width: 18; height: 18
            color: "white"
            radius: width/2
        }
        
        // Move the ball
        onFrameSwapped: {
            ball.x += 5
            ball.y += 3
        }
        
        Component.onCompleted: {
            if (catchColTime()) console.log("Speed = ", speed)    
        }
        
        function catchColTime() {
            while(true)
                if (ball.x >= window.width) {
                    colTime_2 = new Date().getTime()
                    speed = window.width / (colTime_2 - colTime_1)  
                    return true
                }
        }
    }
    


  • I also tried to use Connections as below. Here is the code having the similar issue with the bigger program.

    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        id: window
        visible: true
        width: 1000; height: 800
        color: "royalblue"
        property real colTime_1: new Date().getTime()
        property real colTime_2
        property real speed
        property bool check: false
        property bool hits: false
    
        Rectangle {
            id: ball
            x: window.x + 50; y: window.y + 50
            width: 18; height: 18
            color: "white"
            radius: width/2
        }
    
        // Move the ball
        onFrameSwapped: {
            ball.x += 5
            ball.y += 3
        }
    
        Component.onCompleted: {
            hitsRightWall()
        }
    
        function hitsRightWall() {
            check = true
            if (hits) {
                hits = false
                console.log("Speed = ", speed)
                return true
            }
            return false
        }
    
        Connections {
            enabled: check
            target: ball
            onXChanged :{
                if (ball.x == window.width) {
                    colTime_2 = new Date().getTime()
                    speed = window.width / (colTime_2 - colTime_1)
                    hits = true
                }
            }
        }
    
    }
    

    Unfortunately, we still need a loop or something that checks that collision not only for one time but periodically for one second at least!

    The function hitsRightWall() is called by some other part of the code but here to simulate that, we've used Component.onCompleted: { hitsRightWall() }.
    As you see, when hitsRightWall() is called, it makes check true, and "at the same time" tests hits in the if condition. So it will probably never returns true this way. (hits initially is false).
    What we need is something inside hitsRightWall() that waits for one second to see whether hits becomes true or not, and after that tests the if condition.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.