Commit 2d5c7b6f authored by Bruno Coudoin's avatar Bruno Coudoin
Browse files

click_on_letter, improved graphism

- now all images are svg
- auto detect if we are a carriage or a cloud
- better graphical effects
parent 35bc457e
......@@ -23,57 +23,107 @@
import QtQuick 2.1
import GCompris 1.0
import QtGraphicalEffects 1.0
import "qrc:/gcompris/src/core"
import "click_on_letter.js" as Activity
Component {
Image {
id: carriageImage
source: image
scale: 1 * ApplicationInfo.ratio
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: type == "carriage" ? -8 : 0
anchors.verticalCenter: type == "carriage" ? undefined : parent.verticalCenter
anchors.top: type == "carriage" ? parent.top : undefined
anchors.topMargin: type == "carriage" ? 1 : undefined
z:11
text: letter
font.pointSize: 44
font.bold: true
style: Text.Outline
styleColor: "lightblue"
color: "black"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: ApplicationInfo.isMobile ? false : true
onClicked: {
clickAnimation.restart();
Activity.checkAnswer(index);
carriageImage.focus = false;
Image {
id: carriageImage
fillMode: Image.PreserveAspectFit
source: isCarriage ?
Activity.url + "carriage.svgz":
Activity.url + "cloud.svgz"
property int nbCarriage
property bool isCarriage: index <= nbCarriage
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenterOffset: isCarriage ? -8 : 0
anchors.verticalCenter: parent.verticalCenter
z: 11
text: letter
font.pixelSize: Math.min(parent.width * 0.8, 80)
font.bold: true
style: Text.Outline
styleColor: "black"
color: "white"
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: ApplicationInfo.isMobile ? false : true
onClicked: {
if (Activity.checkAnswer(index)) {
successAnimation.restart();
particle.emitter.burst(30)
} else {
failureAnimation.restart()
}
}
states: State {
name: "scaled"; when: mouseArea.containsMouse
PropertyChanges { target: carriageImage; scale: /*carriageImage.scale * */ 1.2 }
}
ParticleSystemStar {
id: particle
clip: false
}
states: State {
name: "scaled"; when: mouseArea.containsMouse
PropertyChanges {
target: carriageImage
scale: /*carriageImage.scale * */ 1.2 }
}
transitions: Transition {
NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic }
}
SequentialAnimation {
id: successAnimation
NumberAnimation {
target: carriageImage
easing.type: Easing.InOutQuad
property: "rotation"
to: 20; duration: 100
}
NumberAnimation {
target: carriageImage
easing.type: Easing.InOutQuad
property: "rotation"; to: -20
duration: 100 }
NumberAnimation {
target: carriageImage
easing.type: Easing.InOutQuad
property: "rotation"
to: 0
duration: 50 }
}
Colorize {
id: color
anchors.fill: parent
source: parent
hue: 0.0
saturation: 1
opacity: 0
}
transitions: Transition {
NumberAnimation { properties: "scale"; easing.type: Easing.OutCubic }
SequentialAnimation {
id: failureAnimation
NumberAnimation {
target: color
property: "opacity"
to: 1; duration: 400
}
SequentialAnimation {
id: clickAnimation
NumberAnimation { target: carriageImage; easing.type: Easing.InOutQuad; property: "rotation"; to: 20; duration: 100 }
NumberAnimation { target: carriageImage; easing.type: Easing.InOutQuad; property: "rotation"; to: -20; duration: 100 }
NumberAnimation { target: carriageImage; easing.type: Easing.InOutQuad; property: "rotation"; to: 0; duration: 50 }
NumberAnimation {
target: color
property: "opacity"
to: 0; duration: 200
}
}
}
......@@ -36,8 +36,9 @@ ActivityBase {
property string mode: "lowercase"
pageComponent: Image {
source: "qrc:/gcompris/src/activities/click_on_letter/resource/background.svgz"
id: background
source: Activity.url + "background.svgz"
fillMode: Image.PreserveAspectCrop
signal start
signal stop
focus: true
......@@ -104,17 +105,28 @@ ActivityBase {
Component.onCompleted: win.connect(Activity.nextSubLevel)
}
Image {
id: railway
source: Activity.url + "railway.svgz"
fillMode: Image.PreserveAspectCrop
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width
height: 15 * ApplicationInfo.ratio
sourceSize.width: parent.width
anchors.bottomMargin: 13 * ApplicationInfo.ratio
}
Item {
id: questionItem
anchors.left: parent.left
anchors.top: parent.top
anchors.leftMargin: 10 * ApplicationInfo.ratio
anchors.topMargin: 160 * ApplicationInfo.ratio
anchors.topMargin: parent.height * 0.25
z: 10
width: 80
height: 80
scale: 1 * ApplicationInfo.ratio
visible: false;
width: questionText.width * 2
height: questionText.height * 1.3
visible: false
property alias text: questionText.text
......@@ -128,7 +140,7 @@ ActivityBase {
opacity: 0.31
radius: 10
}
Text {
id: questionText
anchors.horizontalCenter: parent.horizontalCenter
......@@ -139,47 +151,62 @@ ActivityBase {
font.pointSize: 44
font.bold: true
style: Text.Outline
styleColor: "darkblue"
styleColor: "black"
color: "white"
}
}
ListModel {
id: trainModel
id: trainModel
}
property int itemWidth: Math.min(parent.width / 7.5, parent.height / 5)
property int itemHeight: itemWidth * 1.11
Image {
id: engine
source: "qrc:/gcompris/src/activities/click_on_letter/resource/engine.svgz"
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.bottomMargin: 13 * ApplicationInfo.ratio
source: Activity.url + "engine.svgz"
anchors.bottom: railway.bottom
anchors.left: railway.left
anchors.leftMargin: 10 * ApplicationInfo.ratio
anchors.bottomMargin: 5 * ApplicationInfo.ratio
sourceSize.width: itemWidth
fillMode: Image.PreserveAspectFit
}
scale: 1 * ApplicationInfo.ratio
Image {
id: smoke
source: Activity.url + "smoke.svgz"
anchors.bottom: engine.top
anchors.left: railway.left
anchors.leftMargin: 10 * ApplicationInfo.ratio
anchors.bottomMargin: 5 * ApplicationInfo.ratio
sourceSize.width: itemWidth
fillMode: Image.PreserveAspectFit
}
GridView {
id: train
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.bottomMargin: 13 * ApplicationInfo.ratio
anchors.leftMargin: (10 + engine.width) * ApplicationInfo.ratio
width: (820 - 144) * ApplicationInfo.ratio
height: parent.height - anchors.bottomMargin
cellWidth: 112 * ApplicationInfo.ratio
cellHeight: 126 * ApplicationInfo.ratio
flickableDirection: Flickable.HorizontalFlick
interactive: ApplicationInfo.isMobile ? true : false // FIXME allow scrolling the train horizontally on mobile: need to implement a kind of returnToBounds()
clip: ApplicationInfo.isMobile ? true : false // flick only the carriages
anchors.bottom: railway.bottom
anchors.left: engine.right
anchors.right: parent.right
anchors.top: parent.top
anchors.bottomMargin: 5 * ApplicationInfo.ratio
cellWidth: itemWidth
cellHeight: itemHeight
clip: false
interactive: false
verticalLayoutDirection: GridView.BottomToTop
layoutDirection: Qt.LeftToRight
model: trainModel
delegate: Carriage { }
delegate: Carriage {
sourceSize.width: background.itemWidth
width: background.itemWidth
nbCarriage: (parent.width - engine.width) / background.itemWidth
}
}
File {
......
......@@ -25,6 +25,7 @@
.import QtQuick 2.0 as Quick
.import GCompris 1.0 as GCompris //for ApplicationInfo
var url = "qrc:/gcompris/src/activities/click_on_letter/resource/"
var defaultLevelsFile = ":/gcompris/src/activities/click_on_letter/resource/levels-en.json";
var maxLettersPerLine = 6;
......@@ -78,7 +79,12 @@ function parseLevels(json)
function loadLevels()
{
var ret;
var json = items.levelsFile.read(GCompris.ApplicationInfo.getAudioFilePath("click_on_letter/levels-$LOCALE.json")); // FIXME: this should be something like ApplicationInfo.getDataPath() + "click_on_letter" + "levels-" + ApplicationInfo.getCurrentLocale() + ".json" once it is there.
// FIXME: this should be something like
// ApplicationInfo.getDataPath() + "click_on_letter" +
// "levels-" + ApplicationInfo.getCurrentLocale() + ".json" once it is there.
var json = items.levelsFile.read(
GCompris.ApplicationInfo.getAudioFilePath(
"click_on_letter/levels-$LOCALE.json"));
if (json == "" || !parseLevels(json)) {
console.warn("Click_on_letter: Invalid levels file " +
items.levelsFile.name);
......@@ -135,20 +141,10 @@ function initLevel() {
items.trainModel.clear();
for (var i = 0; i < answerArr.length; i++) {
items.trainModel.append({
"image": i < maxLettersPerLine ?
"qrc:/gcompris/src/activities/click_on_letter/resource/carriage-off.png":
"qrc:/gcompris/src/activities/click_on_letter/resource/cloud-off.png",
"letter": answerArr[i],
"type": i < maxLettersPerLine ? "carriage" : "cloud"
});
}
} else {
// reset all images:
for (var i = 0; i < items.trainModel.count; i++) {
items.trainModel.setProperty(i, "image", i < maxLettersPerLine ?
"qrc:/gcompris/src/activities/click_on_letter/resource/carriage-off.png":
"qrc:/gcompris/src/activities/click_on_letter/resource/cloud-off.png");
}
items.score.currentSubLevel = currentSubLevel + 1;
}
......@@ -159,8 +155,9 @@ function initLevel() {
items.letterAudio.source = GCompris.ApplicationInfo.getAudioFilePath("voices/$LOCALE/alphabet/"
+ getSoundFilenamForChar(currentLetter));
items.letterAudio.playDelayed(1500);
} //else
if (!getSetting("fx") || GCompris.ApplicationInfo.isMobile) { // FIXME once we have voices on mobile
}
// FIXME once we have voices on mobile
if (!getSetting("fx") || GCompris.ApplicationInfo.isMobile) {
// no sound -> show question
items.questionItem.visible = true;
items.questionItem.text = currentLetter;
......@@ -194,13 +191,11 @@ function nextSubLevel() {
function checkAnswer(index)
{
var modelEntry = items.trainModel.get(index);
if (modelEntry.letter == currentLetter)
if (modelEntry.letter == currentLetter) {
items.bonus.good("flower");
else {
items.bonus.bad("flower");
modelEntry.image = index < maxLettersPerLine ?
"qrc:/gcompris/src/activities/click_on_letter/resource/carriage-on.png" :
"qrc:/gcompris/src/activities/click_on_letter/resource/cloud-on.png";
return true
} else {
return false
}
}
......
......@@ -9,9 +9,9 @@ APP_FILES += \
APP_FILES += \
$$PWD/resource/background.svgz \
$$PWD/resource/engine.svgz \
$$PWD/resource/carriage-on.png \
$$PWD/resource/carriage-off.png \
$$PWD/resource/cloud-off.png \
$$PWD/resource/cloud-on.png \
$$PWD/resource/carriage.svgz \
$$PWD/resource/cloud.svgz \
$$PWD/resource/levels-en.json \
$$PWD/resource/levels-fr.json
$$PWD/resource/levels-fr.json \
$$PWD/resource/railway.svgz \
$$PWD/resource/smoke.svgz
......@@ -37,7 +37,7 @@ Window {
id: audio
source: "qrc:/gcompris/src/core/resource/intro.ogg"
onError: console.log("intro play error: " + errorString)
autoPlay: true
autoPlay: false
}
StackView {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment