Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved How to gain the speed of a moving component

    QML and Qt Quick
    3
    6
    337
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • tomy
      tomy last edited by

      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
          }
      }
      
      
      Bhushan_Sure ODБOï 2 Replies Last reply Reply Quote 0
      • Bhushan_Sure
        Bhushan_Sure @tomy last edited by

        @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.

        tomy 1 Reply Last reply Reply Quote 1
        • ODБOï
          ODБOï @tomy last edited by

          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) {
          
          tomy 1 Reply Last reply Reply Quote 1
          • tomy
            tomy @Bhushan_Sure last edited by

            @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)
                    }
                }
            }
            
            1 Reply Last reply Reply Quote 0
            • tomy
              tomy @ODБOï last edited by

              @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
                          }
                  }
              }
              
              1 Reply Last reply Reply Quote 0
              • tomy
                tomy last edited by tomy

                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.

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post