Find the Best Demos and Examples

Check out this quick tour to find the best demos and examples for you, and to see how the Felgo SDK can help you to develop your next app or game!

Stack With Friends Demo

 import QtQuick 2.0
 import Felgo 3.0
 import "../common"

 Item {
   // make it span the whole scene
 //  anchors.top: gameScene.gameWindowAnchorItem.top
 //  width: gameScene.width
 //  height: header.height
   anchors.fill: gameScene.gameWindowAnchorItem

   // can either be "enterLevelName", "enterLevelNameInPublishing" or "enterUserName"
   property string dialogState

   // this may also be called after updating the username
   function publishLevel() {

     if(levelEditor.currentLevelNameString === qsTr("Unnamed")) {
       // prevent publishing with levelName unnamed
       dialogState = "enterLevelNameInPublishing"
       nativeUtils.displayTextInput("Enter levelName", "Enter a level name before you can publish this level. Choose a name that expresses what makes your level special.", "", levelEditor.currentLevelNameString)
       return
     }

     if(!gameNetwork.isUserNameSet(gameNetwork.userName)) {
       // prevent publishing if no authorName was set!
       dialogState = "enterUserName"
       nativeUtils.displayTextInput("Enter your name", "Before you can publish this level, enter your userName that will be shown to all other players.", "", gameNetwork.userName)
       return
     }

     levelEditor.saveCurrentLevel()
     levelEditor.publishLevel()
     if(cameFromScene === "menu") {
       mainItem.state = "menu"
     } else {
       mainItem.state = "selectLevel"
     }
   }
   Connections {
     id: nativeUtilsConnection

     target: nativeUtils
     onTextInputFinished: {
       if(accepted) {

         if(dialogState === "enterLevelName" || dialogState === "enterLevelNameInPublishing") {

           if(enteredText.indexOf(' ') !== -1) {
             nativeUtils.displayMessageBox("Invalid level name", "No whitespaces allowed!")
             return
           }

           if(enteredText.length > 20) {
             nativeUtils.displayMessageBox("Invalid level name", "A maximum of 20 characters is allowed!")
             return
           }

           if(gameNetwork.isValidUserInput(enteredText) && enteredText !== qsTr("Unnamed")) {
             levelEditor.saveCurrentLevel( {levelMetaData: {levelName: enteredText}} )

             if(dialogState ==="enterLevelNameInPublishing") {
               // if the level name was changed in the publishing process, continue with publishing
               publishLevel()
             }
           } else {
             nativeUtils.displayMessageBox("Invalid level name", "You entered an invalid level name. Please do not use any swear words for your level name.")
           }
         } else if(dialogState === "enterUserName") {

           var validName = gameNetwork.updateUserName(enteredText)
           if(!validName) {
             // maybe open another textInput here - this would then loop until a valid username is entered
             nativeUtils.displayMessageBox(qsTr(""), qsTr("You entered an invalid username, please try a different one. The username must not start with a number or contain any swearwords."))
           } else {
             //continue publishing the level - no the check for valid userName will pass and the level gets published
             publishLevel()
           }

         }
       }
       dialogState = ""
     }
   }

   MultiResolutionImage {
     id: header
     source: "../../assets/img/levelstore-top.png"
     anchors.horizontalCenter: parent.horizontalCenter
     z: 1
     opacity: gameScene.state != "levelEditing" ? 0.5 : 1
     visible: gameScene.state === "levelEditing" || gameScene.state === "testing"

     Item {
       width: 39
       height: 39
       y: -1
       x: 5
       MultiResolutionImage {
         source: "../../assets/img/back-button.png"
         anchors.centerIn: parent
       }
       MouseArea {
         anchors.fill: parent
         onClicked: {
           if(gameScene.state === "levelEditing" || gameScene.state === "testing") {
             // save the current level when going back if in editing mode
             gameScene.entitySelected(null)
             levelEditor.saveCurrentLevel({levelMetaData: {levelName: levelEditor.currentLevelNameString}})
             //levelEditor.saveCurrentLevel()
           }

   //        // make sure the state is in levelEditing when left, otherwise the boxes would keep falling down
   //        scene.state = "levelEditing"
           // if previous state was level, return to the level menu!
           gameScene.stopGame()
           if(cameFromScene === "menu") {
             mainItem.state = "menu"
           } else {
             mainItem.state = "selectLevel"
           }
         }
       }
     }

     Row {
       id: headerRow

       z: 1
       spacing: 20
       x: 64

       MenuButton {
         text: "Balance"
         onClicked: itemEditor.visible = !itemEditor.visible
         // DONE: only make visible if the gameScene is entered in levelMode - currently the only game mode is levelMode
         active: itemEditor.visible
         clickable: levelEditor.isCurrentLevelOfLocation(levelEditor.authorGeneratedLevelsLocation)
       }

       MenuButton {
         text: gameScene.state === "testing" ? "Edit" : "Test"
         onClicked: {
           if(text === "Edit")
             gameScene.state = "levelEditing"
           else {
             gameScene.entitySelected(null)
             gameScene.state = "testing"
           }
         }
         // DONE: only make visible if the gameScene is entered in levelMode - currently the only game mode is levelMode
         clickable: levelEditor.isCurrentLevelOfLocation(levelEditor.authorGeneratedLevelsLocation)
       }

       MenuButton {
         id: changeLevelNameButton
         text: "Level Name"
         onClicked: {
           dialogState = "enterLevelName"
           nativeUtils.displayTextInput("Enter levelName", "Enter a level name before you can publish this level. Choose a name that expresses what makes your level special.", "", levelEditor.currentLevelNameString)
         }
         clickable: gameScene.state === "levelEditing"
       }

       MenuButton {
         text: "Publish"

         onClicked: {
           publishLevel()
         }
         // do not allow publishing for an already published web level; to do that, go to the local storage and re-press update there, then the name will also be updated
         clickable: gameScene.state === "levelEditing" && levelEditor.isCurrentLevelOfLocation(levelEditor.authorGeneratedLevelsLocation)
       }

       MenuButton {
         text: "Delete" //levelEditor.isCurrentLevelOfLocation(levelEditor.authorGeneratedLevelsLocation) ? "Delete Local" : "Delete Online"
         onClicked: {

           levelEditor.removeCurrentLevel()

           // go back to the selection list
           mainItem.state = "selectLevel"
         }
         clickable: gameScene.state === "levelEditing"
       }
     }
   }

   MultiResolutionImage {
     id: buildButtons
     source: "../../assets/img/obstacle-buttons.png"
     anchors.horizontalCenter: parent.horizontalCenter
     anchors.bottom: parent.bottom
     z: 1
     property bool hide: false
     visible: gameScene.state === "levelEditing" && !hide
     Row {
       spacing: 10
       anchors.horizontalCenter: parent.horizontalCenter
       y: 5
       BuildEntityButton {
         toCreateEntityTypeUrl: Qt.resolvedUrl("../entities/ObstacleBlock.qml")

         width: 32
         height: 32

         // the obstacle is just a grey entity, we can customize the look of the button here
         Item {
           width: parent.width
           height: parent.height
           Image {
             source: "../../assets/img/block.png"
             width: 16
             height: 16
           }
           Image {
             source: "../../assets/img/block.png"
             width: 16
             height: 16
             x: 16
           }
           Image {
             source: "../../assets/img/block.png"
             width: 16
             height: 16
             y: 16
           }
           Image {
             source: "../../assets/img/block.png"
             width: 16
             height: 16
             x: 16
             y: 16
           }
         }

         onEntityWasBuilt: {
           var entity = entityManager.getEntityById(builtEntityId)
           gameScene.entitySelected(entity)
           entity.entityState = "entitySelected"
         }
       }

       BuildEntityButton {
         toCreateEntityTypeUrl: Qt.resolvedUrl("../entities/ObstacleTriangle.qml")

         width: 32
         height: 32

         // the obstacle is just a grey entity, we can customize the look of the button here
         Image {
           width: parent.width
           height: parent.height
           source: "../../assets/img/block2.png"
         }

         onEntityWasBuilt: {
           var entity = entityManager.getEntityById(builtEntityId)
           gameScene.entitySelected(entity)
           entity.entityState = "entitySelected"
         }
       }
     }
   }

   Image {
     visible: gameScene.state === "levelEditing"
     width: 16
     height: 16
     source: "../../assets/img/hide-obstacle-buttons.png"
     anchors.left: buildButtons.right
     anchors.bottom: buildButtons.bottom
     Text {
       text: buildButtons.hide ? "+" : "-"
       anchors.centerIn: parent
       color: "red"
       font.pixelSize: 16
     }
     MouseArea {
       anchors.fill: parent
       onClicked: buildButtons.hide = !buildButtons.hide
     }
   }

   MultiResolutionImage {
     source: "../../assets/img/gamescene-top.png"
     anchors.horizontalCenter: parent.horizontalCenter
     z: 1
     opacity: 0.5
     visible: gameScene.state == "playing"

     Item {
       width: 39
       height: 39
       x: 12
       y: -1
       MultiResolutionImage {
         source: "../../assets/img/back-button.png"
         anchors.centerIn: parent
       }
       MouseArea {
         anchors.fill: parent
         onClicked: {
           gameScene.stopGame()
           if(cameFromScene === "menu") {
             mainItem.state = "menu"
           } else {
             mainItem.state = "selectLevel"
           }
         }
       }
     }