Warning, /games/kbreakout/src/qml/main.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2012 Viranch Mehta <viranch.mehta@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 import QtQuick 2.3
0008 import org.kde.games.core 0.1 as KgCore
0009 import "globals.js" as Globals
0010 import "logic.js" as Logic
0011 
0012 Item {
0013     id: canvas
0014 
0015     signal levelComplete()
0016     signal gameEnded(int score, int level, int elapsedTime)
0017     signal mousePressed()
0018 
0019     property real speed
0020     property bool paused: false
0021     property bool gameOver: false
0022     property bool gameWon: false
0023     readonly property Item jailItem: bgOverlay
0024     readonly property bool ballMoving: !paused && fireBallMessage.opacity !== 1
0025 
0026     function updateGeometry() {
0027         var bw = Globals.BRICK_WIDTH*Globals.WIDTH + 1;
0028         // bh = (overlayHeight = BRICK_HEIGHT*HEIGHT+1)
0029         //     +(headerItemsHeight = BRICK_HEIGHT*1.5)
0030         //     +(margin = headerItemHeight*0.2)
0031         var bh = Globals.BRICK_HEIGHT*Globals.HEIGHT + 1 + Globals.BRICK_HEIGHT*1.5*1.2;
0032 
0033         var w = canvas.height*bw/bh;
0034         var h = canvas.width*bh/bw;
0035 
0036         if (w > canvas.width) {
0037             container.width = canvas.width-20;
0038             container.height = container.width*bh/bw;
0039         } else if (h > canvas.height) {
0040             container.height = canvas.height-50;
0041             container.width = container.height*bw/bh;
0042         } else {
0043             // Never happens, don't know what to do in case it does!
0044         }
0045     }
0046 
0047     property real m_scale: container.width/(Globals.BRICK_WIDTH*Globals.WIDTH)
0048 
0049     CanvasItem {
0050         id: background
0051         spriteKey: "Background"
0052         anchors.fill: parent
0053     }
0054 
0055     Item {
0056         id: container
0057         anchors.centerIn: parent
0058     }
0059 
0060     property int barCenter: mapFromItem(bgOverlay, Math.round(bar.x + bar.width/2), 0).x
0061 
0062     CanvasItem {
0063         id: bgOverlay
0064         spriteKey: "BackgroundOverlay"
0065         anchors {
0066             left: container.left
0067             bottom: container.bottom
0068         }
0069         width: m_scale * (Globals.BRICK_WIDTH*Globals.WIDTH + 1)
0070         height: m_scale * (Globals.BRICK_HEIGHT*Globals.HEIGHT + 1)
0071 
0072         Bar {
0073             id: bar
0074             anchors {
0075                 bottom: parent.bottom
0076             }
0077             posX: 300
0078         }
0079     }
0080 
0081     Rectangle {
0082         id: pauseOverlay
0083         anchors.fill: parent
0084         color: "#646464"
0085         opacity: paused ? 0.6 : 0
0086         z: 1 // to show above all the elements (except messageBox)
0087 
0088         Behavior on opacity { NumberAnimation { duration: 100 } }
0089     }
0090     function setGamePaused(paused) {
0091         Logic.setGamePaused(paused);
0092     }
0093 
0094     TextItem {
0095         id: messageBox
0096         anchors.centerIn: bgOverlay
0097         z: 2 // to make it display above the pause overlay
0098         width: m_scale * Globals.BRICK_WIDTH*9
0099         height: m_scale * Globals.BRICK_HEIGHT*5
0100         opacity: 0
0101 
0102         Behavior on opacity { NumberAnimation { duration: 100 } }
0103     }
0104 
0105     property string fireShortcut: "Space"
0106     TextItem {
0107         id: fireBallMessage
0108         anchors {
0109             horizontalCenter: bgOverlay.horizontalCenter
0110             bottom: bgOverlay.bottom
0111             bottomMargin: (bgOverlay.height-height)/4
0112         }
0113         width: m_scale * Globals.BRICK_WIDTH*9
0114         height: m_scale * Globals.BRICK_HEIGHT*2
0115         text: i18n("Press %1 to fire the ball", fireShortcut)
0116         opacity: 0
0117 
0118         Behavior on opacity { NumberAnimation { duration: 100 } }
0119     }
0120 
0121     property int score
0122     TextItem {
0123         id: scoreDisplay
0124         width: m_scale * (Globals.BRICK_WIDTH*Globals.WIDTH)/6
0125         height: m_scale * Globals.BRICK_HEIGHT*1.5
0126         anchors {
0127             left: bgOverlay.left
0128             bottom: bgOverlay.top
0129             bottomMargin: height/5
0130         }
0131         text: Logic.scoreString(parent.score)
0132     }
0133 
0134     property int level
0135     TextItem {
0136         id: levelDisplay
0137         width: m_scale * (Globals.BRICK_WIDTH*Globals.WIDTH)/5
0138         height: m_scale * Globals.BRICK_HEIGHT*1.5
0139         anchors {
0140             left: scoreDisplay.right
0141             leftMargin: width-scoreDisplay.width
0142             bottom: bgOverlay.top
0143             bottomMargin: height/5
0144         }
0145         text: i18n("Level %1", parent.level)
0146     }
0147 
0148     property int lives
0149     Row {
0150         id: lifeBars
0151         spacing: m_scale * Globals.BRICK_WIDTH*0.23
0152         anchors {
0153             right: bgOverlay.right
0154             rightMargin: 20
0155             bottom: bgOverlay.top
0156             bottomMargin: levelDisplay.height/5
0157         }
0158 
0159         Repeater {
0160             model: canvas.lives
0161             Bar {
0162                 width: m_scale * Globals.BRICK_WIDTH/1.3
0163                 height: m_scale * Globals.BRICK_HEIGHT/1.3
0164             }
0165         }
0166     }
0167 
0168     function reset() {
0169         Logic.reset();
0170     }
0171 
0172     function loadLine(line, lineNumber) {
0173         Logic.showLine(line, lineNumber);
0174     }
0175 
0176     function loadGift(gift, times, pos) {
0177         Logic.putGift(gift, times, pos);
0178     }
0179 
0180     function updateBarDirection(direction) {
0181         bar.direction = direction;
0182     }
0183 
0184     function startGame() {
0185         Logic.startLevel();
0186     }
0187 
0188     Timer {
0189         id: gameTimer
0190         interval: Globals.REPAINT_INTERVAL
0191         repeat: true
0192         onTriggered: {
0193             for (x = 0; x < Logic.substeps; ++x) {
0194                 Logic.moveBalls()
0195                 Logic.detectCollisions()
0196             }
0197         }
0198     }
0199 
0200     Timer {
0201         id: elapsedTimeTimer
0202         interval: 1000
0203         repeat: true
0204         property int elapsedTime: 0
0205         onTriggered: elapsedTime++;
0206     }
0207 
0208     Timer {
0209         id: handleDeathTimer
0210         interval: 1000
0211         onTriggered: Logic.handleDeath()
0212     }
0213 
0214     // hides the current showed message by target
0215     // unless the game is paused, won or game over
0216     Timer {
0217         id: hideTimer
0218         property variant target
0219         onTriggered: {
0220             if (paused) return;
0221             target.opacity = 0;
0222         }
0223     }
0224 
0225     function fire() {
0226         Logic.fireBall();
0227     }
0228 
0229     function cheatAddLife() {
0230         Logic.addLife();
0231     }
0232 
0233     function cheatSkipLevel() {
0234         Logic.loadNextLevel();
0235     }
0236 
0237     Timer {
0238         id: burnBricksTimer
0239         property variant target
0240         interval: Globals.BURNING_SPEED
0241         onTriggered: Logic.burnNearbyBricks(target);
0242     }
0243 
0244     MouseArea {
0245         id: mouseArea
0246         enabled: false
0247         anchors.fill: parent
0248         hoverEnabled: true
0249         onPositionChanged: mouse => {
0250             if (paused) return;
0251 
0252             // avoids accidentally moving the mouse while playing using the keys
0253             if (bar.direction != 0) return;
0254 
0255             var barX = canvas.mapToItem(bgOverlay, mouse.x, 0).x - bar.width/2;
0256             bar.moveTo(barX/m_scale);
0257         }
0258         onClicked: canvas.mousePressed()
0259     }
0260 
0261     Item {
0262         id: keyEventHandler
0263         focus: true
0264         anchors.fill: parent
0265         Keys.onPressed: event => {
0266             if (event.key == Qt.Key_Right) {
0267                 updateBarDirection(1);
0268             } else if (event.key == Qt.Key_Left) {
0269                 updateBarDirection(-1);
0270             }
0271         }
0272 
0273         Keys.onReleased: event => {
0274             if (event.key == Qt.Key_Right || event.key == Qt.Key_Left) {
0275                 updateBarDirection(0);
0276             }
0277         }
0278     }
0279 }