Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Stack With Friends Demo

 import Felgo 3.0
 import QtQuick 2.0
 import "scene-level"
 import "scene-menu"
 import "scene-game"
 import "scene-vpgn"
 import "common"

 Item {

   id: mainItem

   state: "menu"

   property alias itemEditor: gameScene.itemEditor

   // this is set to either "", "exitConfirmation" or "visitVPlayWebsite"
   // it is needed to distinguish which button caused the nativeUtils.displayMessageBox() call
   property string messageBoxInputState
   Connections {
     target: nativeUtils
     onMessageBoxFinished: {
       if(accepted) {
         if(mainItem.messageBoxInputState === "exitConfirmation") {
           flurry.logEvent("MainMenu.ACKQuit")
           Qt.quit()
         } else if(mainItem.messageBoxInputState === "visitVPlayWebsite") {
           flurry.logEvent("MainMenu.Website")
           nativeUtils.openUrl("https://felgo.com/2014/02/user-generated-content-level-sharing-level-store?utm_medium=game&utm_source=stackwithfriends&utm_campaign=stackwithfriends")
         }
       }

       mainItem.messageBoxInputState = ""
     }
   }

   // balancing settings for the MouseJoint
   property real maxForce: 30000
   property real dampingRatio: 1
   property real frequencyHz: 2

   property int spawnInterval: 2000

   EditableComponent {
     // The default target: parent does not work when the EditableComponent is located directly in the GameWindow because the parent is not the actual GameWindow. Therefore, use the concrete GameWindow id assigned to the target.
     target: window
     editableType: "Balancing"
     defaultGroup: "Environment"
     properties: {
         "spawnInterval": {"min": 1000, "max": 5000,"stepsize": 10},
         "maxForce": {"min": 10000, "max": 100000,"stepsize": 100},
         "dampingRatio": {"min": 0, "max": 1,"stepsize": 0.1 },
         "frequencyHz": {"min": 1, "max": 50, "stepsize": 1 }
     }
   }

   Component.onCompleted: {
     // give the player 5 Credits on first app start
     if(!settings.getValue("firstAppStart")) {
       settings.setValue("firstAppStart",1)
       levelStore.giveCurrency(5)
     }
   }

   AudioManager {
     id: audioManager
   }

   // Flurry is only available on iOS and Android
   Flurry {
     id: flurry
     // this is the app key for the Stack With Friends-SDK-Demo, be sure to get one for your own application if you want to use Flurry
     apiKey: "HFPMDJBVNKRY6YZBWTQK"
   }

   STBGameNetwork {
     id: gameNetwork
   }

   Facebook {
     // the user will automatically connect with facebook
     // once "connect" is pressed in the ProfileView in the GameNetworkView
     id: facebook

     // this is the Facebook App Id received from the settings in developers.facebook.com/apps
     appId: "589825414405454"

     readPermissions: ["email", "read_friendlists"]
     publishPermissions: ["publish_actions"]
   }

   EntityManager {
     id: entityManager
     entityContainer: gameScene
     // required for LevelEditor, so the entities can be created by entityType
     dynamicCreationEntityList: [ Qt.resolvedUrl("entities/ObstacleBlock.qml"),Qt.resolvedUrl("entities/ObstacleTriangle.qml") ]
   }

   LevelEditor {
     // gets accessed from LevelScene and StackTheBoxGameScene, thus required to define the id in the root qml file here
     id: levelEditor
     toRemoveEntityTypes: [ "obstacleBlock","obstacleTriangle" ]
     toStoreEntityTypes: [ "obstacleBlock","obstacleTriangle" ]

     Component.onCompleted: {
       // it is not ideal to do this in onCompleted, because then this request might be sent before the initial login! instead load it when the user got initialized, and when the app is resumed after it was in the background
 //      loadBestLevelStats()
     }

     onLevelDownloadedSuccessfully: {
       gameNetwork.increaseDownloadedLevels()
     }
     onLevelRated: {
       // check if this level was rated before to avoid the player gets multiple points for rating the same level
       // if the level was alread rated by the user, he has a rating value in the level data
       // NOTE: this only works, because after the rating the userGeneratedLevels do not get updated automatically!
       for(var i=0;i<userGeneratedLevels.length; i++) {
         // look for the just rated level
         var level = userGeneratedLevels[i]
         if(level.levelId === levelId) {
           if(level["rating"] && level.rating.quality) {
             console.debug("the player has already rated this level, thus do not increase the achievement counter")
             return
           }
         }
       }

       gameNetwork.increaseRatedLevels()
     }
     onLevelPublished: {
       gameNetwork.increasePublishedLevels()
       nativeUtils.displayMessageBox(qsTr("Congratulations for publishing a level!"), qsTr("You can earn more credits by unlocking achievements with your published levels. The more downloads and good ratings you get, the more credits you are rewarded! Every time you start StackTheBox, we update your level stats.\n\nTo see how many downloads and ratings you got for your levels, go to the \"Friend Levels\" or \"Community Levels\" tab in the level selection and press the Info button on your level."))
     }

     // this is called after reloadUserBestLevelStats() is called
     onUserBestLevelStatsChanged: {
       // if no level was ever downloaded or rated, userBestLevelStats is an empty {}
       console.debug("__new bestLevelStats:", JSON.stringify(userBestLevelStats))
       if(userBestLevelStats["best_quality"]) {
         gameNetwork.setBestLevelRatingOfOwnLevels(userBestLevelStats["best_quality"]["average_quality"])
       }
       if(userBestLevelStats["most_downloaded"]) {
         gameNetwork.setLevelDownloadsOfOwnLevels(userBestLevelStats["most_downloaded"]["times_downloaded"])
       }
     }

   }

   // this is called from FelgoGameNetwork when it gets synced
   // and after resuming the app after it was in background from StackTheBoxWithCommunityEditorMain
   function reloadUserBestLevelStats() {
     console.debug("reloadUserBestLevelStats() called")
     // if the user is not in sync yet, it will be called from STBGameNetwork when it gets in sync
     if(gameNetwork.userInitiallyInSync) {
       levelEditor.loadBestLevelStats()
     }
   }

   STBLevelStore {
     id: levelStore

     levelEditorItem: levelEditor
   }

   GameScene {
     id: gameScene

     // after every lost game, increase the rewards counter
     onGameLost: gameNetwork.increaseGamesPlayed()
   }

   MainMenuScene {
     id: menuScene

     onPlayClicked: {
       flurry.logEvent("MainMenu.Play")
       levelEditor.createNewLevel({ levelMetaData: {levelName: qsTr("Training")} })
       gameScene.goToPlayMode()
       gameScene.cameFromScene = "menu"
       mainItem.state = "game"
     }
     onMyLevelsClicked: {
       flurry.logEvent("MainMenu.MyLevels")
       levelScene.state = "myLevels"
       mainItem.state = "selectLevel"
     }
     onGameNetworkViewClicked: {
       flurry.logEvent("MainMenu.GameNetwork")
       gameNetwork.showAchievements()
       vplayGameNetworkScene.cameFromScene = "menu"
       mainItem.state = "gameNetwork"
     }

     onBackButtonPressed: {
       flurry.logEvent("MainMenu.Quit")
       mainItem.messageBoxInputState = "exitConfirmation"
       nativeUtils.displayMessageBox(qsTr("Really quit the game?"), "", 2);
     }

   }

   LevelScene {
     id: levelScene

     onBackClicked: mainItem.state = "menu"
     onNewLevelClicked: {
       levelEditor.createNewLevel({levelMetaData:{ levelName: qsTr("Unnamed")}})
       gameScene.goToLevelEditingMode()
       gameScene.cameFromScene = "myLevels"
       mainItem.state = "game"
       flurry.logEvent("LevelSelection.NewLevel")
     }
     onShowProfileView: {
       vplayGameNetworkScene.cameFromScene = "selectLevel"
       mainItem.state = "gameNetwork"
       // this opens the profileView tab
       gameNetwork.showProfileView()
       flurry.logEvent("LevelSelection.ShowProfile")
     }
     onShowHighscoreForLevel: {
       // gets called from LevelItem
       // showLeaderboard() activates the view of the leaderboard and sets it as currentActiveLeaderboard
       gameNetwork.showLeaderboard(leaderboard)
       vplayGameNetworkScene.cameFromScene = "selectLevel"
       mainItem.state = "gameNetwork"
       flurry.logEvent("LevelSelection.ShowHighscore","leaderboard",leaderboard)
     }

   }

   FelgoGameNetworkScene {
     id: vplayGameNetworkScene
     onBackButtonPressed: {
       flurry.logEvent("GameNetwork.BackPressed","from",cameFromScene)
       if(cameFromScene === "menu") {
         mainItem.state = "menu"
       } else {
         mainItem.state = "selectLevel"
       }
     }
   }

   AchievementOverlay {
     id: achievementOverlay
     z: 100
   }

   states: [
     State {
       name: "menu"
       PropertyChanges {target: menuScene; opacity: 1}
       PropertyChanges {target: window; activeScene: menuScene}
       StateChangeScript {
         script: {
           menuScene.dailyBonus.checkForDailyBonus()
           bgMusic.volume = 1
         }
       }
     },
     State {
       name: "selectLevel"
       PropertyChanges {target: levelScene; opacity: 1}
       PropertyChanges {target: window; activeScene: levelScene}
     },
     State {
       name: "gameNetwork"
       PropertyChanges {target: vplayGameNetworkScene; opacity: 1}
       PropertyChanges {target: window; activeScene: vplayGameNetworkScene}
     },
     State {
       name: "game"
       PropertyChanges {target: gameScene; opacity: 1}
       PropertyChanges {target: window; activeScene: gameScene}
       StateChangeScript {
         script: {
           bgMusic.volume = 0.3
         }
       }
Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded