File indexing completed on 2024-04-28 15:07:53
0001 /* GCompris - land_safe.js 0002 * 0003 * SPDX-FileCopyrightText: 2016 Holger Kaelberer <holger.k@elberer.de> 0004 * 0005 * Authors: 0006 * Matilda Bernard <serah4291@gmail.com> (GTK+ version) 0007 * Holger Kaelberer <holger.k@elberer.de> (Qt Quick port) 0008 * 0009 * SPDX-License-Identifier: GPL-3.0-or-later 0010 */ 0011 0012 /* ToDo: 0013 * - check for shader availability 0014 * - test more generic on-screen controls 0015 * (- use polygon fixture for rocket) 0016 * 0017 * Some gravitational forces: 0018 * !- Ceres 0,27 0019 * !- Pluto: 0,62 m/s² 0020 * !- Titan: 1,352 m/s² 0021 * - Ganymed: 1,428 0022 * !- Moon: 1,622 m/s² 0023 * - Io: 1,796 m/s² 0024 * !- Mars: 3,711 m/s² 0025 * - Merkur: 3,7 m/s² 0026 * !- Venus: 8,87 m/s² 0027 * !- Earth: 9,807 m/s² 0028 * - Jupiter: 24,79 m/s² 0029 */ 0030 0031 .pragma library 0032 .import QtQuick 2.12 as Quick 0033 .import GCompris 1.0 as GCompris 0034 .import "qrc:/gcompris/src/core/core.js" as Core 0035 0036 var levels; 0037 var numberOfLevel; 0038 var items = null; 0039 var baseUrl = "qrc:/gcompris/src/activities/land_safe/resource"; 0040 var startingAltitudeReal = 100.0; 0041 var startingOffsetPx = 10; // y-value for setting rocket initially 0042 var maxLandingVelocity = 10; 0043 var leftRightAccel = 0.1; // accel force set on horizontal accel 0044 //var minAccel = 0.1; 0045 var maxAccel = 0.15; 0046 var accelSteps = 3; 0047 var dAccel = maxAccel / accelSteps;//- minAccel; 0048 var barAtStart; 0049 var maxFuel = 100.0; 0050 var currentFuel = 0.0; 0051 var lastLevel = -1; 0052 var debugDraw = false; 0053 var zoomStack = new Array; 0054 0055 function start(items_) { 0056 items = items_; 0057 lastLevel = -1; 0058 levels = items_.levels; 0059 numberOfLevel = levels.length; 0060 items.currentLevel = Core.getInitialLevel(numberOfLevel); 0061 0062 barAtStart = GCompris.ApplicationSettings.isBarHidden; 0063 GCompris.ApplicationSettings.isBarHidden = true; 0064 initLevel(); 0065 } 0066 0067 function stop() { 0068 GCompris.ApplicationSettings.isBarHidden = barAtStart; 0069 } 0070 0071 function initLevel() { 0072 if (items === null) 0073 return; 0074 0075 0076 items.zoom = 1; 0077 zoomStack = []; 0078 // init level: 0079 items.accelerometer.min = -levels[items.currentLevel].gravity; 0080 items.accelerometer.max = levels[items.currentLevel].maxAccel*10-levels[items.currentLevel].gravity; 0081 maxAccel = levels[items.currentLevel].maxAccel; 0082 accelSteps = levels[items.currentLevel].accelSteps; 0083 dAccel = maxAccel / accelSteps;//- minAccel; 0084 startingAltitudeReal = levels[items.currentLevel].alt; 0085 items.gravity = levels[items.currentLevel].gravity; 0086 items.mode = levels[items.currentLevel].mode; 0087 maxFuel = levels[items.currentLevel].fuel; 0088 currentFuel = (maxFuel == -1 ? 1 : maxFuel); // -1 means unlimited fuel 0089 0090 // reset everything: 0091 items.explosion.hide(); 0092 items.rocket.show(); 0093 // place rocket randomly: 0094 var max = items.background.width - items.accelerometer.width - items.landing.width - items.rocket.width; 0095 var min = 20; 0096 items.rocket.x = Math.random() * (max- min) + min; 0097 items.rocket.y = startingOffsetPx; 0098 items.rocket.rotation = 0; 0099 items.rocket.accel = 0; 0100 items.rocket.leftAccel = 0; 0101 items.rocket.rightAccel = 0; 0102 items.rocket.body.linearVelocity = Qt.point(0,0) 0103 // for landing random placement shall not intersect with bar -- or osd 0104 // controls on mobile: 0105 min = items.onScreenControls ? items.leftRightControl.width : items.bar.fullButton * items.bar.barZoom; 0106 max = items.onScreenControls ? items.background.width - items.upDownControl.width - items.landing.width : max; 0107 items.landing.anchors.leftMargin = Math.random() * (max- min) + min; 0108 items.landing.overlayColor = "-g"; 0109 items.leftEngine.reset(); 0110 items.rightEngine.reset(); 0111 items.bottomEngine.reset(); 0112 0113 // initialize world: 0114 items.world.pixelsPerMeter = pxYToAltitude(items.rocket.y) / startingAltitudeReal; 0115 items.world.gravity = Qt.point(0, items.gravity) 0116 items.world.running = false; 0117 0118 // console.log("Starting level (surfaceOff=" + items.ground.surfaceOffset + ", ppm=" + items.world.pixelsPerMeter + ")"); 0119 0120 if (levels[items.currentLevel].intro !== undefined) { 0121 items.ok.visible = false; 0122 items.intro.intro = [levels[items.currentLevel].intro]; 0123 items.intro.index = 0; 0124 } else { 0125 // go 0126 items.intro.intro = []; 0127 items.intro.index = -1; 0128 items.ok.visible = true; 0129 } 0130 lastLevel = items.currentLevel; 0131 } 0132 0133 function pxAltitudeToY(alt) 0134 { 0135 var y = items.background.height - items.ground.height + items.ground.surfaceOffset 0136 - items.rocket.height - 1 - alt; 0137 return y; 0138 } 0139 0140 function pxYToAltitude(y) 0141 { 0142 var altPx = items.background.height - items.ground.height + items.ground.surfaceOffset 0143 - y - items.rocket.height 0144 - 1; // landing is 1 pixel above ground surface 0145 return altPx; 0146 } 0147 0148 // calc real height of rocket in meters above surface 0149 function getAltitudeReal() 0150 { 0151 var altPx = pxYToAltitude(items.rocket.y); 0152 var altReal = altPx / items.world.pixelsPerMeter; 0153 return altReal; 0154 } 0155 0156 function nextLevel() { 0157 items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel); 0158 initLevel(); 0159 } 0160 0161 function previousLevel() { 0162 items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel); 0163 initLevel(); 0164 } 0165 0166 function processKeyPress(event) 0167 { 0168 var key = event.key; 0169 event.accepted = true; 0170 if(!items.world.running) { 0171 if(key === Qt.Key_Enter || key === Qt.Key_Return || key == Qt.Key_Space) 0172 items.ok.clicked(); 0173 else 0174 return; 0175 } 0176 0177 if(items.bonus.isPlaying) { 0178 return; 0179 } 0180 var newAccel = 0; 0181 if(key === Qt.Key_Up || key === Qt.Key_Down) { 0182 if (key === Qt.Key_Up) { 0183 if(items.rocket.accel === 0) 0184 newAccel = dAccel; 0185 else 0186 newAccel = items.rocket.accel + dAccel; 0187 } else if(key === Qt.Key_Down) 0188 newAccel = items.rocket.accel - dAccel; 0189 0190 if (newAccel < 0) 0191 newAccel = 0; 0192 if (newAccel > maxAccel) 0193 newAccel = maxAccel; 0194 0195 if(newAccel !== items.rocket.accel && currentFuel > 0) 0196 items.rocket.accel = newAccel; 0197 } else if(key === Qt.Key_Right || key === Qt.Key_Left) { 0198 if (items.mode === "simple") { 0199 if(key === Qt.Key_Right && !event.isAutoRepeat && currentFuel > 0) { 0200 items.rocket.leftAccel = leftRightAccel; 0201 items.rocket.rightAccel = 0.0; 0202 } else if(key === Qt.Key_Left && !event.isAutoRepeat && currentFuel > 0) { 0203 items.rocket.rightAccel = leftRightAccel; 0204 items.rocket.leftAccel = 0.0; 0205 } 0206 } else { // "rotation" 0207 if(key === Qt.Key_Right) 0208 items.rocket.rotation += 10; 0209 else if(key === Qt.Key_Left) 0210 items.rocket.rotation -= 10; 0211 //console.log("XXX rotation=" + items.rocket.rotation + " bodyRot=" + items.rocket.body.rotation); 0212 } 0213 } 0214 } 0215 0216 function processKeyRelease(event) 0217 { 0218 if (!items.world.running) { 0219 event.accepted = false; 0220 return; 0221 } 0222 if(items.bonus.isPlaying) { 0223 event.accepted = false; 0224 return; 0225 } 0226 0227 var key = event.key; 0228 event.accepted = true; 0229 //console.log("XXX release " + key + " = " + event.isAutoRepeat + " = " + Qt.Key_Right); 0230 if (key === Qt.Key_Right && !event.isAutoRepeat) { 0231 items.rocket.leftAccel = 0; 0232 } else if (key === Qt.Key_Left && !event.isAutoRepeat) { 0233 items.rocket.rightAccel = 0; 0234 } else 0235 event.accepted = false; 0236 } 0237 0238 function finishLevel(success) 0239 { 0240 items.rocket.accel = 0; 0241 if (success) { 0242 items.rocket.leftAccel = 0; 0243 items.rocket.rightAccel = 0; 0244 items.rocket.body.linearVelocity = Qt.point(0,0) 0245 0246 items.bonus.good("lion"); 0247 } else { 0248 // don't reset physics on a crash so the explosion rolls along landscape. 0249 0250 items.explosion.show(); 0251 items.rocket.hide(); 0252 items.bonus.bad("lion"); 0253 } 0254 } 0255 0256 function degToRad(degrees) { 0257 return degrees * Math.PI / 180; 0258 } 0259 0260 //note: using 0 with transparent font color instead of space to keep consistent spacing 0261 //simple function for the fuel and altitude values 0262 function minimum3Chars(number_) { 0263 var numberTxt = number_.toString(); 0264 if(number_ < 100 && number_ >= 10) 0265 numberTxt = "<font color=\"#00FFFFFF\">0</font>" + numberTxt; 0266 else if(number_ < 10) 0267 numberTxt = "<font color=\"#00FFFFFF\">00</font>" + numberTxt; 0268 return numberTxt; 0269 } 0270 0271 //function for the velocity and acceleration values 0272 function fixedSizeString(number_, multiplier_, chars_, emptyDecimal_) { 0273 var numberRound = Math.round(number_ * multiplier_) / multiplier_; 0274 var numberTxt = numberRound.toString(); 0275 if(numberRound % 1 === 0) 0276 numberTxt = numberTxt + emptyDecimal_; 0277 var charsToAdd = chars_ - numberTxt.length; 0278 if(numberRound >= 0) { 0279 numberTxt = "<font color=\"#00FFFFFF\">-</font>" + numberTxt; 0280 charsToAdd--; 0281 } 0282 for(; charsToAdd > 0; charsToAdd--) 0283 numberTxt = "<font color=\"#00FFFFFF\">0</font>" + numberTxt; 0284 return numberTxt; 0285 }