diff --git a/src/activities/land_safe/LandSafe.qml b/src/activities/land_safe/LandSafe.qml index ab70fe816..622401f81 100644 --- a/src/activities/land_safe/LandSafe.qml +++ b/src/activities/land_safe/LandSafe.qml @@ -1,714 +1,723 @@ /* 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 QtGraphicalEffects 1.0 import "../../core" import "land_safe.js" as Activity ActivityBase { id: activity property bool inForeground: false // to avoid unneeded reconfigurations onStart: { inForeground = true; focus = true; } onStop: inForeground = false; Keys.onPressed: Activity.processKeyPress(event) Keys.onReleased: Activity.processKeyRelease(event) onWidthChanged: if (inForeground) Activity.initLevel(); onHeightChanged: if (inForeground) Activity.initLevel(); pageComponent: Image { id: background source: Activity.baseUrl + "/background4.jpg"; anchors.centerIn: parent anchors.fill: parent fillMode: Image.PreserveAspectCrop 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 intro: intro property alias ok: ok property alias leftRightControl: leftRightControl property alias upDownControl: upDownControl property alias accelerometer: accelerometer 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 velocity: 0.0 property double altitude: 0.0 property double fuel: 0.0 property double lastVelocity: 0.0 property double gravity: 0.0 property double scale: background.height / 400 property bool onScreenControls: /* items.world.running && */ ApplicationInfo.isMobile } onStart: { Activity.start(items) } onStop: { Activity.stop() } World { id: physicsWorld running: false; gravity: Qt.point(0, items.gravity) 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 = items.velocity; items.velocity = rocket.body.linearVelocity.y; if (rocket.body.linearVelocity.y > Activity.maxLandingVelocity) - landing.source = Activity.baseUrl + "/landing_red.png"; + landing.overlayColor = "#80ff0000" // redish + else if (rocket.body.linearVelocity.y > Activity.maxLandingVelocity - 2) + landing.overlayColor = "#80ffff00" // yellowish else - landing.source = Activity.baseUrl + "/landing_green.png"; - + landing.overlayColor = "#8000ff00" // greenish items.altitude = 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); items.fuel = Math.round(Activity.currentFuel / Activity.maxFuel * 100); if (Activity.currentFuel === 0) // fuel consumed: items.rocket.accel = items.rocket.leftAccel = items.rocket.rightAccel = 0; } } MouseArea { id: mouse anchors.fill: parent onClicked: debugDraw.visible = !debugDraw.visible; enabled: Activity.debugDraw } // 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 } } } 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: items.scale * 28// * 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 // decompose a force/acceleration vector v using angle into x/y components function decomposeVector(v, angle) { return Qt.point(v * Math.sin(Activity.degToRad(angle)), // x-component v * Math.cos(Activity.degToRad(items.rocket.rotation))); // y-component } // map acceleration to box2d forces applying appropriate factors: function applyForces() { var totForce = (accel / 0.5 * 5) var v; if (items.mode === "simple") v = Qt.point((leftAccel-rightAccel) * 10 /* base of 10 m/s^2 */ * 5, /* factor to make movement smooth */ -totForce ); else { // "rotation" v = decomposeVector(totForce, rotation); v.y = -v.y; } v.x *= items.rocket.body.getMass(); v.y *= items.rocket.body.getMass(); physicsWorld.clearForces(); items.rocket.body.applyForceToCenter(v); // console.log("XXX rocket.acc=" + rocket.accel + " acc.current=" + items.accelerometer.current + " bottomMargin=" + items.accelerometer.currentRect.bottomMargin); } 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) 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 * items.scale / 1.9 : 0 // 50 lifeSpan: rocket.leftAccel > 0 ? 600 * items.scale / 1.9 : 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 * items.scale / 1.9 : 0 // 50 lifeSpan: rocket.rightAccel > 0 ? 600 * items.scale / 1.9 : 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 ? (80 + 60 * rocket.accel) : 0 // 75-150 lifeSpan: (700 + 450 * rocket.accel) * items.scale / 2.5 // 500 - 1000 size: rocket.width/1.8 + 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 + property alias overlayColor: overlay.color z: 2 - source: Activity.baseUrl + "/landing_green.png"; + source: Activity.baseUrl + "/landing.png"; anchors.left: ground.left anchors.leftMargin: 270 anchors.top: ground.top anchors.topMargin: ground.surfaceOffset - height sourceSize.width: 1024 width: 66 * items.scale height: width / 116 * 34 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 } } + ColorOverlay { + id: overlay + anchors.fill: landing + source: landing + } } Item { id: osdWrapper anchors.right: background.right anchors.rightMargin: 10 * ApplicationInfo.ratio anchors.bottom: upDownControl.bottom anchors.bottomMargin: -(planetText.height + gravityText.height + 20 * ApplicationInfo.ratio) width: 200 height: background.height z: 2 GCText { id: fuelText anchors.right: parent.right anchors.bottom: altitudeText.top anchors.bottomMargin: 10 color: "white" fontSize: tinySize horizontalAlignment: Text.AlignRight text: qsTr("Fuel: %1").arg(items.fuel) } GCText { id: altitudeText anchors.right: parent.right anchors.bottom: velocityText.top anchors.bottomMargin: 10 color: "white" fontSize: tinySize horizontalAlignment: Text.AlignRight text: qsTr("Altitude: %1").arg(items.altitude) } GCText { id: velocityText anchors.right: parent.right // anchors.rightMargin: 10 * ApplicationInfo.ratio anchors.bottom: accelText.top anchors.bottomMargin: 10 color: "white" fontSize: tinySize horizontalAlignment: Text.AlignRight text: qsTr("Velocity: %1").arg(Math.round(items.velocity * 10) / 10) } GCText { id: accelText anchors.bottom: accelerometer.top anchors.bottomMargin: 10 * ApplicationInfo.ratio anchors.right: parent.right fontSize: tinySize // width: 50 // height: 50 color: "white" horizontalAlignment: Text.AlignRight text: qsTr("Acceleration: %1").arg(Math.round(accelerometer.current * 100) / 100) } Accelerometer { id: accelerometer current: rocket.decomposeVector(rocket.accel, rocket.rotation).y * 10 - items.gravity anchors.right: parent.right anchors.bottom: gravityText.top anchors.bottomMargin: 10 * ApplicationInfo.ratio // anchors.bottom: upDownControl.bottom // anchors.bottomMargin: upDownControl.bottomMargin width: 15 + 3 * items.scale * ApplicationInfo.ratio height: background.height / 2.5 z: 2 // on top of rocket and ground opacity: 1 } GCText { id: gravityText anchors.bottom: planetText.top anchors.bottomMargin: 10 * ApplicationInfo.ratio anchors.right: parent.right horizontalAlignment: Text.AlignRight fontSize: tinySize color: "white" text: qsTr("Gravity: %1").arg(Math.round(items.gravity * 100) / 100); } GCText { id: planetText anchors.right: parent.right anchors.bottom: parent.bottom color: "white" fontSize: tinySize horizontalAlignment: Text.AlignRight text: qsTr("Planet: ") + Activity.levels[Activity.currentLevel].planet } } Column { id: upDownControl anchors.right: background.right anchors.rightMargin: accelerometer.width anchors.bottom: bar.top anchors.bottomMargin: 10 * ApplicationInfo.ratio width: upButton.width + 20 * ApplicationInfo.ratio height: upButton.height + downButton.height + 20 * ApplicationInfo.ratio visible: items.onScreenControls z: 19 // below intro, above the rest opacity: 0.4 spacing: 10 * ApplicationInfo.ratio ControlButton { id: upButton source: Activity.baseUrl + "/arrow_up.svg" onPressed: Activity.processKeyPress({key: Qt.Key_Up}); } ControlButton { id: downButton source: Activity.baseUrl + "/arrow_down.svg" onPressed: Activity.processKeyPress({key: Qt.Key_Down}); } } Row { id: leftRightControl anchors.left: parent.left anchors.leftMargin: 10 * ApplicationInfo.ratio anchors.bottom: bar.top anchors.bottomMargin: 10 * ApplicationInfo.ratio width: leftButton.width + rightButton.width + 20 * ApplicationInfo.ratio height: leftButton.height + 10 * ApplicationInfo.ratio visible: items.onScreenControls z: 19 // below intro, on top of the rest opacity: 0.4 spacing: 10 * ApplicationInfo.ratio ControlButton { id: leftButton source: Activity.baseUrl + "/arrow_left.svg" onPressed: Activity.processKeyPress({key: Qt.Key_Left}); onReleased: Activity.processKeyRelease({key: Qt.Key_Left}); } ControlButton { id: rightButton source: Activity.baseUrl + "/arrow_right.svg" onPressed: Activity.processKeyPress({key: Qt.Key_Right}); onReleased: Activity.processKeyRelease({key: Qt.Key_Right}); } } DebugDraw { id: debugDraw world: physicsWorld visible: false z: 1 } DialogHelp { id: dialogHelp onClose: home() } Bar { id: bar content: BarEnumContent { value: help | home | level } onHelpClicked: { Activity.initLevel(); displayDialog(dialogHelp); } onPreviousLevelClicked: Activity.previousLevel() onNextLevelClicked: Activity.nextLevel() onHomeClicked: activity.home() } Bonus { id: bonus Component.onCompleted: { loose.connect(Activity.initLevel); win.connect(Activity.nextLevel) } } IntroMessage { id: intro onIntroDone: { items.world.running = true; } intro: [ Activity.introText1 ] z: 20 anchors { top: parent.top topMargin: 10 right: parent.right rightMargin: 5 left: parent.left leftMargin: 5 } } BarButton { id: ok source: "qrc:/gcompris/src/core/resource/bar_ok.svg"; sourceSize.width: 75 * ApplicationInfo.ratio visible: false anchors.centerIn: background onClicked: { visible = false; items.world.running = true; } } } } diff --git a/src/activities/land_safe/land_safe.js b/src/activities/land_safe/land_safe.js index 88b352a60..84c5ae52d 100644 --- a/src/activities/land_safe/land_safe.js +++ b/src/activities/land_safe/land_safe.js @@ -1,291 +1,291 @@ /* 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! * - check for shader availability * - reduce difficulty: no fuel limits at lower levels * - on-screen buttons smaller with bigger MouseArea * - test more generic on-screen controls * - no left/right borders * (- use polygon fixture for rocket) * * Some 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 introTextSimple = qsTr("Use the up and down keys to control the thrust." + "
Use the right and left keys to control direction." + "
You must drive Tux's ship towards the landing platform." + "
The landing platform turns green when the velocity is safe to land.") var introTextRotate = qsTr("The up and down keys control the thrust of the rear engine." + "
The right and left keys now control the rotation of the ship." + "
To move the ship in horizontal direction you must first rotate and then accelerate it.") var currentLevel = 0; var numberOfLevel; var items = null; var baseUrl = "qrc:/gcompris/src/activities/land_safe/resource"; var startingHeightReal = 100.0; var startingOffsetPx = 10; // y-value for setting rocket initially 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; var lastLevel = -1; var debugDraw = false; 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() { if (items === null) return; items.bar.level = currentLevel + 1 // init level: items.accelerometer.min = -levels[currentLevel].gravity; items.accelerometer.max = levels[currentLevel].maxAccel*10-levels[currentLevel].gravity; maxAccel = levels[currentLevel].maxAccel; accelSteps = levels[currentLevel].accelSteps; dAccel = maxAccel / accelSteps;//- minAccel; startingHeightReal = levels[currentLevel].alt; items.gravity = levels[currentLevel].gravity; items.mode = levels[currentLevel].mode; maxFuel = currentFuel = levels[currentLevel].fuel; // reset everything: items.rocket.explosion.hide(); // place rocket randomly: var max = items.background.width - items.accelerometer.width - items.landing.width - items.rocket.width; var min = 20; 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) // for landing random placement shall not intersect with bar -- or osd // controls on mobile: min = items.onScreenControls ? items.leftRightControl.width : items.bar.fullButton * items.bar.barZoom; max = items.onScreenControls ? items.background.width - items.upDownControl.width - items.landing.width : max; items.landing.anchors.leftMargin = Math.random() * (max- min) + min; - items.landing.source = baseUrl + "/landing_green.png"; + items.landing.overlayColor = "#8000ff00"; // initialize world: items.world.pixelsPerMeter = getHeightPx() / startingHeightReal; items.world.gravity = Qt.point(0, items.gravity) items.world.running = false; // console.log("Starting level (surfaceOff=" + items.ground.surfaceOffset + ", ppm=" + items.world.pixelsPerMeter + ")"); if (currentLevel === 0 && lastLevel !== 0) { items.ok.visible = false; items.intro.intro = [introTextSimple]; items.intro.index = 0; } else if (currentLevel === 5 && lastLevel !== 0) { items.ok.visible = false; items.intro.intro = [introTextRotate]; items.intro.index = 0; } else { // go items.intro.index = -1; items.ok.visible = true; } lastLevel = currentLevel; } 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) { if (!items.world.running) { event.accepted = false; return; } 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) { if (!items.world.running) { event.accepted = false; return; } var key = event.key; event.accepted = true; //console.log("XXX release " + key + " = " + event.isAutoRepeat + " = " + Qt.Key_Right); 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/resource/landing.png b/src/activities/land_safe/resource/landing.png new file mode 100644 index 000000000..57b363cb7 Binary files /dev/null and b/src/activities/land_safe/resource/landing.png differ diff --git a/src/activities/land_safe/resource/landing_green.png b/src/activities/land_safe/resource/landing_green.png deleted file mode 100644 index cf3931ee8..000000000 Binary files a/src/activities/land_safe/resource/landing_green.png and /dev/null differ diff --git a/src/activities/land_safe/resource/landing_red.png b/src/activities/land_safe/resource/landing_red.png deleted file mode 100644 index fd489c8bc..000000000 Binary files a/src/activities/land_safe/resource/landing_red.png and /dev/null differ