Player.qml Example File

demos/ChickenOutbreak2/qml/entities/Player.qml
 import QtQuick 2.0
 import Felgo 3.0

 EntityBase {
   entityType: "player"
   // by setting this to true, the removeAllEntities() does not affect this entity, which is called from Level.stopGame()
   preventFromRemovalFromEntityManager: true

   // the key-pressed-signals get emitted from the scene when key presses are detected
   // key pressed cant be detected here, because this item has no size
   signal leftPressed(variant event)
   signal rightPressed(variant event)
   signal upPressed(variant event)
   signal downPressed(variant event)

   signal died
   signal deathAnimationFinished()

   // gets increased over time - it has the same value as the y value of the level
   property int score: 0
   // gets increased when a coin is collected
   property int bonusScore: 0
   // the total score is the one that gets displayed
   property int intermediateScore: (score + (bonusScore * bonusScoreForCoin) + scoreFromItemEditor)
   property int totalScore: (intermediateScore >= 0 ? intermediateScore : 0)
   // the total count of deaths within this gaming session
   property int deaths: 0

   onDeathsChanged: {
     died()
   }

   // this gets added to bonusScore every time the player catches a coin
   property int bonusTextScore: 0
   // flag indicating if parachute is active
   property bool parachute : false
   // remaining time of recieving twice the points for collectibles
   property int doublePointsTime: 0
   // gets increased when a parachute was used
   property int parachutes: 0
   // gets increased when beamed
   property int beams: 0
   // gets increased when a coin is collected
   property int collectedGrains: 0
   property int collectedBadGrains: 0

   // this is needed internally to find out if the image should be inverted
   property bool __isLookingRight: true

   // for access from parents
   property alias controller: twoAxisController
   property alias collider : collider
   property alias teleportParticle: teleportParticle
   property alias teleportGlowParticle: teleportGlowParticle

   property bool controlsEnabled: true

   width: collider.radius * 2
   height: collider.radius * 2

   // gets displayed if the player picks up a collectible showing the points earned (or lost)
   Text {
     id: bonusText
     // the ( is a long --- with the font used because there is no minus sign available in the font.
     text: bonusTextScore<0 ? "("+ bonusTextScore*-1 : bonusTextScore
     visible: bonusTextScore!=0 && displayBonusTextTimer.running
     font.family: fontHUD.name
     font.pixelSize: 17
     color: bonusTextScore<0 ? "#62f45f" : "white"
     anchors.bottom: sprite.top
     anchors.topMargin: 5
     anchors.horizontalCenter: parent.horizontalCenter
   }

   // parachute image
   // the rotation gets changed a little if the player is flying sideways, the x value get's adepted to the rotation
   Image {
     z:4
     source: "../../assets/parachute.png"
     width: 30
     height: 30
     x: {
       if(twoAxisController.xAxis>0) return sprite.x+sprite.width/2-width/2-4
       else if(twoAxisController.xAxis<0) return sprite.x+sprite.width/2-width/2+4
       else return sprite.x+sprite.width/2-width/2
     }
     y: sprite.y-20
     visible: parachute
     rotation: {
       if(twoAxisController.xAxis>0) return -12
       else if(twoAxisController.xAxis<0) return 12
       else return 0
     }
   }

   // hen image when standing still
   Image {
     id: sprite
     source: store.blackHen.purchased ? "../../assets/chicken2-front.png" : "../../assets/chicken4-front.png"
     z:5
     anchors.centerIn: parent
     width: 30
     height: 30
     visible: false // will be visible in default state
     x:0
     y:0
   }

   // image if hen walks sideways
   Image {
     id: spriteMovement
     source: store.blackHen.purchased ? "../../assets/chicken2-side.png" : "../../assets/chicken4-side.png"
     z:5
     anchors.centerIn: parent
     width: 30
     height: 30
     visible: false
     mirror: __isLookingRight
   }

   // hen image when flying
   Image {
     id: spriteFlying
     source: store.blackHen.purchased ? "../../assets/chicken2-fly.png" : "../../assets/chicken4-fly.png"
     z:5
     anchors.centerIn: parent
     width: 30
     height: 30
     visible: false
   }

   // hen image when dead
   Image {
     id: spriteDead
     source: store.blackHen.purchased ? "../../assets/chicken2-dead.png" : "../../assets/chicken4-dead.png"
     z:5
     anchors.centerIn: parent
     width: 30
     height: 30
     visible: false
   }

   // gets increased when a collision with a block occurs in onBeginContact, and decreased in onEndContact
   // when no blockCollisions happened, the fly-state is active!
   property int blockCollisions: 0
   onBlockCollisionsChanged: {
     if(blockCollisions==0){
       state = "fly";
     } else {
       if(lastState === "fly") {
         state = "default"
       }
     }
   }

   CircleCollider {
     id: collider
     bodyType: Body.Dynamic
     fixedRotation: true
     linearDamping: henLinearDamping
     friction: henFriction
     // restitution is bounciness - don't bounce, because then the state would be changed too often
     restitution: 0
     gravityScale: parachute ? parachuteGravityScale : 1
     // this is needed, because otherwise when resetting the level (and the player position), and the body was sleeping before it wouldn't fall down immediately again, because it hasn't woken up from sleeping!
     sleepingAllowed: false
     radius: 14
     fixture.onBeginContact: {
       var fixture = other;
       var body = fixture.getBody();
       var collidedEntity = body.target;
       var collidedEntityType = collidedEntity.entityType;
       if(collidedEntityType === "coin") {
         // the coin is pooled for better performance
         collidedEntity.removeEntity();
         // increase the score, and also play a pling sound
         if(doublePointsTime>0) {
           bonusScore+=2
           bonusTextScore += bonusScoreForCoin*2
         } else {
           bonusScore++
           bonusTextScore += bonusScoreForCoin
         }
         collectedGrains++
         cornParticle.start()
         displayBonusTextTimer.restart()
         audioManager.play(audioManager.idCORN)
       } if(collidedEntityType === "badCoin") {
         collidedEntity.removeEntity();
         // decrease score in this case
         if(doublePointsTime>0) {
           bonusScore-=4
           bonusTextScore -= bonusScoreForCoin*4
         } else {
           bonusScore-=2
           bonusTextScore -= bonusScoreForCoin*2
         }
         collectedBadGrains++
         skullParticle.start()
         displayBonusTextTimer.restart()
         audioManager.play(audioManager.idBADCORN)
       } else if(collidedEntityType === "trippleCoin") {
         collidedEntity.removeEntity();
         if(doublePointsTime>0) {
           bonusScore+=6
           bonusTextScore += bonusScoreForCoin*6
         } else {
           bonusScore+=3
           bonusTextScore += bonusScoreForCoin*3
         }
         collectedGrains++
         cornParticle.start()
         displayBonusTextTimer.restart()
         audioManager.play(audioManager.idCORN)
       } else if(collidedEntityType === "parachute") {
         collidedEntity.removeEntity();
         if(doublePointsTime>0) {
           bonusScore+=2
           bonusTextScore += bonusScoreForCoin*2
         } else {
           bonusScore++
           bonusTextScore += bonusScoreForCoin
         }
         displayBonusTextTimer.restart()
         parachuteCount++
         audioManager.play(audioManager.idPOWERUP)
       } else if(collidedEntityType === "doublePoints") {
         collidedEntity.removeEntity();
         if(doublePointsTime>0) {
           bonusScore+=2
           bonusTextScore += bonusScoreForCoin*2
         } else {
           bonusScore++
           bonusTextScore += bonusScoreForCoin
         }
         displayBonusTextTimer.restart()
         doublePointsTime = doublePointsDuration
         // only start timer if the level is running, not if you pick it up while you are in teleport mode (game is in "paused" state), the timer will be started when the game resumes
         if(level.state == "running") doublePointsTimer.start()
         audioManager.play(audioManager.idPOWERUP)
       } else if(collidedEntityType === "roost") {
         // increase blockCollisions to determine if the player is flying or not
         blockCollisions++;
         // if parachute is active and you hit a roost, stop the parachute
         if(parachute === true) startOrStopParachute()
       } else if(collidedEntityType === "wheel") {
         if(parachute === true) startOrStopParachute()
       }
     }

     fixture.onEndContact: {
       // decrease blockCollisions to determine if the player is flying or not
       var fixture = other;
       var body = fixture.getBody();
       var collidedEntity = body.target;
       var collidedEntityType = collidedEntity.entityType;
       if(collidedEntityType === "roost") {
         blockCollisions--;
       }
     }
   }

   property bool updateAccelerometer: true
   function updateWithAccData(reading) {
     if(!updateAccelerometer)
       return
     // connect the TwoAxisController with the acceleration data
     if(state !== "fly" && Math.abs(reading.x) < accelerometerOffset)
       twoAxisController.xAxis = 0
     else twoAxisController.xAxis = reading.x * -accelerometerMultiplier;
   }

   // using keys on desktop for steering. Its axis is also used when steering with the accelerometer to avoid duplicate code
   TwoAxisController {
     id: twoAxisController

     inputActionsToKeyCode: {
         "up": Qt.Key_Up,
         "down": Qt.Key_Down,
         "left": Qt.Key_Left,
         "right": Qt.Key_Right,
         "fire": Qt.Key_Space
       }

     onInputActionPressed: {
       if(!system.desktopPlatform)
         return

       if(actionName === "fire" && controlsEnabled) {
         startOrStopParachute()
       } else if(actionName === "up" && controlsEnabled) {
         activateTeleport()
       } else if(actionName === "down") {
         deactivateTeleport()
       }
     }
   }

   // apply the velocity to the hen constantly to steer
   Timer {
     id: updateTimer
     interval: 1000 / 60
     running: true
     repeat: true
     onTriggered: {
       // this must be done every frame, because the linearVelocity gets reduced because of the damping!
       if(level.state === "running") {
         var xAxis = controller.xAxis;
         if(xAxis < 0 || xAxis > 0) {
           collider.body.linearVelocity.x = xAxis*rightValue;
           if(blockCollisions!=0) {
             state = "moveLeftRight";
           }
           if(xAxis>0)
             __isLookingRight = true;
           else if(xAxis<0)
             __isLookingRight = false;
         }
       }
     }
   }

   // counts down the time for recieving double points
   Timer {
     id: doublePointsTimer
     running: false
     repeat: true
     onTriggered: {
       if(doublePointsTime>0) {
         audioManager.play(audioManager.idTICK)
         doublePointsTime--
       } else {
         stop()
       }
     }
   }

   // timer to display the score after picking up a collectible
   Timer {
     id: displayBonusTextTimer
     interval: 500
     running: false
     repeat: false
     onTriggered: {
       bonusTextScore = 0
     }
   }

   // particle for picking up good collectibles
   Particle {
     id: cornParticle
     z: 1
     fileName: "../particles/CornSplatter.json"
     autoStart: false
     anchors.centerIn: parent
   }

   // particle for picking up a poisoned corn
   Particle {
     id: skullParticle
     z: 1
     fileName: "../particles/SkullParticle.json"
     autoStart: false
     anchors.centerIn: parent
   }

   // particle when using teleport
   Particle {
     id: teleportParticle
     z: 1
     fileName: "../particles/TeleportParticle.json"
     autoStart: false
     anchors.centerIn: parent
   }

   Particle {
     id: teleportGlowParticle
     z: 1
     fileName: "../particles/TeleportGlowParticle.json"
     autoStart: false
     duration: ParticleBase.Infinite
     anchors.centerIn: parent
   }

   onStateChanged: {
     lastState = state
   }

   property string lastState: "default"
   state: "default"
   // determine the state of the player depending on block collisions and the TwoAxisController

   states: [
     State {
       name: "default"
       PropertyChanges { target: sprite; visible: true }
     },
     State {
       name: "fly"
       PropertyChanges { target: spriteFlying; visible: true }
     },
     State {
       name: "moveLeftRight"
       PropertyChanges { target: spriteMovement; visible: true }
     }
   ]

   // if parachute was true and got false (landing) it's not available anymore, until a new one is picked up
   onParachuteChanged: {
     if(parachute === true) parachuteCount--
   }

   // starts parachute if it is available, or stops it if its active
   function startOrStopParachute() {
     if(parachute === true) parachute = false
     else if(state==="fly" && parachuteCount > 0) {
       player.parachutes++
       audioManager.play(audioManager.idPARACHUTE)
       parachute = true
     }
   }

   // starts the player (needed after he got stopped for teleporting or balancing with the ItemEditor)
   function start() {
     controlsEnabled = true
     updateAccelerometer = true
     collider.body.linearDamping = henLinearDamping
     collider.gravityScale = Qt.binding(function() {return parachute ? parachuteGravityScale : 1})
     spriteDead.visible = false
     if(doublePointsTime>0) doublePointsTimer.start()
   }

   // stops the player (used for teleporting and balancing with the ItemEditor)
   function stop() {
     controlsEnabled = false
     twoAxisController.xAxis = 0
     collider.body.linearVelocity.x = 0
     updateAccelerometer = false
     collider.body.linearDamping = 10
     collider.gravityScale = 0
     doublePointsTimer.stop()
   }

   function prepareForDeath() {
     spriteDead.visible = true
   }

   function saveIt() {
     spriteDead.visible = false
   }

   function killIt() {
     audioManager.play(audioManager.idGAMEOVER)
     saveitDialog.setDissable()
     // lastScore is used in GameOverScreen to check if a new highscore is reached
     lastScore = player.totalScore;
     // Increment the player's death count
     player.deaths++;
     spriteDead.visible = false
     deathAnimationFinished()
   }

 }

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