File indexing completed on 2024-04-28 15:07:52

0001 /* GCompris - gravity.js
0002 *
0003 * SPDX-FileCopyrightText: 2020 Timothée Giet <animtim@gmail.com>
0004 *
0005 * Authors:
0006 *   Bruno Coudoin <bruno.coudoin@gcompris.net> and Matilda Bernard (GTK+ version)
0007 *   Siddhesh suthar <siddhesh.it@gmail.com> (Qt Quick port)
0008 *   Timothée Giet <animtim@gmail.com> (complete activity rewrite)
0009 *
0010 *   SPDX-License-Identifier: GPL-3.0-or-later
0011 */
0012 .pragma library
0013 .import QtQuick 2.12 as Quick
0014 .import "qrc:/gcompris/src/core/core.js" as Core
0015 
0016 var url = "qrc:/gcompris/src/activities/gravity/resource/"
0017 
0018 var levels = [
0019             { // Level 1
0020                 planetFrequency: 12000,
0021                 planetCount: 5
0022             },
0023             { // Level 2
0024                 planetFrequency: 10000,
0025                 planetCount: 10
0026             },
0027             { // Level 3
0028                 planetFrequency: 8000,
0029                 planetCount: 15
0030             },
0031             { // Level 4
0032                 planetFrequency: 7000,
0033                 planetCount: 20
0034             },
0035             { // Level 5
0036                 planetFrequency: 6000,
0037                 planetCount: 25
0038             },
0039             { // Level 6
0040                 planetFrequency: 5000,
0041                 planetCount: 30
0042             }
0043         ]
0044 
0045 var numberOfLevel = levels.length;
0046 var items;
0047 var message;
0048 
0049 // delta move
0050 var move = 0;
0051 // control move
0052 var controlMove = 0;
0053 // gravity of current planet
0054 var planetGravity = 0;
0055 // speed for key controls
0056 var controlSpeed = 0.2;
0057 
0058 var currentPlanet;
0059 var planetsCounter = 0;
0060 
0061 function start(items_,message_) {
0062     items = items_;
0063     items.currentLevel = Core.getInitialLevel(numberOfLevel);
0064     message = message_;
0065     initLevel();
0066 }
0067 
0068 function stop() {
0069     items.processTimer.stop();
0070     items.planetCreation.stop();
0071     destroyPlanet();
0072     planetsCounter = 0;
0073     controlMove = 0;
0074     move = 0;
0075 }
0076 
0077 function initLevel() {
0078     stop();
0079     items.planetFrequency = levels[items.currentLevel].planetFrequency;
0080     items.background.initSpace();
0081     items.explosion.hide();
0082     items.spaceship.opacity = 100;
0083     items.spaceshipX = items.background.width * 0.5;
0084     items.stationDown.stop();
0085     items.station.y = -items.station.height;
0086     controlSpeed = 0.2 * (items.currentLevel * 0.25 + 1);
0087     if(!items.startMessage) {
0088         items.processTimer.start();
0089         createPlanet();
0090         items.planetCreation.start();
0091         message.index = -1;
0092     } else {
0093         message.index = 0;
0094     }
0095 }
0096 
0097 function nextLevel() {
0098     items.currentLevel = Core.getNextLevel(items.currentLevel, numberOfLevel);
0099     initLevel();
0100 }
0101 
0102 function previousLevel() {
0103     items.currentLevel = Core.getPreviousLevel(items.currentLevel, numberOfLevel);
0104     initLevel();
0105 }
0106 
0107 function processKeyPress(event) {
0108     var key = event.key;
0109     event.accepted = true;
0110     if(key === Qt.Key_Left) {
0111         controlMove += -controlSpeed;
0112     } else if(key === Qt.Key_Right) {
0113         controlMove += controlSpeed;
0114     }
0115 }
0116 
0117 function processKeyRelease(event) {
0118     var key = event.key;
0119     event.accepted = true;
0120     if(key === Qt.Key_Left || key === Qt.Key_Right) {
0121         controlMove = 0;
0122     }
0123 }
0124 
0125 function createPlanet() {
0126     if(planetsCounter < levels[items.currentLevel].planetCount) {
0127         var planetSide = Math.floor( Math.random() * 2);  
0128         var planetSize = Math.max(Math.random() * items.maxPlanetSize, items.minPlanetSize);
0129         if(planetSide == 0) {
0130             currentPlanet = items.planet0;
0131         } else if(planetSide == 1) {
0132             currentPlanet = items.planet1;
0133         }
0134         currentPlanet.source = url + "planet" + Math.floor(Math.random() * 2) + ".webp";
0135         currentPlanet.fallDuration = levels[items.currentLevel].planetFrequency;
0136         currentPlanet.height = planetSize;
0137         currentPlanet.width = planetSize;
0138         currentPlanet.y = currentPlanet.height * -2;
0139         currentPlanet.visible = true;
0140         currentPlanet.startMoving();
0141         planetGravity = currentPlanet.leftSide ? -currentPlanet.width * 0.5: currentPlanet.width * 0.5;
0142         planetsCounter++;
0143     } else {
0144         items.stationDown.restart();
0145     }
0146 }
0147 
0148 function moveSpaceship() {
0149     // calculate gravity
0150     if(planetsCounter > 0) {
0151         // calculate distance between planet center and spaceship center
0152         var hypothenuse = Math.sqrt(
0153             Math.pow((currentPlanet.x + (currentPlanet.width * 0.5)) - items.spaceshipX, 2) +
0154             Math.pow((currentPlanet.y + (currentPlanet.height * 0.5)) - items.spaceshipY, 2));
0155         items.gravity = (planetGravity * (items.currentLevel * 0.33 + 1)) / Math.pow(hypothenuse, 2) * 100;
0156     } else {
0157         items.gravity = 0;
0158     }
0159     move += controlMove + (items.gravity);
0160     items.spaceshipX += move;
0161 
0162     // Check for crash
0163     computeOverlap();
0164 
0165     // Don't go out of the screen or stay stuck on the borders
0166     if(items.spaceshipX > items.background.width - items.borderMargin) {
0167         move = 0;
0168         controlMove = 0;
0169         items.spaceshipX -= 1;
0170     } else if(items.spaceshipX < items.borderMargin) {
0171         move = 0;
0172         controlMove = 0;
0173         items.spaceshipX += 1;
0174     }
0175 }
0176 
0177 function computeOverlap() {
0178     if(planetsCounter > 0) {
0179         // compute overlap with a little margin on the planets to not hit too much on corners
0180         var xOverlap = Math.min(items.spaceship.x + items.spaceship.width,
0181                                 currentPlanet.x + currentPlanet.width * 0.9) - 
0182                        Math.max(items.spaceship.x, currentPlanet.x + currentPlanet.width * 0.1);
0183         var yOverlap = Math.min(items.spaceship.y + items.spaceship.height,
0184                                 currentPlanet.y + currentPlanet.height * 0.9) - 
0185                        Math.max(items.spaceship.y, currentPlanet.y +
0186                                 currentPlanet.height * 0.1);
0187         // again add a safety margin to avoid hitting on corners
0188         if(xOverlap > items.spaceship.width * 0.2 && yOverlap > items.spaceship.height * 0.2) {
0189             crash();
0190             items.bonus.bad("lion");
0191         }
0192     }
0193 }
0194 
0195 function destroyPlanet() {
0196     planetGravity = 0;
0197     items.gravity = 0;
0198     if(planetsCounter > 0) {
0199         currentPlanet.visible = false;
0200     }
0201 }
0202 
0203 function crash() {
0204     items.audioEffects.play("qrc:/gcompris/src/core/resource/sounds/crash.wav");
0205     items.explosion.show();
0206     items.spaceship.hide();
0207     stop();
0208 }