Warning, /education/gcompris/src/activities/mining/Mining.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - mining.qml 0002 * 0003 * SPDX-FileCopyrightText: 2014 Bruno Coudoin <bruno.coudoin@gcompris.net> 0004 * 0005 * Authors: 0006 * Peter Albrecht <pa-dev@gmx.de> (GTK+ version) 0007 * Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 import QtQuick 2.12 0012 import GCompris 1.0 0013 0014 import "../../core" 0015 import "mining.js" as Activity 0016 0017 ActivityBase { 0018 id: activity 0019 0020 onStart: focus = true 0021 onStop: {} 0022 0023 pageComponent: Item { 0024 id: background 0025 anchors.fill: parent 0026 0027 signal start 0028 signal stop 0029 0030 property bool gotIt: false 0031 property bool horizontalLayout: background.width >= background.height 0032 0033 Component.onCompleted: { 0034 activity.start.connect(start) 0035 activity.stop.connect(stop) 0036 } 0037 0038 // Add here the QML items you need to access in javascript 0039 QtObject { 0040 id: items 0041 property Item main: activity.main 0042 property alias background: background 0043 property alias miningBg: miningBg 0044 property int currentLevel: activity.currentLevel 0045 property alias bonus: bonus 0046 property alias mineModel: mineObjects.model 0047 property Item nugget 0048 property int collectedNuggets: 0 0049 } 0050 0051 onStart: { Activity.start(items) } 0052 onStop: { Activity.stop() } 0053 0054 Image { 0055 id: miningBg 0056 source: Activity.url + "rockwall.svg" 0057 anchors.horizontalCenter: parent.horizontalCenter 0058 anchors.verticalCenter: parent.verticalCenter 0059 sourceSize.width: parent.width 0060 width: parent.width 0061 height: parent.height 0062 scale: miningBg._MIN_SCALE 0063 0064 property int subLevel 0065 property int maxSubLevel 0066 property real _MAX_SCALE: 3 0067 property real _MIN_SCALE: 1 0068 0069 onScaleChanged: items.nugget.checkOnScreen() 0070 0071 Image { 0072 source: Activity.url + "vertical_border.svg" 0073 sourceSize.height: parent.height 0074 width: parent.width * 0.05 0075 anchors { 0076 top: parent.top 0077 left: parent.left 0078 bottom: parent.bottom 0079 } 0080 } 0081 0082 Image { 0083 source: Activity.url + "vertical_border.svg" 0084 sourceSize.height: parent.height 0085 width: parent.width * 0.05 0086 anchors { 0087 top: parent.top 0088 right: parent.right 0089 bottom: parent.bottom 0090 } 0091 } 0092 0093 Image { 0094 source: Activity.url + "horizontal_border.svg" 0095 sourceSize.width: parent.width 0096 height: parent.height * 0.05 0097 anchors { 0098 top: parent.top 0099 right: parent.right 0100 left: parent.left 0101 } 0102 } 0103 0104 GridView { 0105 id: mineObjects 0106 anchors.fill: parent 0107 cellWidth: parent.width / 4 0108 cellHeight: parent.height / 4 0109 0110 delegate: Item { 0111 width: mineObjects.cellWidth 0112 height: mineObjects.cellHeight 0113 // Calculated value true when the nugget is on the visible 0114 // part of the screen 0115 property bool onScreen: true 0116 property alias nuggetImg: nuggetImg 0117 signal hit(real x, real y) 0118 signal checkOnScreen 0119 0120 onHit: { 0121 if(!mouseArea.enabled) 0122 return 0123 0124 var point = parent.mapToItem(nuggetImg, x, y) 0125 if(point.x > 0 && point.x < nuggetImg.width && 0126 point.y > 0 && point.y < nuggetImg.height) 0127 nuggetImg.hit() 0128 } 0129 0130 onCheckOnScreen: { 0131 // Calc if the nugget is visible or not 0132 var nuggetCoord1 = 0133 background.mapFromItem(miningBg, 0134 items.nugget.x + items.nugget.nuggetImg.x, 0135 items.nugget.y + items.nugget.nuggetImg.y) 0136 var nuggetCoord2 = 0137 background.mapFromItem(miningBg, 0138 items.nugget.x + items.nugget.nuggetImg.x + items.nugget.nuggetImg.width, 0139 items.nugget.y + items.nugget.nuggetImg.y + items.nugget.nuggetImg.height) 0140 0141 if(nuggetCoord1.x > miningBg.width || 0142 nuggetCoord2.x < 0 || 0143 nuggetCoord1.y > miningBg.height || 0144 nuggetCoord2.y < 0) 0145 onScreen = false 0146 else 0147 onScreen = true 0148 } 0149 0150 Image { 0151 id: nuggetImg 0152 source: Activity.url + "gold_nugget.svg" 0153 sourceSize.width: mineObjects.cellWidth * 3 0154 width: mineObjects.cellWidth * modelData.widthFactor / 2 0155 height: mineObjects.cellHeight * modelData.widthFactor / 2 0156 anchors.horizontalCenter: parent.horizontalCenter 0157 anchors.verticalCenter: parent.verticalCenter 0158 opacity: modelData.isTarget && 0159 miningBg.scale === miningBg._MAX_SCALE && 0160 !background.gotIt ? 1 : 0 0161 0162 signal hit 0163 onHit: { 0164 activity.audioEffects.play(Activity.url + "pickaxe.wav") 0165 background.gotIt = true 0166 items.collectedNuggets++ 0167 tuto.setState("Unzoom") 0168 } 0169 0170 Component.onCompleted: { 0171 if(modelData.isTarget) 0172 items.nugget = parent 0173 } 0174 0175 MouseArea { 0176 id: mouseArea 0177 anchors.fill: parent 0178 enabled: modelData.isTarget && 0179 miningBg.scale === miningBg._MAX_SCALE && 0180 background.gotIt === false 0181 onClicked: parent.hit() 0182 } 0183 0184 Behavior on opacity { PropertyAnimation { duration: 1000 } } 0185 } 0186 0187 Image { 0188 id: cell 0189 source: modelData.source 0190 sourceSize.width: mineObjects.cellWidth * 3 0191 width: mineObjects.cellWidth * modelData.widthFactor 0192 height: mineObjects.cellHeight * modelData.widthFactor 0193 anchors.horizontalCenter: parent.horizontalCenter 0194 anchors.verticalCenter: parent.verticalCenter 0195 rotation: modelData.rotation 0196 opacity: !modelData.isTarget ? 1 : (background.gotIt ? 0 : 1) 0197 0198 Component.onCompleted: { 0199 activity.audioEffects.play(Activity.url + "realrainbow.wav") 0200 } 0201 0202 ParallelAnimation { 0203 running: modelData.isTarget && !background.gotIt 0204 loops: Animation.Infinite 0205 SequentialAnimation { 0206 loops: Animation.Infinite 0207 NumberAnimation { 0208 target: cell 0209 property: "rotation" 0210 from: 0; to: 360 0211 duration: 5000; 0212 easing.type: Easing.InOutQuad 0213 } 0214 NumberAnimation { 0215 target: cell; property: "rotation" 0216 from: 360; to: 0 0217 duration: 5000; 0218 easing.type: Easing.InOutQuad 0219 } 0220 } 0221 SequentialAnimation { 0222 loops: Animation.Infinite 0223 NumberAnimation { 0224 target: cell; property: "scale" 0225 from: 0; to: 1 0226 duration: 3000; 0227 easing.type: Easing.InOutQuad 0228 } 0229 PauseAnimation { duration: 300 + Math.random() * 300 } 0230 NumberAnimation { 0231 target: cell 0232 property: "scale" 0233 from: 1; to: 0 0234 duration: 1000; 0235 easing.type: Easing.InOutQuad 0236 } 0237 } 0238 } 0239 } 0240 } 0241 } 0242 0243 function updateScale(zoomDelta, x, y) { 0244 var xx1 = background.mapFromItem(miningBg, x, y) 0245 var previousScale = miningBg.scale 0246 var miningBgScale = miningBg.scale 0247 var miningBgHOffset = miningBg.anchors.horizontalCenterOffset 0248 var miningBgVOffset = miningBg.anchors.verticalCenterOffset 0249 if (zoomDelta > 0 && miningBg.scale < miningBg._MAX_SCALE) { 0250 if(miningBgScale < miningBg._MAX_SCALE - 0.1) 0251 miningBgScale += 0.1; 0252 else 0253 miningBgScale = miningBg._MAX_SCALE 0254 0255 if(gotIt) 0256 tuto.setState("Unzoom") 0257 else if(miningBgScale < miningBg._MAX_SCALE) 0258 tuto.setState(items.nugget.onScreen ? "ZoomOk" : "ZoomBad") 0259 else 0260 tuto.setState(items.nugget.onScreen ? "NuggetSeen" : "NuggetNotSeen") 0261 0262 } else if (zoomDelta < 0) { 0263 if(miningBgScale > miningBg._MIN_SCALE) { 0264 miningBgScale -= 0.1; 0265 0266 if(gotIt) 0267 tuto.setState("Unzoom") 0268 else if(miningBgScale > miningBg._MIN_SCALE) 0269 tuto.setState(items.nugget.onScreen ? "UnzoomOk" : "UnzoomBad") 0270 else 0271 tuto.setState("Started") 0272 } else if (gotIt) { 0273 gotIt = false 0274 if(miningBg.subLevel == miningBg.maxSubLevel) { 0275 bonus.good("lion") 0276 } else { 0277 miningBg.subLevel++ 0278 miningBgScale = miningBg._MIN_SCALE 0279 miningBgHOffset = 0 0280 miningBgVOffset = 0 0281 Activity.createLevel() 0282 } 0283 tuto.setState("Stopped") 0284 } else { 0285 miningBgScale = miningBg._MIN_SCALE 0286 miningBgHOffset = 0 0287 miningBgVOffset = 0 0288 if(miningBg.subLevel != items.collectedNuggets) 0289 tuto.setState("Started") 0290 } 0291 } 0292 if(miningBgScale <= miningBg._MIN_SCALE) { 0293 miningBgScale = miningBg._MIN_SCALE 0294 } 0295 miningBg.scale = miningBgScale 0296 if(previousScale != miningBg.scale && miningBg.scale > miningBg._MIN_SCALE) { 0297 var xx2 = background.mapFromItem(miningBg, x, y) 0298 miningBgHOffset += xx1.x - xx2.x 0299 miningBgVOffset += xx1.y - xx2.y 0300 } else if(miningBg.scale === miningBg._MIN_SCALE) { 0301 miningBgHOffset = 0 0302 miningBgVOffset = 0 0303 } 0304 miningBg.anchors.horizontalCenterOffset = miningBgHOffset 0305 miningBg.anchors.verticalCenterOffset = miningBgVOffset 0306 } 0307 0308 MouseArea { 0309 anchors.fill: parent 0310 propagateComposedEvents: true 0311 onWheel: miningBg.updateScale(wheel.angleDelta.y, wheel.x, wheel.y) 0312 } 0313 0314 MultiPointTouchArea { 0315 anchors.fill: parent 0316 mouseEnabled: false 0317 minimumTouchPoints: 1 0318 maximumTouchPoints: 2 0319 // To determine if we zoom or unzoom 0320 property int prevDist: 0 0321 // To avoid having too many updates or the zoom flickers 0322 property date dateEvent: new Date() 0323 touchPoints: [ 0324 TouchPoint { id: point1 }, 0325 TouchPoint { id: point2 } 0326 ] 0327 onReleased: prevDist = 0 0328 onTouchUpdated: { 0329 if(!point2.pressed) { 0330 mineObjects.itemAt(point1.x, point1.y).hit(point1.x, point1.y) 0331 return 0332 } 0333 // Calc Distance 0334 var dist = Math.floor(Math.sqrt(Math.pow(point1.x - point2.x, 2) + 0335 Math.pow(point1.y - point2.y, 2))) 0336 var newDateEvent = new Date() 0337 if(prevDist != dist && 0338 newDateEvent.getTime() - dateEvent.getTime() > 50) { 0339 miningBg.updateScale(dist - prevDist, 0340 (point1.x + point2.x) / 2, 0341 (point1.y + point2.y) / 2) 0342 dateEvent = newDateEvent 0343 } 0344 prevDist = dist 0345 } 0346 } 0347 } 0348 0349 Image { 0350 id: carriage 0351 source: Activity.url + "gold_carriage.svg" 0352 sourceSize.height: background.horizontalLayout ? 120 * ApplicationInfo.ratio : 80 * ApplicationInfo.ratio 0353 anchors { 0354 right: parent.right 0355 bottom: background.horizontalLayout ? parent.bottom : bar.top 0356 } 0357 0358 GCText { 0359 id: score 0360 anchors { 0361 horizontalCenter: parent.horizontalCenter 0362 verticalCenter: parent.verticalCenter 0363 horizontalCenterOffset: parent.width / 10 0364 } 0365 text: items.collectedNuggets + "/" + miningBg.maxSubLevel 0366 color: "white" 0367 font.bold: true 0368 style: Text.Outline 0369 styleColor: "black" 0370 fontSize: 22 0371 } 0372 } 0373 0374 Rectangle { 0375 id: tutoBackground 0376 color: "#C0b7b353" 0377 border.color: "black" 0378 border.width: 2 0379 radius: 10 0380 anchors { 0381 left: parent.left 0382 right: parent.right 0383 top: parent.top 0384 margins: 10 0385 } 0386 height: tuto.height + anchors.margins * 2 0387 visible: tuto.state != "Stopped" 0388 Behavior on height { PropertyAnimation { duration: 100 } } 0389 0390 GCText { 0391 id: tuto 0392 fontSize: 13 0393 anchors { 0394 left: parent.left 0395 right: parent.right 0396 top: parent.top 0397 margins: 10 0398 } 0399 color: "white" 0400 wrapMode: TextEdit.WordWrap 0401 horizontalAlignment: TextEdit.AlignHCenter 0402 0403 property string newState 0404 0405 function setState(nextState) { 0406 if(bar.level == 1) { 0407 if(newState != nextState) { 0408 newState = nextState 0409 anim.restart() 0410 } 0411 } else { 0412 newState = "Stopped" 0413 anim.restart() 0414 } 0415 } 0416 0417 states: [ 0418 State { 0419 name: "Started" 0420 PropertyChanges { 0421 target: tuto; 0422 text: qsTr("Find the sparkle and zoom in around it. If you have a mouse, point the cursor on the sparkle then use the scroll wheel. If you have a trackpad, point the cursor on the sparkle then drag one finger on the right area or two fingers on the center. On a touch area, drag two fingers away from the sparkle, one in each direction.") 0423 } 0424 }, 0425 State { 0426 name: "Stopped" 0427 PropertyChanges { target: tuto; text: ""} 0428 }, 0429 State { 0430 name: "ZoomOk" 0431 PropertyChanges { 0432 target: tuto 0433 text: qsTr("Perfect you are zooming. Continue until you see the nugget.")} 0434 }, 0435 State { 0436 name: "ZoomBad" 0437 PropertyChanges { 0438 target: tuto 0439 text: qsTr("Hum, take care, you are zooming too far from the sparkle.")} 0440 }, 0441 State { 0442 name: "NuggetSeen" 0443 PropertyChanges { 0444 target: tuto 0445 text: qsTr("Now you see the nugget, click on it to catch it.")} 0446 }, 0447 State { 0448 name: "NuggetNotSeen" 0449 PropertyChanges { 0450 target: tuto 0451 text: qsTr("Hum, you are too far from the nugget to see it. Unzoom then zoom again as close as you can from the sparkle.")} 0452 }, 0453 State { 0454 name: "Unzoom" 0455 PropertyChanges { 0456 target: tuto 0457 text: qsTr("Now unzoom and try to find another sparkle.")} 0458 }, 0459 State { 0460 name: "UnzoomBad" 0461 PropertyChanges { 0462 target: tuto 0463 text: qsTr("Continue to unzoom until you see the sparkle.")} 0464 }, 0465 State { 0466 name: "UnzoomOk" 0467 PropertyChanges { 0468 target: tuto 0469 text: qsTr("Now you see the sparkle, go ahead, you can zoom on it.")} 0470 } 0471 ] 0472 0473 SequentialAnimation { 0474 id: anim 0475 PropertyAnimation { 0476 target: tuto 0477 property: "opacity" 0478 easing.type: Easing.Linear 0479 from: 1.0; to: 0 0480 duration: 200 0481 } 0482 PropertyAction { 0483 target: tuto 0484 property: "state" 0485 value: tuto.newState 0486 } 0487 PropertyAnimation { 0488 target: tuto 0489 property: "opacity" 0490 easing.type: Easing.Linear 0491 from: 0; to: 1.0 0492 duration: 200 0493 } 0494 } 0495 0496 Behavior on opacity { PropertyAnimation { duration: 100 } } 0497 transitions: Transition { 0498 PropertyAnimation { 0499 target: tuto 0500 property: "opacity" 0501 to: 1.0 0502 } 0503 } 0504 } 0505 } 0506 0507 DialogHelp { 0508 id: dialogHelp 0509 onClose: home() 0510 } 0511 0512 Bar { 0513 id: bar 0514 level: items.currentLevel + 1 0515 content: BarEnumContent { value: help | home | level } 0516 onHelpClicked: { 0517 displayDialog(dialogHelp) 0518 } 0519 onPreviousLevelClicked: Activity.previousLevel() 0520 onNextLevelClicked: Activity.nextLevel() 0521 onHomeClicked: activity.home() 0522 0523 onLevelChanged: { 0524 miningBg.subLevel = 1 0525 miningBg.anchors.horizontalCenterOffset = 0 0526 miningBg.anchors.verticalCenterOffset = 0 0527 miningBg.scale = miningBg._MIN_SCALE 0528 tuto.setState("Started") 0529 0530 switch(bar.level) { 0531 case 1: 0532 miningBg.maxSubLevel = 2 0533 break 0534 case 2: 0535 miningBg.maxSubLevel = 4 0536 break 0537 case 3: 0538 miningBg.maxSubLevel = 10 0539 break 0540 } 0541 0542 } 0543 } 0544 0545 Bonus { 0546 id: bonus 0547 Component.onCompleted: win.connect(Activity.nextLevel) 0548 } 0549 0550 } 0551 0552 }