Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Offer me a good QML exercise
Forum Updated to NodeBB v4.3 + New Features

Offer me a good QML exercise

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
41 Posts 4 Posters 14.8k Views 3 Watching
  • 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.
  • J.HilkJ J.Hilk

    @tomy
    first of let me tell you, as a person with slight ocd-issues, the fact that your indenting is off, is driving me nuts x)

    Anyway:

    you define a function nextPos() and insinde the function-body you try to define a ParallelAnimation item and NumberAnimation items. That can't work.

    only calculate assign values&properties in functions! Not new items.
    In C++ you would, kind of, get way with it, but defenitly not in QML :-)

    tomyT Offline
    tomyT Offline
    tomy
    wrote on last edited by
    #17

    @J.Hilk
    Sorry, I don't know if there is an option that offer automatic indenting on Qt Creator. Do you mean the code looks ugly? :-)

    Anyway,
    The functions Math.random() and nextPos() and if-condition are fixed:

    import QtQuick 2.8
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 800
        height: 600
        title: qsTr("The Ping Pong game")
    
        Rectangle {
            id: root
            width: 700; height: 500
            border.width: 10
            border.color: "black"
            color: "royalblue"
            property int duration: 1000
            property real xPos: root.width
            property real yPos: Math.random() * root.height
    
       Racket {
           id: redRacket
           x: 630; y: 100
           color: "red"
       }
    
       Racket {
           id: blackRacket
           x: 50; y: 100
           color: "black"
       }
    
       Ball {
           id: ball
           x: root.width/2 - 50
           y: root.height/2
       }
    
       Column {
           spacing: 3
           x: root.width/2
           y: 10
              Repeater {
                model: 21
                 delegate: Rectangle {
                          width: 5
                          height: 20
                          color: "white"
                       }
                 }
           }
    
       ParallelAnimation {
          id: anim1
              NumberAnimation {
                       target: ball
                       properties: "x"
                       to: root.xPos
                       duration: root.duration
                       easing.type: Easing.Linear
                   }
              NumberAnimation {
                       target: ball
                       properties: "y"
                       to: root.yPos
                       duration: root.duration
                       easing.type: Easing.Linear
                   }
              }
    
       ParallelAnimation {
          id: anim2
             NumberAnimation {
                 target: ball
                 properties: "x"
                 to: -root.xPos
                 duration: root.duration
                 easing.type: Easing.Linear
             }
             NumberAnimation {
                 target: ball
                 properties: "y"
                 to: root.yPos
                 duration: root.duration
                 easing.type: Easing.Linear
             }
        }
    
       function nextPos() {
    
         if(ball.x >= redRacket.x && ball.x <= redRacket.x + redRacket.height)
         {
           anim1.stop();
           anim2.start();
         }
       }
    
        MouseArea {
            anchors.fill: ball
            onClicked: { anim1.start(); root.nextPos(); }
        }
      }
    }
    

    The x position of the ball is for when it hasn't been animated yet so it won't work in the condition. I need something like:

    if (hit(ball,redRacket))
    

    The second is that in:

    anim1.stop();
    anim2.start();
    

    anim2.start() doesn't let anim1.start() work!

    J.HilkJ 1 Reply Last reply
    0
    • tomyT tomy

      @J.Hilk
      Sorry, I don't know if there is an option that offer automatic indenting on Qt Creator. Do you mean the code looks ugly? :-)

      Anyway,
      The functions Math.random() and nextPos() and if-condition are fixed:

      import QtQuick 2.8
      import QtQuick.Window 2.2
      
      Window {
          visible: true
          width: 800
          height: 600
          title: qsTr("The Ping Pong game")
      
          Rectangle {
              id: root
              width: 700; height: 500
              border.width: 10
              border.color: "black"
              color: "royalblue"
              property int duration: 1000
              property real xPos: root.width
              property real yPos: Math.random() * root.height
      
         Racket {
             id: redRacket
             x: 630; y: 100
             color: "red"
         }
      
         Racket {
             id: blackRacket
             x: 50; y: 100
             color: "black"
         }
      
         Ball {
             id: ball
             x: root.width/2 - 50
             y: root.height/2
         }
      
         Column {
             spacing: 3
             x: root.width/2
             y: 10
                Repeater {
                  model: 21
                   delegate: Rectangle {
                            width: 5
                            height: 20
                            color: "white"
                         }
                   }
             }
      
         ParallelAnimation {
            id: anim1
                NumberAnimation {
                         target: ball
                         properties: "x"
                         to: root.xPos
                         duration: root.duration
                         easing.type: Easing.Linear
                     }
                NumberAnimation {
                         target: ball
                         properties: "y"
                         to: root.yPos
                         duration: root.duration
                         easing.type: Easing.Linear
                     }
                }
      
         ParallelAnimation {
            id: anim2
               NumberAnimation {
                   target: ball
                   properties: "x"
                   to: -root.xPos
                   duration: root.duration
                   easing.type: Easing.Linear
               }
               NumberAnimation {
                   target: ball
                   properties: "y"
                   to: root.yPos
                   duration: root.duration
                   easing.type: Easing.Linear
               }
          }
      
         function nextPos() {
      
           if(ball.x >= redRacket.x && ball.x <= redRacket.x + redRacket.height)
           {
             anim1.stop();
             anim2.start();
           }
         }
      
          MouseArea {
              anchors.fill: ball
              onClicked: { anim1.start(); root.nextPos(); }
          }
        }
      }
      

      The x position of the ball is for when it hasn't been animated yet so it won't work in the condition. I need something like:

      if (hit(ball,redRacket))
      

      The second is that in:

      anim1.stop();
      anim2.start();
      

      anim2.start() doesn't let anim1.start() work!

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by J.Hilk
      #18

      @tomy Hiho

      So, I took a look at your code. I'm not quite sure why it's not working like you want it to.
      My guess would be, its quite difficult to click upon the ball when its in the window when its in the Racket.

      So I simpliefied the situation a bit

      I added 2 Properties and a timer to help:
      The timer was needed in my testing, otherwise it would change animation an

      property bool toTheRight: true
      property bool delay: false
      
      Timer{
              id: delayTimer
              interval: 500; running:  false; repeat: false
              onTriggered: delay = false
      }
      onToTheRightChanged: {
              delay = true
              delayTimer.start()
      }
      

      nextPos() was slighly changed, it currently only checks if the ball is past a line:

      function nextPos() {
              if(!delay){
                  if(ball.x + ball.width >= redRacket.x || ball.x <= blackRacket.x + blackRacket.width){
                      toRight = !toRight
                      console.log("Ball hits a racket")
                      if(anim1.running)
                          anim1.stop()
                      else
                          anim1.start()
      
                      if(anim2.running)
                          anim2.stop()
                      else
                          anim2.start()
                  }
             }
      }
      

      The Ball item calls nextPos():

      Ball {
             id: ball
             x: root.width/2 - 50
             y: root.height/2
             onXChanged: nextPos()
      }
      ...
      MouseArea {
              anchors.fill: ball
              onClicked: { anim1.start(); /*root.nextPos();*/}
          }
      

      This works fine for me, its results in the ball pinging from one wall to the other.
      Next step would be to add the player input conditions.

      hope this helps.


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      tomyT 1 Reply Last reply
      2
      • J.HilkJ J.Hilk

        @tomy Hiho

        So, I took a look at your code. I'm not quite sure why it's not working like you want it to.
        My guess would be, its quite difficult to click upon the ball when its in the window when its in the Racket.

        So I simpliefied the situation a bit

        I added 2 Properties and a timer to help:
        The timer was needed in my testing, otherwise it would change animation an

        property bool toTheRight: true
        property bool delay: false
        
        Timer{
                id: delayTimer
                interval: 500; running:  false; repeat: false
                onTriggered: delay = false
        }
        onToTheRightChanged: {
                delay = true
                delayTimer.start()
        }
        

        nextPos() was slighly changed, it currently only checks if the ball is past a line:

        function nextPos() {
                if(!delay){
                    if(ball.x + ball.width >= redRacket.x || ball.x <= blackRacket.x + blackRacket.width){
                        toRight = !toRight
                        console.log("Ball hits a racket")
                        if(anim1.running)
                            anim1.stop()
                        else
                            anim1.start()
        
                        if(anim2.running)
                            anim2.stop()
                        else
                            anim2.start()
                    }
               }
        }
        

        The Ball item calls nextPos():

        Ball {
               id: ball
               x: root.width/2 - 50
               y: root.height/2
               onXChanged: nextPos()
        }
        ...
        MouseArea {
                anchors.fill: ball
                onClicked: { anim1.start(); /*root.nextPos();*/}
            }
        

        This works fine for me, its results in the ball pinging from one wall to the other.
        Next step would be to add the player input conditions.

        hope this helps.

        tomyT Offline
        tomyT Offline
        tomy
        wrote on last edited by tomy
        #19

        @J.Hilk
        Thank you.
        Timer was very useful. I wrote this:

        import QtQuick 2.8
        import QtQuick.Window 2.2
        
        Window {
            visible: true
            width: 800
            height: 600
            title: qsTr("The Ping Pong game")
        
            Rectangle {
                id: table
                width: 700; height: 500
                border.width: 10
                border.color: "black"
                color: "royalblue"
        
           Racket {
               id: redRacket
               x: 630; y: 100
               color: "red"
           }
        
           Racket {
               id: blackRacket
               x: 50; y: 100
               color: "black"
           }
        
           Ball {
               id: ball
               x: table.width/2 - 50
               y: table.height/2
               property double ran: Math.random() + 0.5
               property double xincrement: ran
               property double yincrement: ran
           }
        
           Column {
               spacing: 3
               x: table.width/2
               y: 10
                  Repeater {
                    model: 21
                     delegate: Rectangle {
                              width: 5
                              height: 20
                              color: "white"
                           }
                     }
               }
        
           Timer {
             interval: 5; repeat: true; running: true
        
                onTriggered: {
                    ball.x = ball.x + (ball.xincrement * 2.0);
                    ball.y = ball.y + (ball.yincrement * 2.0);
        
                    if((ball.x + ball.width  >= redRacket.x)  &&
                      ((ball.y + ball.height >= redRacket.y)  &&
                       (ball.y + ball.height <= redRacket.y + redRacket.height)))
                           ball.xincrement *= (-1);
        
                    if((ball.x - ball.width  <= blackRacket.x)  &&
                      ((ball.y + ball.height >= blackRacket.y)  &&
                       (ball.y + ball.height <= blackRacket.y + blackRacket.height)))
                           ball.xincrement *= (-1);
        
                     if(ball.y <= 0 || ball.y + ball.height >= table.height)
                          ball.yincrement *= (-1);
                   }
                }
            }
         }
        

        It works fine but the players can't shoot the ball towards a target they want! The rackets are this way only for defending. I need to alter the code so that when the racket has speed upward or downward hitting the ball, the ball goes and gets acceleration on that direction. The real game has that feature.
        How can I do that, please?

        After that I'll go for other missing parts for the game.

        J.HilkJ 1 Reply Last reply
        0
        • tomyT tomy

          @J.Hilk
          Thank you.
          Timer was very useful. I wrote this:

          import QtQuick 2.8
          import QtQuick.Window 2.2
          
          Window {
              visible: true
              width: 800
              height: 600
              title: qsTr("The Ping Pong game")
          
              Rectangle {
                  id: table
                  width: 700; height: 500
                  border.width: 10
                  border.color: "black"
                  color: "royalblue"
          
             Racket {
                 id: redRacket
                 x: 630; y: 100
                 color: "red"
             }
          
             Racket {
                 id: blackRacket
                 x: 50; y: 100
                 color: "black"
             }
          
             Ball {
                 id: ball
                 x: table.width/2 - 50
                 y: table.height/2
                 property double ran: Math.random() + 0.5
                 property double xincrement: ran
                 property double yincrement: ran
             }
          
             Column {
                 spacing: 3
                 x: table.width/2
                 y: 10
                    Repeater {
                      model: 21
                       delegate: Rectangle {
                                width: 5
                                height: 20
                                color: "white"
                             }
                       }
                 }
          
             Timer {
               interval: 5; repeat: true; running: true
          
                  onTriggered: {
                      ball.x = ball.x + (ball.xincrement * 2.0);
                      ball.y = ball.y + (ball.yincrement * 2.0);
          
                      if((ball.x + ball.width  >= redRacket.x)  &&
                        ((ball.y + ball.height >= redRacket.y)  &&
                         (ball.y + ball.height <= redRacket.y + redRacket.height)))
                             ball.xincrement *= (-1);
          
                      if((ball.x - ball.width  <= blackRacket.x)  &&
                        ((ball.y + ball.height >= blackRacket.y)  &&
                         (ball.y + ball.height <= blackRacket.y + blackRacket.height)))
                             ball.xincrement *= (-1);
          
                       if(ball.y <= 0 || ball.y + ball.height >= table.height)
                            ball.yincrement *= (-1);
                     }
                  }
              }
           }
          

          It works fine but the players can't shoot the ball towards a target they want! The rackets are this way only for defending. I need to alter the code so that when the racket has speed upward or downward hitting the ball, the ball goes and gets acceleration on that direction. The real game has that feature.
          How can I do that, please?

          After that I'll go for other missing parts for the game.

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #20

          @tomy
          well, first you'll need to somehow monitor if the racket moved up or down as its last movement.

          I don't see how in the code examples you posted how you manage the "Racket-Movement" .

          but it doesn't matter much, it can be a property of the Racket Item

          #untested Stuff
          e.g:

          Rectangle {
                 id: redRacket
                 x: 630; y: 100
                 color: "red"
          
                 property int oldY: 100
                 
                 property bool upMovement: false
          
                onYChanged:{
                    upMovement = y -oldY < 0  ? true : false
                    oldY = y
                }
          
                 width: 50
                 height: 100
             }
          

          and when the Ball hits the racket you decrease the duration, and depending on the up or down movement you change the angle

          function onCollisionWithRacket(){
              root.duration = root.duration -10
              if(redRacket.upMovement){
                  //Angle to the Top
              }else{
                  //Angle to the bottom
              }
          }
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          tomyT 1 Reply Last reply
          1
          • J.HilkJ J.Hilk

            @tomy
            well, first you'll need to somehow monitor if the racket moved up or down as its last movement.

            I don't see how in the code examples you posted how you manage the "Racket-Movement" .

            but it doesn't matter much, it can be a property of the Racket Item

            #untested Stuff
            e.g:

            Rectangle {
                   id: redRacket
                   x: 630; y: 100
                   color: "red"
            
                   property int oldY: 100
                   
                   property bool upMovement: false
            
                  onYChanged:{
                      upMovement = y -oldY < 0  ? true : false
                      oldY = y
                  }
            
                   width: 50
                   height: 100
               }
            

            and when the Ball hits the racket you decrease the duration, and depending on the up or down movement you change the angle

            function onCollisionWithRacket(){
                root.duration = root.duration -10
                if(redRacket.upMovement){
                    //Angle to the Top
                }else{
                    //Angle to the bottom
                }
            }
            
            tomyT Offline
            tomyT Offline
            tomy
            wrote on last edited by tomy
            #21

            @J.Hilk
            Thanks.
            I tried to make the work done and here is the code.
            I don't use the prior versions of the code (above) but this one.

            Ball.qml and Racket.qml are as before but main.qml is completely as below.

            As you see I haven't used a function and I don't know if it's needed or not.
            If possible please run that code to see its function. I don't think it's flawless.
            The code also to me is very messy. If it can make the work done using little changes, what to do for removing the problems from that please?

            import QtQuick 2.8
            import QtQuick.Window 2.2
            
            Window {
                visible: true
                width: 800
                height: 600
                title: qsTr("The PingPong Game")
            
                Rectangle {
                    id: table
                    width: 700; height: 500
                    border.width: 10
                    border.color: "black"
                    color: "royalblue"
            
               Racket {
                   id: redRacket
                   x: 630; y: 100
                   color: "red"
                   property int  rOldy: y
                   property bool rYmovement: false
                   onYChanged: {
                       rYmovement = y - rOldy < 0 ? true : false
                       rOldy = y
                   }
               }
            
               Racket {
                   id: blackRacket
                   x: 50; y: 100
                   color: "black"
                   property int  bOldy: y
                   property bool bYmovement: false
                   onYChanged: {
                       bYmovement = y - bOldy < 0 ? true : false
                       bOldy = y
                   }
               }
            
               Ball {
                   id: ball
                   x: table.width/2 - 50
                   y: table.height/2
                   property double ran: Math.random() + 0.5
                   property double xincrement: ran
                   property double yincrement: ran
               }
            
               Column {
                   spacing: 3
                   x: table.width/2
                   y: 10
                      Repeater {
                        model: 21
                         delegate: Rectangle {
                                  width: 5
                                  height: 20
                                  color: "white"
                               }
                         }
                   }
            
               Timer {
                 interval: 15; repeat: true; running: true
            
                    onTriggered: {
                        ball.x = ball.x + (ball.xincrement * 2.0);
                        ball.y = ball.y + (ball.yincrement * 2.0);
            
                        if((ball.x + ball.width  >= redRacket.x)  &&
                          ((ball.y + ball.height >= redRacket.y)  &&
                           (ball.y + ball.height <= redRacket.y + redRacket.height)))
                            if(redRacket.rYmovement) {
                                 ball.yincrement *= -1
                                 ball.xincrement *= -1
                                redRacket.rYmovement = false
                               }
                             else ball.xincrement *= -1
            
                        if((ball.x - ball.width  <= blackRacket.x)  &&
                          ((ball.y + ball.height >= blackRacket.y)  &&
                           (ball.y + ball.height <= blackRacket.y + blackRacket.height)))
                            if(blackRacket.bYmovement) {
                                 ball.yincrement *= -1
                                 ball.xincrement *= -1
                                blackRacket.bYmovement = false
                               }
                             else ball.xincrement *= -1
            
                         if(ball.y <= 0 || ball.y + ball.height >= table.height)
                              ball.yincrement *= -1
                       }
                   }
                }
             }
            
            
            J.HilkJ 1 Reply Last reply
            0
            • tomyT tomy

              @J.Hilk
              Thanks.
              I tried to make the work done and here is the code.
              I don't use the prior versions of the code (above) but this one.

              Ball.qml and Racket.qml are as before but main.qml is completely as below.

              As you see I haven't used a function and I don't know if it's needed or not.
              If possible please run that code to see its function. I don't think it's flawless.
              The code also to me is very messy. If it can make the work done using little changes, what to do for removing the problems from that please?

              import QtQuick 2.8
              import QtQuick.Window 2.2
              
              Window {
                  visible: true
                  width: 800
                  height: 600
                  title: qsTr("The PingPong Game")
              
                  Rectangle {
                      id: table
                      width: 700; height: 500
                      border.width: 10
                      border.color: "black"
                      color: "royalblue"
              
                 Racket {
                     id: redRacket
                     x: 630; y: 100
                     color: "red"
                     property int  rOldy: y
                     property bool rYmovement: false
                     onYChanged: {
                         rYmovement = y - rOldy < 0 ? true : false
                         rOldy = y
                     }
                 }
              
                 Racket {
                     id: blackRacket
                     x: 50; y: 100
                     color: "black"
                     property int  bOldy: y
                     property bool bYmovement: false
                     onYChanged: {
                         bYmovement = y - bOldy < 0 ? true : false
                         bOldy = y
                     }
                 }
              
                 Ball {
                     id: ball
                     x: table.width/2 - 50
                     y: table.height/2
                     property double ran: Math.random() + 0.5
                     property double xincrement: ran
                     property double yincrement: ran
                 }
              
                 Column {
                     spacing: 3
                     x: table.width/2
                     y: 10
                        Repeater {
                          model: 21
                           delegate: Rectangle {
                                    width: 5
                                    height: 20
                                    color: "white"
                                 }
                           }
                     }
              
                 Timer {
                   interval: 15; repeat: true; running: true
              
                      onTriggered: {
                          ball.x = ball.x + (ball.xincrement * 2.0);
                          ball.y = ball.y + (ball.yincrement * 2.0);
              
                          if((ball.x + ball.width  >= redRacket.x)  &&
                            ((ball.y + ball.height >= redRacket.y)  &&
                             (ball.y + ball.height <= redRacket.y + redRacket.height)))
                              if(redRacket.rYmovement) {
                                   ball.yincrement *= -1
                                   ball.xincrement *= -1
                                  redRacket.rYmovement = false
                                 }
                               else ball.xincrement *= -1
              
                          if((ball.x - ball.width  <= blackRacket.x)  &&
                            ((ball.y + ball.height >= blackRacket.y)  &&
                             (ball.y + ball.height <= blackRacket.y + blackRacket.height)))
                              if(blackRacket.bYmovement) {
                                   ball.yincrement *= -1
                                   ball.xincrement *= -1
                                  blackRacket.bYmovement = false
                                 }
                               else ball.xincrement *= -1
              
                           if(ball.y <= 0 || ball.y + ball.height >= table.height)
                                ball.yincrement *= -1
                         }
                     }
                  }
               }
              
              
              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #22

              @tomy

              to make it a bit cleaner, if you for example moved some stuff to the Ball and Racket qml-files

              //Racket
              import QtQuick 2.8
              
              Rectangle {
                  id: root
                  width: 15; height: 50
                  x: 400; y: 100
                  color: "red"
              
                  property int oldY: y
                  property bool yMovement: false
                  onYChanged: {
                      yMovement = y - oldY < 0 ? true : false
                      oldY = y
                  }
              
                  MouseArea {
                      anchors.fill: parent
                      drag.target: root
                      drag.axis: Drag.YAxis
                      drag.minimumY: 10
                      drag.maximumY: 440
                  }
              }
              
              //Ball.qml
              import QtQuick 2.8
              
              Rectangle {
                  width: 20; height: 20
                  x: 250; y: 250
                  color: "white"
                  radius: width/2
              
                  property double ran: Math.random() + 0.5
                  property double xincrement: ran
                  property double yincrement: ran
              }
              

              Besides that I don't see what the problem is, theres at least 1 bug I run into whilst playing, x) but thats part of coding.

              If you thinks the animation is a but stuttery thats to be expected, you replaced a propertyanimation with a Timer and x/y changes.

              I believe, PropertyAnimation does some internal stuff to make the animation as smooth as possible, a change each refresh frame e.g. Where as with a timer aproeach you are fixed to 5 ms updates and in that you only increase the distance the ball is moved. That gonna look like jumps eventually ;-)


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              tomyT 1 Reply Last reply
              1
              • J.HilkJ J.Hilk

                @tomy

                to make it a bit cleaner, if you for example moved some stuff to the Ball and Racket qml-files

                //Racket
                import QtQuick 2.8
                
                Rectangle {
                    id: root
                    width: 15; height: 50
                    x: 400; y: 100
                    color: "red"
                
                    property int oldY: y
                    property bool yMovement: false
                    onYChanged: {
                        yMovement = y - oldY < 0 ? true : false
                        oldY = y
                    }
                
                    MouseArea {
                        anchors.fill: parent
                        drag.target: root
                        drag.axis: Drag.YAxis
                        drag.minimumY: 10
                        drag.maximumY: 440
                    }
                }
                
                //Ball.qml
                import QtQuick 2.8
                
                Rectangle {
                    width: 20; height: 20
                    x: 250; y: 250
                    color: "white"
                    radius: width/2
                
                    property double ran: Math.random() + 0.5
                    property double xincrement: ran
                    property double yincrement: ran
                }
                

                Besides that I don't see what the problem is, theres at least 1 bug I run into whilst playing, x) but thats part of coding.

                If you thinks the animation is a but stuttery thats to be expected, you replaced a propertyanimation with a Timer and x/y changes.

                I believe, PropertyAnimation does some internal stuff to make the animation as smooth as possible, a change each refresh frame e.g. Where as with a timer aproeach you are fixed to 5 ms updates and in that you only increase the distance the ball is moved. That gonna look like jumps eventually ;-)

                tomyT Offline
                tomyT Offline
                tomy
                wrote on last edited by tomy
                #23

                @J.Hilk

                I replaced the PropertyAnimation with Timer because I didn't know how to achieve what I have now without Timer but with PropertyAnimation.
                The Timer works fine with smoothness but in this example I'd changed the interval from 2 to 15 to slow the movement of the ball for better testing.

                The game has defects even in this point unfortunately. And it's the feature of targeting.
                The if(redRacket.rYmovement) conditions code don't work as expected. I should think over them so that they work as needed.
                But a question here, does the y coordinate change relate to the "last" movement of the racket before the ball hits it?

                J.HilkJ 1 Reply Last reply
                0
                • tomyT tomy

                  @J.Hilk

                  I replaced the PropertyAnimation with Timer because I didn't know how to achieve what I have now without Timer but with PropertyAnimation.
                  The Timer works fine with smoothness but in this example I'd changed the interval from 2 to 15 to slow the movement of the ball for better testing.

                  The game has defects even in this point unfortunately. And it's the feature of targeting.
                  The if(redRacket.rYmovement) conditions code don't work as expected. I should think over them so that they work as needed.
                  But a question here, does the y coordinate change relate to the "last" movement of the racket before the ball hits it?

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #24

                  @tomy

                  I changed the timer stuff a bit, to make it more readable, what happens

                     Timer {
                       interval: 15; repeat: true; running: true
                  
                       function hitsRightRacket(){
                           if(ball.x +ball.width >= redRacket.x  && ball.x < redRacket.x + redRacket.width){
                               if(ball.y >= redRacket.y && ball.y <= redRacket.y+redRacket.height)
                                   return true
                           }
                           return false
                       }
                  
                       function hitsLeftRacket(){
                           if(ball.x +ball.width >= blackRacket.x  && ball.x < blackRacket.x + blackRacket.width){
                               if(ball.y >= blackRacket.y && ball.y <= blackRacket.y+blackRacket.height)
                                   return true
                           }
                           return false
                       }
                  
                       function hitsRightWall(){
                           if(ball.x +ball.width >= table.width)
                               return true
                           else
                               return false
                       }
                  
                       function hitsLeftWall(){
                           if(ball.x <= 0)
                               return true
                           else
                               return false
                       }
                  
                       function hitsUpperOrLowerWall(){
                           if(ball.y <= 0 || ball.y + ball.height >= table.height)
                                return true
                           return false
                       }
                  
                       property bool lastHitLeft: false
                       property bool lastHitRight: false
                  
                          onTriggered: {
                              if(hitsRightWall()){
                                  console.log("Point Left Side")
                                  running = false
                              }else if(hitsLeftWall()){
                                  console.log("Point Right Side")
                                  running = false
                              }else if(hitsLeftRacket() && !lastHitLeft){
                                  console.log("Hits Black Racket",blackRacket.yMovement)
                                  lastHitLeft = true
                                  lastHitRight = false
                                  if(blackRacket.yMovement){
                                      ball.yincrement *= -1
                                      ball.xincrement *= -1
                                   }else
                                      ball.xincrement *= -1
                              }else if(hitsRightRacket() && !lastHitRight){
                                  console.log("Hits Red Racket",redRacket.yMovement)
                                  lastHitLeft = false
                                  lastHitRight = true
                                  if(redRacket.yMovement) {
                                       ball.yincrement *= -1
                                       ball.xincrement *= -1
                                     }
                                   else ball.xincrement *= -1
                              }else if(hitsUpperOrLowerWall())
                                  ball.yincrement *= -1
                  
                              //Move Ball
                              ball.x = ball.x + (ball.xincrement * 2.0);
                              ball.y = ball.y + (ball.yincrement * 2.0);
                             }
                         }
                  

                  This showed me that you'll need a better case handleing for ball movement and racket movement,

                  • ball moves towards y = 0 and Racket moves towards y = 0
                  • ball moves towards y = 0 and Racket moves towards y = table height
                  • ball moves towards y = table and Racket moves towards y = 0
                  • ball moves towards y = table Racket moves towards y = table height

                  currently you're only checking in what direction the racket moved,


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  tomyT 1 Reply Last reply
                  1
                  • J.HilkJ J.Hilk

                    @tomy

                    I changed the timer stuff a bit, to make it more readable, what happens

                       Timer {
                         interval: 15; repeat: true; running: true
                    
                         function hitsRightRacket(){
                             if(ball.x +ball.width >= redRacket.x  && ball.x < redRacket.x + redRacket.width){
                                 if(ball.y >= redRacket.y && ball.y <= redRacket.y+redRacket.height)
                                     return true
                             }
                             return false
                         }
                    
                         function hitsLeftRacket(){
                             if(ball.x +ball.width >= blackRacket.x  && ball.x < blackRacket.x + blackRacket.width){
                                 if(ball.y >= blackRacket.y && ball.y <= blackRacket.y+blackRacket.height)
                                     return true
                             }
                             return false
                         }
                    
                         function hitsRightWall(){
                             if(ball.x +ball.width >= table.width)
                                 return true
                             else
                                 return false
                         }
                    
                         function hitsLeftWall(){
                             if(ball.x <= 0)
                                 return true
                             else
                                 return false
                         }
                    
                         function hitsUpperOrLowerWall(){
                             if(ball.y <= 0 || ball.y + ball.height >= table.height)
                                  return true
                             return false
                         }
                    
                         property bool lastHitLeft: false
                         property bool lastHitRight: false
                    
                            onTriggered: {
                                if(hitsRightWall()){
                                    console.log("Point Left Side")
                                    running = false
                                }else if(hitsLeftWall()){
                                    console.log("Point Right Side")
                                    running = false
                                }else if(hitsLeftRacket() && !lastHitLeft){
                                    console.log("Hits Black Racket",blackRacket.yMovement)
                                    lastHitLeft = true
                                    lastHitRight = false
                                    if(blackRacket.yMovement){
                                        ball.yincrement *= -1
                                        ball.xincrement *= -1
                                     }else
                                        ball.xincrement *= -1
                                }else if(hitsRightRacket() && !lastHitRight){
                                    console.log("Hits Red Racket",redRacket.yMovement)
                                    lastHitLeft = false
                                    lastHitRight = true
                                    if(redRacket.yMovement) {
                                         ball.yincrement *= -1
                                         ball.xincrement *= -1
                                       }
                                     else ball.xincrement *= -1
                                }else if(hitsUpperOrLowerWall())
                                    ball.yincrement *= -1
                    
                                //Move Ball
                                ball.x = ball.x + (ball.xincrement * 2.0);
                                ball.y = ball.y + (ball.yincrement * 2.0);
                               }
                           }
                    

                    This showed me that you'll need a better case handleing for ball movement and racket movement,

                    • ball moves towards y = 0 and Racket moves towards y = 0
                    • ball moves towards y = 0 and Racket moves towards y = table height
                    • ball moves towards y = table and Racket moves towards y = 0
                    • ball moves towards y = table Racket moves towards y = table height

                    currently you're only checking in what direction the racket moved,

                    tomyT Offline
                    tomyT Offline
                    tomy
                    wrote on last edited by tomy
                    #25

                    @J.Hilk
                    Hi,
                    Thank you for your assistance.

                    If we divide the task into part I and II, the first part I think is almost done! Please take a look at the code below and if possible please run the program on your system. It works fine for me.

                    In part I, I need two extra components I think: one, a series of buttons for starting, resuming and finishing the game when it's not over yet. And second, some sound for goals and when a player wins the game.
                    If we can complete part I, I assume part II will be about networking! :)

                    Ball.qml:

                    import QtQuick 2.9
                    
                    Rectangle {
                        width: 12; height: 12
                        x: 250; y: 250
                        color: "white"
                        radius: width/2
                        property double ran: Math.random() + 0.5
                        property double xincrement: ran
                        property double yincrement: ran
                    }
                    
                    

                    Counter.qml:

                    import QtQuick 2.9
                    
                    Rectangle {
                        width: 40; height: 50
                        color: "lightskyblue"
                        property int count: 0
                    
                        Text {
                            id: text
                            anchors.centerIn: parent
                            text: count.toString()
                            color: "gray"
                            font.bold: true
                            font.pixelSize: 30
                        }
                    }
                    

                    Light.qml:

                    import QtQuick 2.9
                    
                    Rectangle {
                        width: 50; height: 50
                        border.width: 5
                        border.color: "silver"
                        radius: width/2
                        property bool start: false
                    }
                    
                    

                    Racket.qml:

                    import QtQuick 2.9
                    
                    Rectangle {
                        id: root
                        width: 12; height: 40
                        property int oldY: y
                        property bool yUwards: false
                        property bool yDwards: false
                    
                           onYChanged: {
                               if(y > oldY)
                                   yDwards = true
                               else if (y < oldY)
                                   yUwards = true
                               oldY = y
                           }
                    
                        MouseArea {
                            anchors.fill: parent
                            drag.target: root
                            drag.axis: Drag.YAxis
                            drag.minimumY: table.y - 20
                            drag.maximumY: table.y + table.height - 60
                        }
                    }
                    
                    

                    WinBox.qml:

                    import QtQuick 2.9
                    
                    Text {
                         width: 50; height: 50
                         text: "WINNER"
                         color: "royalblue"
                         font.bold: true
                         font.pixelSize: 40
                         visible: false
                    }
                    

                    main.qml:

                    import QtQuick 2.9
                    import QtQuick.Window 2.2
                    
                    Window {
                        visible: true
                        width: 820
                        height: 620
                        title: qsTr("The PingPong Game")
                        color: "gray"
                    
                        Rectangle {
                            x: 10; y: 10
                            width: 800; height: 500
                            color: "white"
                        }
                    
                        Rectangle {
                            id: table
                            x: 20; y: 20
                            width: 780; height: 480
                            color: "royalblue"
                            property int count: 1
                            property bool turn: false
                            property bool lightState: false
                    
                            Racket {
                                id: redRacket
                                x: table.width - 30; y: 100
                                color: "red"
                            }
                    
                            Racket {
                                id: blackRacket
                                x: table.x; y: 100
                                color: "black"
                            }
                    
                            Ball {
                                id: ball
                                x: table.width/2
                                y: table.height/2
                            }
                    
                            Column {
                                spacing: 3
                                x: table.width/2
                                Repeater {
                                    model: 21
                                    delegate: Rectangle {
                                        width: 5
                                        height: 20
                                        color: "white"
                                    }
                                }
                            }
                    
                            Counter {
                                id: rightCounter
                                x: table.width / 2 + 90
                                y: 50
                            }
                    
                            Counter {
                                id: leftCounter
                                x: table.width / 4 + 70
                                y: 50
                            }
                    
                            Light {
                                id: rightLight
                                x: table.width/2 + 80
                                y: table.height + 20
                                color: "silver"
                            }
                    
                            Light {
                                id: leftLight
                                x: table.width/2 - 120
                                y: table.height + 20
                                color: "lime"
                            }
                    
                            WinBox {
                                id: rightWin
                                x: table.width/2 + 160
                                y: table.height + 40
                            }
                    
                            WinBox {
                                id: leftWin
                                x: table.width/2 - 350
                                y: table.height + 40
                            }
                    
                            Timer {
                                interval: 40; repeat: true; running: true
                    
                                onTriggered: {
                                    redRacket.yUwards = false
                                    redRacket.yDwards = false
                                    blackRacket.yUwards = false
                                    blackRacket.yDwards = false
                                }
                            }
                    
                            Timer {
                                id: out_timer
                                interval: 1; repeat: false; running: false
                    
                                function lightChange() {
                                    if (table.lightState) {
                                        rightLight.color = "silver"
                                        leftLight.color= "lime"
                                      }
                    
                                    else {
                                        rightLight.color = "lime"
                                        leftLight.color= "silver"
                                      }
                                    table.lightState = !table.lightState
                                }
                    
                                onTriggered: {
                                    ball.xincrement = Math.random() + 0.5
                                    ball.yincrement = Math.random() + 0.5
                    
                                    if( table.count % 5 == 0) {
                                        table.turn = !table.turn
                                        lightChange()
                                    }
                    
                    
                                     if(table.turn)
                                        ball.xincrement *= -1
                    
                                    ball.x = table.width/2
                                    ball.y = table.height/2
                    
                                    if (ball.yincrement > 1.1)
                                        ball.yincrement *= -1
                    
                                    in_timer.restart()
                                    table.count++
                                }
                            }
                    
                            Timer {
                                id: in_timer
                                interval: duration; repeat: true; running: true
                                property int duration: 2
                    
                                function hitsRightWall() {
                                    if (ball.x + ball.width >= table.width)
                                        return true
                                    else return false
                                }
                    
                                function hitsLeftWall() {
                                    if(ball.x <= 0) return true
                                    else return false
                                }
                    
                                property bool lastHitLeft: false
                                property bool lastHitRight: false
                    
                                onTriggered: {
                    
                                    if(hitsRightWall()) {
                                        in_timer.stop()
                                        leftCounter.count++
                                        out_timer.interval = 2000
                                        out_timer.running = true
                                    }
                    
                                    else if(hitsLeftWall()) {
                                        in_timer.stop()
                                        rightCounter.count++
                                        out_timer.interval = 2000
                                        out_timer.running = true
                                    }
                    
                                    ball.x = ball.x + (ball.xincrement * 2.0);
                                    ball.y = ball.y + (ball.yincrement * 2.0);
                    
                                    if ((ball.x + ball.width >= redRacket.x  &&
                                         ball.x < redRacket.x + redRacket.width / 3) &&
                                            (ball.y + ball.height >= redRacket.y - 10 &&
                                             ball.y <= redRacket.y + redRacket.height))
                                    {
                                        if(redRacket.yUwards) {
                                            if(ball.yincrement == 0)
                                                ball.yincrement = -ball.ran
                                            else if(ball.yincrement > 0)
                                                ball.yincrement *= -1
                                            interval = duration/2
                                        }
                                        else if (redRacket.yDwards) {
                                            if(ball.yincrement == 0)
                                                ball.yincrement = ball.ran
                                            else if(ball.yincrement < 0)
                                                ball.yincrement *= -1
                                            interval = duration/2
                                        }
                                        else {
                                            ball.yincrement = 0
                                            interval = duration
                                        }
                    
                                        ball.xincrement *= -1
                                    }
                    
                                    if ((ball.x + ball.width >= blackRacket.x &&
                                         ball.x < blackRacket.x + blackRacket.width)  &&
                                            (ball.y + ball.height >= blackRacket.y &&
                                             ball.y <= blackRacket.y + blackRacket.height))
                                    {
                                        if(blackRacket.yUwards) {
                                            if(ball.yincrement == 0)
                                                ball.yincrement = -ball.ran
                                            else if(ball.yincrement > 0)
                                                ball.yincrement *= -1
                                            interval = duration/2
                                        }
                                        else if (blackRacket.yDwards) {
                                            if(ball.yincrement == 0)
                                                ball.yincrement = ball.ran
                                            else if(ball.yincrement < 0)
                                                ball.yincrement *= -1
                                            interval = duration/2
                                        }
                                        else {
                                            ball.yincrement = 0
                                            interval = duration
                                        }
                    
                                        ball.xincrement *= -1
                                    }
                    
                                    if(ball.x <= 0 || ball.x + ball.width >= table.width)
                                        ball.xincrement *= (-1);
                    
                                    if(ball.y <= 0 || ball.y + ball.height >= table.height)
                                        ball.yincrement *= -1
                    
                                    if(rightCounter.count + leftCounter.count == 21) {
                                           in_timer.stop()
                                        if(rightCounter.count > leftCounter.count)
                                            rightWin.visible = true
                                        else if (rightCounter.count < leftCounter.count)
                                            leftWin.visible = true
                                        else {
                                            rightWin.visible = true
                                            leftWin.visible = true
                                        }
                                    }
                                }            
                            }
                        }
                    }
                    
                    
                    1 Reply Last reply
                    0
                    • J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #26

                      Looks great! You're defenitly on the right track.

                      However I have a bug to report. I managed to catch the ball in the racket. That's the reasdon why I introtuced the 2 properties lastHitLeft and lastHitRight in my previous post. You still have them in your code, but they are not used.
                      0_1513750776832_catch.PNG


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      tomyT 1 Reply Last reply
                      0
                      • J.HilkJ J.Hilk

                        Looks great! You're defenitly on the right track.

                        However I have a bug to report. I managed to catch the ball in the racket. That's the reasdon why I introtuced the 2 properties lastHitLeft and lastHitRight in my previous post. You still have them in your code, but they are not used.
                        0_1513750776832_catch.PNG

                        tomyT Offline
                        tomyT Offline
                        tomy
                        wrote on last edited by tomy
                        #27

                        @J.Hilk
                        Hi, thanks.

                        Well, I laid those factors and ran the code. Unfortunately it made the issue more prominent! The ball passes through the ball obliquely.

                        So I think I must return back to the version without them and the issue is subtle! It happens when a racket tries to hit the ball from the top/down moving downwards/upwards and the ball gets stuck in the upper/lower edge of the racket. I think I should work on this.

                        Previously I was thinking of making the racket thinner to prevent this bug. But I try to find a more logical way.

                        1 Reply Last reply
                        0
                        • tomyT Offline
                          tomyT Offline
                          tomy
                          wrote on last edited by tomy
                          #28

                          Hi,

                          For a while I was trying to use contains(point p), mapFromItem(...) or mapToItem(...). But unfortunately, no success! So I got back to the prior method, which was using the X and Y coordinates as follows.

                          Please run it on your system. It works fine for me. The bug is also solved.
                          But there's another bug!

                          • Moving the racket when playing the game on the Desktop kit (Windows) doesn't affect the speed of ball's movement but when run on an Android device, moving the racket affects the speed of ball's movement as though their movements have been tied together.

                          I also tried to manipulate the MouseArea in the Racket.qml to cope with that, but no change in the result! :(

                          Please check it and express your idea how to solve that issue.

                          QML files Ball, Counter, Light and Winbox are as before.

                          Racket.qml:

                          import QtQuick 2.9
                          
                          Rectangle {
                              id: root
                              width: 15; height: 65
                              property int oldY: y
                              property bool yUwards: false
                              property bool yDwards: false
                          
                              onYChanged: {
                                  if(y > oldY)  yDwards = true
                                  else if (y < oldY)  yUwards = true
                                  oldY = y
                              }
                          
                              MouseArea {
                                  anchors.fill: parent
                                  anchors.margins: -root.height
                                  drag.target: root
                                  focus: true
                                  hoverEnabled: true
                                  pressAndHoldInterval: 0
                                  drag.axis: Drag.YAxis
                                  drag.minimumY: table.y
                                  drag.maximumY: table.height - root.height - 10
                              }
                          }
                          
                          
                          

                          main.qml:

                          import QtQuick 2.9
                          import QtQuick.Window 2.2
                          import QtQuick.Controls 2.1
                          
                          Window {
                              id: window
                              visibility: Window.Maximized
                              title: qsTr("The PingPong Game - A QML Game")
                              color: "gray"
                              
                              Rectangle {
                                  id: table
                                  width: window.width / 1.15; height: window.height / 1.15
                                  x: window.x + 100; y: 10;
                                  border.width: 10
                                  border.color: "white"
                                  color: "royalblue"
                                  property int count: 1
                                  property bool turn: false
                                  property bool lightState: false
                                  property double step: 3.0
                                  property int duration: 4
                                  
                                  Racket {
                                      id: blackRacket
                                      anchors.left: table.left
                                      anchors.leftMargin: width * 2
                                      y: height
                                      color: "black"
                                  }
                                  Racket {
                                      id: redRacket
                                      anchors.right: table.right
                                      anchors.rightMargin: width * 2
                                      y: height
                                      color: "red"
                                  }
                                  
                                  
                                  Ball {
                                      id: ball
                                      x: table.width/2
                                      y: table.height/2
                                  }
                                  
                                  Column {
                                      spacing: 3
                                      anchors.centerIn: table
                                      anchors.top: table.top
                                      Repeater {
                                          model: table.height/(blackRacket.height / 2 + 3)
                                          delegate: Rectangle {
                                              width: 5
                                              height: blackRacket.height / 2
                                              color: "white"
                                          }
                                      }
                                  }
                                  
                                  Counter {
                                      id: leftCounter
                                      x: table.width / 2 - height - 100
                                      y: 50
                                  }
                                  Counter {
                                      id: rightCounter
                                      x: table.width / 2 + 100
                                      y: 50
                                  }
                                  
                                  
                                  Light {
                                      id: leftLight
                                      x: table.width/2 - 280
                                      y: table.height + 10
                                      color: "lime"
                                  }
                                  Light {
                                      id: rightLight
                                      x: table.width/2 + 220
                                      y: table.height + 10
                                      color: "silver"
                                  }
                                  
                                  WinBox {
                                      id: rightWin
                                      x: table.width/2 + 380
                                      y: table.height + 10
                                  }
                                  WinBox {
                                      id: leftWin
                                      x: table.x + 40
                                      y: table.height + 10
                                  }
                                  
                                  Button {
                                      x: table.width/2 - 45
                                      y: table.height + 10
                                      
                                      contentItem: Text {
                                          id: st_tx
                                          horizontalAlignment: Text.AlignHCenter
                                          verticalAlignment: Text.AlignVCenter
                                          text: qsTr("START")
                                          font.bold: true
                                          font.pixelSize: 20
                                          color: "green"
                                      }
                                      background: Rectangle {
                                          implicitHeight: 60
                                          implicitWidth: 100
                                          color: "lightGrey"
                                          border.width: 8
                                          border.color: "lightBlue"
                                          radius: 20
                                      }
                                      onClicked: table.startGame()
                                  }
                                  Button {
                                      x: table.width/2 - 150
                                      y: table.height + 10
                                      
                                      contentItem: Text {
                                          id: pu_tx
                                          horizontalAlignment: Text.AlignHCenter
                                          verticalAlignment: Text.AlignVCenter
                                          text: qsTr("PAUSE")
                                          font.bold: true
                                          font.pixelSize: 20
                                          color: "green"
                                      }
                                      background: Rectangle {
                                          id: pu_rec
                                          implicitHeight: 60
                                          implicitWidth: 100
                                          color: "lightGrey"
                                          border.width: 8
                                          border.color: "lightBlue"
                                          radius: 20
                                      }
                                      onClicked: table.pauseGame()
                                  }
                                  Button {
                                      x: table.width/2 + 60
                                      y: table.height + 10
                                      
                                      contentItem: Text {
                                          id: sp_tx
                                          horizontalAlignment: Text.AlignHCenter
                                          verticalAlignment: Text.AlignVCenter
                                          text: qsTr("STOP")
                                          font.bold: true
                                          font.pixelSize: 20
                                          color: "green"
                                      }
                                      background: Rectangle {
                                          implicitHeight: 60
                                          implicitWidth: 100
                                          color: "lightGrey"
                                          border.width: 8
                                          border.color: "lightBlue"
                                          radius: 20
                                          
                                      }
                                      onClicked: table.stopGame()
                                  }
                                  
                                  Text {
                                      x: window.x; y: table.height + 50
                                      color: "white"
                                      text: "Ver: 1.1"
                                      font.family: "Helvetica"
                                      font.pointSize: 15
                                  }
                                  Text {
                                      x: table.width - 200; y: table.height + 50
                                      color: "white"
                                      text: " Programmed By S.R. Abbasi (Tomy)"
                                      font.family: "Helvetica"
                                      font.pointSize: 10
                                  }
                                  
                                  function startGame() {
                                      st_tx.text = qsTr("START")
                                      if (leftWin.visible)
                                          leftWin.visible = false
                                      if (rightWin.visible)
                                          rightWin.visible = false
                                      in_timer.restart()
                                  }
                                  function pauseGame() {
                                      st_tx.text = qsTr("RESUME")
                                      in_timer.running = false
                                  }
                                  function stopGame() {
                                      st_tx.text = qsTr("START")
                                      in_timer.running = false
                                      rightCounter.count = 0
                                      leftCounter.count = 0
                                      ball.x = table.width/2
                                      ball.y = table.height/2
                                      table.count = 1
                                      table.turn = false
                                      rightLight.color = "silver"
                                      leftLight.color = "lime"
                                      
                                      if(ball.xincrement < 0 )
                                          ball.xincrement *= -1
                                  }
                                  
                                  Timer {
                                      interval: 40; repeat: true; running: true
                                      
                                      onTriggered: {
                                          redRacket.yUwards = false
                                          redRacket.yDwards = false
                                          blackRacket.yUwards = false
                                          blackRacket.yDwards = false
                                      }
                                  }
                                  Timer {
                                      id: out_timer
                                      interval: 1; repeat: false; running: false
                                      
                                      function lightChange() {
                                          if (table.lightState) {
                                              rightLight.color = "silver"
                                              leftLight.color= "lime"
                                          }
                                          else {
                                              rightLight.color = "lime"
                                              leftLight.color= "silver"
                                          }
                                          table.lightState = !table.lightState
                                      }
                                      
                                      onTriggered: {
                                          ball.xincrement = Math.random() + 0.5
                                          ball.yincrement = Math.random() + 0.5
                                          
                                          if (table.count % 5 == 0) {
                                              table.turn = !table.turn
                                              lightChange()
                                          }
                                          
                                          if (table.turn)
                                              ball.xincrement *= -1
                                          
                                          ball.x = table.width/2
                                          ball.y = table.height/2
                                          
                                          if (ball.yincrement > 1.1)
                                              ball.yincrement *= -1
                                          
                                          in_timer.restart()
                                          table.count++
                                      }
                                  }
                                  Timer {
                                      id: right_return_timer
                                      interval: 1; repeat: true; running: false
                                      onTriggered: {
                                          ball.x = ball.x + (ball.xincrement * table.step)
                                          ball.y = ball.y + (ball.yincrement * table.step)
                                          if(ball.x + ball.width < redRacket.x) {
                                              running = false
                                              in_timer.running = true
                                          }
                                      }
                                  }
                                  Timer {
                                      id: left_return_timer
                                      interval: 1; repeat: true; running: false
                                      onTriggered: {
                                          ball.x = ball.x + (ball.xincrement * table.step)
                                          ball.y = ball.y + (ball.yincrement * table.step)
                                          if(ball.x > blackRacket.x + blackRacket.width) {
                                              running = false
                                              in_timer.running = true
                                          }
                                      }
                                  }
                                  Timer {
                                      id: in_timer
                                      interval: table.duration; repeat: true; running: false
                                      
                                      
                                      function hitsRightRacket() {
                                          if ((ball.x + ball.width >= redRacket.x &&
                                               ball.x <= redRacket.x + redRacket.width) &&
                                                  (ball.y + ball.height >= redRacket.y &&
                                                   ball.y <= redRacket.y + redRacket.height))
                                              return true
                                          return false
                                      }
                                      function hitsLeftRacket() {
                                          if ((ball.x + ball.width >= blackRacket.x &&
                                               ball.x < blackRacket.x + blackRacket.width)  &&
                                                  (ball.y + ball.height >= blackRacket.y &&
                                                   ball.y <= blackRacket.y + blackRacket.height))
                                              return true
                                          return false
                                      }
                                      function hitsUpperOrLowerWall(){
                                          if (ball.y <= 0 || ball.y + ball.height >= table.height)
                                              return true
                                          return false
                                      }
                                      function hitsRightWall() {
                                          if (ball.x + ball.width >= table.width)
                                              return true
                                          else return false
                                      }
                                      function hitsLeftWall() {
                                          if (ball.x <= 0) return true
                                          else return false
                                      }
                                      
                                      onTriggered: {
                                          if (hitsRightWall()) {
                                              in_timer.stop()
                                              leftCounter.count++
                                              out_timer.interval = 2000
                                              out_timer.running = true
                                          }
                                          else if (hitsLeftWall()) {
                                              in_timer.stop()
                                              rightCounter.count++
                                              out_timer.interval = 2000
                                              out_timer.running = true
                                          }
                                          else if (hitsRightRacket()) {
                                              if (redRacket.yUwards) {
                                                  if (ball.yincrement == 0)
                                                      ball.yincrement = -ball.ran
                                                  else if (ball.yincrement > 0)
                                                      ball.yincrement *= -1
                                                  interval = (table.duration/4)
                                              }
                                              else if (redRacket.yDwards) {
                                                  if (ball.yincrement == 0)
                                                      ball.yincrement = ball.ran
                                                  else if (ball.yincrement < 0)
                                                      ball.yincrement *= -1
                                                  interval = (table.duration/4)
                                              }
                                              else {
                                                  ball.yincrement = 0
                                                  interval = (table.duration/2)
                                              }
                                              ball.xincrement *= -1
                                              running = false
                                              right_return_timer.running = true
                                          }
                                          else if (hitsLeftRacket()) {
                                              if(blackRacket.yUwards) {
                                                  if (ball.yincrement == 0)
                                                      ball.yincrement = -ball.ran
                                                  else if (ball.yincrement > 0)
                                                      ball.yincrement *= -1
                                                  interval = (table.duration/4)
                                              }
                                              else if (blackRacket.yDwards) {
                                                  if (ball.yincrement == 0)
                                                      ball.yincrement = ball.ran
                                                  else if (ball.yincrement < 0)
                                                      ball.yincrement *= -1
                                                  interval = (table.duration/4)
                                              }
                                              else {
                                                  ball.yincrement = 0
                                                  interval = (table.duration/2)
                                              }
                                              ball.xincrement *= -1
                                              running = false
                                              left_return_timer.running = true
                                          }
                                          else if (hitsUpperOrLowerWall())
                                              ball.yincrement *= -1
                                          
                                          // Move Ball
                                          ball.x = ball.x + (ball.xincrement * table.step);
                                          ball.y = ball.y + (ball.yincrement * table.step);
                                          
                                          if(rightCounter.count + leftCounter.count == 21) {
                                              in_timer.stop()
                                              if (rightCounter.count > leftCounter.count)
                                                  rightWin.visible = true
                                              else
                                                  leftWin.visible = true
                                          }
                                      }
                                  }
                              }
                          }
                          
                          
                          J.HilkJ 1 Reply Last reply
                          1
                          • tomyT tomy

                            Hi,

                            For a while I was trying to use contains(point p), mapFromItem(...) or mapToItem(...). But unfortunately, no success! So I got back to the prior method, which was using the X and Y coordinates as follows.

                            Please run it on your system. It works fine for me. The bug is also solved.
                            But there's another bug!

                            • Moving the racket when playing the game on the Desktop kit (Windows) doesn't affect the speed of ball's movement but when run on an Android device, moving the racket affects the speed of ball's movement as though their movements have been tied together.

                            I also tried to manipulate the MouseArea in the Racket.qml to cope with that, but no change in the result! :(

                            Please check it and express your idea how to solve that issue.

                            QML files Ball, Counter, Light and Winbox are as before.

                            Racket.qml:

                            import QtQuick 2.9
                            
                            Rectangle {
                                id: root
                                width: 15; height: 65
                                property int oldY: y
                                property bool yUwards: false
                                property bool yDwards: false
                            
                                onYChanged: {
                                    if(y > oldY)  yDwards = true
                                    else if (y < oldY)  yUwards = true
                                    oldY = y
                                }
                            
                                MouseArea {
                                    anchors.fill: parent
                                    anchors.margins: -root.height
                                    drag.target: root
                                    focus: true
                                    hoverEnabled: true
                                    pressAndHoldInterval: 0
                                    drag.axis: Drag.YAxis
                                    drag.minimumY: table.y
                                    drag.maximumY: table.height - root.height - 10
                                }
                            }
                            
                            
                            

                            main.qml:

                            import QtQuick 2.9
                            import QtQuick.Window 2.2
                            import QtQuick.Controls 2.1
                            
                            Window {
                                id: window
                                visibility: Window.Maximized
                                title: qsTr("The PingPong Game - A QML Game")
                                color: "gray"
                                
                                Rectangle {
                                    id: table
                                    width: window.width / 1.15; height: window.height / 1.15
                                    x: window.x + 100; y: 10;
                                    border.width: 10
                                    border.color: "white"
                                    color: "royalblue"
                                    property int count: 1
                                    property bool turn: false
                                    property bool lightState: false
                                    property double step: 3.0
                                    property int duration: 4
                                    
                                    Racket {
                                        id: blackRacket
                                        anchors.left: table.left
                                        anchors.leftMargin: width * 2
                                        y: height
                                        color: "black"
                                    }
                                    Racket {
                                        id: redRacket
                                        anchors.right: table.right
                                        anchors.rightMargin: width * 2
                                        y: height
                                        color: "red"
                                    }
                                    
                                    
                                    Ball {
                                        id: ball
                                        x: table.width/2
                                        y: table.height/2
                                    }
                                    
                                    Column {
                                        spacing: 3
                                        anchors.centerIn: table
                                        anchors.top: table.top
                                        Repeater {
                                            model: table.height/(blackRacket.height / 2 + 3)
                                            delegate: Rectangle {
                                                width: 5
                                                height: blackRacket.height / 2
                                                color: "white"
                                            }
                                        }
                                    }
                                    
                                    Counter {
                                        id: leftCounter
                                        x: table.width / 2 - height - 100
                                        y: 50
                                    }
                                    Counter {
                                        id: rightCounter
                                        x: table.width / 2 + 100
                                        y: 50
                                    }
                                    
                                    
                                    Light {
                                        id: leftLight
                                        x: table.width/2 - 280
                                        y: table.height + 10
                                        color: "lime"
                                    }
                                    Light {
                                        id: rightLight
                                        x: table.width/2 + 220
                                        y: table.height + 10
                                        color: "silver"
                                    }
                                    
                                    WinBox {
                                        id: rightWin
                                        x: table.width/2 + 380
                                        y: table.height + 10
                                    }
                                    WinBox {
                                        id: leftWin
                                        x: table.x + 40
                                        y: table.height + 10
                                    }
                                    
                                    Button {
                                        x: table.width/2 - 45
                                        y: table.height + 10
                                        
                                        contentItem: Text {
                                            id: st_tx
                                            horizontalAlignment: Text.AlignHCenter
                                            verticalAlignment: Text.AlignVCenter
                                            text: qsTr("START")
                                            font.bold: true
                                            font.pixelSize: 20
                                            color: "green"
                                        }
                                        background: Rectangle {
                                            implicitHeight: 60
                                            implicitWidth: 100
                                            color: "lightGrey"
                                            border.width: 8
                                            border.color: "lightBlue"
                                            radius: 20
                                        }
                                        onClicked: table.startGame()
                                    }
                                    Button {
                                        x: table.width/2 - 150
                                        y: table.height + 10
                                        
                                        contentItem: Text {
                                            id: pu_tx
                                            horizontalAlignment: Text.AlignHCenter
                                            verticalAlignment: Text.AlignVCenter
                                            text: qsTr("PAUSE")
                                            font.bold: true
                                            font.pixelSize: 20
                                            color: "green"
                                        }
                                        background: Rectangle {
                                            id: pu_rec
                                            implicitHeight: 60
                                            implicitWidth: 100
                                            color: "lightGrey"
                                            border.width: 8
                                            border.color: "lightBlue"
                                            radius: 20
                                        }
                                        onClicked: table.pauseGame()
                                    }
                                    Button {
                                        x: table.width/2 + 60
                                        y: table.height + 10
                                        
                                        contentItem: Text {
                                            id: sp_tx
                                            horizontalAlignment: Text.AlignHCenter
                                            verticalAlignment: Text.AlignVCenter
                                            text: qsTr("STOP")
                                            font.bold: true
                                            font.pixelSize: 20
                                            color: "green"
                                        }
                                        background: Rectangle {
                                            implicitHeight: 60
                                            implicitWidth: 100
                                            color: "lightGrey"
                                            border.width: 8
                                            border.color: "lightBlue"
                                            radius: 20
                                            
                                        }
                                        onClicked: table.stopGame()
                                    }
                                    
                                    Text {
                                        x: window.x; y: table.height + 50
                                        color: "white"
                                        text: "Ver: 1.1"
                                        font.family: "Helvetica"
                                        font.pointSize: 15
                                    }
                                    Text {
                                        x: table.width - 200; y: table.height + 50
                                        color: "white"
                                        text: " Programmed By S.R. Abbasi (Tomy)"
                                        font.family: "Helvetica"
                                        font.pointSize: 10
                                    }
                                    
                                    function startGame() {
                                        st_tx.text = qsTr("START")
                                        if (leftWin.visible)
                                            leftWin.visible = false
                                        if (rightWin.visible)
                                            rightWin.visible = false
                                        in_timer.restart()
                                    }
                                    function pauseGame() {
                                        st_tx.text = qsTr("RESUME")
                                        in_timer.running = false
                                    }
                                    function stopGame() {
                                        st_tx.text = qsTr("START")
                                        in_timer.running = false
                                        rightCounter.count = 0
                                        leftCounter.count = 0
                                        ball.x = table.width/2
                                        ball.y = table.height/2
                                        table.count = 1
                                        table.turn = false
                                        rightLight.color = "silver"
                                        leftLight.color = "lime"
                                        
                                        if(ball.xincrement < 0 )
                                            ball.xincrement *= -1
                                    }
                                    
                                    Timer {
                                        interval: 40; repeat: true; running: true
                                        
                                        onTriggered: {
                                            redRacket.yUwards = false
                                            redRacket.yDwards = false
                                            blackRacket.yUwards = false
                                            blackRacket.yDwards = false
                                        }
                                    }
                                    Timer {
                                        id: out_timer
                                        interval: 1; repeat: false; running: false
                                        
                                        function lightChange() {
                                            if (table.lightState) {
                                                rightLight.color = "silver"
                                                leftLight.color= "lime"
                                            }
                                            else {
                                                rightLight.color = "lime"
                                                leftLight.color= "silver"
                                            }
                                            table.lightState = !table.lightState
                                        }
                                        
                                        onTriggered: {
                                            ball.xincrement = Math.random() + 0.5
                                            ball.yincrement = Math.random() + 0.5
                                            
                                            if (table.count % 5 == 0) {
                                                table.turn = !table.turn
                                                lightChange()
                                            }
                                            
                                            if (table.turn)
                                                ball.xincrement *= -1
                                            
                                            ball.x = table.width/2
                                            ball.y = table.height/2
                                            
                                            if (ball.yincrement > 1.1)
                                                ball.yincrement *= -1
                                            
                                            in_timer.restart()
                                            table.count++
                                        }
                                    }
                                    Timer {
                                        id: right_return_timer
                                        interval: 1; repeat: true; running: false
                                        onTriggered: {
                                            ball.x = ball.x + (ball.xincrement * table.step)
                                            ball.y = ball.y + (ball.yincrement * table.step)
                                            if(ball.x + ball.width < redRacket.x) {
                                                running = false
                                                in_timer.running = true
                                            }
                                        }
                                    }
                                    Timer {
                                        id: left_return_timer
                                        interval: 1; repeat: true; running: false
                                        onTriggered: {
                                            ball.x = ball.x + (ball.xincrement * table.step)
                                            ball.y = ball.y + (ball.yincrement * table.step)
                                            if(ball.x > blackRacket.x + blackRacket.width) {
                                                running = false
                                                in_timer.running = true
                                            }
                                        }
                                    }
                                    Timer {
                                        id: in_timer
                                        interval: table.duration; repeat: true; running: false
                                        
                                        
                                        function hitsRightRacket() {
                                            if ((ball.x + ball.width >= redRacket.x &&
                                                 ball.x <= redRacket.x + redRacket.width) &&
                                                    (ball.y + ball.height >= redRacket.y &&
                                                     ball.y <= redRacket.y + redRacket.height))
                                                return true
                                            return false
                                        }
                                        function hitsLeftRacket() {
                                            if ((ball.x + ball.width >= blackRacket.x &&
                                                 ball.x < blackRacket.x + blackRacket.width)  &&
                                                    (ball.y + ball.height >= blackRacket.y &&
                                                     ball.y <= blackRacket.y + blackRacket.height))
                                                return true
                                            return false
                                        }
                                        function hitsUpperOrLowerWall(){
                                            if (ball.y <= 0 || ball.y + ball.height >= table.height)
                                                return true
                                            return false
                                        }
                                        function hitsRightWall() {
                                            if (ball.x + ball.width >= table.width)
                                                return true
                                            else return false
                                        }
                                        function hitsLeftWall() {
                                            if (ball.x <= 0) return true
                                            else return false
                                        }
                                        
                                        onTriggered: {
                                            if (hitsRightWall()) {
                                                in_timer.stop()
                                                leftCounter.count++
                                                out_timer.interval = 2000
                                                out_timer.running = true
                                            }
                                            else if (hitsLeftWall()) {
                                                in_timer.stop()
                                                rightCounter.count++
                                                out_timer.interval = 2000
                                                out_timer.running = true
                                            }
                                            else if (hitsRightRacket()) {
                                                if (redRacket.yUwards) {
                                                    if (ball.yincrement == 0)
                                                        ball.yincrement = -ball.ran
                                                    else if (ball.yincrement > 0)
                                                        ball.yincrement *= -1
                                                    interval = (table.duration/4)
                                                }
                                                else if (redRacket.yDwards) {
                                                    if (ball.yincrement == 0)
                                                        ball.yincrement = ball.ran
                                                    else if (ball.yincrement < 0)
                                                        ball.yincrement *= -1
                                                    interval = (table.duration/4)
                                                }
                                                else {
                                                    ball.yincrement = 0
                                                    interval = (table.duration/2)
                                                }
                                                ball.xincrement *= -1
                                                running = false
                                                right_return_timer.running = true
                                            }
                                            else if (hitsLeftRacket()) {
                                                if(blackRacket.yUwards) {
                                                    if (ball.yincrement == 0)
                                                        ball.yincrement = -ball.ran
                                                    else if (ball.yincrement > 0)
                                                        ball.yincrement *= -1
                                                    interval = (table.duration/4)
                                                }
                                                else if (blackRacket.yDwards) {
                                                    if (ball.yincrement == 0)
                                                        ball.yincrement = ball.ran
                                                    else if (ball.yincrement < 0)
                                                        ball.yincrement *= -1
                                                    interval = (table.duration/4)
                                                }
                                                else {
                                                    ball.yincrement = 0
                                                    interval = (table.duration/2)
                                                }
                                                ball.xincrement *= -1
                                                running = false
                                                left_return_timer.running = true
                                            }
                                            else if (hitsUpperOrLowerWall())
                                                ball.yincrement *= -1
                                            
                                            // Move Ball
                                            ball.x = ball.x + (ball.xincrement * table.step);
                                            ball.y = ball.y + (ball.yincrement * table.step);
                                            
                                            if(rightCounter.count + leftCounter.count == 21) {
                                                in_timer.stop()
                                                if (rightCounter.count > leftCounter.count)
                                                    rightWin.visible = true
                                                else
                                                    leftWin.visible = true
                                            }
                                        }
                                    }
                                }
                            }
                            
                            
                            J.HilkJ Offline
                            J.HilkJ Offline
                            J.Hilk
                            Moderators
                            wrote on last edited by
                            #29

                            Hi @tomy , sorry for the late response.

                            I had a lengthly break, sickness and holiday - thankfully not overlapping. But I'm back now and will take a look later today. I actually managed not to touch my laptop during that time, that was difficult I'll tell ya.

                            Any progress in the last 23 days ?

                            Greetings.


                            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                            Q: What's that?
                            A: It's blue light.
                            Q: What does it do?
                            A: It turns blue.

                            tomyT 1 Reply Last reply
                            2
                            • J.HilkJ J.Hilk

                              Hi @tomy , sorry for the late response.

                              I had a lengthly break, sickness and holiday - thankfully not overlapping. But I'm back now and will take a look later today. I actually managed not to touch my laptop during that time, that was difficult I'll tell ya.

                              Any progress in the last 23 days ?

                              Greetings.

                              tomyT Offline
                              tomyT Offline
                              tomy
                              wrote on last edited by
                              #30

                              @J.Hilk
                              Hi J.Hilk, welcome back. :)
                              I'm very glad that your sickness and holiday haven't had overlapping. :)
                              I hope you're very well now. And Happy New Year to you. :)

                              I see and it's OK. I'm appreciative for your assistance. :) Thanks.
                              Welcome back once again.

                              Any progress in the last 23 days ?

                              That last version was actually modified many times. :) That is, each time I modified it and edited the code here in that last version making it the most recent one for you when you'll get back.

                              The problem was that and I found no remedy so I thought of using a ParallelAnimation as the tool for moving the ball hoping it resolves the issue with the effect of moving the rackets on the ball's movement.

                              I'm still working on it and today or tomorrow will test this new version and post it here too. Can it be a good solution to the problem in your point of view please?

                              1 Reply Last reply
                              1
                              • tomyT Offline
                                tomyT Offline
                                tomy
                                wrote on last edited by
                                #31

                                Well, to cope with that problem I tried Animations in the code the way below.
                                Other components are as before and here is the code after the stopGame() function in main.qml:

                                ...
                                ParallelAnimation {
                                           id: anim
                                           NumberAnimation {
                                               target: ball
                                               properties: "x"
                                               to: in_timer.xMove
                                           }
                                           NumberAnimation {
                                               target: ball
                                               properties: "y"
                                               to: in_timer.yMove
                                           }
                                       }
                                       
                                       Timer {
                                           interval: 40; repeat: true; running: true
                                           
                                           onTriggered: {
                                               redRacket.yUwards = false
                                               redRacket.yDwards = false
                                               blackRacket.yUwards = false
                                               blackRacket.yDwards = false
                                           }
                                       }
                                       Timer {
                                           id: out_timer
                                           interval: 1; repeat: false; running: false
                                           
                                           function lightChange() {
                                               if (table.lightState) {
                                                   rightLight.color = "silver"
                                                   leftLight.color= "lime"
                                               }
                                               else {
                                                   rightLight.color = "lime"
                                                   leftLight.color= "silver"
                                               }
                                               table.lightState = !table.lightState
                                           }
                                           
                                           onTriggered: {
                                               ball.xincrement = Math.random() + 0.5
                                               ball.yincrement = Math.random() + 0.5
                                               
                                               if (table.count % 5 == 0) {
                                                   table.turn = !table.turn
                                                   lightChange()
                                               }
                                               
                                               if (table.turn)
                                                   ball.xincrement *= -1
                                               
                                               ball.x = table.width/2
                                               ball.y = table.height/2
                                               
                                               if (ball.yincrement > 1.1)
                                                   ball.yincrement *= -1
                                               
                                               in_timer.restart()
                                               table.count++
                                           }
                                       }
                                       Timer {
                                           id: right_return_timer
                                           interval: 1; repeat: true; running: false
                                           onTriggered: {
                                               in_timer.xMove += ball.xincrement * table.step
                                               in_timer.yMove += ball.yincrement * table.step
                                               anim.restart()
                                               if(ball.x + ball.width < redRacket.x) {
                                                   running = false
                                                   in_timer.running = true
                                               }
                                           }
                                       }
                                       Timer {
                                           id: left_return_timer
                                           interval: 1; repeat: true; running: false
                                           onTriggered: {
                                               in_timer.xMove += ball.xincrement * table.step
                                               in_timer.yMove += ball.yincrement * table.step
                                               anim.restart()
                                               if(ball.x > blackRacket.x + blackRacket.width) {
                                                   running = false
                                                   in_timer.running = true
                                               }
                                           }
                                       }
                                       Timer {
                                           id: in_timer
                                           interval: table.duration; repeat: true; running: false
                                           property double xMove: ball.x
                                           property double yMove: ball.y
                                           
                                           function hitsRightRacket() {
                                               if ((ball.x + ball.width >= redRacket.x &&
                                                    ball.x <= redRacket.x + redRacket.width) &&
                                                       (ball.y + ball.height >= redRacket.y &&
                                                        ball.y <= redRacket.y + redRacket.height))
                                                   return true
                                               return false
                                           }
                                           function hitsLeftRacket() {
                                               if ((ball.x + ball.width >= blackRacket.x &&
                                                    ball.x < blackRacket.x + blackRacket.width)  &&
                                                       (ball.y + ball.height >= blackRacket.y &&
                                                        ball.y <= blackRacket.y + blackRacket.height))
                                                   return true
                                               return false
                                           }
                                           function hitsUpperOrLowerWall(){
                                               if (ball.y <= 0)
                                                   return true
                                               else if (ball.y + ball.height >= table.height)
                                                   return true
                                               return false
                                           }
                                           function hitsRightWall() {
                                               if (ball.x + ball.width >= table.width)
                                                   return true
                                               return false
                                           }
                                           function hitsLeftWall() {
                                               if (ball.x <= 0) return true
                                               else return false
                                           }
                                           
                                           onTriggered: {
                                               if (hitsRightWall()) {
                                                   stop()
                                                   leftCounter.count++
                                                   out_timer.interval = 2000
                                                   out_timer.running = true
                                               }
                                               else if (hitsLeftWall()) {
                                                   stop()
                                                   rightCounter.count++
                                                   out_timer.interval = 2000
                                                   out_timer.running = true
                                               }
                                               else if (hitsRightRacket()) {
                                                   if (redRacket.yUwards) {
                                                       if (ball.yincrement == 0)
                                                           ball.yincrement = -ball.ran
                                                       else if (ball.yincrement > 0)
                                                           ball.yincrement = ball.yincrement > 0 ?
                                                                       -ball.yincrement: ball.yincrement
                                                       interval = (table.duration/4)
                                                   }
                                                   else if (redRacket.yDwards) {
                                                       if (ball.yincrement == 0)
                                                           ball.yincrement = ball.ran
                                                       else if (ball.yincrement < 0)
                                                           ball.yincrement = ball.yincrement > 0 ?
                                                                       -ball.yincrement: ball.yincrement
                                                       interval = (table.duration/4)
                                                   }
                                                   else {
                                                       ball.yincrement = 0
                                                       interval = (table.duration/2)
                                                   }
                                                   ball.xincrement = ball.xincrement > 0 ?
                                                               -ball.xincrement: ball.xincrement
                                                   running = false
                                                   right_return_timer.running = true
                                               }
                                               else if (hitsLeftRacket()) {
                                                   if(blackRacket.yUwards) {
                                                       if (ball.yincrement == 0)
                                                           ball.yincrement = -ball.ran
                                                       else if (ball.yincrement > 0)
                                                           ball.yincrement = ball.yincrement > 0 ?
                                                                       -ball.yincrement: ball.yincrement
                                                       interval = (table.duration/4)
                                                   }
                                                   else if (blackRacket.yDwards) {
                                                       if (ball.yincrement == 0)
                                                           ball.yincrement = ball.ran
                                                       else if (ball.yincrement < 0)
                                                           ball.yincrement = ball.yincrement > 0 ?
                                                                       -ball.yincrement: ball.yincrement
                                                       interval = (table.duration/4)
                                                   }
                                                   else {
                                                       ball.yincrement = 0
                                                       interval = (table.duration/2)
                                                   }
                                                   ball.xincrement = ball.xincrement > 0 ?
                                                               -ball.xincrement: ball.xincrement
                                                   running = false
                                                   left_return_timer.running = true
                                               }
                                               else if (hitsUpperOrLowerWall())
                                                   ball.yincrement = ball.yincrement > 0 ?
                                                               -ball.yincrement: ball.yincrement
                                               
                                               // Move Ball
                                               xMove += (ball.xincrement * table.step);
                                               yMove += (ball.yincrement * table.step);
                                               anim.restart()
                                               
                                               if(rightCounter.count + leftCounter.count == 21) {
                                                   stop()
                                                   if (rightCounter.count > leftCounter.count)
                                                       rightWin.visible = true
                                                   else
                                                       leftWin.visible = true
                                               }
                                           }
                                       }
                                   }
                                }
                                

                                This code also has several problems! One of them is that the ball doesn't stop when it hits the right or left wall. I tired several statements, like:
                                stop()
                                in_timer.stop()
                                running = false
                                anim.stop()
                                but neither works!

                                J.HilkJ 1 Reply Last reply
                                0
                                • tomyT tomy

                                  Well, to cope with that problem I tried Animations in the code the way below.
                                  Other components are as before and here is the code after the stopGame() function in main.qml:

                                  ...
                                  ParallelAnimation {
                                             id: anim
                                             NumberAnimation {
                                                 target: ball
                                                 properties: "x"
                                                 to: in_timer.xMove
                                             }
                                             NumberAnimation {
                                                 target: ball
                                                 properties: "y"
                                                 to: in_timer.yMove
                                             }
                                         }
                                         
                                         Timer {
                                             interval: 40; repeat: true; running: true
                                             
                                             onTriggered: {
                                                 redRacket.yUwards = false
                                                 redRacket.yDwards = false
                                                 blackRacket.yUwards = false
                                                 blackRacket.yDwards = false
                                             }
                                         }
                                         Timer {
                                             id: out_timer
                                             interval: 1; repeat: false; running: false
                                             
                                             function lightChange() {
                                                 if (table.lightState) {
                                                     rightLight.color = "silver"
                                                     leftLight.color= "lime"
                                                 }
                                                 else {
                                                     rightLight.color = "lime"
                                                     leftLight.color= "silver"
                                                 }
                                                 table.lightState = !table.lightState
                                             }
                                             
                                             onTriggered: {
                                                 ball.xincrement = Math.random() + 0.5
                                                 ball.yincrement = Math.random() + 0.5
                                                 
                                                 if (table.count % 5 == 0) {
                                                     table.turn = !table.turn
                                                     lightChange()
                                                 }
                                                 
                                                 if (table.turn)
                                                     ball.xincrement *= -1
                                                 
                                                 ball.x = table.width/2
                                                 ball.y = table.height/2
                                                 
                                                 if (ball.yincrement > 1.1)
                                                     ball.yincrement *= -1
                                                 
                                                 in_timer.restart()
                                                 table.count++
                                             }
                                         }
                                         Timer {
                                             id: right_return_timer
                                             interval: 1; repeat: true; running: false
                                             onTriggered: {
                                                 in_timer.xMove += ball.xincrement * table.step
                                                 in_timer.yMove += ball.yincrement * table.step
                                                 anim.restart()
                                                 if(ball.x + ball.width < redRacket.x) {
                                                     running = false
                                                     in_timer.running = true
                                                 }
                                             }
                                         }
                                         Timer {
                                             id: left_return_timer
                                             interval: 1; repeat: true; running: false
                                             onTriggered: {
                                                 in_timer.xMove += ball.xincrement * table.step
                                                 in_timer.yMove += ball.yincrement * table.step
                                                 anim.restart()
                                                 if(ball.x > blackRacket.x + blackRacket.width) {
                                                     running = false
                                                     in_timer.running = true
                                                 }
                                             }
                                         }
                                         Timer {
                                             id: in_timer
                                             interval: table.duration; repeat: true; running: false
                                             property double xMove: ball.x
                                             property double yMove: ball.y
                                             
                                             function hitsRightRacket() {
                                                 if ((ball.x + ball.width >= redRacket.x &&
                                                      ball.x <= redRacket.x + redRacket.width) &&
                                                         (ball.y + ball.height >= redRacket.y &&
                                                          ball.y <= redRacket.y + redRacket.height))
                                                     return true
                                                 return false
                                             }
                                             function hitsLeftRacket() {
                                                 if ((ball.x + ball.width >= blackRacket.x &&
                                                      ball.x < blackRacket.x + blackRacket.width)  &&
                                                         (ball.y + ball.height >= blackRacket.y &&
                                                          ball.y <= blackRacket.y + blackRacket.height))
                                                     return true
                                                 return false
                                             }
                                             function hitsUpperOrLowerWall(){
                                                 if (ball.y <= 0)
                                                     return true
                                                 else if (ball.y + ball.height >= table.height)
                                                     return true
                                                 return false
                                             }
                                             function hitsRightWall() {
                                                 if (ball.x + ball.width >= table.width)
                                                     return true
                                                 return false
                                             }
                                             function hitsLeftWall() {
                                                 if (ball.x <= 0) return true
                                                 else return false
                                             }
                                             
                                             onTriggered: {
                                                 if (hitsRightWall()) {
                                                     stop()
                                                     leftCounter.count++
                                                     out_timer.interval = 2000
                                                     out_timer.running = true
                                                 }
                                                 else if (hitsLeftWall()) {
                                                     stop()
                                                     rightCounter.count++
                                                     out_timer.interval = 2000
                                                     out_timer.running = true
                                                 }
                                                 else if (hitsRightRacket()) {
                                                     if (redRacket.yUwards) {
                                                         if (ball.yincrement == 0)
                                                             ball.yincrement = -ball.ran
                                                         else if (ball.yincrement > 0)
                                                             ball.yincrement = ball.yincrement > 0 ?
                                                                         -ball.yincrement: ball.yincrement
                                                         interval = (table.duration/4)
                                                     }
                                                     else if (redRacket.yDwards) {
                                                         if (ball.yincrement == 0)
                                                             ball.yincrement = ball.ran
                                                         else if (ball.yincrement < 0)
                                                             ball.yincrement = ball.yincrement > 0 ?
                                                                         -ball.yincrement: ball.yincrement
                                                         interval = (table.duration/4)
                                                     }
                                                     else {
                                                         ball.yincrement = 0
                                                         interval = (table.duration/2)
                                                     }
                                                     ball.xincrement = ball.xincrement > 0 ?
                                                                 -ball.xincrement: ball.xincrement
                                                     running = false
                                                     right_return_timer.running = true
                                                 }
                                                 else if (hitsLeftRacket()) {
                                                     if(blackRacket.yUwards) {
                                                         if (ball.yincrement == 0)
                                                             ball.yincrement = -ball.ran
                                                         else if (ball.yincrement > 0)
                                                             ball.yincrement = ball.yincrement > 0 ?
                                                                         -ball.yincrement: ball.yincrement
                                                         interval = (table.duration/4)
                                                     }
                                                     else if (blackRacket.yDwards) {
                                                         if (ball.yincrement == 0)
                                                             ball.yincrement = ball.ran
                                                         else if (ball.yincrement < 0)
                                                             ball.yincrement = ball.yincrement > 0 ?
                                                                         -ball.yincrement: ball.yincrement
                                                         interval = (table.duration/4)
                                                     }
                                                     else {
                                                         ball.yincrement = 0
                                                         interval = (table.duration/2)
                                                     }
                                                     ball.xincrement = ball.xincrement > 0 ?
                                                                 -ball.xincrement: ball.xincrement
                                                     running = false
                                                     left_return_timer.running = true
                                                 }
                                                 else if (hitsUpperOrLowerWall())
                                                     ball.yincrement = ball.yincrement > 0 ?
                                                                 -ball.yincrement: ball.yincrement
                                                 
                                                 // Move Ball
                                                 xMove += (ball.xincrement * table.step);
                                                 yMove += (ball.yincrement * table.step);
                                                 anim.restart()
                                                 
                                                 if(rightCounter.count + leftCounter.count == 21) {
                                                     stop()
                                                     if (rightCounter.count > leftCounter.count)
                                                         rightWin.visible = true
                                                     else
                                                         leftWin.visible = true
                                                 }
                                             }
                                         }
                                     }
                                  }
                                  

                                  This code also has several problems! One of them is that the ball doesn't stop when it hits the right or left wall. I tired several statements, like:
                                  stop()
                                  in_timer.stop()
                                  running = false
                                  anim.stop()
                                  but neither works!

                                  J.HilkJ Offline
                                  J.HilkJ Offline
                                  J.Hilk
                                  Moderators
                                  wrote on last edited by J.Hilk
                                  #32

                                  hey @tomy ,

                                  I used the code from your previous post, the one before the last one, and brought it on my iphone.

                                  For me it works flawlessly, no slowdown at all.

                                  Take a look at this video:
                                  Video
                                  Edit: video link fixed, thanks to @mrjj

                                  In fact, the animation/movement of the ball is too fast in my opinion.

                                  Did you compile the release version for your android device? Debug versions are ressource demanding and may result in slow animations on old devices.

                                  The racket movment invokes a property binding recalculations, that is executed as soon as the event loop returns, I believe.
                                  The Movement of the ball and checks are all depending on timers, during the property binding induced calculations those timers may queue up, that then results in a slow Ball-Animation.


                                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                  Q: What's that?
                                  A: It's blue light.
                                  Q: What does it do?
                                  A: It turns blue.

                                  tomyT 1 Reply Last reply
                                  1
                                  • mrjjM Offline
                                    mrjjM Offline
                                    mrjj
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #33

                                    Hi
                                    Video link didnt work for me but i could extract
                                    https://vimeo.com/251451461

                                    1 Reply Last reply
                                    1
                                    • J.HilkJ J.Hilk

                                      hey @tomy ,

                                      I used the code from your previous post, the one before the last one, and brought it on my iphone.

                                      For me it works flawlessly, no slowdown at all.

                                      Take a look at this video:
                                      Video
                                      Edit: video link fixed, thanks to @mrjj

                                      In fact, the animation/movement of the ball is too fast in my opinion.

                                      Did you compile the release version for your android device? Debug versions are ressource demanding and may result in slow animations on old devices.

                                      The racket movment invokes a property binding recalculations, that is executed as soon as the event loop returns, I believe.
                                      The Movement of the ball and checks are all depending on timers, during the property binding induced calculations those timers may queue up, that then results in a slow Ball-Animation.

                                      tomyT Offline
                                      tomyT Offline
                                      tomy
                                      wrote on last edited by tomy
                                      #34

                                      @J.Hilk

                                      For me it works flawlessly, no slowdown at all.
                                      Take a look at this video:
                                      Video
                                      Edit: video link fixed, thanks to @mrjj

                                      Hallo, Thank you very much.

                                      In fact, the animation/movement of the ball is too fast in my opinion.

                                      I think by increasing table.duration it will be solved

                                      Did you compile the release version for your android device? Debug versions are ressource demanding and may result in slow animations on old devices.

                                      Well, when testing on the Desktop kit on my Windows, the program has no problem. It's fine. When switching to "Android for armeabi-v7a (GCC 4.9, Qt 5.10.0 for Android armv7)" kit in both Debug and Release modes, I get these two issues in the Issues window which are the same apparently. I don't know if it's related to the problem on Android devices or not.

                                      :-1: warning: "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc" is used by qmake, but "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe" is configured in the kit.
                                      Please update your kit or choose a mkspec for qmake that matches your target environment better.

                                      :-1: warning: "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++" is used by qmake, but "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++.exe" is configured in the kit.
                                      Please update your kit or choose a mkspec for qmake that matches your target environment better.

                                      The racket movment invokes a property binding recalculations, that is executed as soon as the event loop returns, I believe.
                                      The Movement of the ball and checks are all depending on timers, during the property binding induced calculations those timers may queue up, that then results in a slow Ball-Animation.

                                      I'm not sure I can understand it well. Probably it's a too advanced for me. If it can be a lead, is there any solution for that please?

                                      J.HilkJ 1 Reply Last reply
                                      0
                                      • tomyT tomy

                                        @J.Hilk

                                        For me it works flawlessly, no slowdown at all.
                                        Take a look at this video:
                                        Video
                                        Edit: video link fixed, thanks to @mrjj

                                        Hallo, Thank you very much.

                                        In fact, the animation/movement of the ball is too fast in my opinion.

                                        I think by increasing table.duration it will be solved

                                        Did you compile the release version for your android device? Debug versions are ressource demanding and may result in slow animations on old devices.

                                        Well, when testing on the Desktop kit on my Windows, the program has no problem. It's fine. When switching to "Android for armeabi-v7a (GCC 4.9, Qt 5.10.0 for Android armv7)" kit in both Debug and Release modes, I get these two issues in the Issues window which are the same apparently. I don't know if it's related to the problem on Android devices or not.

                                        :-1: warning: "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc" is used by qmake, but "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-gcc.exe" is configured in the kit.
                                        Please update your kit or choose a mkspec for qmake that matches your target environment better.

                                        :-1: warning: "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++" is used by qmake, but "D:\android-ndk-r10e\toolchains\arm-linux-androideabi-4.9\prebuilt\windows-x86_64\bin\arm-linux-androideabi-g++.exe" is configured in the kit.
                                        Please update your kit or choose a mkspec for qmake that matches your target environment better.

                                        The racket movment invokes a property binding recalculations, that is executed as soon as the event loop returns, I believe.
                                        The Movement of the ball and checks are all depending on timers, during the property binding induced calculations those timers may queue up, that then results in a slow Ball-Animation.

                                        I'm not sure I can understand it well. Probably it's a too advanced for me. If it can be a lead, is there any solution for that please?

                                        J.HilkJ Offline
                                        J.HilkJ Offline
                                        J.Hilk
                                        Moderators
                                        wrote on last edited by
                                        #35

                                        @tomy mmh, my Idea would be to marry your QMl-program with a cpp class, that does the heavy stuff.

                                        Your cpp-class could/should have Q_properties that are bound to ball.x and ball.y and right/leftracket position.

                                        That class could emit signals when the ball hits something and trigger the new ball position etc.

                                        Thats a bit more work than I can justify right now, but I'll look into it a bit more during lunch-break ;-)


                                        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                                        Q: What's that?
                                        A: It's blue light.
                                        Q: What does it do?
                                        A: It turns blue.

                                        tomyT 1 Reply Last reply
                                        2
                                        • J.HilkJ J.Hilk

                                          @tomy mmh, my Idea would be to marry your QMl-program with a cpp class, that does the heavy stuff.

                                          Your cpp-class could/should have Q_properties that are bound to ball.x and ball.y and right/leftracket position.

                                          That class could emit signals when the ball hits something and trigger the new ball position etc.

                                          Thats a bit more work than I can justify right now, but I'll look into it a bit more during lunch-break ;-)

                                          tomyT Offline
                                          tomyT Offline
                                          tomy
                                          wrote on last edited by
                                          #36

                                          @J.Hilk
                                          Hi, thank you for your suggestion. I've used C++ for console applications on Visual Studio and also used it on Qt Creator for a few Qt programs. And also have used QML on Qt Creator as in this program. But I've never used C++ in a QML program! So it seems hard for me. But if it's the solution to make the program run correctly on Android devices, OK, I will go for that. But where to start?

                                          J.HilkJ 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved