diff --git a/src/activities/play_rhythm/PlayRhythm.qml b/src/activities/play_rhythm/PlayRhythm.qml index ee5272f61..bf3deffd4 100644 --- a/src/activities/play_rhythm/PlayRhythm.qml +++ b/src/activities/play_rhythm/PlayRhythm.qml @@ -1,317 +1,324 @@ /* GCompris - PlayRhythm.qml * * Copyright (C) 2018 Aman Kumar Gupta * * Authors: * Beth Hadley (GTK+ version) * Aman Kumar Gupta (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.6 import GCompris 1.0 import "../../core" import "../piano_composition" import "play_rhythm.js" as Activity ActivityBase { id: activity onStart: focus = true onStop: {} isMusicalActivity: true property bool horizontalLayout: width > height pageComponent: Rectangle { id: background anchors.fill: parent color: "#ABCDEF" 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 GCSfx audioEffects: activity.audioEffects property alias background: background property alias bar: bar property alias bonus: bonus property alias parser: parser property alias score: score property alias multipleStaff: multipleStaff property alias iAmReady: iAmReady property alias introductoryAudioTimer: introductoryAudioTimer property alias metronomeOscillation: metronomeOscillation property bool isMetronomeVisible: false property bool isWrongRhythm: false } onStart: { Activity.start(items) } onStop: { Activity.stop() } property string clefType: "Treble" property bool isRhythmPlaying: false - property int metronomeSpeed: 30000 / multipleStaff.bpmValue - 37 + property int metronomeSpeed: 60000 / multipleStaff.bpmValue - 53 + property real weightOffset: metronome.height * multipleStaff.bpmValue * 0.004 Keys.onSpacePressed: if (!background.isRhythmPlaying && !bonus.isPlaying) tempo.tempoPressed() Rectangle { id: instructionBox radius: 10 width: background.width * 0.7 height: background.height / 9 anchors.horizontalCenter: parent.horizontalCenter opacity: 0.8 border.width: 6 color: "white" border.color: "#87A6DD" GCText { id: instructionText color: "black" z: 3 anchors.fill: parent anchors.rightMargin: parent.width * 0.02 anchors.leftMargin: parent.width * 0.02 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter fontSizeMode: Text.Fit wrapMode: Text.WordWrap text: items.isMetronomeVisible ? qsTr("Use the metronome to estimate the time intervals and play the rhythm correctly.") : qsTr("Follow the vertical line and click on the tempo or press space key and play the rhythm correctly.") } } Timer { id: introductoryAudioTimer interval: 3500 onRunningChanged: { if(running) Activity.isIntroductoryAudioPlaying = true else { Activity.isIntroductoryAudioPlaying = false Activity.initSubLevel() } } } JsonParser { id: parser } Rectangle { anchors.fill: parent color: "black" opacity: 0.3 visible: iAmReady.visible z: 10 MouseArea { anchors.fill: parent } } ReadyButton { id: iAmReady focus: true z: 10 onClicked: { Activity.initLevel() } } Score { id: score anchors.top: background.top anchors.bottom: undefined numberOfSubLevels: 3 width: horizontalLayout ? parent.width / 10 : (parent.width - instructionBox.x - instructionBox.width - 1.5 * anchors.rightMargin) } MultipleStaff { id: multipleStaff width: horizontalLayout ? parent.width * 0.6 : parent.width * 0.9 height: horizontalLayout ? parent.height * 1.1 : parent.height * 0.76 bpmValue: 90 nbStaves: 1 clef: clefType isFlickable: false anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top anchors.topMargin: horizontalLayout ? 0 : parent.height * 0.1 centerNotesPosition: true firstCenteredNotePosition: width / (2 * (musicElementModel.count - 1)) spaceBetweenNotes: width / (2.5 * (musicElementModel.count - 1)) enableNotesSound: false onPulseMarkerAnimationFinished: background.isRhythmPlaying = false onPlayDrumSound: { if(background.isRhythmPlaying && !metronomeOscillation.running) GSynth.generate(60, 100) } } Image { id: tempo source: "qrc:/gcompris/src/activities/play_rhythm/resource/drumhead.png" width: horizontalLayout ? parent.width / 7 : parent.width / 4 height: width / 2 anchors.top: metronome.top anchors.horizontalCenter: parent.horizontalCenter MouseArea { anchors.fill: parent enabled: !background.isRhythmPlaying && !bonus.isPlaying onPressed: tempo.tempoPressed() onReleased: tempo.scale = 1 } function tempoPressed() { tempo.scale = 0.85 if(!multipleStaff.isMusicPlaying && Activity.currentNote == 0) { multipleStaff.play() } else if (!multipleStaff.isMusicPlaying && Activity.currentNote > 0){ items.bonus.bad("flower") } GSynth.generate(60, 100) Activity.checkAnswer(multipleStaff.pulseMarkerX) } } Image { id: metronome source: "qrc:/gcompris/src/activities/play_rhythm/resource/metronome_stand.svg" fillMode: Image.PreserveAspectFit sourceSize.width: parent.width / 3 sourceSize.height: parent.height / 4 width: sourceSize.width height: sourceSize.height anchors.bottom: bar.top anchors.bottomMargin: 20 visible: items.isMetronomeVisible MouseArea { anchors.fill: parent onClicked: { if(metronomeOscillation.running) metronomeOscillation.stop() else metronomeOscillation.start() } } Image { id: metronomeNeedle - source: "qrc:/gcompris/src/activities/play_rhythm/resource/metronome_needle.svg" fillMode: Image.PreserveAspectFit width: parent.height height: parent.height anchors.centerIn: parent transformOrigin: Item.Bottom SequentialAnimation { id: metronomeOscillation loops: Animation.Infinite + onStarted: metronomeNeedle.rotation = 12 onStopped: metronomeNeedle.rotation = 0 - RotationAnimator { - target: metronomeNeedle - from: 0 - to: 12 - direction: RotationAnimator.Shortest - duration: metronomeSpeed - } ScriptAction { script: items.audioEffects.play("qrc:/gcompris/src/activities/play_rhythm/resource/click.wav") } RotationAnimator { target: metronomeNeedle from: 12 - to: 0 - direction: RotationAnimator.Shortest - duration: metronomeSpeed - } - RotationAnimator { - target: metronomeNeedle - from: 0 to: 348 direction: RotationAnimator.Shortest duration: metronomeSpeed } ScriptAction { script: items.audioEffects.play("qrc:/gcompris/src/activities/play_rhythm/resource/click.wav") } RotationAnimator { target: metronomeNeedle from: 348 - to: 0 + to: 12 direction: RotationAnimator.Shortest duration: metronomeSpeed } } + Image { + id: metronomeWeight + source: "qrc:/gcompris/src/activities/play_rhythm/resource/metronome_weight.svg" + fillMode: Image.PreserveAspectFit + width: parent.height + height: parent.height + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: weightOffset + } + + } + Image { + id: metronomeFront + source: "qrc:/gcompris/src/activities/play_rhythm/resource/metronome_front.svg" + fillMode: Image.PreserveAspectFit + width: parent.height + height: parent.height + anchors.centerIn: parent } } OptionsRow { id: optionsRow anchors.verticalCenter: tempo.verticalCenter anchors.left: tempo.right bpmVisible: true onBpmDecreased: { - if(multipleStaff.bpmValue - 1 >= 1) + if(multipleStaff.bpmValue >= 51) multipleStaff.bpmValue-- } onBpmIncreased: { + if(multipleStaff.bpmValue <= 179) multipleStaff.bpmValue++ } onBpmChanged: { Activity.initSubLevel() background.isRhythmPlaying = true } } DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | level | reload } onHelpClicked: { displayDialog(dialogHelp) } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() onReloadClicked: { Activity.initSubLevel() } } Bonus { id: bonus Component.onCompleted: { win.connect(Activity.nextSubLevel) loose.connect(Activity.initSubLevel) } } } } diff --git a/src/activities/play_rhythm/resource/README b/src/activities/play_rhythm/resource/README new file mode 100644 index 000000000..11025bf48 --- /dev/null +++ b/src/activities/play_rhythm/resource/README @@ -0,0 +1,7 @@ +Copyright: 2018, Timothee Giet +License: CC-BY-SA 4.0 +Files: +metronome_front.svg +metronome_needle.svg +metronome_stand.svg +metronome_weight.svg diff --git a/src/activities/play_rhythm/resource/metronome_front.svg b/src/activities/play_rhythm/resource/metronome_front.svg new file mode 100644 index 000000000..674b68e16 --- /dev/null +++ b/src/activities/play_rhythm/resource/metronome_front.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/activities/play_rhythm/resource/metronome_needle.svg b/src/activities/play_rhythm/resource/metronome_needle.svg index 0865e857c..911ca55c9 100644 --- a/src/activities/play_rhythm/resource/metronome_needle.svg +++ b/src/activities/play_rhythm/resource/metronome_needle.svg @@ -1,194 +1,113 @@ - Metronome - - - - - - - - - - - - - - - - - - - - - + id="defs4" /> + fit-margin-bottom="0" + units="px"> image/svg+xml - Metronome - 2016-06-11 + + 2018 - Algot Runeman + Timothée Giet - Algot Runeman + - runeman.org + - metronome.svg + + rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> + rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + + + - - - - + transform="translate(300.59358,-266.64809)"> + diff --git a/src/activities/play_rhythm/resource/metronome_stand.svg b/src/activities/play_rhythm/resource/metronome_stand.svg index e0966c822..8dae71417 100644 --- a/src/activities/play_rhythm/resource/metronome_stand.svg +++ b/src/activities/play_rhythm/resource/metronome_stand.svg @@ -1,502 +1,265 @@ - Metronome - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + id="defs4" /> + fit-margin-bottom="0" + units="px"> image/svg+xml - Metronome - 2016-06-11 + + 2018 - Algot Runeman + Timothée Giet - Algot Runeman + - runeman.org + - metronome.svg + + rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" /> + rdf:about="http://creativecommons.org/licenses/by-sa/4.0/"> + + + + transform="translate(300.59358,-266.64809)"> - - + style="fill:#53290f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.04113817px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -197.46859,267.58559 -42.41752,20.44409 -53.02338,296.4309 h 190.88181 l -53.02144,-296.4309 z" + id="path3338-3" + inkscape:connector-curvature="0" /> + id="g3394" + style="stroke:#794d2b;stroke-opacity:1;stroke-width:1.88532001;stroke-miterlimit:4;stroke-dasharray:none" + transform="matrix(0.9945261,0,0,0.9945261,11.381898,1.3297833)"> + d="m -218.82976,316.82918 h 18.8532 l 0,216.8118 h -18.8532 z" + style="fill:#e6d4b7;fill-opacity:1;fill-rule:evenodd;stroke:#794d2b;stroke-width:1.88532007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:nodetypes="ccccc" /> + d="m -199.97656,524.21438 h -18.8532" + style="fill:none;fill-rule:evenodd;stroke:#794d2b;stroke-width:1.88532007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:nodetypes="cc" /> + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + d="m -199.97656,486.50798 h -18.8532" + style="fill:none;fill-rule:evenodd;stroke:#794d2b;stroke-width:1.88532007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:nodetypes="cc" /> - - + style="fill:none;fill-rule:evenodd;stroke:#794d2b;stroke-width:1.88532019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m -199.97656,448.80158 h -18.8532" + id="path3358-5" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cc" /> + id="path3362-2" + d="m -199.97656,429.94838 h -18.8532" + style="fill:none;fill-rule:evenodd;stroke:#794d2b;stroke-width:1.88532019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:nodetypes="cc" /> + + id="path3360-6-0" + d="m -204.68986,382.81538 h -9.4266" + style="fill:none;fill-rule:evenodd;stroke:#794d2b;stroke-width:1.88532019;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + sodipodi:nodetypes="cc" /> + + + - - diff --git a/src/activities/play_rhythm/resource/metronome_weight.svg b/src/activities/play_rhythm/resource/metronome_weight.svg new file mode 100644 index 000000000..0e70d2385 --- /dev/null +++ b/src/activities/play_rhythm/resource/metronome_weight.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + image/svg+xml + + + 2018 + + + Timothée Giet + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +