diff --git a/src/activities/numbers-odd-even/ActivityInfo.qml b/src/activities/numbers-odd-even/ActivityInfo.qml index cd2155cce..23c0b0629 100644 --- a/src/activities/numbers-odd-even/ActivityInfo.qml +++ b/src/activities/numbers-odd-even/ActivityInfo.qml @@ -1,40 +1,41 @@ /* GCompris - ActivityInfo.qml * * Copyright (C) 2015 Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import GCompris 1.0 ActivityInfo { name: "numbers-odd-even/NumbersOddEven.qml" difficulty: 2 icon: "numbers-odd-even/numbers-odd-even.svg" author: "Bruno Coudoin <bruno.coudoin@gcompris.net>" demo: false //: Activity title title: qsTr("Even and Odd Numbers") //: Help title description: qsTr("Move the helicopter to catch the clouds having even or odd numbers") // intro: "Move the helicopter to catch the clouds having even or odd numbers, in the shown order." //: Help goal goal: qsTr("Numeration training") //: Help prerequisite prerequisite: "" //: Help manual manual: qsTr("Catch the odd or even number clouds. With a keyboard use the arrow keys to move the helicopter. With a pointing device you just click or tap on the target location. To know which number you have to catch you can either remember it or check the bottom right corner.") credit: "" section: "math numeration" - createdInVersion: 0 + createdInVersion: 0 + levels: "1,2" } diff --git a/src/activities/numbers-odd-even/resource/1/Data.qml b/src/activities/numbers-odd-even/resource/1/Data.qml new file mode 100644 index 000000000..83f872210 --- /dev/null +++ b/src/activities/numbers-odd-even/resource/1/Data.qml @@ -0,0 +1,55 @@ + +/* GCompris - Data.qml + * + * Copyright (C) 2019 Akshay Kumar + * + * Authors: + * Akshay Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "../../../../core" + +Dataset { + objective: qsTr("Select even and odd numbers upto 20") + difficulty: 1 + data: [ + { + data: "0 2 4".split(" "), + showNext: true + }, + { + data: "1 3 5".split(" "), + showNext: true + }, + { + data: "0 2 4 6 8 10 12".split(" "), + showNext: true + }, + { + data: "1 3 5 7 9 11 13".split(" "), + showNext: false + }, + { + data: "0 2 4 6 8 10 12 14 16 18 20".split(" "), + showNext: false + }, + { + data: "1 3 5 7 9 11 13 15 17 19 21".split(" "), + showNext: false + } + ] +} \ No newline at end of file diff --git a/src/activities/numbers-odd-even/resource/2/Data.qml b/src/activities/numbers-odd-even/resource/2/Data.qml new file mode 100644 index 000000000..937d2eeef --- /dev/null +++ b/src/activities/numbers-odd-even/resource/2/Data.qml @@ -0,0 +1,55 @@ + +/* GCompris - Data.qml + * + * Copyright (C) 2019 Akshay Kumar + * + * Authors: + * Akshay Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "../../../../core" + +Dataset { + objective: qsTr("Select even and odd numbers upto 30") + difficulty: 1 + data: [ + { + data: "0 2 4 6 8 10 12 14 16 18 20".split(" "), + showNext: true + }, + { + data: "1 3 5 7 9 11 13 15 17 19 21".split(" "), + showNext: true + }, + { + data: "0 2 4 6 8 10 12 14 16 18 20 22 24 26".split(" "), + showNext: false + }, + { + data: "1 3 5 7 9 11 13 15 17 19 21 23 25 27".split(" "), + showNext: false + }, + { + data: "0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30".split(" "), + showNext: false + }, + { + data: "1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31".split(" "), + showNext: false + } + ] +} \ No newline at end of file diff --git a/src/activities/planegame/ActivityInfo.qml b/src/activities/planegame/ActivityInfo.qml index aa6e82b54..77c1d8721 100644 --- a/src/activities/planegame/ActivityInfo.qml +++ b/src/activities/planegame/ActivityInfo.qml @@ -1,40 +1,41 @@ /* GCompris - ActivityInfo.qml * * Copyright (C) 2015 Johnny Jazeix * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ import GCompris 1.0 ActivityInfo { name: "planegame/Sequence.qml" difficulty: 2 icon: "planegame/planegame.svg" author: "Johnny Jazeix <jazeix@gmail.com>" demo: true //: Activity title title: qsTr("Numbers in Order") //: Help title description: qsTr("Move the helicopter to catch the clouds in the correct order") // intro: "Move the helicopter with the arrow keys and catch the numbers in the clouds, in ascending order." //: Help goal goal: qsTr("Numeration training") //: Help prerequisite prerequisite: "" //: Help manual manual: qsTr("Catch the clouds in increasing order. With a keyboard use the arrow keys to move the helicopter. With a pointing device you just click or tap on the target location. To know which number you have to catch you can either remember it or check the bottom right corner.") credit: "" - section: "math numeration" - createdInVersion: 0 + section: "math numeration" + createdInVersion: 0 + levels: "1,2" } diff --git a/src/activities/planegame/Planegame.qml b/src/activities/planegame/Planegame.qml index ea1172e20..f2f6af601 100644 --- a/src/activities/planegame/Planegame.qml +++ b/src/activities/planegame/Planegame.qml @@ -1,183 +1,206 @@ /* gcompris - Planegame.qml Copyright (C) 2014 Johnny Jazeix 2003, 2014: Bruno Coudoin: initial version 2014: Johnny Jazeix: Qt port This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ import QtQuick 2.6 import GCompris 1.0 import "../../core" import "planegame.js" as Activity ActivityBase { id: activity focus: true onStart: { focus = true; } onStop: { } Keys.onPressed: Activity.processPressedKey(event) Keys.onReleased: Activity.processReleasedKey(event) property var dataset property var tutorialInstructions property bool showTutorial: false property int oldWidth: width onWidthChanged: { // Reposition helico and clouds, same for height Activity.repositionObjectsOnWidthChanged(width / oldWidth) oldWidth = width } property int oldHeight: height onHeightChanged: { // Reposition helico and clouds, same for height Activity.repositionObjectsOnHeightChanged(height / oldHeight) oldHeight = height } pageComponent: Image { id: background anchors.fill: parent signal start signal stop source: Activity.url + "../algorithm/resource/desert_scene.svg" sourceSize.width: parent.width Component.onCompleted: { - activity.start.connect(start) - activity.stop.connect(stop) + dialogActivityConfig.initialize() + activity.start.connect(start) + activity.stop.connect(stop) } QtObject { id: items property alias background: background property alias bar: bar property alias bonus: bonus + property var levels: activity.datasetLoader.item.data property alias score: score property alias plane: plane property GCAudio audioVoices: activity.audioVoices property GCSfx audioEffects: activity.audioEffects property alias movePlaneTimer: movePlaneTimer property alias cloudCreation: cloudCreation property bool showTutorial: activity.showTutorial } onStart: { Activity.start(items, dataset) } onStop: { Activity.stop() } //Tutorial section starts Loader { active: showTutorial anchors.fill: parent z: 1 sourceComponent: tutorialComponent Component { id: tutorialComponent Image { id: tutorialImage source: "../digital_electricity/resource/texture01.png" anchors.fill: parent fillMode: Image.Tile Tutorial { id: tutorialSection tutorialDetails: tutorialInstructions useImage: false onSkipPressed: { showTutorial = false Activity.initLevel() } } } } } // Tutorial section ends MultiPointTouchArea { anchors.fill: parent touchPoints: [ TouchPoint { id: point1 } ] onReleased: { plane.x = point1.x - plane.width / 2 plane.y = point1.y - plane.height / 2 } } + DialogChooseLevel { + id: dialogActivityConfig + currentActivity: activity.activityInfo + + onSaveData: { + levelFolder = dialogActivityConfig.chosenLevel + currentActivity.currentLevel = dialogActivityConfig.chosenLevel + ApplicationSettings.setCurrentLevel(currentActivity.name, dialogActivityConfig.chosenLevel) + home() + } + onClose: { + home() + } + onStartActivity: { + background.start() + } + } + DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar - content: BarEnumContent { value: items.showTutorial ? (help | home) : (help | home | level) } + content: BarEnumContent { value: items.showTutorial ? (help | home | activityConfig) : (help | home | level | activityConfig) } onHelpClicked: displayDialog(dialogHelp) onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() + onActivityConfigClicked: { + displayDialog(dialogActivityConfig) + } } Bonus { id: bonus Component.onCompleted: win.connect(Activity.nextLevel) } Score { id: score visible: !showTutorial fontSize: background.width >= background.height ? internalTextComponent.largeSize : internalTextComponent.mediumSize height: internalTextComponent.height + 10 anchors.bottom: bar.top anchors.margins: 10 } property int movePlaneTimerCounter: 0 Timer { id: movePlaneTimer running: false repeat: true onTriggered: { plane.state = "play" interval = 50 if(movePlaneTimerCounter++ % 3 == 0) { /* Do not call this too often or plane commands are too hard */ Activity.handleCollisionsWithCloud(); } Activity.computeVelocity(); Activity.planeMove(); } } Timer { id: cloudCreation running: false repeat: true interval: 10200 - (bar.level * 200) onTriggered: Activity.createCloud() } Plane { id: plane visible: !showTutorial background: background } } } diff --git a/src/activities/planegame/planegame.js b/src/activities/planegame/planegame.js index ab7dfcb9d..e9699981c 100644 --- a/src/activities/planegame/planegame.js +++ b/src/activities/planegame/planegame.js @@ -1,335 +1,338 @@ /* gcompris - planegame.js Copyright (C) 2003, 2014: Bruno Coudoin: initial version 2014: Johnny Jazeix: Qt port 2014: Bruno Coudoin: Added support for dataset, smooth plane anim This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . */ .pragma library .import QtQuick 2.6 as Quick .import GCompris 1.0 as GCompris //for ApplicationInfo .import "qrc:/gcompris/src/core/core.js" as Core var url = "qrc:/gcompris/src/activities/planegame/" var max_velocity = 500 * GCompris.ApplicationInfo.ratio var currentLevel var numberOfLevel var currentSubLevel var numberOfSubLevels var upPressed var downPressed var leftPressed var rightPressed var items var dataset var cloudComponent = Qt.createComponent(url + "Cloud.qml"); var clouds = new Array; var cloudsErased = new Array; function start(items_, dataset_) { Core.checkForVoices(items_.background); items = items_ - dataset = dataset_ + if(items.levels) + dataset = items.levels + else + dataset = dataset_ numberOfLevel = dataset.length currentLevel = 0 if(items.showTutorial === false) { initLevel() } } function stop() { cloudDestroy(clouds) cloudDestroy(cloudsErased) items.movePlaneTimer.stop() items.cloudCreation.stop() } function cloudDestroy(clouds) { for(var i = clouds.length - 1; i >= 0 ; --i) { var cloud = clouds[i]; // Remove the cloud cloud.destroy() // Remove the element from the list clouds.splice(i, 1) } } function initLevel() { items.bar.level = currentLevel + 1; currentSubLevel = 0 numberOfSubLevels = dataset[currentLevel].data.length items.movePlaneTimer.stop(); items.cloudCreation.stop() items.score.message = dataset[currentLevel].data[currentSubLevel] items.score.visible = dataset[currentLevel].showNext upPressed = false downPressed = false leftPressed = false rightPressed = false cloudDestroy(clouds) cloudDestroy(cloudsErased) // Tend towards 0.5 ratio items.plane.state = "init" items.movePlaneTimer.interval = 1000 items.movePlaneTimer.start(); items.cloudCreation.start() //Inject the first cloud now createCloud() } function nextLevel() { if(numberOfLevel <= ++currentLevel) { currentLevel = 0 } initLevel(); } function previousLevel() { if(--currentLevel < 0) { currentLevel = numberOfLevel - 1 } initLevel(); } function repositionObjectsOnWidthChanged(factor) { if(items && items.plane) { items.movePlaneTimer.interval = 1000 items.plane.state = "init" } for(var i = clouds.length - 1; i >= 0 ; --i) { var cloud = clouds[i]; } } function repositionObjectsOnHeightChanged(factor) { if(items && items.plane) { items.movePlaneTimer.interval = 1000 items.plane.state = "init" } for(var i = clouds.length - 1; i >= 0 ; --i) { var cloud = clouds[i]; cloud.y *= factor } } var cloudCounter = 1 function createCloud() { var cloud = cloudComponent.createObject( items.background, { "background": items.background, "x": items.background.width, "heightRatio": 1.0 - 0.5 * currentLevel / 10 }); /* Random cloud number but at least one in 3 */ if(cloudCounter++ % 3 == 0 || getRandomInt(0, 1) === 0) { /* Put the target */ cloud.text = dataset[currentLevel].data[currentSubLevel]; cloudCounter = 1 } else { var min = Math.max(1, currentSubLevel - 1); var index = Math.min(min + getRandomInt(0, currentSubLevel - min + 3), numberOfSubLevels - 1) cloud.text = dataset[currentLevel].data[index] } clouds.push(cloud); } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } function processPressedKey(event) { switch(event.key) { case Qt.Key_Right: rightPressed = true; event.accepted = true; break; case Qt.Key_Left: leftPressed = true; event.accepted = true; break; case Qt.Key_Up: upPressed = true; event.accepted = true; break; case Qt.Key_Down: downPressed = true; event.accepted = true; } } function processReleasedKey(event) { switch(event.key) { case Qt.Key_Right: rightPressed = false; event.accepted = true; break; case Qt.Key_Left: leftPressed = false; event.accepted = true; break; case Qt.Key_Up: upPressed = false; event.accepted = true; break; case Qt.Key_Down: downPressed = false; event.accepted = true; } } var speedX = 0 var speedY = 0 var speedFactor = 20 function computeVelocity() { if(rightPressed && speedX < 300) speedX += speedFactor if(leftPressed && speedX > -300) speedX -= speedFactor if(!rightPressed && speedX > 0) speedX = 0 else if(!leftPressed && speedX < 0) speedX = 0 else if(leftPressed || rightPressed) items.plane.x += speedX if(upPressed && speedY > -300) speedY -= speedFactor if(downPressed && speedY < 300) speedY += speedFactor if(!upPressed && speedY < 0) speedY = 0 else if(!downPressed && speedY > 0) speedY = 0 else if(upPressed || downPressed) items.plane.y += speedY items.plane.rotation = speedX * 10 / max_velocity } /* We move x/y of the plane to let its smooth animation track it */ function planeMove() { if(items.plane.x + items.plane.width > items.background.width) { items.plane.x = items.background.width - items.plane.width; } if(items.plane.x < 0) { items.plane.x = 0; } if(items.plane.y < 0) { items.plane.y = 0; } if(items.plane.y + items.plane.height > items.background.height - items.bar.height) { items.plane.y = items.background.height - (items.plane.height + items.bar.height); } } function isIn(x1, y1, px1, py1, px2, py2) { return (x1>px1 && x1py1 && y1= 0 ; --i) { var cloud = clouds[i]; var x1 = cloud.x var x2 = cloud.x + cloud.width var y1 = cloud.y var y2 = cloud.y + cloud.height if(x2 < 0) { // Remove the cloud cloud.destroy() clouds.splice(i, 1) } else if(isIn(x1, y1, planeX1, planeY1, planeX2, planeY2) || isIn(x2, y1, planeX1, planeY1, planeX2, planeY2) || isIn(x1, y2, planeX1, planeY1, planeX2, planeY2) || isIn(x2, y2, planeX1, planeY1, planeX2, planeY2)) { gotOne = true // Collision, look for id if(cloud.text === dataset[currentLevel].data[currentSubLevel]) { playLetterSound(cloud.text) // Move the cloud to the erased list cloud.done() cloudsErased.push(cloud) clouds.splice(i, 1) currentSubLevel++ if(currentSubLevel === numberOfSubLevels) { /* Try the next level */ items.bonus.good("flower") } else { items.score.message = dataset[currentLevel].data[currentSubLevel] } } else { /* Touched the wrong cloud */ if(!cloud.touched) items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/crash.wav") cloud.touch() } break; } } // Reset the touched state on the clouds if(!gotOne) { for(var i = clouds.length - 1; i >= 0 ; --i) { clouds[i].touched = false } } } } function playLetterSound(number) { if(number > 9) items.audioVoices.play(GCompris.ApplicationInfo.getAudioFilePath("voices-$CA/$LOCALE/alphabet/" + number + ".$CA")) else items.audioVoices.play( GCompris.ApplicationInfo.getAudioFilePath("voices-$CA/$LOCALE/alphabet/" + Core.getSoundFilenamForChar(number))) } diff --git a/src/activities/planegame/resource/1/Data.qml b/src/activities/planegame/resource/1/Data.qml new file mode 100644 index 000000000..08be8e936 --- /dev/null +++ b/src/activities/planegame/resource/1/Data.qml @@ -0,0 +1,59 @@ + +/* GCompris - Data.qml + * + * Copyright (C) 2019 Akshay Kumar + * + * Authors: + * Akshay Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "../../../../core" + +Dataset { + objective: qsTr("Count numbers upto 15") + difficulty: 1 + data: [ + { + data: "0 1 2 3".split(" "), + showNext: true + }, + { + data: "0 1 2 3 4 5".split(" "), + showNext: true + }, + { + data: "0 1 2 3 4 5 6 7".split(" "), + showNext: true + }, + { + data: "0 1 2 3 4 5 6 7 8 9".split(" "), + showNext: false + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11".split(" "), + showNext: false + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12 13".split(" "), + showNext: false + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15".split(" "), + showNext: false + } + ] +} \ No newline at end of file diff --git a/src/activities/planegame/resource/2/Data.qml b/src/activities/planegame/resource/2/Data.qml new file mode 100644 index 000000000..b302f7de3 --- /dev/null +++ b/src/activities/planegame/resource/2/Data.qml @@ -0,0 +1,55 @@ + +/* GCompris - Data.qml + * + * Copyright (C) 2019 Akshay Kumar + * + * Authors: + * Akshay Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +import QtQuick 2.6 +import GCompris 1.0 +import "../../../../core" + +Dataset { + objective: qsTr("Count numbers upto 20") + difficulty: 2 + data: [ + { + data: "0 1 2 3 4 5 6 7 8 9 10".split(" "), + showNext: true + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12".split(" "), + showNext: true + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14".split(" "), + showNext: false + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16".split(" "), + showNext: false + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18".split(" "), + showNext: false + }, + { + data: "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20".split(" "), + showNext: false + } + ] +} \ No newline at end of file