How to make a game like Pong with Felgo - AI

Tutorial Chapters

  1. Overview
  2. Creation of a Felgo game
  3. GameWindow, Scenes and Physical Worlds
  4. The Level and the Ball
  5. Level Boundaries
  6. Paddles
  7. HUD
  8. Menus
  9. AI
  10. Special Effects
  11. Music and Sound
  12. Further Perspectives

AI

Testing a game without enemy is hardly possible. Now you are going implement a simple AI in the Paddle.qml to test the game. First of all you gonna need a flag to distinguish if the player is AI or human - which can be set via the reset method. Furthermore, a difficulty flag is added which can have values of 2 (easy), 4 (medium), 6(hard). Once started, the MultiTouchArea should only be touchable for human players, therefore, change the enable flag dependent on the isAI flag. The move function will be called regularly which drives the AI calculations. Based on the difficulty flag, 3 different approaches have been used as demonstration.

  • Easy is based on ball velocity changes.
  • Medium is based on ball position changes.
  • Hard is based on the according paddle position.

After the position calculation, there are some bounding checks that the paddles stay in the game field.

 ...
   // Save the score of the player
   property int score: 0

   // Flag to identify if the paddle is human or AI
   property bool isAI : false
   // Difficulty for SimpleAI, can be used
   property int difficulty : 2
   // last pad position
   property real lastPadPosY: 0
   // movement speed of the paddle
   property real paddleSpeed : 0

   // update the speed of the paddle which can be used by the ball during collision events
   onYChanged: {
     paddleSpeed = lastPadPosY-y
     lastPadPosY=y
   }
 ...

   MultiTouchArea {
 ...
   // the touch are should only be usable when a human is the player
   enabled: !isAI
   }
 ...

   // Resetting the score and set if AI or not
   function reset(isPlayerAI) {
     isAI = isPlayerAI
     score = 0
   }

   // move the paddle used for AI
   function move(ballEntity) {
     if(!isAI)
       return

     // remove jittering
     if(lastPadPosY === ballEntity.y)
       return
     else if(Math.abs(lastPadPosY - ballEntity.y) < 8)
       return
     lastPadPosY = ballEntity.y

     // calculate paddle position based on difficulty
     if(difficulty <= 2) {
       easy(ballEntity)
     } else if(difficulty >2 && difficulty < 8) {
       medium(ballEntity)
     } else {
       hard(ballEntity)
     }

     // check the boundaries of the word, so that the paddle does not intersect
     var bumper = level.blockHeight+sprite.height/2

     if(y > scene.height - bumper) {
       y = scene.height - bumper
     }
     if(y < bumper) {
       y = bumper
     }
   }

   // position change based on the linear velocity
   function easy(ballEntity) {
     if(ballEntity.linearVelocity().y > 0)
     {
       y += difficulty*4
     }
     else if(ballEntity.linearVelocity().y < 0)
     {
       y -= difficulty*4
     }
   }

   // position change based on position
   function medium(ballEntity) {
     if(ballEntity.y > y)
         y += difficulty*3
     else if( ballEntity.y < y)
         y -= difficulty*3
   }

   // position change based on ball position
   function hard(ballEntity) {
     y = ballEntity.y
   }
 ...

The difficulty of the AI can be changed via the buttons in the MainMenu.qml. You can create a game session for left/right handed player or a multi player session or a game session AI vs. AI.

 Column {
   anchors.centerIn: parent
   MenuButton {
     text: "Multi Player"
     onClicked: {
       scene.state = "game"
       // Reset player and if it is an AI player (true) or not (false)
       player1.reset(false)
       player2.reset(false)
     }
   }
   MenuButton {
     text: "SP - Left Handed"
     onClicked: {
       scene.state = "game"
       player1.reset(true)
       player2.reset(false)
     }
   }
   MenuButton {
     text: "SP - Right Handed"
     onClicked: {
       scene.state = "game"
       player1.reset(false)
       player2.reset(true)
     }
   }
   MenuButton {
     text: "AI Fight"
     onClicked: {
       scene.state = "game"
       player1.reset(true)
       player2.reset(true)
     }
   }
   MenuButton {
     property int difficulty : 2
     text: "Difficulty: " + ((difficulty==2) ? "easy" : (difficulty==4) ? "normal" : "epic")
     onClicked: {
       difficulty+=2;
       if(difficulty>6) {
         difficulty = 2
       }
       player1.difficulty = difficulty
       player2.difficulty = difficulty
     }
   }
 }

The calculation of the AI needs to be triggered by calling the move() function of the paddles which is done with timers.

 ...
   // timer to calculate AI movement, does need to be called each frame
   // therefore we use a timer.
   Timer {
     interval: 32; running: true; repeat: true
     onTriggered: {
       player1.move(ball)
       player2.move(ball)
     }
   }
 ...

Now the paddles move around automatically, based on the difficulty level.

Now it's time to add some special effects to the game.

Voted #1 for:

  • Easiest to learn
  • Most time saving
  • Best support

Develop Cross-Platform Apps and Games 50% Faster!

  • Voted the best supported, most time-saving and easiest to learn cross-platform development tool
  • Based on the Qt framework, with native performance and appearance on all platforms including iOS and Android
  • Offers a variety of plugins to monetize, analyze and engage users
FREE!
create apps
create games
cross platform
native performance
3rd party services
game network
multiplayer
level editor
easiest to learn
biggest time saving
best support