Warning, /education/gcompris/src/activities/gravity/Gravity.qml is written in an unsupported language. File is not indexed.

0001 /* GCompris - Gravity.qml
0002 *
0003 * SPDX-FileCopyrightText: 2020 Timothée Giet <animtim@gmail.com>
0004 *
0005 * Authors:
0006 *   Bruno Coudoin <bruno.coudoin@gcompris.net> and Matilda Bernard (GTK+ version)
0007 *   Siddhesh suthar <siddhesh.it@gmail.com> (Qt Quick port)
0008 *   Timothée Giet <animtim@gmail.com> (complete activity rewrite)
0009 *
0010 *   SPDX-License-Identifier: GPL-3.0-or-later
0011 */
0012 import QtQuick 2.12
0013 import GCompris 1.0
0014 
0015 import "../../core"
0016 import "gravity.js" as Activity
0017 
0018 ActivityBase {
0019     id: activity
0020 
0021     onStart: focus = true
0022     onStop: {}
0023 
0024     Keys.onPressed: Activity.processKeyPress(event)
0025     Keys.onReleased: Activity.processKeyRelease(event)
0026 
0027     pageComponent: Rectangle {
0028         id: background
0029         anchors.fill: parent
0030         color: "#171717"
0031 
0032         signal start
0033         signal stop
0034 
0035         Component.onCompleted: {
0036             activity.start.connect(start)
0037             activity.stop.connect(stop)
0038         }
0039 
0040         // Needed to get keyboard focus on IntroMessage
0041         Keys.forwardTo: message
0042 
0043         // Add here the QML items you need to access in javascript
0044         QtObject {
0045             id: items
0046             property Item main: activity.main
0047             property bool startMessage: true
0048             property alias background: background
0049             property int currentLevel: activity.currentLevel
0050             property alias bonus: bonus
0051             property alias processTimer: processTimer
0052             property alias planetCreation: planetCreation
0053             property int maxPlanetSize: background.width - spaceship.width
0054             property int minPlanetSize: background.width * 0.2
0055             property alias planet0: planet0
0056             property alias planet1: planet1
0057             property alias arrow: arrow
0058             property GCSfx audioEffects: activity.audioEffects
0059             property double gravity: 0
0060             property int planetFrequency: 0
0061             property int spaceSpeed: planetFrequency * 4
0062             property alias spaceship: spaceship
0063             property alias station: station
0064             property alias stationDown: stationDown
0065             // the center value for the spaceship
0066             property double spaceshipX
0067             property double spaceshipY: parent.height  * 0.5
0068             property int borderMargin: spaceship.width * 0.5
0069             property bool onScreenControls: ApplicationInfo.isMobile
0070             property alias explosion: explosion
0071         }
0072 
0073         onStart: {
0074             explosion.hide()
0075             Activity.start(items,message)
0076         }
0077         onStop: {
0078             explosionTimer.stop()
0079             spaceRepeat.stop()
0080             Activity.stop()
0081         }
0082 
0083         onWidthChanged: {
0084             initSpace()
0085             items.spaceshipX = parent.width * 0.5
0086         }
0087         onHeightChanged: {
0088             initSpace()
0089             items.spaceshipX = parent.width * 0.5
0090         }
0091         // alternate rewind space1 and space2
0092         property bool rewindSpace1: true
0093 
0094         function initSpace(){
0095             space1.height = Math.max(parent.width, parent.height)
0096             space1.y = 0
0097             space2.y = -space1.height
0098             down.duration = items.spaceSpeed * 0.5
0099             down2.duration = items.spaceSpeed
0100             spaceRepeat.interval = items.spaceSpeed * 0.5
0101             space1.startMoving()
0102             space2.startMoving()
0103             spaceRepeat.restart()
0104             rewindSpace1 = true
0105             station.width = background.width
0106             station.y = -station.height
0107         }
0108 
0109         Image {
0110             id: space1
0111             source: Activity.url+"background.svg"
0112             width: height
0113             height: Math.max(parent.width, parent.height)
0114             sourceSize.height: height
0115             fillMode: Image.PreserveAspectFit
0116             anchors.horizontalCenter: parent.horizontalCenter
0117             y: 0
0118             function startMoving() {
0119                 down.restart()
0120             }
0121         }
0122         NumberAnimation {
0123             id: down
0124             target: space1
0125             property: "y"
0126             to: space1.height
0127             duration: items.spaceSpeed * 0.5
0128         }
0129 
0130         Image {
0131             id: space2
0132             source: Activity.url+"background.svg"
0133             width: space1.height
0134             height: space1.height
0135             sourceSize.height: space1.height
0136             fillMode: Image.PreserveAspectFit
0137             anchors.horizontalCenter: parent.horizontalCenter
0138             y: -space1.height
0139             function startMoving() {
0140                 down2.restart()
0141             }
0142         }
0143         NumberAnimation {
0144             id: down2
0145             target: space2
0146             property: "y"
0147             to: space1.height
0148             duration: items.spaceSpeed
0149         }
0150 
0151         Timer {
0152             id: spaceRepeat
0153             running: false
0154             repeat: true
0155             interval: items.spaceSpeed * 0.5
0156             onTriggered: {
0157                 if(rewindSpace1) {
0158                     down.duration = 0
0159                     space1.y = -space1.height
0160                     down.duration = items.spaceSpeed
0161                     space1.startMoving()
0162                 } else {
0163                     down2.duration = 0
0164                     space2.y = -space1.height
0165                     down2.duration = items.spaceSpeed
0166                     space2.startMoving()
0167                 }
0168                 rewindSpace1 = !rewindSpace1
0169             }
0170         }
0171 
0172         DialogHelp {
0173             id: dialogHelp
0174             onClose: {
0175                 home()
0176                 Activity.initLevel()
0177             }
0178         }
0179 
0180         Bar {
0181             id: bar
0182             level: items.currentLevel + 1
0183             content: BarEnumContent { value: help | home | level }
0184             onHelpClicked: {
0185                 Activity.stop()
0186                 displayDialog(dialogHelp)
0187             }
0188             onPreviousLevelClicked: if(!bonus.isPlaying) Activity.previousLevel()
0189             onNextLevelClicked: if(!bonus.isPlaying) Activity.nextLevel()
0190             onHomeClicked: home();
0191         }
0192 
0193         Bonus {
0194             id: bonus
0195             Component.onCompleted: {
0196                 loose.connect(Activity.initLevel)
0197                 win.connect(Activity.nextLevel)
0198             }
0199         }
0200 
0201         IntroMessage {
0202             id: message
0203             onIntroDone: {
0204                 items.startMessage = false
0205                 items.processTimer.start()
0206                 Activity.createPlanet()
0207                 items.planetCreation.start()
0208             }
0209             intro: [
0210                 qsTr("Gravity is universal and Newton's law of universal gravitation extends gravity"
0211                      +" beyond earth. This force of gravitational attraction is directly dependent"
0212                      +" upon the mass of both objects and inversely proportional to"
0213                      +" the square of the distance between their centers."),
0214                 qsTr("Since the gravitational force is directly proportional to the mass of both interacting"
0215                      +" objects, more massive objects will attract each other with a greater gravitational"
0216                      +" force."),
0217                 qsTr("But as this force is inversely proportional to the square of the distance"
0218                      +" between the two interacting objects, more distance will"
0219                      +" result in weaker gravitational force."),
0220                 qsTr("Your goal is to move the spaceship and avoid hitting the planets until you reach the"
0221                      +" space station. The arrow indicates the direction and the intensity of the gravity"
0222                      +" on your ship."),
0223                 qsTr("Try to stay near the center of the screen, and anticipate by looking at the size"
0224                     +" and direction of the arrow.")
0225             ]
0226             z: 110
0227             anchors {
0228                 top: parent.top
0229                 topMargin: 10
0230                 right: parent.right
0231                 rightMargin: 5
0232                 left: parent.left
0233                 leftMargin: 5
0234             }
0235         }
0236 
0237         Planet {
0238             id: planet0
0239             leftSide: true
0240         }
0241 
0242         Planet {
0243             id: planet1
0244             leftSide: false
0245         }
0246 
0247         Image {
0248             id: station
0249             source: Activity.url + "space_station.svg"
0250             x: 0
0251             y: -height
0252             width: background.width
0253             sourceSize.width: width
0254             fillMode: Image.PreserveAspectFit
0255         }
0256         NumberAnimation {
0257             id: stationDown
0258             target: station
0259             property: "y"
0260             to: items.spaceshipY - (station.height * 0.5)
0261             duration: items.planetFrequency / 4
0262             onRunningChanged: if(station.y > -station.height) {
0263                 Activity.stop();
0264                 items.bonus.good("lion");
0265             }
0266         }
0267 
0268         Image {
0269             id: spaceship
0270             source: Activity.url + "tux_spaceship.svg"
0271             sourceSize.width: 120 * ApplicationInfo.ratio
0272             x: items.spaceshipX - width * 0.5
0273             y: items.spaceshipY - height * 0.5
0274             z: 100
0275 
0276             function show() {
0277                 opacity = 100;
0278             }
0279             function hide() {
0280                 opacity = 0;
0281             }
0282 
0283             Behavior on opacity {
0284                 NumberAnimation {
0285                     duration: 500
0286                     easing.type: Easing.OutExpo
0287                 }
0288             }
0289         }
0290 
0291         Image {
0292             id: explosion
0293             anchors.centerIn: spaceship
0294             width: spaceship.width
0295             height: width
0296             source: Activity.url + "crash.svg"
0297             visible: false
0298             scale: 0
0299             opacity: 0
0300             z: 105
0301 
0302             Timer {
0303                 id: explosionTimer
0304                 interval: 600; running: false; repeat: false
0305                 onTriggered: explosion.opacity = 0
0306             }
0307 
0308             function show() {
0309                 visible = true;
0310                 opacity = 100
0311                 scale = 1;
0312                 explosionTimer.running = true
0313             }
0314             function hide() {
0315                 visible = false;
0316                 scale = 0;
0317                 explosionTimer.running = false
0318             }
0319 
0320             Behavior on opacity {
0321                 NumberAnimation {
0322                     duration: 500
0323                     easing.type: Easing.Linear
0324                 }
0325             }
0326             Behavior on scale {
0327                 NumberAnimation {
0328                     duration: 500
0329                     easing.type: Easing.OutCubic
0330                 }
0331             }
0332 
0333         }
0334 
0335         // line to show force magnitude and direction
0336         Image {
0337             id: arrow
0338             visible: width >= 20 && processTimer.running
0339             x: items.gravity > 0 ?
0340                    items.spaceshipX : items.spaceshipX - width
0341             y: spaceship.y - height * 1.1
0342             z: 101
0343             sourceSize.height: height
0344             width: Math.abs(items.gravity * 2000)
0345             height: 40 * ApplicationInfo.ratio
0346             source: Activity.url + "arrow.svg"
0347             rotation: items.gravity < 0 ? 0 : 180
0348             Behavior on width {
0349                 NumberAnimation{ duration: 100 }
0350             }
0351         }
0352 
0353         Row {
0354             id: leftRightControl
0355             anchors.horizontalCenter: background.horizontalCenter
0356             anchors.bottom: bar.top
0357             anchors.bottomMargin: spacing
0358             width: leftButton.width + rightButton.width + spacing
0359             height: leftButton.height
0360             visible: items.onScreenControls
0361             z: 102
0362             opacity: 0.4
0363             spacing: height
0364 
0365             ControlButton {
0366                 id: leftButton
0367                 source: "qrc:/gcompris/src/core/resource/arrow_left.svg"
0368                 onPressed: Activity.processKeyPress({key: Qt.Key_Left});
0369                 onReleased: Activity.processKeyRelease({key: Qt.Key_Left});
0370                 exceed: height * 0.4
0371             }
0372 
0373             ControlButton {
0374                 id: rightButton
0375                 source: "qrc:/gcompris/src/core/resource/arrow_right.svg"
0376                 onPressed: Activity.processKeyPress({key: Qt.Key_Right});
0377                 onReleased: Activity.processKeyRelease({key: Qt.Key_Right});
0378                 exceed: leftButton.exceed
0379             }
0380         }
0381 
0382         Timer {
0383             id: planetCreation
0384             running: false
0385             repeat: true
0386             interval: items.planetFrequency
0387             onTriggered: {
0388                 Activity.destroyPlanet()
0389                 Activity.createPlanet()
0390             }
0391         }
0392 
0393         Timer {
0394             id: processTimer
0395             interval: 16
0396             running: false
0397             repeat: true
0398             onTriggered: {
0399                 Activity.moveSpaceship()
0400             }
0401         }
0402     }
0403 }