diff --git a/src/activities/activities.txt b/src/activities/activities.txt index f020a5005..e79b86ce9 100644 --- a/src/activities/activities.txt +++ b/src/activities/activities.txt @@ -1,123 +1,124 @@ # 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 baby_wordprocessor balancebox ballcatch braille_alphabets braille_fun canal_lock chess chess_2players chess_partyend chronos clickanddraw clickgame click_on_letter click_on_letter_up clockgame color_mix color_mix_light colors details drawnumber enumerate erase erase_2clic erase_clic explore_farm_animals explore_monuments explore_world_animals explore_world_music fifteen followline football geo-country geography gletters gnumch-equality gnumch-factors gnumch-inequality gnumch-multiples gnumch-primes graph-coloring guessnumber hangman hanoi hanoi_real hexagon imagename instruments intro_gravity lang +land_safe leftright lightsoff louis-braille magic-hat-minus magic-hat-plus maze mazeinvisible mazerelative melody 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 paintings penalty planegame readingh readingv redraw redraw_symmetrical renewable_energy reversecount scalesboard scalesboard_weight scalesboard_weight_avoirdupois simplepaint smallnumbers smallnumbers2 sudoku superbrain tangram target tic_tac_toe tic_tac_toe_2players traffic watercycle wordsgame diff --git a/src/activities/land_safe/ActivityInfo.qml b/src/activities/land_safe/ActivityInfo.qml new file mode 100644 index 000000000..e5a4fce9a --- /dev/null +++ b/src/activities/land_safe/ActivityInfo.qml @@ -0,0 +1,39 @@ +/* GCompris - ActivityInfo.qml + * + * Copyright (C) 2015 Holger Kaelberer + * + * 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: "land_safe/LandSafe.qml" + difficulty: 4 + icon: "land_safe/land_safe.svg" + author: "Matilda Bernard (Gtk+), Holger Kaelberer (Qt Quick)" + demo: true + title: qsTr("Land Safe") + description: qsTr("Understanding acceleration due to gravity.") + goal: qsTr("Pilot the spaceship towards the green landing area.") + prerequisite: "" + manual: qsTr("Acceleration due to gravity experienced by the spaceship is directly proportional to the mass of the planet and inversely proportional to the square of the distance from the center of the planet. Thus, with every planet the acceleration will differ and as the spaceship comes closer and closer to the planet the acceleration increases. + +Use the up/down keys to control the thrust and the right/left keys to control direction. + +In higher levels, you can use the right/left keys to rotate the spaceship. By rotating the spaceship you can trigger an acceleration in non-vertical direction using the up/down keys. + +The landing platform is green if your speed is fine for a safe landing.") + credit: "" + section: "experiments" +} diff --git a/src/activities/land_safe/CMakeLists.txt b/src/activities/land_safe/CMakeLists.txt new file mode 100644 index 000000000..313019f98 --- /dev/null +++ b/src/activities/land_safe/CMakeLists.txt @@ -0,0 +1 @@ +GCOMPRIS_ADD_RCC(activities/land_safe *.qml *.svg *.js resource/*) diff --git a/src/activities/land_safe/LandSafe.qml b/src/activities/land_safe/LandSafe.qml new file mode 100644 index 000000000..45df2a2cc --- /dev/null +++ b/src/activities/land_safe/LandSafe.qml @@ -0,0 +1,530 @@ +/* GCompris - LandSafe.qml + * + * Copyright (C) 2016 Holger Kaelberer + * + * Authors: + * Matilda Bernard (GTK+ version) + * Holger Kaelberer (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.1 +import Box2D 2.0 +import QtQuick.Particles 2.0 +import GCompris 1.0 + +import "../../core" +import "land_safe.js" as Activity + +ActivityBase { + id: activity + + onStart: focus = true + onStop: {} + + Keys.onPressed: Activity.processKeyPress(event) + Keys.onReleased: Activity.processKeyRelease(event) + + pageComponent: Image { + id: background + + source: Activity.baseUrl + "/background4.jpg"; + anchors.centerIn: parent + anchors.fill: parent + + 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 rocket: rocket + property alias world: physicsWorld + property alias landing: landing + property alias ground: ground + property alias stats: stats + property var rocketCategory: Fixture.Category1 + property var groundCategory: Fixture.Category2 + property var landingCategory: Fixture.Category3 + property var borderCategory: Fixture.Category4 + property string mode: "rotate" // "simple" + property double lastVelocity: 0.0 + } + + onStart: { Activity.start(items) } + onStop: { Activity.stop() } + + World { + id: physicsWorld + + running: false; + gravity: Qt.point(0, Activity.gravity) + pixelsPerMeter: 0 + autoClearForces: false + //timeStep: 1.0/60.0 // default: 60Hz + + onStepped: { + if (Math.abs(rocket.body.linearVelocity.y) > 0.01) // need to store velocity before it is aaaalmost 0 because of ground/landing contact + items.lastVelocity = stats.velocity.y; + stats.velocity = rocket.body.linearVelocity; + + stats.height = Math.max(0, Math.round(Activity.getRealHeight())); + + // update fuel: + var dt = timeStep; + var dFuel = -(dt * (items.rocket.accel + items.rocket.leftAccel + + items.rocket.rightAccel)); + Activity.currentFuel = Math.max(0, Activity.currentFuel + dFuel); + stats.fuel = Math.round(Activity.currentFuel / Activity.maxFuel * 100); + if (Activity.currentFuel === 0) + // fuel consumed: + items.rocket.accel = items.rocket.leftAccel = items.rocket.rightAccel = 0; + +// console.log("VVV changed: " + items.lastVelocity + " --> " + stats.velocity.y + " / " + rocket.body.linearVelocity.y); + } + + } + + MouseArea { + id: mouse + anchors.fill: parent + onClicked: debugDraw.visible = !debugDraw.visible; + } + + // bounding fixtures + Item { + id: leftBorder + width: 1 + height: parent.height + anchors.left: parent.left + anchors.top: parent.top + + readonly property string collisionName: "leftBorder" + + Body { + id: leftBody + + target: leftBorder + bodyType: Body.Static + sleepingAllowed: false + fixedRotation: true + linearDamping: 0 + + fixtures: Box { + id: leftFixture + categories: items.borderCategory + collidesWith: items.rocketCategory + density: 1 + friction: 0 + restitution: 0 + width: leftBorder.width + height: leftBorder.height + } + } + } + + Item { + id: rightBorder + width: 1 + height: parent.height + anchors.right: parent.right + anchors.rightMargin: 1 + anchors.top: parent.top + + readonly property string collisionName: "rightBorder" + + Body { + id: rightBody + + target: rightBorder + bodyType: Body.Static + sleepingAllowed: false + fixedRotation: true + linearDamping: 0 + + fixtures: Box { + id: rightFixture + categories: items.borderCategory + collidesWith: items.rocketCategory + density: 1 + friction: 0 + restitution: 0 + width: rightBorder.width + height: rightBorder.height + } + } + } + + GCText { + id: stats + z: 0 + property var velocity: rocket.body.linearVelocity + property double fuel: 100.0 + property double heigth: Activity.startingHeightReal + + anchors.left: background.left + anchors.leftMargin: 20 + anchors.top: background.top + anchors.topMargin: 20 + width: 100 + height: 100 + color: "gray" + + fontSize: tinySize + text: qsTr("Planet: ") + Activity.levels[Activity.currentLevel].planet + "
" + + qsTr("Velocity: ") + Math.round(velocity.y * 10) / 10 + "
" + + qsTr("Fuel: ") + fuel + "
" + + qsTr("Altitude: ") + height + "
" + + qsTr("Gravity: ") + Math.round(Activity.gravity * 100)/100 + } + + Item { + id: rocket + property double accel: 0.0 + property double leftAccel: 0.0 + property double rightAccel: 0.0 + property alias body: rocketBody + property alias leftEngine: leftEngine + property alias rightEngine: rightEngine + property alias explosion: explosion + //property float rotate + + rotation: 0 + width: background.width / 18// * ApplicationInfo.ratio + height: width / 232 * 385 + x: 300 + y: 50 + z: 3 + + Component.onCompleted: rocket.body.applyForceToCenter(Qt.point(0, 5)); + + onAccelChanged: applyForces(); + onLeftAccelChanged: applyForces(); + onRightAccelChanged: applyForces(); + onRotationChanged: if (accel > 0) // should only happen in + applyForces(); // "rotation" mode + + // map acceleration to box2d forces applying appropriate factors: + function applyForces() + { + var totForce = (accel / 0.5 * 5) + var xForce; + var yForce; + + if (items.mode === "simple") { + yForce = -totForce; + xForce = (leftAccel-rightAccel) + * 10 /* base of 10 m/s^2 */ + * 5 /* factor to make movement smooth */; + } else { // "rotation" + yForce = -(totForce * Math.cos(Activity.degToRad(items.rocket.rotation))); + xForce = (totForce * Math.sin(Activity.degToRad(items.rocket.rotation))); + } + var yFForce = yForce * items.rocket.body.getMass(); + var xFForce = xForce * items.rocket.body.getMass(); + var force = Qt.point(xFForce, yFForce); + console.log("applying force " + force + " - " + " - mass=" + items.rocket.body.getMass() + " v=" + items.rocket.body.linearVelocity + " totForce=" + totForce + " - rotation=" + items.rocket.rotation + " - xForce=" + xForce + " xFForce=" + xFForce + " mass=" + items.rocket.body.getMass()); + + physicsWorld.clearForces(); + items.rocket.body.applyForceToCenter(force); + } + + Image { + id: rocketImage + + width: parent.width + height: parent.height + sourceSize.width: 1024 + source: Activity.baseUrl + "/rocket.svg"; + anchors.centerIn: parent + anchors.fill: parent + } + + Image { + id: explosion + +// width: parent.height +// height: width/785*621 + width: height/621 * 785 + height: 2*parent.height + sourceSize.width: 1024 + source: Activity.baseUrl + "/explosion.svg"; + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + scale: 0 + + function show() { + visible = true; + scale = 1; + } + function hide() { + visible = false; + scale = 0; + } + + Behavior on scale { + NumberAnimation { + duration: 150 + easing.type: Easing.InExpo + } + } + } + + Body { + id: rocketBody + + target: rocket + bodyType: Body.Dynamic + sleepingAllowed: false + fixedRotation: true + linearDamping: 0 + property double rotation: Activity.degToRad(rocket.rotation % 360) + + onLinearVelocityChanged: console.log("v = " + linearVelocity); + + fixtures: Box { + id: rocketFixture + categories: items.rocketCategory + collidesWith: items.groundCategory | items.landingCategory | items.borderCategory + density: 1 + friction: 0 + restitution: 0 + width: rocket.width + height: rocket.height + rotation: rocketBody.rotation + + onBeginContact: { + console.log("XXX beginning contact with " + + other.getBody().target.collisionName + + " abs v=" + Math.abs(items.lastVelocity) + + + " maxV=" + Activity.maxLandingVelocity); + + if (other.getBody().target === leftBorder || + other.getBody().target === rightBorder) + ; //nothing to do + else if (other.getBody().target === landing && + Math.abs(items.lastVelocity) <= Activity.maxLandingVelocity && + (items.mode === "simple" || rocket.rotation === 0)) + Activity.finishLevel(true); + else // ground + Activity.finishLevel(false); // crash + } + onEndContact: console.log("XXX ending contact with " + other.getBody().target.collisionName); + } + } + + ParticleSystem { + id: leftEngine + + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.verticalCenter: parent.verticalCenter + height: 30 + + ImageParticle { + groups: ["flameLeft"] + source: "qrc:///particleresources/glowdot.png" + color: "#11ff400f" + colorVariation: 0.1 + } + Emitter { + anchors.centerIn: parent + group: "flameLeft" + + emitRate: rocket.leftAccel > 0 ? 50 : 0 // 50 + lifeSpan: rocket.leftAccel > 0 ? 600 : 0 // 600 + size: rocket.leftAccel > 0 ? leftEngine.height : 0 + endSize: 5 + sizeVariation: 5 + acceleration: PointDirection { x: -40 } + velocity: PointDirection { x: -40 } + } + } + + ParticleSystem { + id: rightEngine + + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + height: 30 + + ImageParticle { + groups: ["flameRight"] + source: "qrc:///particleresources/glowdot.png" + color: "#11ff400f" + colorVariation: 0.1 + } + Emitter { + anchors.centerIn: parent + group: "flameRight" + + emitRate: rocket.rightAccel > 0 ? 50 : 0 // 50 + lifeSpan: rocket.rightAccel > 0 ? 600 : 0 // 600 + size: rocket.rightAccel > 0 ? rightEngine.height : 0 + endSize: 5 + sizeVariation: 5 + acceleration: PointDirection { x: 40 } + velocity: PointDirection { x: 40 } + } + } + + ParticleSystem { + id: bottomEngine + anchors.top: parent.bottom + anchors.topMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + width: rocket.width + + ImageParticle { + groups: ["flame"] + source: "qrc:///particleresources/glowdot.png" + color: "#11ff400f" + colorVariation: 0.1 + } + Emitter { + anchors.centerIn: parent + group: "flame" + + emitRate: rocket.accel > 0 ? (75 + 75*rocket.accel) : 0 // 75-150 + lifeSpan: (500 + 500 * rocket.accel) * background.height / 600 // 500 - 1000 + size: rocket.width/2 + rocket.width/2*rocket.accel // width*-0.5 - width + endSize: size/1.85 + sizeVariation: 10 + acceleration: PointDirection { y: 80 } + velocity: PointDirection { y: 80 } + } + } + + } + + Image { + id: ground + + z: 1 + width: parent.width +// height: parent.height + source: Activity.baseUrl + "/land4.png"; + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + + readonly property string collisionName: "ground" + property int surfaceOffset: height/2 + + Body { + id: groundBody + + target: ground + bodyType: Body.Static + sleepingAllowed: true + fixedRotation: true + linearDamping: 0 + + fixtures: Box { + id: groundFixture + + categories: items.groundCategory + collidesWith: items.rocketCategory + density: 1 + friction: 0 + restitution: 0 + width: ground.width + height: ground.height - ground.surfaceOffset + x: 0 + y: ground.surfaceOffset + } + } + } + + Image { + id: landing + + readonly property string collisionName: "landing" + property int surfaceOffset: landing.height - 1 + + z: 2 + source: Activity.baseUrl + "/landing_red.png"; + anchors.left: ground.left + anchors.leftMargin: 270 + anchors.top: ground.top + anchors.topMargin: ground.surfaceOffset - height + width: 116 * background.width / 900 + + Body { + id: landingBody + + target: landing + bodyType: Body.Static + sleepingAllowed: true + fixedRotation: true + linearDamping: 0 + + fixtures: Box { + id: landingFixture + + categories: items.landingCategory + collidesWith: items.rocketCategory + density: 1 + friction: 0 + restitution: 0 + width: landing.width + height: landing.height - landing.surfaceOffset + y: landing.surfaceOffset + } + } + } + + DebugDraw { + id: debugDraw + world: physicsWorld + visible: false + z: 1 + } + + 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: { + loose.connect(Activity.initLevel); + win.connect(Activity.nextLevel) + } + } + } + +} diff --git a/src/activities/land_safe/land_safe.js b/src/activities/land_safe/land_safe.js new file mode 100644 index 000000000..4e9ca1d3d --- /dev/null +++ b/src/activities/land_safe/land_safe.js @@ -0,0 +1,250 @@ +/* GCompris - land_safe.js + * + * Copyright (C) 2016 Holger Kaelberer + * + * Authors: + * Matilda Bernard (GTK+ version) + * Holger Kaelberer (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 . + */ + +/* ToDo: + * - zoom out if too high! + * - support android + * - check for shader availability + * - use polygon fixture for rocket + * - succesful landing only if on platform + * - red/green colors for crash/save landing + * - Einleitung + Ueberleitung simple -> rotate + * + * Gravitational forces: + * !- Pluto: 0,62 m/s² + * - Titan: 1,352 m/s² + * !- Moon: 1,622 m/s² + * - Io: 1,796 m/s² + * !- Mars: 3,711 m/s² + * - Merkur: 3,7 m/s² + * !- Venus: 8,87 m/s² + * - Earth: 9,807 m/s² + * - Jupiter: 24,79 m/s² + */ + +.pragma library +.import QtQuick 2.0 as Quick +.import GCompris 1.0 as GCompris + +var levels = [ + /** simple **/ + { "planet": "Pluto", "gravity": 0.62, "maxAccel": 0.2, + "accelSteps": 3, "alt": 100.0, "mode": "simple", + "fuel" : 5 }, + { "planet": "Moon", "gravity": 1.62, "maxAccel": 0.4, + "accelSteps": 4, "alt": 150.0, "mode": "simple", + "fuel" : 10 }, + { "planet": "Mars", "gravity": 3.71, "maxAccel": 0.6, + "accelSteps": 5, "alt": 200.0, "mode": "simple", + "fuel" : 20 }, + { "planet": "Vulc@n", "gravity": 5.55, "maxAccel": 1.0, + "accelSteps": 5, "alt": 300.0, "mode": "simple", + "fuel" : 30 }, + { "planet": "Venus", "gravity": 8.87, "maxAccel": 1.2, + "accelSteps": 5, "alt": 300.0, "mode": "simple", + "fuel" : 70 }, + + /** rotation **/ + { "planet": "Pluto", "gravity": 0.62, "maxAccel": 0.2, + "accelSteps": 3, "alt": 100.0, "mode": "rotation", + "fuel" : 5 }, + { "planet": "Moon", "gravity": 1.62, "maxAccel": 0.4, + "accelSteps": 4, "alt": 150.0, "mode": "rotation", + "fuel" : 10 }, + { "planet": "Mars", "gravity": 3.71, "maxAccel": 0.6, + "accelSteps": 5, "alt": 200.0, "mode": "rotation", + "fuel" : 20 }, + { "planet": "Vulc@n", "gravity": 5.55, "maxAccel": 1.0, + "accelSteps": 5, "alt": 300.0, "mode": "rotation", + "fuel" : 30 }, + { "planet": "Venus", "gravity": 8.87, "maxAccel": 1.2, + "accelSteps": 5, "alt": 300.0, "mode": "rotation", + "fuel" : 70 } +]; + +var currentLevel = 0; +var numberOfLevel; +var items; +var baseUrl = "qrc:/gcompris/src/activities/land_safe/resource"; +var startingHeightReal = 100.0; +var startingOffsetPx = 10; // y-value for setting rocket initially +var gravity = 1; +var maxLandingVelocity = 10; +var leftRightAccel = 0.1; // accel force set on horizontal accel +//var minAccel = 0.1; +var maxAccel = 0.15; +var accelSteps = 3; +var dAccel = maxAccel / accelSteps;//- minAccel; +var barAtStart; +var maxFuel = 100.0; +var currentFuel = 0.0; + +function start(items_) { + items = items_; + currentLevel = 0; + numberOfLevel = levels.length; + barAtStart = GCompris.ApplicationSettings.isBarHidden; + GCompris.ApplicationSettings.isBarHidden = true; + initLevel() +} + +function stop() { + GCompris.ApplicationSettings.isBarHidden = barAtStart; +} + +function initLevel() { + items.bar.level = currentLevel + 1 + + var max = items.background.width - items.landing.width-20; + var min = 20; + items.rocket.explosion.hide(); + items.rocket.x = Math.random() * (max- min) + min; + items.rocket.y = startingOffsetPx; + items.rocket.rotation = 0; + items.rocket.accel = 0; + items.rocket.leftAccel = 0; + items.rocket.rightAccel = 0; + items.rocket.body.linearVelocity = Qt.point(0,0) + items.landing.anchors.leftMargin = Math.random() * (max- min) + min; + + maxAccel = levels[currentLevel].maxAccel; + accelSteps = levels[currentLevel].accelSteps; + dAccel = maxAccel / accelSteps;//- minAccel; + startingHeightReal = levels[currentLevel].alt; + gravity = levels[currentLevel].gravity; + items.mode = levels[currentLevel].mode; + maxFuel = currentFuel = levels[currentLevel].fuel; + + items.world.pixelsPerMeter = getHeightPx() / startingHeightReal; + items.world.gravity = Qt.point(0, gravity) + console.log("Starting level (surfaceOff=" + items.ground.surfaceOffset + ", ppm=" + items.world.pixelsPerMeter + ")"); + items.world.running = true; +} + +function getHeightPx() +{ + var heightPx = items.background.height - items.ground.height + items.ground.surfaceOffset + - items.rocket.y - items.rocket.height + - 1; // landing is 1 pixel above ground surface + return heightPx; +} + +// calc real height of rocket in meters above surface +function getRealHeight() +{ + var heightPx = getHeightPx(); + var heightReal = heightPx / items.world.pixelsPerMeter; + return heightReal; +} + +function nextLevel() { + if(numberOfLevel <= ++currentLevel ) { + currentLevel = 0 + } + initLevel(); +} + +function previousLevel() { + if(--currentLevel < 0) { + currentLevel = numberOfLevel - 1 + } + initLevel(); +} + +function processKeyPress(event) +{ + var key = event.key; + event.accepted = true; + var newAccel = 0; + if (key === Qt.Key_Up || key === Qt.Key_Down) { + if (key === Qt.Key_Up) { + if (items.rocket.accel === 0) + newAccel = dAccel; + else + newAccel = items.rocket.accel + dAccel; + } else if (key === Qt.Key_Down) + newAccel = items.rocket.accel - dAccel; + + if (newAccel < dAccel) + newAccel = 0; + if (newAccel > maxAccel) + newAccel = maxAccel; + + if (newAccel !== items.rocket.accel && currentFuel > 0) + items.rocket.accel = newAccel; + } else if (key === Qt.Key_Right || key === Qt.Key_Left) { + if (items.mode === "simple") { + if (key === Qt.Key_Right && !event.isAutoRepeat && currentFuel > 0) { + items.rocket.leftAccel = leftRightAccel; + items.rocket.rightAccel = 0.0; + } else if (key === Qt.Key_Left && !event.isAutoRepeat && currentFuel > 0) { + items.rocket.rightAccel = leftRightAccel; + items.rocket.leftAccel = 0.0; + } + } else { // "rotation" + if (key === Qt.Key_Right) + items.rocket.rotation += 10; + else if (key === Qt.Key_Left) + items.rocket.rotation -= 10; + //console.log("XXX rotation=" + items.rocket.rotation + " bodyRot=" + items.rocket.body.rotation); + } + } else + event.accepted = false; +} + +function processKeyRelease(event) +{ + var key = event.key; + event.accepted = true; + //console.log("XXX release " + key + " = " + event.isAutoRepeat + " = " + Qt.Key_Right); + if (key===Qt.Key_1) { + items.rocket.explosion.show(); + } + if (key===Qt.Key_0) { + items.rocket.explosion.hide(); + } + + if (key === Qt.Key_Right && !event.isAutoRepeat) { + items.rocket.leftAccel = 0; + } else if (key === Qt.Key_Left && !event.isAutoRepeat) { + items.rocket.rightAccel = 0; + } else + event.accepted = false; +} + +function finishLevel(success) +{ + items.rocket.accel = 0; + items.rocket.leftAccel = 0; + items.rocket.rightAccel = 0; + items.rocket.body.linearVelocity = Qt.point(0,0) + if (success) + items.bonus.good("lion"); + else { + items.rocket.explosion.show(); + items.bonus.bad("lion"); + } +} + +function degToRad(degrees) { + return degrees * Math.PI / 180; +} diff --git a/src/activities/land_safe/land_safe.svg b/src/activities/land_safe/land_safe.svg new file mode 100644 index 000000000..5f9d3cf5c --- /dev/null +++ b/src/activities/land_safe/land_safe.svg @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Clipart by Nicu Buculei - piggybank + + + Nicu Buculei + + + + + image/svg+xml + + + + + + + + + diff --git a/src/activities/land_safe/resource/README b/src/activities/land_safe/resource/README new file mode 100644 index 000000000..5d1e9e279 --- /dev/null +++ b/src/activities/land_safe/resource/README @@ -0,0 +1,3 @@ +flames and crash.png taken from OpenClipart.org +rocket.png also taken from openclipart.org and modified according to requirement. +Last background image is from nasaimages.org diff --git a/src/activities/land_safe/resource/background1.jpg b/src/activities/land_safe/resource/background1.jpg new file mode 100644 index 000000000..373e0ea1b Binary files /dev/null and b/src/activities/land_safe/resource/background1.jpg differ diff --git a/src/activities/land_safe/resource/background2.jpg b/src/activities/land_safe/resource/background2.jpg new file mode 100644 index 000000000..b81248b48 Binary files /dev/null and b/src/activities/land_safe/resource/background2.jpg differ diff --git a/src/activities/land_safe/resource/background3.jpg b/src/activities/land_safe/resource/background3.jpg new file mode 100644 index 000000000..728fe2c30 Binary files /dev/null and b/src/activities/land_safe/resource/background3.jpg differ diff --git a/src/activities/land_safe/resource/background4.jpg b/src/activities/land_safe/resource/background4.jpg new file mode 100644 index 000000000..9e0f971c0 Binary files /dev/null and b/src/activities/land_safe/resource/background4.jpg differ diff --git a/src/activities/land_safe/resource/explosion.svg b/src/activities/land_safe/resource/explosion.svg new file mode 100644 index 000000000..6a9d84e1d --- /dev/null +++ b/src/activities/land_safe/resource/explosion.svg @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Openclipart + + + Explosion + 2010-04-08T21:41:28 + + https://openclipart.org/detail/40477/explosion-by-cybergedeon + + + dominiquechappard + + + + + burst + comic + explosion + fire + noise + noisy + onomatopoeia + sound + + + + + + + + + + + diff --git a/src/activities/land_safe/resource/land1.png b/src/activities/land_safe/resource/land1.png new file mode 100644 index 000000000..1a06b8938 Binary files /dev/null and b/src/activities/land_safe/resource/land1.png differ diff --git a/src/activities/land_safe/resource/land2.png b/src/activities/land_safe/resource/land2.png new file mode 100644 index 000000000..84733e88d Binary files /dev/null and b/src/activities/land_safe/resource/land2.png differ diff --git a/src/activities/land_safe/resource/land3.png b/src/activities/land_safe/resource/land3.png new file mode 100644 index 000000000..a69b0e8f2 Binary files /dev/null and b/src/activities/land_safe/resource/land3.png differ diff --git a/src/activities/land_safe/resource/land4.png b/src/activities/land_safe/resource/land4.png new file mode 100644 index 000000000..be138996f Binary files /dev/null and b/src/activities/land_safe/resource/land4.png differ diff --git a/src/activities/land_safe/resource/landing_area_green.png b/src/activities/land_safe/resource/landing_area_green.png new file mode 100644 index 000000000..05c9f486a Binary files /dev/null and b/src/activities/land_safe/resource/landing_area_green.png differ diff --git a/src/activities/land_safe/resource/landing_area_red.png b/src/activities/land_safe/resource/landing_area_red.png new file mode 100644 index 000000000..5b9b38fe4 Binary files /dev/null and b/src/activities/land_safe/resource/landing_area_red.png differ diff --git a/src/activities/land_safe/resource/landing_red.png b/src/activities/land_safe/resource/landing_red.png new file mode 100644 index 000000000..fd489c8bc Binary files /dev/null and b/src/activities/land_safe/resource/landing_red.png differ diff --git a/src/activities/land_safe/resource/rocket.png b/src/activities/land_safe/resource/rocket.png new file mode 100644 index 000000000..153dcbb77 Binary files /dev/null and b/src/activities/land_safe/resource/rocket.png differ diff --git a/src/activities/land_safe/resource/rocket.svg b/src/activities/land_safe/resource/rocket.svg new file mode 100644 index 000000000..a3b84a865 --- /dev/null +++ b/src/activities/land_safe/resource/rocket.svg @@ -0,0 +1,667 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +