diff --git a/src/activities/activities.txt b/src/activities/activities.txt index e2cbf8380..56878927d 100644 --- a/src/activities/activities.txt +++ b/src/activities/activities.txt @@ -1,107 +1,106 @@ # The list of activities that will be loaded at GCompris start. # Keep it sorted advanced_colors algebra_by algebra_div algebra_minus algebra_plus algorithm align4 align4-2players alphabet-sequence babymatch babyshapes ballcatch braille_alphabets braille_fun canal_lock chronos click_on_letter click_on_letter_up clickanddraw clickgame clockgame color_mix color_mix_light colors details drawnumber enumerate erase erase_2clic erase_clic fifteen followline football geo-country geography gletters gnumch-equality gnumch-factors gnumch-inequality gnumch-multiples gnumch-primes guessnumber hanoi hanoi_real hexagon imageid imagename instruments intro_gravity leftright lightsoff louis-braille magic-hat-minus magic-hat-plus maze mazeinvisible mazerelative memory memory-enumerate memory-math-add memory-math-add-minus memory-math-add-minus-mult-div memory-math-add-minus-mult-div-tux memory-math-add-minus-tux memory-math-add-tux memory-math-div memory-math-div-tux memory-math-minus memory-math-minus-tux memory-math-mult memory-math-mult-div memory-math-mult-div-tux memory-math-mult-tux memory-sound memory-sound-tux memory-tux memory-wordnumber mining missing-letter money money_back money_back_cents money_cents mosaic numbers-odd-even penalty planegame -readingh -readingv +programmingMaze redraw redraw_symmetrical reversecount scalesboard scalesboard_weight scalesboard_weight_avoirdupois simplepaint smallnumbers smallnumbers2 sudoku superbrain target tic_tac_toe tic_tac_toe_2players traffic wordsgame diff --git a/src/activities/programmingMaze/ActivityInfo.qml b/src/activities/programmingMaze/ActivityInfo.qml new file mode 100644 index 000000000..85b062881 --- /dev/null +++ b/src/activities/programmingMaze/ActivityInfo.qml @@ -0,0 +1,35 @@ +/* GCompris - ActivityInfo.qml + * + * Copyright (C) 2015 Your Name + * + * 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: "programmingMaze/ProgrammingMaze.qml" + difficulty: 3 + icon: "maze/maze.svg" + author: "Siddhesh Suthar <siddhesh.it@gmail.com>" + demo: false + title: qsTr("ProgrammingMaze activity") + description: qsTr("This activity teaches the kid to program the Tux to its goal using +simple instructions like move forward, turn left etc") + goal: qsTr("Tux is hungry. Help him find fish by programming him to the correct ice spot.") + prerequisite: qsTr("Can read instructions. Thinking of the path logically") + manual: qsTr("Choose the instructions from given menu. Arrange the instruction in an +order so that they can make the tux reach to its goal") + credit: "" + section: "fun" +} diff --git a/src/activities/programmingMaze/CMakeLists.txt b/src/activities/programmingMaze/CMakeLists.txt new file mode 100644 index 000000000..6ab9f7d21 --- /dev/null +++ b/src/activities/programmingMaze/CMakeLists.txt @@ -0,0 +1 @@ +GCOMPRIS_ADD_RCC(activities/programmingMaze *.qml *.svg *.js resource/*) diff --git a/src/activities/programmingMaze/ProgrammingMaze.qml b/src/activities/programmingMaze/ProgrammingMaze.qml new file mode 100644 index 000000000..91efae9be --- /dev/null +++ b/src/activities/programmingMaze/ProgrammingMaze.qml @@ -0,0 +1,476 @@ +/* GCompris - programmingMaze.qml + * + * Copyright (C) 2014 Siddhesh Suthar + * + * Authors: + * Siddhesh Suthar (Qt Quick 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.2 +import "../../core" +import GCompris 1.0 +import "programmingMaze.js" as Activity + +import QtQuick.Controls 1.0 +import QtQuick.Layouts 1.0 + + +ActivityBase { + id: activity + + onStart: focus = true + onStop: {} + + pageComponent: Rectangle { + id: background + anchors.fill: parent + color: "#8C8984" + property bool keyNavigation: false + + signal start + signal stop + + Component.onCompleted: { + activity.start.connect(start) + activity.stop.connect(stop) + } + + // Add here the QML items you need to access in javascript + QtObject { + id: items + property Item main: activity.main + property alias background: background + property alias bar: bar + property alias bonus: bonus + property alias mazeModel: mazeModel + property alias instructionModel: instructionModel + property alias answerModel: answerModel + property alias player: player + property alias fish: fish + } + + onStart: { + Activity.start(items) + keyNavigation = false + } + onStop: { Activity.stop() } + + + Keys.onRightPressed: { + keyNavigation = true + instruction.incrementCurrentIndex() + } + Keys.onLeftPressed: { + keyNavigation = true + instruction.decrementCurrentIndex() + } + Keys.onDownPressed: { + keyNavigation = true + instruction.incrementCurrentIndex() + } + Keys.onUpPressed: { + keyNavigation = true + instruction.decrementCurrentIndex() + } + Keys.onSpacePressed: { + keyNavigation = true + instruction.currentItem.children[3].clicked() + } + Keys.onEnterPressed: { + keyNavigation = true + instruction.currentItem.children[3].clicked() + } + Keys.onReturnPressed: { + keyNavigation = true + instruction.currentItem.children[3].clicked() + } + + ListModel { + id: instructionModel + ListElement { + name: "Move Forward" + } + ListElement { + name: "Turn Left" + } + ListElement { + name: "Turn Right" + } + } + + ListModel { + id: answerModel + } + + Repeater { + id: mazeModel + model: Activity.mazeBlocks[0] + + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: instruction.top + + Image { + x: modelData[0] * background.width / 8 + y: modelData[1] * (background.height - background.height/8) / 8 + width: background.width / 8 + height: background.height / 8 + source: Activity.reverseCountUrl + "iceblock.svg" + } + } + + Image { + id: player + source: "qrc:/gcompris/src/activities/maze/resource/" + "tux_top_south.svg" + sourceSize.width: background.width / 10 + x: 0; y: 0; z: 11 + property int duration: 1000 + + signal init + + onInit: { + player.rotation = -90 +// Activity.runCode() + } + + Behavior on x { + SmoothedAnimation { +// reversingMode: SmoothedAnimation.Immediate +// onRunningChanged: Activity.playerRunningChanged() + duration: player.duration + } + } + Behavior on y { + SmoothedAnimation { +// reversingMode: SmoothedAnimation.Immediate +// onRunningChanged: Activity.playerRunningChanged() + duration: player.duration + } + } + Behavior on rotation { + RotationAnimation { + duration: player.duration / 2 + direction: RotationAnimation.Shortest + } + } + + } + + Image { + id: fish + source: Activity.reverseCountUrl + "blue-fish.svg" + sourceSize.width: background.width / 10 +// anchors.leftMargin: 20 * ApplicationInfo.ratio + + width: background.width / 10 + height: (background.height - background.height/10) / 10 + x: 0; y: 0; z: 5 + } + + ListView { + id: instruction + width: parent.width * 0.625 + height: parent.height * 0.375 - bar.height / 2 + + anchors.left: parent.left + anchors.bottom: bar.top + anchors.margins: 10 * ApplicationInfo.ratio + anchors.bottomMargin: bar.height / 2 + + orientation: Qt.Vertical + verticalLayoutDirection: ListView.TopToBottom + spacing: 5 * ApplicationInfo.ratio + interactive: false + model: instructionModel + + header: instructionHeaderComponent + + highlight: Rectangle { + width: instruction.width + height: instruction.buttonHeight + color: "lightsteelblue" + border.width: 3 + border.color: "black" + visible: background.keyNavigation + y: instruction.currentItem.y + Behavior on y { SpringAnimation { spring: 3; damping: 0.2 } } + } + highlightFollowsCurrentItem: false + focus: true + keyNavigationWraps: true + + property int buttonHeight: instruction.height / instructionModel.count - instruction.spacing + + delegate: Item { + width: instruction.width - instruction.spacing + height: instruction.buttonHeight + + Rectangle { + id: rect + anchors.fill: parent + gradient: Gradient { + GradientStop { position: 0.0; color: "#0191C8" } + GradientStop { position: 1.0; color: "#005B9A" } + } + opacity: 0.5 + + } + + Image { + source: "qrc:/gcompris/src/core/resource/button.svg" + sourceSize { height: parent.height; width: parent.width } + width: sourceSize.width + height: sourceSize.height + smooth: false + } + + GCText { + id: instructionText + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + width: instruction.width + fontSizeMode: Text.Fit + minimumPointSize: 7 + fontSize: regularSize + wrapMode: Text.WordWrap + color: "white" + text: name + } + + MouseArea { + id: mouseArea + anchors.fill: parent + signal clicked + onClicked: { + clickedAnim.start() + answerModel.append({"name": instructionText.text, "selected": false}) + } + onPressed: { + clickedAnim.start() + answerModel.append({"name": instructionText.text, "selected": false}) + } + } + + SequentialAnimation { + id: clickedAnim + PropertyAnimation { + target: rect + property: "opacity" + to: "1" + duration: 300 + } + + PropertyAnimation { + target: rect + property: "opacity" + to: "0.5" + duration: 300 + } + } + } + } + + // insert data upon clicking the list items into this answerData + // and then process it to run the code + + ListView { + id: answerSheet + + width: parent.width * 0.350 + height: parent.height * 0.80 - bar.height + anchors.right: parent.right + anchors.top: parent.top + anchors.margins: 10 * ApplicationInfo.ratio + + orientation: Qt.Vertical + verticalLayoutDirection: ListView.TopToBottom + spacing: 5 * ApplicationInfo.ratio + interactive: false + model: answerModel + + header: answerHeaderComponent + footer: answerFooterComponent + + delegate: Item { + width: answerSheet.width - answerSheet.spacing + height: answerSheet.height / answerModel.count - answerSheet.spacing + + Rectangle { + id: answerRect + anchors.fill: parent + color: "#005B9A" + opacity: 1 + } + + Image { + source: "qrc:/gcompris/src/core/resource/button.svg" + sourceSize { height: parent.height; width: parent.width } + width: sourceSize.width + height: sourceSize.height + smooth: false + } + + GCText { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + width: parent.width + fontSizeMode: Text.Fit + minimumPointSize: 7 + fontSize: regularSize + wrapMode: Text.WordWrap + color: "white" + text: name + } + + Image { + source: "qrc:/gcompris/src/core/resource/bar_exit.svg" + sourceSize { height: parent.height ; width: parent.width } + width: sourceSize.width / 8 + height: sourceSize.height / 3 + smooth: false + + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.rightMargin: 10 * ApplicationInfo.ratio + + MouseArea { + id: answerRemove + anchors.fill: parent + onPressed: { + answerModel.remove(model.index) + } + } + + } + + } + } + + Component { + id: answerFooterComponent + Image { + id: runCode + source:"qrc:/gcompris/src/core/resource/bar_ok.svg" + width: background.width / 8 + height: background.height / 8 + fillMode: Image.PreserveAspectFit + + MouseArea { + id: runCodeMouseArea + anchors.fill: parent + hoverEnabled: true + onEntered: runCode.scale = 1.1 + onClicked: { + console.log(answerModel) + Activity.runCode() + } + onExited: runCode.scale = 1 + } + } + } + + + + Component { + id: instructionHeaderComponent + Rectangle { + id: headerRect + width: ListView.view.width + height: 40 * ApplicationInfo.ratio + color: "#005B9A" + opacity: 1 + + Image { + source: "qrc:/gcompris/src/core/resource/button.svg" + sourceSize { height: parent.height; width: parent.width } + width: sourceSize.width + height: sourceSize.height + smooth: false + } + + GCText { + id: headerText + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + width: parent.width + fontSizeMode: Font.DemiBold + minimumPointSize: 7 + fontSize: mediumSize + wrapMode: Text.WordWrap + color: "white" + text: qsTr("Choose the instructions") + } + } + } + + Component { + id: answerHeaderComponent + Rectangle { + id: answerHeaderRect + width: ListView.view.width + height: 40 * ApplicationInfo.ratio + color: "#005B9A" + opacity: 1 + + Image { + source: "qrc:/gcompris/src/core/resource/button.svg" + sourceSize { height: parent.height; width: parent.width } + width: sourceSize.width + height: sourceSize.height + smooth: false + } + + GCText { + id: answerHeaderText + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + width: parent.width + fontSizeMode: Font.DemiBold + minimumPointSize: 7 + fontSize: mediumSize + wrapMode: Text.WordWrap + color: "white" + text: qsTr("Your Code") + } + } + } + + DialogHelp { + id: dialogHelp + onClose: home() + } + + Bar { + id: bar + content: BarEnumContent { value: help | home | level } + onHelpClicked: { + displayDialog(dialogHelp) + } + onPreviousLevelClicked: Activity.previousLevel() + onNextLevelClicked: Activity.nextLevel() + onHomeClicked: activity.home() + } + + Bonus { + id: bonus + Component.onCompleted: win.connect(Activity.nextLevel) + } + } + +} diff --git a/src/activities/programmingMaze/programmingMaze.js b/src/activities/programmingMaze/programmingMaze.js new file mode 100644 index 000000000..c923c3fe8 --- /dev/null +++ b/src/activities/programmingMaze/programmingMaze.js @@ -0,0 +1,158 @@ +/* GCompris - programmingMaze.js + * + * Copyright (C) 2014 + * + * Authors: + * "Siddhesh Suthar" (Qt Quick 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 . + */ +.pragma library +.import QtQuick 2.0 as Quick + +var currentLevel = 0 +var numberOfLevel = 4 +var items +var reverseCountUrl = "qrc:/gcompris/src/activities/reversecount/resource/" +var mazeBlocks = [ + [[1,2],[2,2],[3,2]], + [[1,3],[2,3],[2,2],[2,1],[3,1]], + [[1,1],[2,1],[3,1],[3,2],[3,3],[2,3],[1,3]], + [[0,3],[1,3],[1,2],[2,2],[2,1],[3,1]] + ] +var countOfMazeBlocks +var initialX +var initialY +var stepX +var stepY +var playerCode = [] +var currentInstruction +var tuxIceBlockNumber +var currentBlock +var nextBlock +var currentX +var currentY +var nextX +var nextY + +function start(items_) { + items = items_ + currentLevel = 0 + initLevel() +} + +function stop() { +} + +function initLevel() { + items.bar.level = currentLevel + 1 + items.mazeModel.model = mazeBlocks[currentLevel] + items.answerModel.clear() + countOfMazeBlocks = mazeBlocks[currentLevel].length + + stepX = items.background.width / 8 + stepY = (items.background.height - items.background.height/8) / 8 + initialX = mazeBlocks[currentLevel][0][0] * stepX + initialY = mazeBlocks[currentLevel][0][1] * stepY + + items.player.x = initialX + items.player.y = initialY + items.fish.x = mazeBlocks[currentLevel][countOfMazeBlocks -1][0] * stepX + items.fish.y = mazeBlocks[currentLevel][countOfMazeBlocks -1][1] * stepY + tuxIceBlockNumber = 0 + + items.player.init() +} + +function runCode() { + + //initiallize back to starting position and code + playerCode = [] + items.player.x = initialX + items.player.y = initialY + + for(var i = 0; i < items.answerModel.count; i++) { + playerCode.push(items.answerModel.get([i]).name) + } + + for( var j = 0; j < playerCode.length; j++) { + currentInstruction = playerCode[j] +// console.log(j +"th" +" tuxIceBlockNumber "+tuxIceBlockNumber + +// " x: " +items.player.x +" y: "+items.player.y) + + currentBlock = tuxIceBlockNumber % mazeBlocks[currentLevel].length + nextBlock = (tuxIceBlockNumber + 1) % mazeBlocks[currentLevel].length + currentX = mazeBlocks[currentLevel][currentBlock][0] + currentY = mazeBlocks[currentLevel][currentBlock][1] + nextX = mazeBlocks[currentLevel][nextBlock][0] + nextY = mazeBlocks[currentLevel][nextBlock][1] + + if ( currentInstruction == "Move Forward") { + + if (nextX - currentX > 0) { + items.player.x = mazeBlocks[currentLevel][currentBlock][0] * + stepX + + stepX + } + else if(nextX - currentX < 0){ + items.player.x = mazeBlocks[currentLevel][currentBlock][0] * + stepX - + stepX + } + + if (nextY - currentY < 0) { + items.player.y = mazeBlocks[currentLevel][currentBlock][1] * + stepY + + stepY + } + else if (nextY - currentY > 0 ) { + items.player.y = mazeBlocks[currentLevel][currentBlock][1] * + stepY - + stepY + } + ++tuxIceBlockNumber; + } + + if ( currentInstruction == "Turn Left") { + items.player.rotation -= 90 + } + if ( currentInstruction == "Turn Right") { + items.player.rotation += 90 + } + + if(items.player.x == items.fish.x && items.player.y == items.fish.y){ + items.bonus.good("smiley") + } + } + + + + + +} + +function nextLevel() { + if(numberOfLevel <= ++currentLevel ) { + currentLevel = 0 + } + initLevel(); +} + +function previousLevel() { + if(--currentLevel < 0) { + currentLevel = numberOfLevel - 1 + } + initLevel(); +} + diff --git a/src/activities/programmingMaze/programmingMaze.svg b/src/activities/programmingMaze/programmingMaze.svg new file mode 100644 index 000000000..0316223e2 --- /dev/null +++ b/src/activities/programmingMaze/programmingMaze.svg @@ -0,0 +1,83 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + +