File indexing completed on 2024-04-28 04:02:03
0001 /* 0002 SPDX-FileCopyrightText: 2012 Viranch Mehta <viranch.mehta@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 var ballComponent = Qt.createComponent("Ball.qml"); 0008 var balls = new Array; 0009 var brickComponent = Qt.createComponent("Brick.qml"); 0010 var bricks = new Array; 0011 var giftComponent = Qt.createComponent("Gift.qml"); 0012 var gifts = new Array; 0013 // score to add if you hit a brick 0014 // decreases over time since last hit 0015 var dScore; 0016 // count of remaining bricks 0017 // (not counting the unbreakable ones) 0018 var remainingBricks=0; 0019 var tick = 0; 0020 var repaintInterval; 0021 var randomCounter = 0; 0022 // is set to true when deleteMovingObjects() is called 0023 var itemsGotDeleted; 0024 var singleShotComponent = Qt.createComponent("Singleshot.qml"); 0025 0026 // Substeps are used to avoid that the ball is moved too far in a single update, 0027 // possibly leading to buggy behavior. The movement is divided into multiple 0028 // substeps and collisions are detected after each substep. 0029 var substeps = 1; 0030 0031 function remove(array, object) { 0032 array.splice(array.indexOf(object), 1); 0033 } 0034 0035 function singleShot(interval, slot, target) { 0036 var timer = singleShotComponent.createObject(canvas); 0037 timer.interval = interval; 0038 timer.target = target; 0039 timer.timeout.connect(slot); 0040 timer.start(); 0041 } 0042 0043 function scoreString(score) { 0044 var absScore = Math.abs(score); 0045 var str = absScore.toString().split(""); 0046 0047 // insert spaces every 3 characters 0048 var start = str.length%3; 0049 if (start==0) start=3; 0050 for (; start<str.length; start+=4) { 0051 str.splice(start, 0, " "); 0052 } 0053 0054 // join the array 0055 var displayString = score<0 ? "-" : ""; 0056 for (var i in str) { 0057 displayString += str[i]; 0058 } 0059 return displayString; 0060 } 0061 0062 function reset() { 0063 level = 0; 0064 score = 0; 0065 resetBricks(); 0066 bar.reset(); 0067 gameOver = false; 0068 gameWon = false; 0069 deleteMovingObjects(); 0070 paused = false; 0071 lives = Globals.INITIAL_LIVES; 0072 mouseArea.enabled = true; 0073 } 0074 0075 function resetBricks() { 0076 for (var i in bricks) { 0077 bricks[i].destroy(); 0078 } 0079 bricks = new Array; 0080 remainingBricks = 0; 0081 } 0082 0083 function getTypeFromChar(type) 0084 { 0085 switch (type) { 0086 case '1': return "PlainBrick1"; 0087 case '2': return "PlainBrick2"; 0088 case '3': return "PlainBrick3"; 0089 case '4': return "PlainBrick4"; 0090 case '5': return "PlainBrick5"; 0091 case '6': return "PlainBrick6"; 0092 case 'm': return "MultipleBrick3"; 0093 case 'x': return "ExplodingBrick"; 0094 case 'u': return "UnbreakableBrick"; 0095 case 'h': return "HiddenBrick"; 0096 default: 0097 print("Invalid File: unknown character '", type, "'"); 0098 return "PlainBrick1"; 0099 } 0100 } 0101 0102 function indexForPos(position) { 0103 var pos = position.split(","); 0104 var column = parseInt(pos[0]) - 1; 0105 var row = parseInt(pos[1]) - 1; 0106 return index(row, column); 0107 } 0108 0109 function index(row, column) { 0110 for (var i in bricks) { 0111 var brick = bricks[i]; 0112 if (brick.row==row && brick.column==column) { 0113 return i; 0114 } 0115 } 0116 return -1; 0117 } 0118 0119 function putGiftOnRandomBrick(gift, except) { 0120 var index; 0121 var brick; 0122 do { 0123 index = Math.round(Math.random()*bricks.length); 0124 brick = bricks[index]; 0125 } while (index==except || brick==null || brick.hasGift); 0126 brick.giftType = gift; 0127 } 0128 0129 function giftlessBricks() { 0130 var count = 0; 0131 for (var i=0; i<bricks.length; i++) { 0132 var brick = bricks[i]; 0133 if (!brick.hasGift) count++; 0134 } 0135 } 0136 0137 function createBrick(row, column, type) { 0138 var brick = brickComponent.createObject(bgOverlay); 0139 brick.row = row; 0140 brick.column = column; 0141 brick.type = type; 0142 bricks.push(brick); 0143 } 0144 0145 function showLine(line, number) { 0146 for (var i=0; i<line.length; i++) { 0147 var c = line[i]; 0148 if (c == '-') continue; 0149 createBrick(number-1, i, getTypeFromChar(c)); 0150 if (c!='h' && c!='u') ++remainingBricks; 0151 } 0152 } 0153 0154 function putGift(gift, times, pos) { 0155 if (pos!="") { 0156 // Put gift at given position 0157 var index = indexForPos(pos); 0158 if (index == -1) { 0159 print("error:", "Can't place gift at position (", pos, "). There is no brick."); 0160 } 0161 else { 0162 var giftBrick = bricks[index]; 0163 if (giftBrick.hasGift) { 0164 // Brick already has a gift -> move this gift to a random position 0165 putGiftOnRandomBrick(giftBrick.giftType, index); 0166 } 0167 giftBrick.giftType = gift; 0168 } 0169 } 0170 else { 0171 // Distribute gifts randomly 0172 var bricksLeft = giftlessBricks(); 0173 if (bricksLeft < times) { 0174 print("error:", "Too many gifts of type", gift); 0175 return; 0176 } 0177 for (var i=0; i<times; i++) { 0178 putGiftOnRandomBrick(gift, -1); 0179 } 0180 } 0181 } 0182 0183 function createBall() { 0184 var ball = ballComponent.createObject(bgOverlay); 0185 ball.posX = (bar.x + ball.barPosition*bar.width)/m_scale; 0186 ball.posY = (bar.y - ball.height)/m_scale; 0187 balls.push(ball); 0188 } 0189 0190 function startLevel() { 0191 if (bricks.length==0) { 0192 if (level == 0) { 0193 // No level in the levelset 0194 print("Invalid levelset"); 0195 } else { 0196 // No more levels: game won 0197 gameWon = true; 0198 score += Globals.GAME_WON_SCORE + lives*Globals.LIFE_SCORE; 0199 showMessage(i18n("Well done! You won the game")); 0200 singleShot(10, endGame, null); 0201 deleteMovingObjects(); 0202 } 0203 return; 0204 } 0205 ++level; 0206 showMessage(i18n("Level %1", level)); 0207 hideLater(messageBox, 2000); 0208 resumeGame(); 0209 } 0210 0211 function loadNextLevel() { 0212 // assign points for each remaining brick 0213 for (var i=0; i<bricks.length; i++) { 0214 var type = bricks[i].type; 0215 // don't assign points for unbreakable bricks 0216 if (type == "UnbreakableBrick") { 0217 continue; 0218 } 0219 if (type == "") { 0220 continue; 0221 } 0222 score += Globals.AUTOBRICK_SCORE; 0223 0224 // add extra points for multiple bricks 0225 if (type == "MultipleBrick3") { 0226 score += Globals.AUTOBRICK_SCORE*2; 0227 } else if (type == "MultipleBrick2") { 0228 score += Globals.AUTOBRICK_SCORE; 0229 } 0230 } 0231 deleteMovingObjects(); 0232 score += Globals.LEVEL_SCORE; 0233 resetBricks(); 0234 canvas.levelComplete(); 0235 } 0236 0237 function resumeGame() { 0238 createBall(); 0239 bar.reset(); 0240 speed = 1.8; 0241 repaintInterval = 1; 0242 substeps = 1; 0243 elapsedTimeTimer.restart(); 0244 gameTimer.interval = Globals.REPAINT_INTERVAL; 0245 gameTimer.restart(); 0246 showFireBallMessage(); 0247 } 0248 0249 function endGame() { 0250 canvas.gameEnded(score, (gameWon ? -1 : level), elapsedTimeTimer.elapsedTime); 0251 } 0252 0253 function moveBalls() { 0254 for (var i in balls) { 0255 var ball = balls[i] 0256 if (ball.toBeFired) { 0257 ball.posX = (bar.x + ball.barPosition*bar.width)/m_scale; 0258 } else { 0259 ball.posX += ball.directionX * speed; 0260 ball.posY += ball.directionY * speed; 0261 } 0262 0263 } 0264 } 0265 0266 function detectCollisions() { 0267 // needed to exit from the loop if the arrays that they cycle 0268 // change (items get deleted) 0269 itemsGotDeleted = false; 0270 0271 dScore *= Globals.SCORE_AUTO_DECREASE; 0272 for (var i in balls) { 0273 var ball = balls[i]; 0274 if (ball.toBeFired) { 0275 continue; 0276 } 0277 0278 // collision detection 0279 firstTime = true; 0280 detectBallCollisions(ball); 0281 if (itemsGotDeleted) { 0282 return; 0283 } 0284 } 0285 0286 for (var i=0; i<gifts.length; i++) { 0287 var gift = gifts[i]; 0288 var giftRect = createRect(gift); 0289 var barRect = createRect(bar); 0290 if (gift.y+gift.height > bgOverlay.height) { 0291 remove(gifts, gift); 0292 gift.destroy(); 0293 i--; 0294 } else if (intersects(giftRect, barRect)) { 0295 executeGift(gift.type); 0296 if (itemsGotDeleted) { 0297 return; 0298 } 0299 remove(gifts, gift); 0300 gift.destroy(); 0301 i--; 0302 } 0303 } 0304 0305 tick = (tick+1) % repaintInterval; 0306 0307 if (tick==0) { 0308 updateBallDirection(); 0309 } 0310 } 0311 0312 function fireBall() { 0313 if (paused) { 0314 print("trying to fire while game is paused!!!"); 0315 return; 0316 } 0317 0318 for (var i in balls) { 0319 var ball = balls[i]; 0320 if (!ball.toBeFired) continue; 0321 0322 var ballCenter = ball.x + ball.width/2; 0323 var barCenter = bar.x + bar.width/2; 0324 var angle = (Math.PI/3) * (barCenter-ballCenter)/(bar.width/2) + Math.PI/2; 0325 0326 ball.directionX = Math.cos(angle) * Globals.BALL_SPEED; 0327 ball.directionY = -Math.sin(angle) * Globals.BALL_SPEED; 0328 ball.toBeFired = false; 0329 } 0330 0331 dScore = Globals.BRICK_SCORE; 0332 hideFireBallMessage(); 0333 0334 randomCounter = 0; 0335 } 0336 0337 function addLife() { 0338 if (lives < Globals.MAXIMUM_LIVES) { 0339 lives++; 0340 } 0341 } 0342 0343 function setGamePaused(paused) { 0344 if (gameOver || gameWon || canvas.paused==paused) return; 0345 canvas.paused = paused; 0346 if (paused) { 0347 showMessage(i18n("Game Paused!")); 0348 elapsedTimeTimer.stop(); 0349 gameTimer.stop(); 0350 } else { 0351 elapsedTimeTimer.start(); 0352 gameTimer.start(); 0353 hideMessage(); 0354 } 0355 } 0356 0357 function showMessage(text) { 0358 if (messageBox.text == text) { 0359 messageBox.opacity = 1; 0360 } else { 0361 messageBox.text = text; 0362 } 0363 } 0364 0365 function showFireBallMessage(text) { 0366 fireBallMessage.opacity = 1; 0367 } 0368 0369 function hideMessage() { 0370 if (gameOver || gameWon || paused) return; 0371 messageBox.opacity = 0; 0372 } 0373 0374 function hideFireBallMessage() { 0375 fireBallMessage.opacity = 0; 0376 } 0377 0378 function hideLater(target, interval) { 0379 hideTimer.target = target; 0380 hideTimer.interval = interval; 0381 hideTimer.start(); 0382 } 0383 0384 function updateBallDirection() { 0385 // avoid infinite loops of the ball 0386 ++randomCounter; 0387 if (randomCounter == 1024) { 0388 randomCounter = 0; 0389 for (var i in balls) { 0390 var ball = balls[i]; 0391 if (Math.floor(Math.random()*10) % 2) { 0392 ball.directionX += 0.002; 0393 } else { 0394 ball.directionY += 0.002; 0395 } 0396 } 0397 0398 // increase the speed a little 0399 // if there is at least one ball moving 0400 // and the game isn't paused 0401 var ballMoving = false; 0402 for (var i in balls) { 0403 if (!balls[i].toBeFired) { 0404 ballMoving = true; 0405 break; 0406 } 0407 } 0408 if (ballMoving && !paused) { 0409 changeSpeed(Globals.AUTO_SPEED_INCREASE); 0410 } 0411 } 0412 } 0413 0414 function changeSpeed(ratio) { 0415 speed *= ratio; 0416 if (speed > 2.0) { 0417 // half the speed 0418 speed /= 2.0; 0419 // and double the number of ticks of the timer per time unit 0420 substeps *= 2; 0421 } 0422 if (speed < 1.0) { 0423 if (substeps == 1) { 0424 speed = Globals.MINIMUM_SPEED 0425 return; 0426 } 0427 // else 0428 0429 // double the speed 0430 speed *= 2.0; 0431 // and half the number of ticks of the timer per time unit 0432 substeps /= 2; 0433 } 0434 } 0435 0436 function deleteMovingObjects() { 0437 itemsGotDeleted = true; 0438 var times = balls.length 0439 for (var i=0; i<times; i++) { 0440 balls.shift().destroy(); 0441 } 0442 0443 times = gifts.length 0444 for (var i=0; i<times; i++) { 0445 gifts.shift().destroy(); 0446 } 0447 } 0448 0449 function createRect(object) { 0450 return { 0451 left: object.x, 0452 top: object.y, 0453 right: object.x + object.width, 0454 bottom: object.y + object.height 0455 }; 0456 } 0457 0458 function intersects(r1, r2) { 0459 return !(r2.left > r1.right || 0460 r2.right < r1.left || 0461 r2.top > r1.bottom || 0462 r2.bottom < r1.top); 0463 } 0464 0465 function intersectArea(r1, r2) { 0466 return (Math.min(r1.right, r2.right) - Math.max(r1.left, r2.left)) * 0467 (Math.min(r1.bottom, r2.bottom) - Math.max(r1.top, r2.top)); 0468 } 0469 0470 // never run this function more than two times recursively 0471 var firstTime = true; 0472 function detectBallCollisions(ball) { 0473 // bounce a little early in some cases so the average position is centered 0474 var rect = createRect(ball); 0475 rect.left += ball.directionX/2; 0476 rect.top += ball.directionY/2; 0477 var x = rect.left; 0478 var y = rect.top; 0479 0480 var barRect = createRect(bar); 0481 0482 // bounce against the wall 0483 if (x < 0 && ball.directionX < 0) { 0484 ball.directionX *= -1; 0485 } else if (x+ball.width > bgOverlay.width 0486 && ball.directionX > 0) { 0487 ball.directionX *= -1; 0488 } else if (y < 0 && ball.directionY < 0) { 0489 ball.directionY *= -1; 0490 } else if (y+ball.height > bgOverlay.height 0491 && ball.directionY > 0) { 0492 // delete the ball 0493 remove(balls, ball); 0494 ball.destroy(); 0495 itemsGotDeleted = true; 0496 if (balls.length == 0) { 0497 showMessage(i18n("Oops! You have lost the ball!")); 0498 handleDeathTimer.start(); 0499 gameTimer.stop(); 0500 0501 deleteMovingObjects(); 0502 } 0503 return; 0504 } 0505 // bounce against the bar 0506 else if (intersects(rect, barRect) && ball.directionY > 0) { 0507 0508 var ballCenter = ball.x + ball.width/2; 0509 var barCenter = bar.x + bar.width/2; 0510 0511 if (ballCenter > bar.x && 0512 ballCenter < bar.x+bar.width) { 0513 // the bar has been hit 0514 0515 if (bar.type == "StickyBar") { 0516 ball.toBeFired = true; 0517 0518 var diff = ball.x - bar.x; 0519 0520 ball.barPosition = diff / bar.width; 0521 ball.posY = (bar.y-ball.height)/m_scale; 0522 } 0523 0524 var angle = (Math.PI/3) * (barCenter-ballCenter)/(bar.width/2) + Math.PI/2; 0525 0526 ball.directionX = Math.cos(angle) * Globals.BALL_SPEED; 0527 ball.directionY = -Math.sin(angle) * Globals.BALL_SPEED; 0528 } 0529 } else { // bounce against the bricks (and optionally break them) 0530 handleBrickCollisions(ball); 0531 } 0532 0533 // never run this function more than two times recursively 0534 if (firstTime) { 0535 firstTime = false; 0536 // check if there is another collision 0537 if (!itemsGotDeleted) { 0538 detectBallCollisions(ball); 0539 } 0540 } else { 0541 firstTime = true; 0542 return; 0543 } 0544 } 0545 0546 function handleDeath() { 0547 hideMessage(); 0548 deleteMovingObjects(); 0549 bar.reset(); 0550 if (lives == 0) { 0551 gameOver = true; 0552 showMessage(i18n("Game Over!")); 0553 elapsedTimeTimer.stop(); 0554 bar.stopMoving(); 0555 singleShot(10, endGame, null); 0556 } else { 0557 lives--; 0558 resumeGame(); 0559 } 0560 } 0561 0562 function handleBrickCollisions(ball) { 0563 if (itemsGotDeleted) { 0564 return; 0565 } 0566 var rect = createRect(ball); 0567 var intersectingBricks = new Array; 0568 0569 for (var i=0; i<bricks.length; i++) { 0570 var brick = bricks[i]; 0571 if (brick == null) continue; 0572 var brickRect = createRect(brick); 0573 0574 if (intersects(brickRect, rect)) { 0575 intersectingBricks.push(brick); 0576 } 0577 } 0578 0579 if (intersectingBricks.length != 0) { 0580 collideWithBricks(ball, intersectingBricks); 0581 } 0582 } 0583 0584 function collideWithBricks(ball, bricks) { 0585 if (bricks.length == 2) { 0586 collideWithTwoBricks(ball, bricks); 0587 } else { 0588 collideWithBrick(ball, bricks[0]); 0589 } 0590 } 0591 0592 function collideWithTwoBricks(ball, bricks) { 0593 var ballRect = createRect(ball); 0594 var r1 = createRect(bricks[0]); 0595 var r2 = createRect(bricks[1]); 0596 0597 var area1 = intersectArea(ballRect, r1); 0598 var area2 = intersectArea(ballRect, r2); 0599 0600 if (area1 > area2) { 0601 // the area of intersection with the first brick is bigger 0602 collideWithBrick(ball, bricks[0]); 0603 } else { 0604 collideWithBrick(ball, bricks[1]); 0605 } 0606 } 0607 0608 function collideWithBrick(ball, brick) { 0609 if (ball.type == "UnstoppableBall") { 0610 forcedHit(brick); 0611 return; // don't bounce 0612 } 0613 if (ball.type == "UnstoppableBurningBall") { 0614 explode(brick); 0615 return; // don't bounce 0616 } 0617 0618 // calculate bounce 0619 var brickRect = createRect(brick); 0620 var ballRect = createRect(ball); 0621 0622 var top = Math.round(ballRect.bottom - brickRect.top); 0623 var bottom = Math.round(brickRect.bottom - ballRect.top); 0624 var left = Math.round(ballRect.right - brickRect.left); 0625 var right = Math.round(brickRect.right - ballRect.left); 0626 var min = Math.min(Math.min(top, bottom), Math.min(left, right)); 0627 0628 // bounce 0629 if (min == top && ball.directionY > 0) { 0630 ball.directionY *= -1; 0631 ball.posY -= top/m_scale; 0632 } else if (min == bottom && ball.directionY < 0) { 0633 ball.directionY *= -1; 0634 ball.posY += bottom/m_scale; 0635 } else if (min == left && ball.directionX > 0) { 0636 ball.directionX *= -1; 0637 ball.posX -= left/m_scale; 0638 } else if (min == right && ball.directionX < 0) { 0639 ball.directionX *= -1; 0640 ball.posX += right/m_scale; 0641 } else { 0642 return; // already bounced 0643 } 0644 0645 if (ball.type == "BurningBall") { 0646 explode(brick); 0647 } else { 0648 hit(brick); 0649 } 0650 } 0651 0652 function addBrickScore() { 0653 score += Math.round(dScore); 0654 dScore = Globals.BRICK_SCORE; 0655 } 0656 0657 function forcedHit(brick) { 0658 if (brick == null) return; 0659 0660 if (brick.type == "ExplodingBrick") { 0661 explode(brick); 0662 } else { 0663 handleDeletion(brick); 0664 } 0665 } 0666 0667 function hit(brick) { 0668 if (brick.type == "HiddenBrick" && !brick.visible) { 0669 brick.visible = true; 0670 ++remainingBricks; 0671 } else if (brick.type == "MultipleBrick3") { 0672 brick.type = "MultipleBrick2"; 0673 addBrickScore(); 0674 } else if (brick.type == "MultipleBrick2") { 0675 brick.type = "MultipleBrick1"; 0676 addBrickScore(); 0677 } else if (brick.type == "ExplodingBrick") { 0678 explode(brick); 0679 } else if (brick.type != "UnbreakableBrick") { 0680 handleDeletion(brick); 0681 } 0682 } 0683 0684 function explode(brick) { 0685 if (brick == null) return; 0686 0687 burn(brick); 0688 singleShot(Globals.BURNING_SPEED, burnNearbyBricks, createRect(brick)); 0689 } 0690 0691 function burnNearbyBricks(brickRect) { 0692 var nearby = nearbyBricks(brickRect); 0693 for (var i in nearby) { 0694 burn(nearby[i]); 0695 } 0696 } 0697 0698 function burn(brick) { 0699 if (brick == null) return; 0700 0701 if (brick.type == "ExplodingBrick") { 0702 // make sure it doesn't explode twice 0703 brick.type = "BurningBrick"; 0704 explode(brick); 0705 } else { 0706 singleShot(Globals.BURNING_SPEED, deleteBrick, new Array(brick.x, brick.y)); 0707 } 0708 0709 if (brick.type == "HiddenBrick" && !brick.visible 0710 || brick.type == "UnbreakableBrick") { 0711 // Add to brick count when burning invisible and ubreakable bricks 0712 ++remainingBricks; 0713 } 0714 brick.type = "BurningBrick"; 0715 } 0716 0717 // wrapper function to get the brick from position 0718 // and then passing it to handleDeletion 0719 function deleteBrick(pos) { 0720 var brick = bgOverlay.childAt(pos[0], pos[1]); 0721 if (brick!=null && bricks.indexOf(brick)>=0) { 0722 handleDeletion(brick); 0723 } 0724 } 0725 0726 function createGiftAt(brick) { 0727 var gift = giftComponent.createObject(bgOverlay); 0728 gift.type = brick.giftType; 0729 gift.setPosition(brick.x/m_scale, brick.y/m_scale); 0730 gift.falling = true; 0731 gifts.push(gift); 0732 } 0733 0734 function handleDeletion(brick) { 0735 remove(bricks, brick); 0736 if (brick.hasGift) { 0737 createGiftAt(brick); 0738 } 0739 0740 // take the properties we want later before destroying the brick 0741 var brickType = brick.type; 0742 var brickVisible = brick.visible; 0743 brick.destroy(); 0744 0745 --remainingBricks; 0746 addBrickScore(); 0747 0748 // these two kind of bricks aren't counted in remainingBricks 0749 if ( (brickType == "HiddenBrick" && !brickVisible) 0750 || brickType == "UnbreakableBrick") { 0751 ++remainingBricks; 0752 return; // never need to load the next level 0753 } 0754 0755 if (remainingBricks == 0) { 0756 loadNextLevel(); 0757 } 0758 } 0759 0760 function nearbyBricks(brickRect) { 0761 var result = new Array; 0762 0763 // coordinates of the center of the brick 0764 var x = (brickRect.left + brickRect.right)/2; 0765 var y = (brickRect.top + brickRect.bottom)/2; 0766 var width = (brickRect.right - brickRect.left); 0767 var height = (brickRect.bottom - brickRect.top); 0768 0769 // points to the left, right, top and bottom of the brick 0770 var points = new Array; 0771 points.push([x-width, y]); 0772 points.push([x+width, y]); 0773 points.push([x, y-height]); 0774 points.push([x, y+height]); 0775 0776 for (var j in points) { 0777 var px = points[j][0]; 0778 var py = points[j][1]; 0779 var b = bgOverlay.childAt(px, py); 0780 if (b != null && bricks.indexOf(b)>=0) result.push(b); 0781 } 0782 return result; 0783 } 0784 0785 function executeGift(type) { 0786 score += Globals.GIFT_SCORE; 0787 0788 if (type == "Gift100Points") { 0789 score += 100 - Globals.GIFT_SCORE; 0790 } 0791 else if (type == "Gift200Points") { 0792 score += 200 - Globals.GIFT_SCORE; 0793 } 0794 else if (type == "Gift500Points") { 0795 score += 500 - Globals.GIFT_SCORE; 0796 } 0797 else if (type == "Gift1000Points") { 0798 score += 1000 - Globals.GIFT_SCORE; 0799 } 0800 else if (type == "GiftAddLife") { 0801 addLife(); 0802 } 0803 else if (type == "GiftLoseLife") { 0804 handleDeath(); 0805 } 0806 else if (type == "GiftNextLevel") { 0807 loadNextLevel(); 0808 } 0809 else if (type == "GiftMagicEye") { 0810 giftMagicEye(); 0811 } 0812 else if (type == "GiftMagicWand") { 0813 giftMagicWand(); 0814 } 0815 else if (type == "GiftSplitBall") { 0816 giftSplitBall(); 0817 } 0818 else if (type == "GiftAddBall") { 0819 createBall(); 0820 } 0821 else if (type == "GiftUnstoppableBall") { 0822 giftUnstoppableBall(); 0823 } 0824 else if (type == "GiftBurningBall") { 0825 giftBurningBall(); 0826 } 0827 else if (type == "GiftDecreaseSpeed") { 0828 changeSpeed(1.0/Globals.CHANGE_SPEED_RATIO); 0829 } 0830 else if (type == "GiftIncreaseSpeed") { 0831 changeSpeed(Globals.CHANGE_SPEED_RATIO); 0832 } 0833 else if (type == "GiftEnlargeBar") { 0834 bar.enlarge(); 0835 } 0836 else if (type == "GiftShrinkBar") { 0837 bar.shrink(); 0838 } 0839 else if (type == "GiftStickyBar") { 0840 bar.type = "StickyBar"; 0841 } 0842 else if (type == "GiftMoreExplosion") { 0843 giftMoreExplosion(); 0844 } 0845 else { 0846 print("Unrecognized gift type!!!", type); 0847 } 0848 } 0849 0850 function giftMagicEye() { 0851 // make all hidden bricks visible 0852 for (var i in bricks) { 0853 var brick = bricks[i]; 0854 if (!brick.visible) { 0855 brick.visible = true; 0856 ++remainingBricks; 0857 } 0858 } 0859 } 0860 0861 function giftMagicWand() { 0862 for (var i in bricks) { 0863 var brick = bricks[i]; 0864 0865 // make unbreakable bricks breakable 0866 if (brick.type == "UnbreakableBrick") { 0867 brick.type = "BreakableBrick"; 0868 ++remainingBricks; 0869 } 0870 0871 // make multiple bricks single 0872 if (brick.type == "MultipleBrick3") { 0873 brick.type = "MultipleBrick1"; 0874 score += Globals.AUTOBRICK_SCORE * 2; 0875 } else if (brick.type == "MultipleBrick2") { 0876 brick.type = "MultipleBrick1"; 0877 score += Globals.AUTOBRICK_SCORE; 0878 } 0879 } 0880 } 0881 0882 function giftSplitBall() { 0883 var newBalls = new Array; 0884 for (var i in balls) { 0885 var ball = balls[i]; 0886 var newBall = ballComponent.createObject(bgOverlay); 0887 0888 // give it a nice direction 0889 newBall.directionX = ball.directionX; 0890 newBall.directionY = ball.directionY; 0891 if (ball.directionY > 0) 0892 newBall.directionY *= -1; 0893 else 0894 newBall.directionX *= -1; 0895 0896 newBall.toBeFired = ball.toBeFired; 0897 newBall.spriteKey = ball.spriteKey; 0898 newBall.type = ball.type; 0899 newBall.posX = ball.posX; 0900 newBall.posY = ball.posY; 0901 newBalls.push(newBall); 0902 } 0903 balls = balls.concat(newBalls); 0904 } 0905 0906 function giftUnstoppableBall() { 0907 for (var i in balls) { 0908 var ball = balls[i]; 0909 if (ball.type == "BurningBall") { 0910 ball.type = "UnstoppableBurningBall"; 0911 } else if (ball.type != "UnstoppableBurningBall") { 0912 ball.type = "UnstoppableBall"; 0913 } 0914 } 0915 } 0916 0917 function giftBurningBall() { 0918 for (var i in balls) { 0919 var ball = balls[i]; 0920 if (ball.type == "UnstoppableBall") { 0921 ball.type = "UnstoppableBurningBall"; 0922 } else if (ball.type != "UnstoppableBurningBall") { 0923 ball.type = "BurningBall"; 0924 } 0925 } 0926 } 0927 0928 function giftMoreExplosion() { 0929 var explodingBricks = new Array; 0930 for (var i in bricks) { 0931 var brick = bricks[i]; 0932 if (brick.type == "ExplodingBrick") { 0933 explodingBricks.push(brick); 0934 } 0935 } 0936 0937 for (var i in explodingBricks) { 0938 var nearby = nearbyBricks(createRect(explodingBricks[i])); 0939 for (var j in nearby) { 0940 var nearbyBrick = nearby[j]; 0941 if (nearbyBrick.type == "UnbreakableBrick") { 0942 ++remainingBricks; 0943 } 0944 if (nearbyBrick.type == "HiddenBrick" && !nearbyBrick.visible) { 0945 nearbyBrick.visible = true; 0946 ++remainingBricks; 0947 } 0948 0949 nearbyBrick.type = "ExplodingBrick"; 0950 } 0951 } 0952 }