{"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":"/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":460,"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"}]
Orange Apple Learning Platform
My Projects
View Project Page
Export
Remix
Import
Delete
Download Android APP (APK)
Screenshot
繁中
简中
English
日本語
1:1:1
1:1
Full Width
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer
Scan the QRCode below with your phone to install
Or you can
download APK
to this computer