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

    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
                          • tomyT tomy

                            @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 Offline
                            J.HilkJ Offline
                            J.Hilk
                            Moderators
                            wrote on last edited by
                            #37

                            @tomy

                            theres a very basic example in the docu, that is really good to get general understanding of a c++ backend for a qml program:

                            Let me link that for you


                            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.

                            1 Reply Last reply
                            1
                            • J.HilkJ Offline
                              J.HilkJ Offline
                              J.Hilk
                              Moderators
                              wrote on last edited by
                              #38

                              heres an quick example how your Backend could look like:

                              //PropertyBase.h
                              #ifndef PROPERTYBASE_H
                              #define PROPERTYBASE_H
                              
                              #include <QObject>
                              
                              class PropertyBase : public QObject
                              {
                                  Q_OBJECT
                                  
                                  Q_PROPERTY(double xBall READ xBall WRITE setXBall NOTIFY xBallChanged)
                                  Q_PROPERTY(double yBall READ yBall WRITE setYBall NOTIFY yBallChanged)
                                  Q_PROPERTY(double wBall READ wBall WRITE setWBall NOTIFY wBallChanged)
                                  Q_PROPERTY(double hBall READ hBall WRITE setHBall NOTIFY hBallChanged)
                                  
                                  Q_PROPERTY(double xRedRacket READ xRedRacket WRITE setXRedRacket NOTIFY xRedRacketChanged)
                                  Q_PROPERTY(double yRedRacket READ yRedRacket WRITE setYRedRacket NOTIFY yRedRacketChanged)
                                  Q_PROPERTY(double wRedRacket READ wRedRacket WRITE setWRedRacket NOTIFY wRedRacketChanged)
                                  Q_PROPERTY(double hRedRacket READ hRedRacket WRITE setHRedRacket NOTIFY hRedRacketChanged)
                                  
                                  Q_PROPERTY(double xBlackRacket READ xBlackRacket WRITE setXBlackRacket NOTIFY xBlackRacketChanged)
                                  Q_PROPERTY(double yBlackRacket READ yBlackRacket WRITE setYBlackRacket NOTIFY yBlackRacketChanged)
                                  Q_PROPERTY(double wBlackRacket READ wBlackRacket WRITE setWBlackRacket NOTIFY wBlackRacketChanged)
                                  Q_PROPERTY(double hBlackRacket READ hBlackRacket WRITE setHBlackRacket NOTIFY hBlackRacketChanged)
                                  
                                  Q_PROPERTY(double wScreen READ wScreen WRITE setWScreen NOTIFY wScreenChanged)
                                  Q_PROPERTY(double hScreen READ hScreen WRITE setHScreen NOTIFY hScreenChanged)
                                  
                                  inline double xBall(){return m_xBall;}
                                  inline double yBall(){return m_yBall;}
                                  inline double wBall(){return m_wBall;}
                                  inline double hBall(){return m_hBall;}
                                  
                                  inline double xRedRacket(){return m_xrRacket;}
                                  inline double yRedRacket(){return m_yrRacket;}
                                  inline double wRedRacket(){return m_wrRacket;}
                                  inline double hRedRacket(){return m_hrRacket;}
                                  
                                  inline double xBlackRacket(){return m_xbRacket;}
                                  inline double yBlackRacket(){return m_ybRacket;}
                                  inline double wBlackRacket(){return m_wbRacket;}
                                  inline double hBlackRacket(){return m_hbRacket;}
                                  
                                  inline double wScreen(){return m_wScreen;}
                                  inline double hScreen(){return m_hScreen;}
                                  
                                  void setXBall(const double &);
                                  void setYBall(const double &);
                                  void setWBall(const double &);
                                  void setHBall(const double &);
                                  
                                  void setXRedRacket(const double &);
                                  void setYRedRacket(const double &);
                                  void setWRedRacket(const double &);
                                  void setHRedRacket(const double &);
                                  
                                  void setXBlackRacket(const double &);
                                  void setYBlackRacket(const double &);
                                  void setWBlackRacket(const double &);
                                  void setHBlackRacket(const double &);
                                  
                                  void setWScreen(const double &);
                                  void setHScreen(const double &);
                              public:
                                  explicit PropertyBase(QObject *parent = nullptr);
                              
                              signals:
                                  void xBallChanged();
                                  void yBallChanged();
                                  void wBallChanged();
                                  void hBallChanged();
                                  
                                  void xRedRacketChanged();
                                  void yRedRacketChanged();
                                  void wRedRacketChanged();
                                  void hRedRacketChanged();
                                  
                                  void xBlackRacketChanged();
                                  void yBlackRacketChanged();
                                  void wBlackRacketChanged();
                                  void hBlackRacketChanged();
                                  
                                  void wScreenChanged();
                                  void hScreenChanged();
                              protected:
                                  double m_xBall;
                                  double m_yBall;
                                  double m_wBall;
                                  double m_hBall;
                                  
                                  double m_xrRacket;
                                  double m_yrRacket;
                                  double m_wrRacket;
                                  double m_hrRacket;
                                  
                                  double m_xbRacket;
                                  double m_ybRacket;
                                  double m_wbRacket;
                                  double m_hbRacket;
                                  
                                  double m_wScreen;
                                  double m_hScreen;
                              };
                              
                              #endif // PROPERTYBASE_H
                              

                              //

                              //PropertyBase.cpp
                              #include "propertybase.h"
                              
                              
                              PropertyBase::PropertyBase(QObject *parent) : QObject(parent)
                              {
                              
                              }
                              
                              void PropertyBase::setXBall(const double &value)
                              {
                                  if(value != m_xBall){
                                      m_xBall = value;
                                      emit xBallChanged();
                                  }
                              }
                              
                              void PropertyBase::setYBall(const double &value)
                              {
                                  if(value != m_YBall){
                                      m_yBall = value;
                                      emit yBallChanged();
                                  }
                              }
                              
                              void PropertyBase::setWBall(const double &value)
                              {
                                  if(value != m_wBall){
                                      m_wBall = value;
                                      emit wBallChanged();
                                  }
                              }
                              
                              void PropertyBase::setHBall(const double &value)
                              {
                                  if(value != m_hBall){
                                      m_hBall = value;
                                      emit hBallChanged();
                                  }
                              }
                              
                              void PropertyBase::setXRedRacket(const double &value)
                              {
                                  if(value != m_xrRacket){
                                      m_xrRacket = value;
                                      emit xRedRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setYRedRacket(const double &value)
                              {
                                  if(value != m_yrRacket){
                                      m_yrRacket = value;
                                      emit yRedRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setWRedRacket(const double &value)
                              {
                                  if(value != m_wrRacket){
                                      m_wrRacket = value;
                                      emit wRedRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setHRedRacket(const double &value)
                              {
                                  if(value != m_hrRacket){
                                      m_hrRacket = value;
                                      emit hRedRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setXBlackRacket(const double &value)
                              {
                                  if(value != m_xbRacket){
                                      m_xbRacket = value;
                                      emit xBlackRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setYBlackRacket(const double &value)
                              {
                                  if(value != m_ybRacket){
                                      m_ybRacket = value;
                                      emit yBlackRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setWBlackRacket(const double &value)
                              {
                                  if(value != m_wbRacket){
                                      m_wbRacket = value;
                                      emit wBlackRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setHBlackRacket(const double &value)
                              {
                                  if(value != m_hbRacket){
                                      m_hbRacket = value;
                                      emit hBlackRacketChanged();
                                  }
                              }
                              
                              void PropertyBase::setWScreen(const double &value)
                              {
                                  if(value != m_wScreen){
                                      m_wScreen = value;
                                      emit wScreenChanged();
                                  }
                              }
                              
                              void PropertyBase::setHScreen(const double &value)
                              {
                                  if(value != m_hScreen){
                                      m_hScreen = value;
                                      emit hScreenChanged();
                                  }
                              }
                              
                              //Backend.h
                              #ifndef BACKEND_H
                              #define BACKEND_H
                              
                              #include "propertybase.h"
                              #include <QTimer>
                              
                              class BackEnd : public PropertyBase
                              {
                                  Q_OBJECT
                                  
                              public:
                                  explicit BackEnd(PropertyBase *parent = nullptr);
                              
                                  Q_INVOKABLE void timerStart(){m_BallTimer.start(m_timerInterval);}
                                  Q_INVOKABLE void timerStop(){m_BallTimer.stop();}
                                  
                                  Q_INVOKABLE void setInterval(int & interval){
                                      m_timerInterval = interval;
                                      m_BallTimer.setInterval(interval);
                                  }
                                  
                              signals:
                                  void rightWallhit();
                                  void leftWallHit();
                                  void rightRacketHit();
                                  void leftRacketHit();
                                  void upperOrLowerWallHit();
                                  
                                  void moveBall();
                              
                              public slots:
                                  
                              private:
                                  bool hitsRightRacket();
                                  bool hitsLeftRacket();
                                  
                                  bool hitsUpperOrLowerWall();
                                  bool hitsRightWall();
                                  bool hitsLeftWall();
                                  
                              private slots:
                                  void doCalculation();
                                  
                              protected:
                                  int m_timerInterval = 10;
                                  QTimer m_BallTimer;
                              };
                              
                              #endif // BACKEND_H
                              
                              //Backend.cpp
                              #include "backend.h"
                              
                              BackEnd::BackEnd(PropertyBase *parent) : PropertyBase(parent)
                              {
                                  connect(&m_BallTimer, &QTimer::timeout, this, &BackEnd::doCalculation);
                              }
                              
                              bool BackEnd::hitsRightRacket()
                              {
                                  if( (xBall() + wBall() >= xRedRacket() && xBall() <= xRedRacket() + wRedRacket() ) &&
                                      (yBall() + hBall() >= yRedRacket() && yBall() <= yRedRacket() + hRedRacket() ))
                                      return true;
                                  
                                  return false;
                              }
                              
                              bool BackEnd::hitsLeftRacket()
                              {
                                  if( (xBall() + wBall() >= xBlackRacket() && xBall() <= xBlackRacket() + wBlackRacket() ) &&
                                      (yBall() + hBall() >= yBlackRacket() && yBall() <= yBlackRacket() + hBlackRacket() ))
                                      return true;
                                  
                                  return false;
                              }
                              
                              bool BackEnd::hitsUpperOrLowerWall()
                              {
                                  if(yBall() <= 0 || yBall() +hBall() >= hScreen())
                                      return true;
                                  
                                  return false;
                              }
                              
                              bool BackEnd::hitsRightWall()
                              {
                                  if(xBall() + wBall() >= wScreen())
                                      return true;
                                  
                                  return false;
                              }
                              
                              bool BackEnd::hitsLeftWall()
                              {
                                  if(xBall() <= 0)
                                      return true;
                                  
                                  return false;
                              }
                              
                              void BackEnd::doCalculation()
                              {
                                  if(hitsRightWall()){
                                      timerStop();
                                      emit rightWallhit();
                                  }
                                  
                                  if(hitsLeftWall()){
                                      timerStop();
                                      emit leftWallHit();
                                  }
                                  
                                  if(hitsRightRacket())
                                      emit rightRacketHit();
                                  
                                  if(hitsLeftRacket())
                                      emit leftRacketHit();
                                  
                                  if(hitsUpperOrLowerWall())
                                      emit upperOrLowerWallHit();
                                  
                                  emit moveBall();
                              }
                              
                              
                              //main.cpp
                              #include <QGuiApplication>
                              #include <QQmlApplicationEngine>
                              
                              #include "backend.h"
                              
                              int main(int argc, char *argv[])
                              {
                                  QGuiApplication app(argc, argv);
                                  
                                  qmlRegisterType<BackEnd>("myBackend",1,0,"BackEnd");
                              
                                  QQmlApplicationEngine engine;
                                  engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                                  if (engine.rootObjects().isEmpty())
                                      return -1;
                              
                                  return app.exec();
                              }
                              
                              
                              //main.qml
                              Window {
                                  id: window
                                  visibility: Window.Maximized
                                  title: qsTr("The PingPong Game - A QML Game")
                                  color: "gray"
                                  
                                  
                                  BackEnd{
                                      id:myBackend
                                      
                                      xBall: ball.x
                                      yBall: ball.y
                                      wBall: ball.width
                                      hBall: ball.height
                                      
                                      xRedRacket: redRacket.x
                                      yRedRacket: redRacket.y
                                      //....
                                      
                                      onRightWallhit: {
                                          leftCounter.count++
                                          out_timer.interval = 2000
                                          out_timer.running = true
                                      }
                                      onLeftWallHit: {
                                          rightCounter.count++
                                          out_timer.interval = 2000
                                          out_timer.running = true
                                      }
                                      onRightRacketHit: {
                                          if (redRacket.yUwards) {
                                              if (ball.yincrement == 0)
                                                  ball.yincrement = -ball.ran
                                              else if (ball.yincrement > 0)
                                                  ball.yincrement *= -1
                                              
                                          }
                                          else if (redRacket.yDwards) {
                                              if (ball.yincrement == 0)
                                                  ball.yincrement = ball.ran
                                              else if (ball.yincrement < 0)
                                                  ball.yincrement *= -1
                                              setInterval(table.duration/4)
                                          }
                                      }
                                       ....
                                  }
                              .....
                              }
                              

                              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

                                heres an quick example how your Backend could look like:

                                //PropertyBase.h
                                #ifndef PROPERTYBASE_H
                                #define PROPERTYBASE_H
                                
                                #include <QObject>
                                
                                class PropertyBase : public QObject
                                {
                                    Q_OBJECT
                                    
                                    Q_PROPERTY(double xBall READ xBall WRITE setXBall NOTIFY xBallChanged)
                                    Q_PROPERTY(double yBall READ yBall WRITE setYBall NOTIFY yBallChanged)
                                    Q_PROPERTY(double wBall READ wBall WRITE setWBall NOTIFY wBallChanged)
                                    Q_PROPERTY(double hBall READ hBall WRITE setHBall NOTIFY hBallChanged)
                                    
                                    Q_PROPERTY(double xRedRacket READ xRedRacket WRITE setXRedRacket NOTIFY xRedRacketChanged)
                                    Q_PROPERTY(double yRedRacket READ yRedRacket WRITE setYRedRacket NOTIFY yRedRacketChanged)
                                    Q_PROPERTY(double wRedRacket READ wRedRacket WRITE setWRedRacket NOTIFY wRedRacketChanged)
                                    Q_PROPERTY(double hRedRacket READ hRedRacket WRITE setHRedRacket NOTIFY hRedRacketChanged)
                                    
                                    Q_PROPERTY(double xBlackRacket READ xBlackRacket WRITE setXBlackRacket NOTIFY xBlackRacketChanged)
                                    Q_PROPERTY(double yBlackRacket READ yBlackRacket WRITE setYBlackRacket NOTIFY yBlackRacketChanged)
                                    Q_PROPERTY(double wBlackRacket READ wBlackRacket WRITE setWBlackRacket NOTIFY wBlackRacketChanged)
                                    Q_PROPERTY(double hBlackRacket READ hBlackRacket WRITE setHBlackRacket NOTIFY hBlackRacketChanged)
                                    
                                    Q_PROPERTY(double wScreen READ wScreen WRITE setWScreen NOTIFY wScreenChanged)
                                    Q_PROPERTY(double hScreen READ hScreen WRITE setHScreen NOTIFY hScreenChanged)
                                    
                                    inline double xBall(){return m_xBall;}
                                    inline double yBall(){return m_yBall;}
                                    inline double wBall(){return m_wBall;}
                                    inline double hBall(){return m_hBall;}
                                    
                                    inline double xRedRacket(){return m_xrRacket;}
                                    inline double yRedRacket(){return m_yrRacket;}
                                    inline double wRedRacket(){return m_wrRacket;}
                                    inline double hRedRacket(){return m_hrRacket;}
                                    
                                    inline double xBlackRacket(){return m_xbRacket;}
                                    inline double yBlackRacket(){return m_ybRacket;}
                                    inline double wBlackRacket(){return m_wbRacket;}
                                    inline double hBlackRacket(){return m_hbRacket;}
                                    
                                    inline double wScreen(){return m_wScreen;}
                                    inline double hScreen(){return m_hScreen;}
                                    
                                    void setXBall(const double &);
                                    void setYBall(const double &);
                                    void setWBall(const double &);
                                    void setHBall(const double &);
                                    
                                    void setXRedRacket(const double &);
                                    void setYRedRacket(const double &);
                                    void setWRedRacket(const double &);
                                    void setHRedRacket(const double &);
                                    
                                    void setXBlackRacket(const double &);
                                    void setYBlackRacket(const double &);
                                    void setWBlackRacket(const double &);
                                    void setHBlackRacket(const double &);
                                    
                                    void setWScreen(const double &);
                                    void setHScreen(const double &);
                                public:
                                    explicit PropertyBase(QObject *parent = nullptr);
                                
                                signals:
                                    void xBallChanged();
                                    void yBallChanged();
                                    void wBallChanged();
                                    void hBallChanged();
                                    
                                    void xRedRacketChanged();
                                    void yRedRacketChanged();
                                    void wRedRacketChanged();
                                    void hRedRacketChanged();
                                    
                                    void xBlackRacketChanged();
                                    void yBlackRacketChanged();
                                    void wBlackRacketChanged();
                                    void hBlackRacketChanged();
                                    
                                    void wScreenChanged();
                                    void hScreenChanged();
                                protected:
                                    double m_xBall;
                                    double m_yBall;
                                    double m_wBall;
                                    double m_hBall;
                                    
                                    double m_xrRacket;
                                    double m_yrRacket;
                                    double m_wrRacket;
                                    double m_hrRacket;
                                    
                                    double m_xbRacket;
                                    double m_ybRacket;
                                    double m_wbRacket;
                                    double m_hbRacket;
                                    
                                    double m_wScreen;
                                    double m_hScreen;
                                };
                                
                                #endif // PROPERTYBASE_H
                                

                                //

                                //PropertyBase.cpp
                                #include "propertybase.h"
                                
                                
                                PropertyBase::PropertyBase(QObject *parent) : QObject(parent)
                                {
                                
                                }
                                
                                void PropertyBase::setXBall(const double &value)
                                {
                                    if(value != m_xBall){
                                        m_xBall = value;
                                        emit xBallChanged();
                                    }
                                }
                                
                                void PropertyBase::setYBall(const double &value)
                                {
                                    if(value != m_YBall){
                                        m_yBall = value;
                                        emit yBallChanged();
                                    }
                                }
                                
                                void PropertyBase::setWBall(const double &value)
                                {
                                    if(value != m_wBall){
                                        m_wBall = value;
                                        emit wBallChanged();
                                    }
                                }
                                
                                void PropertyBase::setHBall(const double &value)
                                {
                                    if(value != m_hBall){
                                        m_hBall = value;
                                        emit hBallChanged();
                                    }
                                }
                                
                                void PropertyBase::setXRedRacket(const double &value)
                                {
                                    if(value != m_xrRacket){
                                        m_xrRacket = value;
                                        emit xRedRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setYRedRacket(const double &value)
                                {
                                    if(value != m_yrRacket){
                                        m_yrRacket = value;
                                        emit yRedRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setWRedRacket(const double &value)
                                {
                                    if(value != m_wrRacket){
                                        m_wrRacket = value;
                                        emit wRedRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setHRedRacket(const double &value)
                                {
                                    if(value != m_hrRacket){
                                        m_hrRacket = value;
                                        emit hRedRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setXBlackRacket(const double &value)
                                {
                                    if(value != m_xbRacket){
                                        m_xbRacket = value;
                                        emit xBlackRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setYBlackRacket(const double &value)
                                {
                                    if(value != m_ybRacket){
                                        m_ybRacket = value;
                                        emit yBlackRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setWBlackRacket(const double &value)
                                {
                                    if(value != m_wbRacket){
                                        m_wbRacket = value;
                                        emit wBlackRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setHBlackRacket(const double &value)
                                {
                                    if(value != m_hbRacket){
                                        m_hbRacket = value;
                                        emit hBlackRacketChanged();
                                    }
                                }
                                
                                void PropertyBase::setWScreen(const double &value)
                                {
                                    if(value != m_wScreen){
                                        m_wScreen = value;
                                        emit wScreenChanged();
                                    }
                                }
                                
                                void PropertyBase::setHScreen(const double &value)
                                {
                                    if(value != m_hScreen){
                                        m_hScreen = value;
                                        emit hScreenChanged();
                                    }
                                }
                                
                                //Backend.h
                                #ifndef BACKEND_H
                                #define BACKEND_H
                                
                                #include "propertybase.h"
                                #include <QTimer>
                                
                                class BackEnd : public PropertyBase
                                {
                                    Q_OBJECT
                                    
                                public:
                                    explicit BackEnd(PropertyBase *parent = nullptr);
                                
                                    Q_INVOKABLE void timerStart(){m_BallTimer.start(m_timerInterval);}
                                    Q_INVOKABLE void timerStop(){m_BallTimer.stop();}
                                    
                                    Q_INVOKABLE void setInterval(int & interval){
                                        m_timerInterval = interval;
                                        m_BallTimer.setInterval(interval);
                                    }
                                    
                                signals:
                                    void rightWallhit();
                                    void leftWallHit();
                                    void rightRacketHit();
                                    void leftRacketHit();
                                    void upperOrLowerWallHit();
                                    
                                    void moveBall();
                                
                                public slots:
                                    
                                private:
                                    bool hitsRightRacket();
                                    bool hitsLeftRacket();
                                    
                                    bool hitsUpperOrLowerWall();
                                    bool hitsRightWall();
                                    bool hitsLeftWall();
                                    
                                private slots:
                                    void doCalculation();
                                    
                                protected:
                                    int m_timerInterval = 10;
                                    QTimer m_BallTimer;
                                };
                                
                                #endif // BACKEND_H
                                
                                //Backend.cpp
                                #include "backend.h"
                                
                                BackEnd::BackEnd(PropertyBase *parent) : PropertyBase(parent)
                                {
                                    connect(&m_BallTimer, &QTimer::timeout, this, &BackEnd::doCalculation);
                                }
                                
                                bool BackEnd::hitsRightRacket()
                                {
                                    if( (xBall() + wBall() >= xRedRacket() && xBall() <= xRedRacket() + wRedRacket() ) &&
                                        (yBall() + hBall() >= yRedRacket() && yBall() <= yRedRacket() + hRedRacket() ))
                                        return true;
                                    
                                    return false;
                                }
                                
                                bool BackEnd::hitsLeftRacket()
                                {
                                    if( (xBall() + wBall() >= xBlackRacket() && xBall() <= xBlackRacket() + wBlackRacket() ) &&
                                        (yBall() + hBall() >= yBlackRacket() && yBall() <= yBlackRacket() + hBlackRacket() ))
                                        return true;
                                    
                                    return false;
                                }
                                
                                bool BackEnd::hitsUpperOrLowerWall()
                                {
                                    if(yBall() <= 0 || yBall() +hBall() >= hScreen())
                                        return true;
                                    
                                    return false;
                                }
                                
                                bool BackEnd::hitsRightWall()
                                {
                                    if(xBall() + wBall() >= wScreen())
                                        return true;
                                    
                                    return false;
                                }
                                
                                bool BackEnd::hitsLeftWall()
                                {
                                    if(xBall() <= 0)
                                        return true;
                                    
                                    return false;
                                }
                                
                                void BackEnd::doCalculation()
                                {
                                    if(hitsRightWall()){
                                        timerStop();
                                        emit rightWallhit();
                                    }
                                    
                                    if(hitsLeftWall()){
                                        timerStop();
                                        emit leftWallHit();
                                    }
                                    
                                    if(hitsRightRacket())
                                        emit rightRacketHit();
                                    
                                    if(hitsLeftRacket())
                                        emit leftRacketHit();
                                    
                                    if(hitsUpperOrLowerWall())
                                        emit upperOrLowerWallHit();
                                    
                                    emit moveBall();
                                }
                                
                                
                                //main.cpp
                                #include <QGuiApplication>
                                #include <QQmlApplicationEngine>
                                
                                #include "backend.h"
                                
                                int main(int argc, char *argv[])
                                {
                                    QGuiApplication app(argc, argv);
                                    
                                    qmlRegisterType<BackEnd>("myBackend",1,0,"BackEnd");
                                
                                    QQmlApplicationEngine engine;
                                    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                                    if (engine.rootObjects().isEmpty())
                                        return -1;
                                
                                    return app.exec();
                                }
                                
                                
                                //main.qml
                                Window {
                                    id: window
                                    visibility: Window.Maximized
                                    title: qsTr("The PingPong Game - A QML Game")
                                    color: "gray"
                                    
                                    
                                    BackEnd{
                                        id:myBackend
                                        
                                        xBall: ball.x
                                        yBall: ball.y
                                        wBall: ball.width
                                        hBall: ball.height
                                        
                                        xRedRacket: redRacket.x
                                        yRedRacket: redRacket.y
                                        //....
                                        
                                        onRightWallhit: {
                                            leftCounter.count++
                                            out_timer.interval = 2000
                                            out_timer.running = true
                                        }
                                        onLeftWallHit: {
                                            rightCounter.count++
                                            out_timer.interval = 2000
                                            out_timer.running = true
                                        }
                                        onRightRacketHit: {
                                            if (redRacket.yUwards) {
                                                if (ball.yincrement == 0)
                                                    ball.yincrement = -ball.ran
                                                else if (ball.yincrement > 0)
                                                    ball.yincrement *= -1
                                                
                                            }
                                            else if (redRacket.yDwards) {
                                                if (ball.yincrement == 0)
                                                    ball.yincrement = ball.ran
                                                else if (ball.yincrement < 0)
                                                    ball.yincrement *= -1
                                                setInterval(table.duration/4)
                                            }
                                        }
                                         ....
                                    }
                                .....
                                }
                                
                                tomyT Offline
                                tomyT Offline
                                tomy
                                wrote on last edited by
                                #39

                                @J.Hilk
                                Thank you many times. :-)
                                I must analyse the code for both being familiar with the code and also the way C++ and QML have been mixed. :-)

                                J.HilkJ 1 Reply Last reply
                                1
                                • tomyT tomy

                                  @J.Hilk
                                  Thank you many times. :-)
                                  I must analyse the code for both being familiar with the code and also the way C++ and QML have been mixed. :-)

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

                                  @tomy
                                  great,

                                  but keep in mind, its just an example.
                                  When I wrote it down, I realized quickly, that I would move a lot more into the c++ class.

                                  You could(should) do the new Ball-Position calculation also in the backend.

                                  you can set the Balls position through the QProperty-binding

                                  xBall: ball.x
                                  yBall: ball.y
                                  

                                  via calling setXBall() and setYBall inside the cpp-class.
                                  In the end there should than be no need for any QML-side timers.

                                  That should clean up and speed up your QML part significantly.


                                  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
                                    great,

                                    but keep in mind, its just an example.
                                    When I wrote it down, I realized quickly, that I would move a lot more into the c++ class.

                                    You could(should) do the new Ball-Position calculation also in the backend.

                                    you can set the Balls position through the QProperty-binding

                                    xBall: ball.x
                                    yBall: ball.y
                                    

                                    via calling setXBall() and setYBall inside the cpp-class.
                                    In the end there should than be no need for any QML-side timers.

                                    That should clean up and speed up your QML part significantly.

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

                                    @J.Hilk
                                    OK, I do my best to make it clear for myself. I should thank you very much. Vielen Dank.

                                    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