作者:薛萌
演示效果

代码
# 在 JavaScript 编程界面中,将此代码复制进去即可。class Vec2 {x : numbery : numberconstructor(x : number, y : number) {this.x = xthis.y = y}Length() : number {return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2))}Normalize() {let s = this.Length()if(s != 0) {this.x = this.x / sthis.y = this.y / s}}GetNormalize() : Vec2 {let v = new Vec2(this.x, this.y)v.Normalize()return v}Add(rhs : Vec2) : Vec2 {let x = this.x + rhs.xlet y = this.y + rhs.yreturn new Vec2(x, y)}Mul(n : number) : Vec2 {let x = this.x * nlet y = this.y * nreturn new Vec2(x, y)}}function ToLeft(a : Vec2, b : Vec2, p : Vec2 ){// | a.x a.y 1 |// | b.x b.y 1 |// | p.x p.y 1 |return a.x * b.y + b.x * p.y + p.x * a.y - a.y * b.x - b.y * p.x - p.y * a.x > 0.0;}let w = scene.screenWidth()let h = scene.screenHeight()let block_size = 10let row = 4let col = 16enum ItemType {None = 0,Green = 2,Yellow = 3,Red = 4,Purple = 5}enum BlockType {None = 0,Red = 1,Green = 2,Yellow = 3,Purple = 4,Brown = 5}enum CollisionEdge {None = 0,Top = 1,Bottom = 2,Left = 3,Right = 4}let Blocks : number[][] = [[3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3],[4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4],[5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5],[1, 2, 3, 4, 5, 4, 3, 2, 2, 3, 4, 5, 4, 3, 2, 1],[1, 2, 3, 4, 5, 4, 3, 1, 1, 3, 4, 5, 4, 3, 2, 1],]class Platform {platform : Spritex : numbery : numberconstructor(x : number, y : number) {this.x = xthis.y = ythis.platform = sprites.create(assets.image`platform`, SpriteKind.Player)this.platform.setPosition(this.x, this.y)this.platform.setStayInScreen(true)controller.moveSprite(this.platform, 80, 0)}}class Ball {ball : Spritespeed : numberconstructor(x : number, y : number, dir : Vec2) {this.speed = 20this.ball = sprites.create(assets.image`ball`, SpriteKind.Projectile)this.ball.setPosition(x, y)this.ball.setStayInScreen(true)this.ball.setBounceOnWall(true)dir.Normalize()this.SetVelocity(dir)}GetDir() : Vec2 {let dir = new Vec2(this.ball.vx, this.ball.vy)dir.Normalize()return dir}SpeedUp(p : number) {this.speed += this.speed * pthis.SetVelocity(this.GetDir())}SetVelocity(dir : Vec2) {this.ball.setVelocity(dir.x * this.speed, dir.y * this.speed)}GetPos() : Vec2 {return new Vec2(this.ball.x, this.ball.y)}}class MyBlock {x : numbery : numberblock : Spritepx : numberpy : numberHP : numberconstructor(x : number, y : number, blockType : number) {this.HP = blockTypethis.x = xthis.y = ythis.CreateBlockByType(blockType)this.px = this.x * block_size + block_size * 0.5this.py = this.y * block_size + block_size * 0.5}CreateBlockByType(blockType : number) {if(blockType == 1) {this.block = sprites.create(assets.image`red_block`, SpriteKind.Enemy)} else if(blockType == 2) {this.block = sprites.create(assets.image`green_block`, SpriteKind.Enemy)} else if(blockType == 3) {this.block = sprites.create(assets.image`yellow_block`, SpriteKind.Enemy)} else if(blockType == 4) {this.block = sprites.create(assets.image`purple_block`, SpriteKind.Enemy)} else if(blockType == 5) {this.block = sprites.create(assets.image`brown_block`, SpriteKind.Enemy)}}BeBreakOut() : boolean {--this.HPif(this.HP == 0) {music.bigCrash.play()return true}music.smallCrash.play()this.block.destroy()this.CreateBlockByType(this.HP)this.Render()return false}GetVertics() : Vec2[] {let p1 = new Vec2(this.px - block_size * 0.5, this.py - block_size * 0.5)let p2 = new Vec2(this.px - block_size * 0.5, this.py + block_size * 0.5)let p3 = new Vec2(this.px + block_size * 0.5, this.py + block_size * 0.5)let p4 = new Vec2(this.px + block_size * 0.5, this.py - block_size * 0.5)return [p1, p2, p3, p4]}Render(){this.block.setPosition(this.px, this.py)}}class Item {item : Spritex : numbery : numberspeed : numberitemType : ItemTypeconstructor(x : number, y : number, itemType : ItemType) {this.x = xthis.y = ythis.speed = 10this.itemType = itemTypeswitch(itemType) {case ItemType.Green:this.item = sprites.create(assets.image`two`, SpriteKind.Food)breakcase ItemType.Yellow:this.item = sprites.create(assets.image`three`, SpriteKind.Food)breakcase ItemType.Red:this.item = sprites.create(assets.image`four`, SpriteKind.Food)breakcase ItemType.Purple:this.item = sprites.create(assets.image`five`, SpriteKind.Food)break}this.item.setPosition(x, y)this.item.setVelocity(0, this.speed)}}let liveItems : Item[] = []sprites.onOverlap(SpriteKind.Food, SpriteKind.Player, function (foodSprite, playerSprite) {music.beamUp.play()for(let i = 0; i < liveItems.length; ++i) {let curItem = liveItems[i]if(curItem.item == foodSprite) {let deadItem = liveItems.removeAt(i)deadItem.item.destroy()if(ballList.length < 25) {GenNewBall(deadItem.itemType)} else {for(let ii = 0; ii < ballList.length; ++ii) {let curBall = ballList[ii]curBall.SpeedUp(0.2)}}break}}})let D2R = Math.PI / 180function RotateVector(v : Vec2, angle : number, isClockwise : boolean) : Vec2 {let vv : Vec2if(isClockwise == true) {vv = new Vec2(-v.y, v.x)} else {vv = new Vec2(v.y, -v.x)}let xl : numberlet yl : numberxl = Math.cos(angle * D2R)yl = Math.sin(angle * D2R)let xx = v.Mul(xl)let yy = vv.Mul(yl)let newV : Vec2 = xx.Add(yy)return newV}function GenNewBall(count : number) {if(ballList.length > 100) {return}let newBalls : Ball[] = []if(count == 2) {for(let i = 0; i < ballList.length; ++i) {let curBall = ballList[i]let v1 = RotateVector(curBall.GetDir(), 15, true)let v2 = RotateVector(curBall.GetDir(), 15, false)curBall.SetVelocity(v1)let pos = curBall.GetPos()let ball = new Ball(pos.x, pos.y, v2)newBalls.push(ball)}} else if(count == 3) {for(let i = 0; i < ballList.length; ++i) {let curBall = ballList[i]let v1 = RotateVector(curBall.GetDir(), 120, true)let v2 = RotateVector(curBall.GetDir(), 120, false)let pos = curBall.GetPos()let ball1 = new Ball(pos.x, pos.y, v1)let ball2 = new Ball(pos.x, pos.y, v2)newBalls.push(ball1)newBalls.push(ball2)}} else if(count == 4) {for(let i = 0; i < ballList.length; ++i) {let curBall = ballList[i]let v1 = RotateVector(curBall.GetDir(), 15, true)let v2 = RotateVector(curBall.GetDir(), 45, true)let v3 = RotateVector(curBall.GetDir(), 15, false)let v4 = RotateVector(curBall.GetDir(), 45, false)curBall.SetVelocity(v1)let pos = curBall.GetPos()let ball2 = new Ball(pos.x, pos.y, v2)let ball3 = new Ball(pos.x, pos.y, v3)let ball4 = new Ball(pos.x, pos.y, v4)newBalls.push(ball2)newBalls.push(ball3)newBalls.push(ball4)}} else if(count == 5) {for(let i = 0; i < ballList.length; ++i) {let curBall = ballList[i]let v1 = RotateVector(curBall.GetDir(), 72, true)let v2 = RotateVector(curBall.GetDir(), 144, true)let v3 = RotateVector(curBall.GetDir(), 72, false)let v4 = RotateVector(curBall.GetDir(), 144, false)let pos = curBall.GetPos()let ball1 = new Ball(pos.x, pos.y, v1)let ball2 = new Ball(pos.x, pos.y, v2)let ball3 = new Ball(pos.x, pos.y, v3)let ball4 = new Ball(pos.x, pos.y, v4)newBalls.push(ball1)newBalls.push(ball2)newBalls.push(ball3)newBalls.push(ball4)}}for(let i = 0; i < newBalls.length; ++i) {ballList.push(newBalls[i])}}function IsIntersection(p1 : Vec2, p2 : Vec2, p3 : Vec2, p4 : Vec2) : boolean {if(ToLeft(p1, p2, p3) && ToLeft(p1, p2, p4)) {return false}if(!ToLeft(p1, p2, p3) && !ToLeft(p1, p2, p4)) {return false}if(ToLeft(p3, p4, p1) && ToLeft(p3, p4, p2)) {return false}if(!ToLeft(p3, p4, p1) && !ToLeft(p3, p4, p2)) {return false}return true}let BlocksObjects : MyBlock[] = []for(let i = 0; i < row; ++i) {for(let j = 0; j < col; ++j) {if(Blocks[i][j] > 0) {BlocksObjects.push(new MyBlock(j, i, Blocks[i][j]))}}}let platform = new Platform(w / 2, h - 20)let ballList : Ball[] = []ballList.push(new Ball(w / 2, h / 2, new Vec2(1, 1)))for(let i = 0; i < BlocksObjects.length; ++i){BlocksObjects[i].Render()}function GetCollisionEdge(sprite : Sprite, otherSprite : Sprite) : CollisionEdge {let otherTop = otherSprite.toplet otherBottom = otherSprite.bottomlet otherLeft = otherSprite.leftlet otherRight = otherSprite.rightlet otherCenter = new Vec2(otherLeft / 2 + otherRight / 2, otherTop / 2 + otherBottom / 2)let otherLeftTop = new Vec2(otherLeft, otherTop)let otherLeftBottom = new Vec2(otherLeft, otherBottom)let otherRightTop = new Vec2(otherRight, otherTop)let otherRightBottom = new Vec2(otherRight, otherBottom)let top = sprite.toplet bottom = sprite.bottomlet left = sprite.leftlet right = sprite.rightlet center = new Vec2(left / 2 + right / 2, top / 2 + bottom / 2)let leftTop = new Vec2(left, top)let leftBottom = new Vec2(left, bottom)let rightTop = new Vec2(right, top)let rightBottom = new Vec2(right, bottom)if(IsIntersection(center, otherCenter, otherLeftTop, otherLeftBottom)) {return CollisionEdge.Left} else if(IsIntersection(center, otherCenter, otherRightTop, otherRightBottom)) {return CollisionEdge.Right} else if(IsIntersection(center, otherCenter, otherLeftTop, otherRightTop)) {return CollisionEdge.Top}else if(IsIntersection(center, otherCenter, otherLeftBottom, otherRightBottom)) {return CollisionEdge.Bottom}return CollisionEdge.None}sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Player, function (sprite, otherSprite) {let edge = GetCollisionEdge(sprite, otherSprite)music.pewPew.play()switch(edge){case CollisionEdge.Top:if(sprite.vy > 0){sprite.vy = -sprite.vyif(sprite.x < otherSprite.x) {sprite.vx -= randint(0, 10) / 10.0} else if(sprite.x > otherSprite.x) {sprite.vx += randint(0, 10) / 10.0}}breakcase CollisionEdge.Bottom:if(sprite.vy < 0){sprite.vy = -sprite.vy}breakcase CollisionEdge.Left:if(sprite.vx > 0) {sprite.vx = -sprite.vx}breakcase CollisionEdge.Right:if(sprite.vx < 0){sprite.vx = -sprite.vx}break}})sprites.onOverlap(SpriteKind.Projectile, SpriteKind.Enemy, function (sprite, otherSprite) {let edge = GetCollisionEdge(sprite, otherSprite)let r = randint(1, 100)if(r > 80 && ballList.length < 25 && liveItems.length < 3) {let item = new Item(sprite.x, sprite.y, randint(2, 5))liveItems.push(item)}switch(edge){case CollisionEdge.Top:if(sprite.vy > 0){sprite.vy = -sprite.vy * 1.05}breakcase CollisionEdge.Bottom:if(sprite.vy < 0){sprite.vy = -sprite.vy * 1.05}breakcase CollisionEdge.Left:if(sprite.vx > 0) {sprite.vx = -sprite.vx * 1.05}breakcase CollisionEdge.Right:if(sprite.vx < 0){sprite.vx = -sprite.vx * 1.05}break}for(let i = 0; i < BlocksObjects.length; ++i) {let myBlock = BlocksObjects[i]if(myBlock.block == otherSprite) {if(myBlock.BeBreakOut() == true) {let item = BlocksObjects.removeAt(i)item.block.destroy()if(BlocksObjects.length == 0) {music.powerUp.play()}}break}}})game.onUpdate(function() {let background = scene.backgroundImage();background.fill(0)for(let i = ballList.length - 1; i >= 0; --i){let pos = ballList[i].GetPos()if(pos.y > 117) {let ball = ballList.removeAt(i)ball.ball.destroy()}}})
