diff --git a/src/activities/alphabet-sequence/ActivityInfo.qml b/src/activities/alphabet-sequence/ActivityInfo.qml index 27712f3a1..3ef9fe5d8 100644 --- a/src/activities/alphabet-sequence/ActivityInfo.qml +++ b/src/activities/alphabet-sequence/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: "alphabet-sequence/AlphabetSequence.qml" difficulty: 2 icon: "alphabet-sequence/alphabet-sequence.svg" author: "Bruno Coudoin <bruno.coudoin@gcompris.net>" demo: false //: Activity title title: qsTr("Alphabet sequence") //: Help title description: qsTr("Move the helicopter to catch the clouds following the order of the alphabet") // intro: "Move the helicopter to catch the clouds following the order of the alphabet." //: Help goal goal: qsTr("Alphabet sequence") //: Help prerequisite prerequisite: qsTr("Can decode letters") //: Help manual manual: qsTr("Catch the alphabet letters. 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 letter you have to catch you can either remember it or check the bottom right corner.") credit: "" section: "reading letters" createdInVersion: 0 + levels: "1,2,3" } diff --git a/src/activities/alphabet-sequence/resource/1/Data.qml b/src/activities/alphabet-sequence/resource/1/Data.qml new file mode 100644 index 000000000..51010fd58 --- /dev/null +++ b/src/activities/alphabet-sequence/resource/1/Data.qml @@ -0,0 +1,63 @@ + +/* 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 letters in alphabetical order") + difficulty: 1 + data: [ + { + data: qsTr("a/b/c/d/e").split("/"), + showNext: true + }, + { + data: qsTr("f/g/h/i/j/k").toUpperCase().split("/"), + showNext: true + }, + { + data: qsTr("a/b/c/d/e/f/g/h/i/j/k").split("/"), + showNext: false + }, + { + data: qsTr("l/m/n/o/p").split("/"), + showNext: false + }, + { + data: qsTr("q/r/s/t/u").split("/"), + showNext: false + }, + { + data: qsTr("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u").split("/"), + showNext: false + }, + { + data: qsTr("u/v/w/x/y/z").split("/"), + showNext: false + }, + { + data: qsTr("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z").split("/"), + showNext: false + } + ] +} \ No newline at end of file diff --git a/src/activities/alphabet-sequence/resource/2/Data.qml b/src/activities/alphabet-sequence/resource/2/Data.qml new file mode 100644 index 000000000..cb0add40a --- /dev/null +++ b/src/activities/alphabet-sequence/resource/2/Data.qml @@ -0,0 +1,143 @@ + +/* 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 words in alphabetical order") + difficulty: 2 + data: [ + { + data: [ + qsTr("fruit"), + qsTr("road"), + qsTr("meat"), + qsTr("speech"), + qsTr("gold"), + qsTr("trip"), + qsTr("dance") + ].sort(), + showNext: true + }, + { + data: [ + qsTr("witch"), + qsTr("ghost"), + qsTr("trip"), + qsTr("house"), + qsTr("live"), + qsTr("like"), + qsTr("road"), + ].sort(), + showNext: true + }, + { + data: [ + qsTr("old"), + qsTr("crown"), + qsTr("tear"), + qsTr("bench"), + qsTr("computer"), + qsTr("key"), + ].sort(), + showNext: true + }, + { + data: [ + qsTr("brake"), + qsTr("dream"), + qsTr("prince"), + qsTr("talk"), + qsTr("fly"), + qsTr("history"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("watch"), + qsTr("shampoo"), + qsTr("sun"), + qsTr("apple"), + qsTr("table"), + qsTr("socks"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("needle"), + qsTr("couch"), + qsTr("peanuts"), + qsTr("stock"), + qsTr("shoes"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("needle"), + qsTr("couch"), + qsTr("peanuts"), + qsTr("stock"), + qsTr("shoes"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("hanger"), + qsTr("toothbrush"), + qsTr("plastic"), + qsTr("machine"), + qsTr("shampoo"), + qsTr("towel"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("bread"), + qsTr("waist"), + qsTr("law"), + qsTr("firm"), + qsTr("fibre"), + qsTr("move"), + qsTr("bright"), + qsTr("green"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("rush"), + qsTr("trade"), + qsTr("line"), + qsTr("boy"), + qsTr("girl"), + qsTr("key"), + ].sort(), + showNext: false + }, + ] +} \ No newline at end of file diff --git a/src/activities/alphabet-sequence/resource/3/Data.qml b/src/activities/alphabet-sequence/resource/3/Data.qml new file mode 100644 index 000000000..0629c93bb --- /dev/null +++ b/src/activities/alphabet-sequence/resource/3/Data.qml @@ -0,0 +1,99 @@ + +/* 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 words(with common initials) in alphabetical order") + difficulty: 3 + data: [ + { + data: [ + qsTr("band"), + qsTr("beautiful"), + qsTr("balance"), + qsTr("ball"), + qsTr("basket"), + qsTr("base"), + ].sort(), + showNext: true + }, + { + data: [ + qsTr("connection"), + qsTr("cook"), + qsTr("condition"), + qsTr("control"), + qsTr("conscious"), + qsTr("complex"), + ].sort(), + showNext: true + }, + { + data: [ + qsTr("discovery"), + qsTr("digestion"), + qsTr("direction"), + qsTr("discussion"), + qsTr("disease"), + qsTr("dirty"), + ].sort(), + showNext: true + }, + { + data: [ + qsTr("engine"), + qsTr("elastic"), + qsTr("egg"), + qsTr("effect"), + qsTr("enough"), + qsTr("end"), + qsTr("electric"), + ].sort(), + showNext: false + }, + { + data: [ + qsTr("family"), + qsTr("face"), + qsTr("fall"), + qsTr("fat"), + qsTr("fact"), + qsTr("false"), + qsTr("far") + ].sort(), + showNext: false + }, + { + data: [ + qsTr("fertile"), + qsTr("feeling"), + qsTr("fiction"), + qsTr("field"), + qsTr("fight"), + qsTr("female"), + ].sort(), + showNext: false + } + ] +} diff --git a/src/activities/alphabet-sequence/resource/README b/src/activities/alphabet-sequence/resource/README new file mode 100644 index 000000000..6aaff91d6 --- /dev/null +++ b/src/activities/alphabet-sequence/resource/README @@ -0,0 +1,6 @@ +Copyright: Timothée Giet, 2015 +License: CC-BY-SA 4.0 +Files: +cloud_storm.svg +cloud.svg +tuxhelico.svg diff --git a/src/activities/alphabet-sequence/resource/cloud.svg b/src/activities/alphabet-sequence/resource/cloud.svg new file mode 100644 index 000000000..7f0ed540a --- /dev/null +++ b/src/activities/alphabet-sequence/resource/cloud.svg @@ -0,0 +1,93 @@ + + + + + + + + + + image/svg+xml + + + 2015 + + + Timothée Giet + + + + + + + + + + + + + + + + + + diff --git a/src/activities/alphabet-sequence/resource/cloud_storm.svg b/src/activities/alphabet-sequence/resource/cloud_storm.svg new file mode 100644 index 000000000..797796989 --- /dev/null +++ b/src/activities/alphabet-sequence/resource/cloud_storm.svg @@ -0,0 +1,107 @@ + + + + + + + + + + image/svg+xml + + + 2015 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/alphabet-sequence/resource/tuxhelico.svg b/src/activities/alphabet-sequence/resource/tuxhelico.svg new file mode 100644 index 000000000..e1180ee52 --- /dev/null +++ b/src/activities/alphabet-sequence/resource/tuxhelico.svg @@ -0,0 +1,261 @@ + + + + + + + image/svg+xml + + + 2015 + + + Timothée Giet + + + + + + + + + + + + + + diff --git a/src/activities/planegame/Cloud.qml b/src/activities/planegame/Cloud.qml index 8d85bf781..6e48fce53 100644 --- a/src/activities/planegame/Cloud.qml +++ b/src/activities/planegame/Cloud.qml @@ -1,115 +1,120 @@ /* gcompris - Cloud.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 "planegame.js" as Activity import "../../core" import GCompris 1.0 Image { id: cloud property Item background property alias text: number.text property double heightRatio: 1 /* An helper property to remember if a cloud has been wrongly touched */ property bool touched: false sourceSize.height: 60 * ApplicationInfo.ratio height: sourceSize.height * heightRatio state: "normal" fillMode: Image.PreserveAspectFit z: 5 signal done signal touch onDone: { particles.burst(50) opacityTimer.start() } onTouch: { touched = true state = "storm" } GCText { id: number + height: cloud.height / 2 + width: cloud.width / 2 anchors.horizontalCenter: cloud.horizontalCenter anchors.verticalCenter: cloud.verticalCenter + horizontalAlignment: Text.AlignHCenter color: "black" font.bold: true - fontSize: 18 + font.pointSize: 100 + minimumPointSize: 10 + fontSizeMode: Text.Fit } Component.onCompleted: { x = -cloud.width - 1 y = Activity.getRandomInt(0, background.height - (cloud.height + Activity.items.bar.height)) } Behavior on x { PropertyAnimation { duration: 20000 } } Behavior on opacity { PropertyAnimation { duration: 400 } } Timer { id: stormy interval: 2000; running: false; repeat: false onTriggered: cloud.state = "normal" } states: [ State { name: "normal" PropertyChanges { target: cloud source: Activity.url + "resource/cloud.svg" } }, State { name: "storm" PropertyChanges { target: cloud source: Activity.url + "resource/cloud_storm.svg" } StateChangeScript { script: stormy.start() } } ] Timer { id: opacityTimer running: false repeat: false interval: 500 onTriggered: opacity = 0 } ParticleSystemStarLoader { id: particles anchors.fill: parent clip: false } } diff --git a/src/activities/planegame/planegame.js b/src/activities/planegame/planegame.js index e9699981c..225ace381 100644 --- a/src/activities/planegame/planegame.js +++ b/src/activities/planegame/planegame.js @@ -1,338 +1,335 @@ /* 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_ - if(items.levels) - dataset = items.levels - else - dataset = dataset_ + dataset = items.levels 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))) }