Warning, /education/gcompris/src/activities/baby_mouse/Baby_mouse.qml is written in an unsupported language. File is not indexed.
0001 /* GCompris - Baby_mouse.qml 0002 * 0003 * SPDX-FileCopyrightText: 2021 Mariam Fahmy <mariamfahmy66@gmail.com> 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 import QtQuick 2.12 0007 import GCompris 1.0 0008 0009 import "../../core" 0010 import "baby_mouse.js" as Activity 0011 import "qrc:/gcompris/src/core/core.js" as Core 0012 0013 ActivityBase { 0014 id: activity 0015 0016 onStart: focus = true 0017 onStop: {} 0018 0019 pageComponent: Image { 0020 id: background 0021 source: "qrc:/gcompris/src/activities/colors/resource/background.svg" 0022 sourceSize.width: width 0023 sourceSize.height: height 0024 fillMode: Image.PreserveAspectCrop 0025 0026 signal start 0027 signal stop 0028 0029 readonly property real defaultScale: 1 0030 readonly property real mediumScale: 1.2 0031 readonly property real largeScale: 1.4 0032 0033 readonly property int toleranceLimit: 5 0034 0035 property bool isArrowPressed: false 0036 0037 Component.onCompleted: { 0038 activity.start.connect(start) 0039 activity.stop.connect(stop) 0040 } 0041 0042 // Add here the QML items you need to access in javascript 0043 QtObject { 0044 id: items 0045 property Item main: activity.main 0046 property GCSfx audioEffects: activity.audioEffects 0047 property alias duckModel: duckModel 0048 property bool hasBeenDragged: false 0049 } 0050 0051 onStart: { 0052 Activity.start(items) 0053 resetDuckPosition() 0054 } 0055 onStop: { 0056 Activity.stop() 0057 resetArrowTimer.stop() 0058 pressArrowTimer.stop() 0059 } 0060 0061 Item { 0062 id: mainArea 0063 width: background.width - duckGrid.width 0064 height: background.height - bar.height * 1.05 - y 0065 anchors.left: duckGrid.right 0066 anchors.top: arrowsArea.bottom 0067 0068 // To detect click in this area with mainAreaBlock... 0069 Rectangle { 0070 anchors.fill: parent 0071 color: "transparent" 0072 } 0073 0074 readonly property double rightDirectionLimit: mainArea.width - mainDuck.width 0075 readonly property double downDirectionLimit: mainArea.height - mainDuck.height 0076 0077 property alias mainDuckX: mainDuck.x 0078 property alias mainDuckY: mainDuck.y 0079 property real previousDuckX 0080 property real previousDuckY 0081 0082 Image { 0083 id: mainDuck 0084 source: Activity.duckColorURL + "blue_duck.svg" 0085 sourceSize.width: 70 * ApplicationInfo.ratio 0086 sourceSize.height: 70 * ApplicationInfo.ratio 0087 0088 SequentialAnimation { 0089 running: true 0090 loops: Animation.Infinite 0091 NumberAnimation { 0092 target: mainDuck 0093 property: "rotation" 0094 from: -10; to: 10 0095 duration: 400 + Math.floor(Math.random() * 400) 0096 easing.type: Easing.InOutQuad 0097 } 0098 NumberAnimation { 0099 target: mainDuck 0100 property: "rotation" 0101 from: 10; to: -10 0102 duration: 400 + Math.floor(Math.random() * 400) 0103 easing.type: Easing.InOutQuad 0104 } 0105 } 0106 } 0107 0108 MouseArea { 0109 id: mouseMovement 0110 anchors.fill: parent 0111 hoverEnabled: true 0112 0113 property real startX: 0 0114 property real startY: 0 0115 0116 onEntered: { 0117 setStartPosition() 0118 } 0119 0120 onPositionChanged: { 0121 if(items.hasBeenDragged) { 0122 setStartPosition() 0123 items.hasBeenDragged = false 0124 return; 0125 } 0126 0127 resetArrowTimer.restart() 0128 0129 // Comparing the current mouse position with the previous mouse position 0130 var moveX = mouseX - startX 0131 var moveY = mouseY - startY 0132 0133 background.moveDuckHorizontally(moveX) 0134 background.moveDuckVertically(moveY) 0135 background.indicateArrowScale() 0136 0137 setStartPosition() 0138 } 0139 0140 function setStartPosition() { 0141 startX = mouseX 0142 startY = mouseY 0143 } 0144 } 0145 } 0146 0147 MultiPointTouchArea { 0148 id: touchArea 0149 anchors.fill: parent 0150 0151 property real previousX 0152 property real previousY 0153 0154 property real startX 0155 property real startY 0156 0157 onPressed: { 0158 for(var i in touchPoints) { 0159 var touch = touchPoints[i] 0160 previousX = touch.x 0161 previousY = touch.y 0162 0163 startX = touch.x 0164 startY = touch.y 0165 0166 items.hasBeenDragged = true 0167 0168 var arrowsPoint = parent.mapToItem(arrowsArea, touch.x, touch.y) 0169 var arrowsBlock = arrowsArea.childAt(arrowsPoint.x, arrowsPoint.y) 0170 0171 if(arrowsBlock) { 0172 background.isArrowPressed = true 0173 if(arrowsArea.contains(arrowsPoint.x, arrowsPoint.y, arrowsArea.upArrow)) { 0174 pressArrowTimer.upPressed = true 0175 pressArrowTimer.start() 0176 } 0177 else if(arrowsArea.contains(arrowsPoint.x, arrowsPoint.y, arrowsArea.downArrow)) { 0178 pressArrowTimer.downPressed = true 0179 pressArrowTimer.start() 0180 } 0181 else if(arrowsArea.contains(arrowsPoint.x, arrowsPoint.y, arrowsArea.leftArrow)) { 0182 pressArrowTimer.start() 0183 } 0184 else if(arrowsArea.contains(arrowsPoint.x, arrowsPoint.y, arrowsArea.rightArrow)) { 0185 pressArrowTimer.rightPressed = true 0186 pressArrowTimer.start() 0187 } 0188 } 0189 } 0190 } 0191 0192 onTouchUpdated: { 0193 if(background.isArrowPressed) return; 0194 for(var i in touchPoints) { 0195 var touch = touchPoints[i] 0196 var moveX = touch.x - previousX 0197 var moveY = touch.y - previousY 0198 0199 background.moveDuckHorizontally(moveX) 0200 background.moveDuckVertically(moveY) 0201 background.indicateArrowScale() 0202 0203 previousX = touch.x 0204 previousY = touch.y 0205 } 0206 } 0207 0208 onReleased: { 0209 for(var i in touchPoints) { 0210 var touch = touchPoints[i] 0211 0212 var maxToleranceX = startX + background.toleranceLimit 0213 var minToleranceX = startX - background.toleranceLimit 0214 0215 var maxToleranceY = startY + background.toleranceLimit 0216 var minToleranceY = startY - background.toleranceLimit 0217 0218 if(minToleranceX <= touch.x && touch.x <= maxToleranceX && minToleranceY <= touch.y && touch.y <= maxToleranceY) { 0219 var ducksPoint = parent.mapToItem(duckGrid, touch.x, touch.y) 0220 var ducksBlock = duckGrid.itemAt(ducksPoint.x, ducksPoint.y) 0221 0222 var mainAreaPoint = parent.mapToItem(mainArea, touch.x, touch.y) 0223 var mainAreaBlock = mainArea.childAt(mainAreaPoint.x, mainAreaPoint.y) 0224 0225 if(ducksBlock) { 0226 ducksBlock.restartAnimation() 0227 } 0228 else if(mainAreaBlock){ 0229 pressCircle.x = touch.x - pressCircle.width / 2 0230 pressCircle.y = touch.y - pressCircle.height / 2 0231 pressCircle.visible = true 0232 Activity.playSound(4) 0233 } 0234 } 0235 0236 background.isArrowPressed = false 0237 background.resetArrowScale() 0238 pressArrowTimer.stopTimer() 0239 } 0240 } 0241 } 0242 0243 Timer { 0244 id: resetArrowTimer 0245 interval: 200 0246 onTriggered: background.resetArrowScale() 0247 } 0248 0249 Timer { 0250 id: pressArrowTimer 0251 0252 property bool upPressed: false 0253 property bool downPressed: false 0254 property bool rightPressed: false 0255 0256 function stopTimer() { 0257 upPressed = false 0258 downPressed = false 0259 rightPressed = false 0260 stop() 0261 } 0262 0263 interval: 10 0264 repeat: true 0265 triggeredOnStart: true 0266 onTriggered: upPressed ? arrowsArea.upArrow.moveDuckUp() : 0267 downPressed ? arrowsArea.downArrow.moveDuckDown() : 0268 rightPressed ? arrowsArea.rightArrow.moveDuckToRight() : 0269 arrowsArea.leftArrow.moveDuckToLeft() 0270 } 0271 0272 function moveDuckHorizontally(moveX) { 0273 mainArea.previousDuckX = mainArea.mainDuckX 0274 0275 // Duck Motion in x-direction. 0276 if(mainArea.previousDuckX + moveX >= mainArea.rightDirectionLimit) { 0277 mainArea.mainDuckX = mainArea.rightDirectionLimit 0278 } 0279 else if(mainArea.previousDuckX + moveX <= 0) { 0280 mainArea.mainDuckX = 0 0281 } 0282 else { 0283 mainArea.mainDuckX += moveX 0284 } 0285 } 0286 0287 function moveDuckVertically(moveY) { 0288 mainArea.previousDuckY = mainArea.mainDuckY 0289 0290 // Duck Motion in y-direction. 0291 if(mainArea.previousDuckY + moveY >= mainArea.downDirectionLimit) { 0292 mainArea.mainDuckY = mainArea.downDirectionLimit 0293 } 0294 else if(mainArea.previousDuckY + moveY <= 0) { 0295 mainArea.mainDuckY = 0 0296 } 0297 else { 0298 mainArea.mainDuckY += moveY 0299 } 0300 } 0301 0302 function indicateArrowScale() { 0303 resetArrowScale() 0304 var diffX = mainArea.mainDuckX - mainArea.previousDuckX 0305 var diffY = mainArea.mainDuckY - mainArea.previousDuckY 0306 0307 if(diffX === 0 && diffY === 0) return; 0308 0309 // In case main duck moves in the y-direction only. 0310 if(diffX === 0) { 0311 if(diffY < 0) arrowsArea.upArrow.scale = largeScale 0312 else arrowsArea.downArrow.scale = largeScale 0313 return 0314 } 0315 0316 // In case main duck moves in the x-direction only. 0317 if(diffY === 0) { 0318 if(diffX < 0) arrowsArea.leftArrow.scale = largeScale 0319 else arrowsArea.rightArrow.scale = largeScale 0320 return 0321 } 0322 0323 // In case main duck moves in both x and y directions. 0324 if(Math.abs(diffX) > Math.abs(diffY)) { 0325 if(diffX < 0) arrowsArea.leftArrow.scale = largeScale 0326 else arrowsArea.rightArrow.scale = largeScale 0327 0328 if(diffY < 0) arrowsArea.upArrow.scale = mediumScale 0329 else arrowsArea.downArrow.scale = mediumScale 0330 } 0331 else if(Math.abs(diffX) < Math.abs(diffY)) { 0332 if(diffX < 0) arrowsArea.leftArrow.scale = mediumScale 0333 else arrowsArea.rightArrow.scale = mediumScale 0334 0335 if(diffY < 0) arrowsArea.upArrow.scale = largeScale 0336 else arrowsArea.downArrow.scale = largeScale 0337 } 0338 else { 0339 if(diffX < 0) arrowsArea.leftArrow.scale = mediumScale 0340 else arrowsArea.rightArrow.scale = mediumScale 0341 0342 if(diffY < 0) arrowsArea.upArrow.scale = mediumScale 0343 else arrowsArea.downArrow.scale = mediumScale 0344 } 0345 } 0346 0347 // Area for displaying the 4 arrows. 0348 Item { 0349 id: arrowsArea 0350 width: duckGrid.cellWidth 0351 height: width 0352 anchors.top: parent.top 0353 anchors.topMargin: width * 0.1 0354 anchors.right: parent.right 0355 anchors.rightMargin: anchors.topMargin 0356 0357 property alias upArrow: upArrow 0358 property alias leftArrow: leftArrow 0359 property alias downArrow: downArrow 0360 property alias rightArrow: rightArrow 0361 0362 function contains(x, y, item) { 0363 return (x > item.x && x < item.x + item.width && 0364 y > item.y && y < item.y + item.height) 0365 } 0366 0367 Image { 0368 id: upArrow 0369 source: Activity.arrowImageURL 0370 width: 0.33 * arrowsArea.width 0371 sourceSize.width: width * largeScale 0372 fillMode: Image.PreserveAspectFit 0373 anchors.top: arrowsArea.top 0374 anchors.horizontalCenter: arrowsArea.horizontalCenter 0375 rotation: -90 0376 0377 function moveDuckUp() { 0378 upArrow.scale = background.largeScale 0379 if(mainArea.mainDuckY - 1 >= 0) { 0380 mainArea.mainDuckY -= 5; 0381 } 0382 } 0383 0384 Behavior on scale { NumberAnimation { duration: 200 } } 0385 } 0386 0387 Image { 0388 id: rightArrow 0389 source: Activity.arrowImageURL 0390 width: upArrow.width 0391 sourceSize.width: upArrow.sourceSize.width 0392 fillMode: Image.PreserveAspectFit 0393 anchors.right: arrowsArea.right 0394 anchors.verticalCenter: arrowsArea.verticalCenter 0395 rotation: 0 0396 0397 function moveDuckToRight() { 0398 rightArrow.scale = background.largeScale 0399 if(mainArea.mainDuckX + 1 <= mainArea.rightDirectionLimit) { 0400 mainArea.mainDuckX += 5; 0401 } 0402 } 0403 0404 Behavior on scale { NumberAnimation { duration: 200 } } 0405 } 0406 0407 Image { 0408 id: downArrow 0409 source: Activity.arrowImageURL 0410 width: upArrow.width 0411 sourceSize.width: upArrow.sourceSize.width 0412 fillMode: Image.PreserveAspectFit 0413 anchors.bottom: arrowsArea.bottom 0414 anchors.horizontalCenter: arrowsArea.horizontalCenter 0415 anchors.left: upArrow.left 0416 rotation: 90 0417 0418 function moveDuckDown() { 0419 downArrow.scale = background.largeScale 0420 if(mainArea.mainDuckY + 1 <= mainArea.downDirectionLimit) { 0421 mainArea.mainDuckY += 5; 0422 } 0423 } 0424 0425 Behavior on scale { NumberAnimation { duration: 200 } } 0426 } 0427 0428 Image { 0429 id: leftArrow 0430 source: Activity.arrowImageURL 0431 width: upArrow.width 0432 sourceSize.width: upArrow.sourceSize.width 0433 fillMode: Image.PreserveAspectFit 0434 anchors.left: arrowsArea.left 0435 anchors.verticalCenter: arrowsArea.verticalCenter 0436 rotation: 180 0437 0438 function moveDuckToLeft() { 0439 leftArrow.scale = background.largeScale 0440 if(mainArea.mainDuckX - 1 >= 0) { 0441 mainArea.mainDuckX -= 5; 0442 } 0443 } 0444 0445 Behavior on scale { NumberAnimation { duration: 200 } } 0446 } 0447 } 0448 0449 ListModel { 0450 id: duckModel 0451 } 0452 0453 GridView { 0454 id: duckGrid 0455 model: duckModel 0456 anchors.top: parent.top 0457 anchors.bottom: bar.top 0458 anchors.left: parent.left 0459 anchors.margins: 5 0460 width: mainDuck.width 0461 flow: GridView.FlowTopToBottom 0462 interactive: false 0463 cellWidth: duckGrid.width 0464 cellHeight: mainDuck.height * 1.1 0465 0466 delegate: Image { 0467 id: duckImage 0468 source: Activity.duckColorURL + model.image + ".svg" 0469 sourceSize.width: duckGrid.cellWidth 0470 sourceSize.height: mainDuck.height 0471 0472 function restartAnimation() { 0473 duckAnim.start() 0474 } 0475 0476 ParticleSystemStarLoader { 0477 id: particles 0478 clip: false 0479 } 0480 0481 SequentialAnimation { 0482 id: duckAnim 0483 loops: 1 0484 NumberAnimation { 0485 target: duckImage 0486 property: "rotation" 0487 from: 0; to: 360 0488 duration: 600 0489 easing.type: Easing.InOutQuad 0490 } 0491 onRunningChanged: { 0492 if(running) { 0493 Activity.playSound(index) 0494 particles.burst(20) 0495 } 0496 else { 0497 rotation = 0 0498 } 0499 } 0500 } 0501 } 0502 0503 add: Transition { 0504 PathAnimation { 0505 path: Path { 0506 PathCurve { x: 0; y: 0} 0507 PathCurve {} 0508 } 0509 easing.type: Easing.InOutQuad 0510 duration: 1000 0511 } 0512 } 0513 } 0514 0515 Rectangle { 0516 id: pressCircle 0517 width: ApplicationInfo.ratio * 20 0518 height: width 0519 color: "#E77936" 0520 border.width: width * 0.1 0521 border.color: "#EEEEEE" 0522 visible: false 0523 radius: width * 0.5 0524 } 0525 0526 onWidthChanged: { 0527 resetDuckPosition() 0528 pressCircle.visible = false; 0529 } 0530 0531 onHeightChanged: { 0532 resetDuckPosition() 0533 pressCircle.visible = false; 0534 } 0535 0536 function resetDuckPosition() { 0537 mainArea.mainDuckX = mainArea.width / 2 0538 mainArea.mainDuckY = mainArea.height / 2 0539 } 0540 0541 function resetArrowScale() { 0542 arrowsArea.upArrow.scale = defaultScale 0543 arrowsArea.downArrow.scale = defaultScale 0544 arrowsArea.leftArrow.scale = defaultScale 0545 arrowsArea.rightArrow.scale = defaultScale 0546 } 0547 0548 DialogHelp { 0549 id: dialogHelp 0550 onClose: home() 0551 } 0552 0553 Bar { 0554 id: bar 0555 content: BarEnumContent { value: help | home } 0556 onHelpClicked: { 0557 displayDialog(dialogHelp) 0558 } 0559 onHomeClicked: activity.home() 0560 } 0561 } 0562 }