File indexing completed on 2024-05-05 15:53:06

0001 /* GCompris - followline.js
0002  *
0003  * SPDX-FileCopyrightText: 2014 Bruno Coudoin
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (GTK+ version)
0007  *   Bruno Coudoin <bruno.coudoin@gcompris.net> (Qt Quick port)
0008  *
0009  *   SPDX-License-Identifier: GPL-3.0-or-later
0010  */
0011 .pragma library
0012 .import QtQuick 2.12 as Quick
0013 .import GCompris 1.0 as GCompris
0014 .import "qrc:/gcompris/src/core/core.js" as Core
0015 
0016 var url = "qrc:/gcompris/src/activities/followline/resource/"
0017 
0018 var numberOfLevel = 8
0019 var items
0020 var createdLineParts
0021 var movedOut = true
0022 // used to bypass initLevel triggered on stop by onHeightChanged...
0023 var isStopped = false
0024 
0025 function start(items_) {
0026     isStopped = false
0027     items = items_
0028     items.currentLevel = Core.getInitialLevel(numberOfLevel)
0029     initLevel()
0030 }
0031 
0032 function stop() {
0033     isStopped = true
0034     items.lineBrokenTimer.stop()
0035     destroyLineParts()
0036 }
0037 
0038 function initLevel() {
0039     /* Check items.bar because when starting followline at least twice,
0040      it is undefined (called by FollowLine.qml:onHeightChanged())
0041     */
0042     if(!items || isStopped)
0043         return
0044 
0045     items.currentLock = 0
0046     movedOut = true
0047     destroyLineParts()
0048     createdLineParts = new Array()
0049     var width = 40 * GCompris.ApplicationInfo.ratio
0050     var nextWidth = Math.max(items.verticalLayout ? items.lineArea.height / 30 : items.lineArea.width / 40,
0051                               5 * GCompris.ApplicationInfo.ratio)
0052     var height = 60 * GCompris.ApplicationInfo.ratio
0053     var index = 0
0054     var y = 0
0055     var x = 0
0056     var angle = 0
0057     var directionStep = items.verticalLayout ? 0.02 * (items.currentLevel + 1) * 0.5 : 0.01 * (items.currentLevel + 1)
0058     var direction = directionStep
0059     if(!items.verticalLayout) {
0060         do {
0061             if(index != 0) {
0062                 width = nextWidth
0063             }
0064             var newy = y + Math.sin(angle) * width * 0.5
0065             var newx = x + Math.cos(angle) * width * 0.5
0066             angle += direction
0067             if(angle > Math.PI / 4)
0068                 direction = - directionStep
0069             else if(angle < - Math.PI / 4)
0070                 direction = directionStep
0071             if(y > items.lineArea.height * 0.5)
0072                 direction = - directionStep
0073             else if(y < 0)
0074                 direction = directionStep
0075             createdLineParts[index] =
0076                             createLinePart(index, x, y, width, height,
0077                                            getAngleOfLineBetweenTwoPoints(x, y, newx, newy) * (180 / Math.PI))
0078             x = newx
0079             y = newy
0080             index++
0081         } while(x < (items.lineArea.width - 10))
0082     } else {
0083         do {
0084             if(index != 0) {
0085                 width = nextWidth
0086             }
0087             var newy = y + Math.sin(angle) * width * 0.5
0088             var newx = x + Math.cos(angle) * width * 0.5
0089             angle += direction
0090             if(angle > Math.PI / 2)
0091                 direction = - directionStep
0092             else if(angle < - Math.PI / 4)
0093                 direction = directionStep
0094             createdLineParts[index] =
0095                             createLinePart(index, x, y, width, height,
0096                                            getAngleOfLineBetweenTwoPoints(x, y, newx, newy) * (180 / Math.PI))
0097             x = newx
0098             y = newy
0099             index++
0100         } while(x < (items.lineArea.width - 10))
0101 
0102     }
0103     items.lastLock = index - 1
0104 }
0105 
0106 function nextLevel() {
0107     items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel);
0108     initLevel();
0109 }
0110 
0111 function previousLevel() {
0112     items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel);
0113     initLevel();
0114 }
0115 
0116 function createLinePart(index, x, y, width, height, rotation) {
0117     var component = Qt.createComponent("qrc:/gcompris/src/activities/followline/LinePart.qml");
0118     var part = component.createObject(
0119                 items.lineArea,
0120                 {
0121                     "audioEffects": items.audioEffects,
0122                     "x": x,
0123                     "y": y,
0124                     "width": width,
0125                     "height": height,
0126                     "rotation": rotation,
0127                     "z": index,
0128                     "items": items,
0129                     "index": index
0130                 });
0131 
0132     if (part === null) {
0133         // Error Handling
0134         console.log("Error creating LinePart object");
0135     }
0136     return part;
0137 }
0138 
0139 // Determines the angle of a straight line drawn between point one and two.
0140 // The number returned, which is a float in radian,
0141 // tells us how much we have to rotate a horizontal line clockwise
0142 // for it to match the line between the two points.
0143 function getAngleOfLineBetweenTwoPoints(x1, y1, x2, y2) {
0144     var xDiff = x2 - x1;
0145     var yDiff = y2 - y1;
0146     return Math.atan2(yDiff, xDiff);
0147 }
0148 
0149 function destroyLineParts() {
0150     if (createdLineParts) {
0151         for(var i = 0;  i < createdLineParts.length; ++i) {
0152             createdLineParts[i].destroy()
0153         }
0154         createdLineParts.length = 0
0155     }
0156 }
0157 
0158 function cursorMovedOut() {
0159     movedOut = true;
0160     if(items.currentLock > 0)
0161         items.currentLock--;
0162 }
0163 
0164 function playAudioFx() {
0165     if(!items.audioEffects.playing)
0166         items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/darken.wav");
0167 }