{"id":25920,"student_id":10,"content":"player.speed = 1.7;\nBlinky.speed = 1.4;\nPinky.speed = 1.6;\nInky.speed = 1.5;\nClyde.speed = 1.4;\n\n// red ghost\nBlinky.AI = function (dirs) {\n let dirToPlayer = directionAtoB(this, player);\n return roundDirection(dirs, dirToPlayer);\n};\n\n// pink ghost\nPinky.AI = function (dirs) {\n player.stepForward(15*5);\n let dirToPlayer = directionAtoB(this, player);\n player.stepForward(-15*5);\n return roundDirection(dirs, dirToPlayer);\n};\n\n// blue ghost\nInky.AI = function (dirs) {\n let vx = player.x - Blinky.x;\n let vy = player.y - Blinky.y;\n let dirToPlayer = directionAtoB(this, {\n x: player.x + vx*2,\n y: player.y + vy*2,\n });\n return roundDirection(dirs, dirToPlayer);\n};\n\n// orange ghost\nClyde.AI = function (dirs) {\n return dirs[Math.floor(Math.random()*dirs.length)];\n};","created_at":"2018-03-28T22:24:40.179+08:00","updated_at":"2019-11-11T08:52:01.669+08:00","name":"zz","language":"javascript","screenshot":{"url":"https://cdn7.koding.school/uploads/project/screenshot/25920/00a1ddcab2f8db3e3d3294c9b6cffc66.jpg"},"parent_id":2,"plugin":"setBackdrop(\"black\");\n\n// chase:追逐模式, scatter:巡邏模式, frightened:逃跑模式\nlet MOD = 'scatter';\nlet clock = 0;\nlet life = 3;\n\nlet map = [\n 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',\n 'X............XX............X',\n 'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',\n 'X*XXXX.XXXXX.XX.XXXXX.XXXX*X',\n 'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',\n 'X..........................X',\n 'X.XXXX.XX.XXXXXXXX.XX.XXXX.X',\n 'X.XXXX.XX.XXXXXXXX.XX.XXXX.X',\n 'X......XX....XX....XX......X',\n 'XXXXXX.XXXXX.XX.XXXXX.XXXXXX',\n 'XXXXXX.XXXXX.XX.XXXXX.XXXXXX',\n 'XXXXXX.XX..........XX.XXXXXX',\n 'XXXXXX.XX.X XXXX X.XX.XXXXXX',\n 'XXXXXX.XX.X X.XX.XXXXXX',\n 'X ....X X.... X',\n 'XXXXXX.XX.X X.XX.XXXXXX',\n 'XXXXXX.XX.X XXXX X.XX.XXXXXX',\n 'XXXXXX.XX..........XX.XXXXXX',\n 'XXXXXX.XX.XXXXXXXX.XX.XXXXXX',\n 'XXXXXX.XX.XXXXXXXX.XX.XXXXXX',\n 'X............XX............X',\n 'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',\n 'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',\n 'X.XXXX.XXXXX.XX.XXXXX.XXXX.X',\n 'X*..XX................XX..*X',\n 'XXX.XX.XX.XXXXXXXX.XX.XX.XXX',\n 'XXX.XX.XX.XXXXXXXX.XX.XX.XXX',\n 'X......XX....XX....XX......X',\n 'X.XXXXXXXXXX.XX.XXXXXXXXXX.X',\n 'X.XXXXXXXXXX.XX.XXXXXXXXXX.X',\n 'X..........................X',\n 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',\n];\nmap.replace = function (x, y, char) {\n map[y] = map[y].substr(0, x) + char + map[y].substr(x + 1);\n}\n\nforever(() =\u003e {\n clock++;\n if (clock == 60 * 7) MOD = 'chase';\n if (clock == 60 * 27) MOD = 'scatter';\n if (clock == 60 * 34) MOD = 'chase';\n if (clock == 60 * 54) MOD = 'scatter';\n if (clock == 60 * 61) MOD = 'chase';\n\n for (let x = 0; x \u003c map.length; x++) {\n for (let y = 0; y \u003c map[x].length; y++) {\n if (map[x][y] == 'X') { // wall\n pen.fillColor = 'blue';\n pen.color = 'blue'\n pen.drawRect(y * 15 + 80, x * 15, 15, 15);\n }\n if (map[x][y] == '.') { // food\n pen.fillColor = 'yellow';\n pen.color = 'yellow';\n pen.drawCircle(y * 15 + 8 + 80, x * 15 + 8, 2);\n }\n if (map[x][y] == '*') { // huge food\n pen.fillColor = 'yellow';\n pen.color = 'yellow';\n pen.drawCircle(y * 15 + 8 + 80, x * 15 + 8, 5);\n }\n }\n }\n});\n\nfunction creature(img) {\n let s = createSprite(img);\n s.rotationStyle = 'fixed';\n s.scale = .6;\n\n s.reset = function (posX, posY, direction) {\n s.direction = direction;\n s.destination = undefined;\n s.target = {\n x: posX + (direction == 90 ? 1 : direction == 270 ? -1 : 0),\n y: posY + (direction == 0 ? -1 : direction == 180 ? 1 : 0),\n }\n\n let pos = getPosByXY(s.target);\n s.x = pos.x;\n s.y = pos.y;\n }\n\n s.forever(function () {\n let d = s.distanceTo(getPosByXY(s.target));\n\n if (d \u003e s.speed) {\n if (s.MOD == 'frightened') s.stepForward(.9);\n else s.stepForward(s.speed);\n } else {\n\n // 如果距離下個格子距離比移動步數少,則直接移動到格子上\n s.moveTo(getPosByXY(s.target));\n\n // 將可以移動的方向收到 dirs 裡\n let dirs = [];\n let x = s.target.x;\n let y = s.target.y;\n if (x == 1 \u0026\u0026 y == 14) return s.reset(26, 14, 270);\n if (x == 26 \u0026\u0026 y == 14) return s.reset(1, 14, 90);\n if (map[y][x + 1] != 'X') dirs.push(90);\n if (map[y][x - 1] != 'X') dirs.push(270);\n if (map[y + 1][x] != 'X') dirs.push(180);\n if (map[y - 1][x] != 'X') dirs.push(0);\n\n // 進行決策判斷角色要往哪個方向移動\n if (s.decision) d = s.decision(dirs);\n else d = dirs[0];\n s.direction = d || 0;\n\n // 更新下一個移動目標的格子\n if (d == 90) s.target.x += 1;\n if (d == 270) s.target.x -= 1;\n if (d == 180) s.target.y += 1;\n if (d == 0) s.target.y -= 1;\n }\n });\n\n return s;\n}\n\nvar Blinky = creature('red.png');\nvar Pinky = creature('pink.png');\nvar Inky = creature('blue.png');\nvar Clyde = creature('orange.png');\nvar player = creature('yellow.png');\nplayer.rotationStyle = 'full';\n\nvar enemies = [Blinky, Pinky, Inky, Clyde];\n\nBlinky.decision = Pinky.decision = Inky.decision = Clyde.decision = function enemyDirection(dirs) {\n if (dirs.length == 2) return antiReversion(this, dirs)[0];\n if (MOD == 'scatter') return this.scatterAI(antiReversion(this, dirs));\n if (MOD == 'frightened') return this.frightenedAI(dirs);\n if (MOD == 'chase') return this.AI(dirs);\n};\n\n// 追逐狀態下的 AI\nBlinky.AI = Pinky.AI = Inky.AI = Clyde.AI = function (dirs) {}\n\n// 驚嚇狀態下的 AI\nBlinky.frightenedAI = Pinky.frightenedAI = Inky.frightenedAI = Clyde.frightenedAI = function (dirs) {\n let dirToPlayer = directionAtoB(this, player);\n dirToPlayer = (dirToPlayer + 180) % 360;\n return roundDirection(dirs, dirToPlayer);\n}\n\n// 巡邏左上角狀態下的 AI\nPinky.scatterAI = function (dirs) {\n let dirToPlayer = directionAtoB(this, getPosByXY({x: 1, y: 1}));\n return roundDirection(dirs, dirToPlayer);\n}\n\n// 巡邏右上角狀態下的 AI\nBlinky.scatterAI = function (dirs) {\n let dirToPlayer = directionAtoB(this, getPosByXY({x: 26, y: 1}));\n return roundDirection(dirs, dirToPlayer);\n}\n\n// 巡邏右下角狀態下的 AI\nInky.scatterAI = function (dirs) {\n let dirToPlayer = directionAtoB(this, getPosByXY({x: 26, y: 30}));\n return roundDirection(dirs, dirToPlayer);\n}\n\n// 巡邏左下角狀態下的 AI\nClyde.scatterAI = function (dirs) {\n let dirToPlayer = directionAtoB(this, getPosByXY({x: 1, y: 30}));\n return roundDirection(dirs, dirToPlayer);\n}\n\nplayer.next = undefined;\nplayer.decision = function (dirs) {\n // 吃到「大力丸」\n if (map[player.target.y][player.target.x] == '*') {\n MOD = 'frightened';\n setTimeout(() =\u003e MOD = 'chase', 10000);\n }\n map.replace(player.target.x, player.target.y, ' ');\n\n let next = player.next;\n if (dirs.indexOf(next) != -1) {\n player.next = undefined;\n return next;\n } else {\n if (dirs.indexOf(player.direction) != -1) {\n return player.direction;\n }\n }\n};\n\nfunction restart() {\n enemies.forEach((e) =\u003e e.reset(14, 14, 0));\n player.reset(1, 1, 90);\n}\n\nfunction getPosByXY(pos) {\n return {\n x: pos.x * 15 + 8 + 80,\n y: pos.y * 15 + 8\n }\n}\n\nfunction directionAtoB(a, b) {\n let tmp1 = a.direction;\n a.toward(b);\n let tmp2 = a.direction;\n a.direction = tmp1;\n return tmp2;\n}\n\nfunction roundDirection(dirs, dir) {\n dirs.sort((a, b) =\u003e {\n let x = (a - dir + 360)%360;\n let y = (b - dir + 360)%360;\n x = x \u003e 180 ? 360 - x : x;\n y = y \u003e 180 ? 360 - y : y;\n return Math.abs(x) - Math.abs(y);\n });\n return dirs[0];\n}\n\nfunction dirAbs(dir) {\n return (dir + 360) % 360;\n}\n\nfunction antiReversion (sprite, dirs) {\n let idx = dirs.indexOf(dirAbs(sprite.direction - 180));\n if (idx != -1) dirs.splice(idx, 1);\n return dirs;\n}\n\nwhen('keydown', 'up', () =\u003e player.next = 0);\nwhen('keydown', 'right', () =\u003e player.next = 90);\nwhen('keydown', 'down', () =\u003e player.next = 180);\nwhen('keydown', 'left', () =\u003e player.next = 270);\n\nforever(() =\u003e {\n enemies.forEach((e) =\u003e {\n if (player.distanceTo(e) \u003c 5) {\n if (MOD == 'frightened') e.reset(14, 14, 0);\n else {\n life--;\n restart();\n }\n }\n if (MOD == 'frightened') e.opacity = .5;\n else e.opacity = 1;\n });\n\n print('life:' + life, 530, 10, 'white', 20);\n if (life \u003c= 0) {\n print('game over', 530, 30, 'red', 20);\n stop();\n }\n});\n\nrestart();","description":null,"note":null,"status":"public","like_student_ids":[],"is_featured":false,"views":289,"hashid":"rdvs422z","is_content_changed":false,"review_status":"unsubmitted","submitted_at":null,"reviewed_at":null,"advise":null,"is_deleted":false}
[{"id":480898,"file_name":"blue.png","project_id":25920,"asset_id":59483,"created_at":"2018-03-29T14:31:38.210+08:00","updated_at":"2018-03-29T14:31:38.210+08:00"},{"id":480899,"file_name":"orange.png","project_id":25920,"asset_id":59484,"created_at":"2018-03-29T14:31:38.212+08:00","updated_at":"2018-03-29T14:31:38.212+08:00"},{"id":480900,"file_name":"pink.png","project_id":25920,"asset_id":59485,"created_at":"2018-03-29T14:31:38.798+08:00","updated_at":"2018-03-29T14:31:38.798+08:00"},{"id":480901,"file_name":"red.png","project_id":25920,"asset_id":59486,"created_at":"2018-03-29T14:31:38.800+08:00","updated_at":"2018-03-29T14:31:38.800+08:00"},{"id":480902,"file_name":"yellow.png","project_id":25920,"asset_id":59487,"created_at":"2018-03-29T14:31:39.275+08:00","updated_at":"2018-03-29T14:31:39.275+08:00"}]
橘蘋學習平台
橘蘋學習平台
我的作品
檢視專案頁
匯出
複製
匯入
刪除
下載 Android APP (APK)
截圖
1:1:1
1:1
full
幫助
用手機掃描下方 QRCode 進行安裝
或您也可以
下載 APK
到這台電腦
用手機掃描下方 QRCode 進行安裝
或您也可以
下載 APK
到這台電腦