# 第 11 章 【互動系統與模擬】物件導向與向量 - Class 粒子系統 [老師講義](https://course.creativecoding.in/note/chap/11) 物件封裝 自有的狀態 速度 等 行為抽象化 Leap motion 物件導向 遊戲 案例分享 https://www.dstrict.com/ART https://natureofcode.com/book/chapter-6-autonomous-agents/ > 或許下一個讀書會內容可以看這個 模擬物理系統講的滿好的書 ```js // 建立一個球的原型 class Ball{ constructor(args){ //初始化物件的時候會被執行的方法 this.p = args.p } move(){ // 每個由 Ball 實例化出來的物件都會有的方法 this.p.x++ } doSomething(){ ... } ... } ``` ```jsx= //直接把 draw() 跟 update() 寫在 class Ball{...} 裡面的話,就可以直接使用 ball.draw() 與 ball.update() 方法了 class Ball{ constructor(args){ this.r = args.r this.color = args.color this.p = args.p ... } draw(){ push() //加入 push&pop確保畫布不會亂跑 fill(this.color) ellipse(this.p.x, this.p.y, this.r) pop() } update(){ this.p.x += this.v.x this.p.y += this.v.y } ... } for(let i=0; i<balls.length;i++){ let ball = balls[i] // 繪製 draw() 的部分 ball.draw() // 更新位置 update() 的部分 ball.update() } ``` new Ball class constructor(args) 把args 包成物件 method間不需要逗號 記得善用 push() pop() 用 mode 方式改變群組內的變化 this.mode == 'happy' 再加上眼睛 移比較快等 ellipse 是以直徑來設定 記得 ```js for(let o =0; o<8 ; o++){ rotate(PI/4) beginShape() for(let i=0; i< 30;i++){ vertex(this.r/2 + i/2, sin(i /10)*10) } endShape() } ``` 互動 ```js function mousePressed(){ for(let ball of balls){ ball.escape(); ball.setHappy(); } } ``` 讓每隻都不一樣 random ID = rid this.rid = random(10000) 讓一些起始角度/速動都跟rid有關 檢查 class內的method ```js isBallInRanged(){ let d = dist() d<dist? 1: 0 } draw()裡面 if(isBallInRanged){ ball.color == } ``` 把setHappy, setCrazy整合起來變成 setMode(mode) 11-4 換成 Vector (x,y) P5.Vector https://p5js.org/reference/#/p5.Vector v1.add(v2) v1.mult(0.99) createVector(mouseX,mouseY) 向量好處 較複雜的操作 ```js let mouseV = createVector(mouseX,mouseY) let delta = mouseV.sub(this.p).limit(2) this.p.add(delta) 小心會動到原本的值 記得先.copy() ``` 值日生: Frank 【互動系統與模擬】物件導向與向量 - Class 粒子系統 多物件互動與鍵盤事件 互動遊戲常用: 讓第二種物件跟病毒做互動吧 crazy, mousePressed, InRange 之前的函式先 command 掉不要觸發 創造第二種物件:子彈 發射子彈攻擊這些病毒 碰到病毒的時候 病毒會死掉 新增 Class Ball 怕整個 code 太長可以開第二個 tab 習慣整理 Code 是程式設計師的美德(K) 新增 Class Bullet 基本屬性:位置 速度 加速度 動作:update, draw 假設從左上角射子彈好了,所以初始的位置是 (0,0) 記得利用 Vector createVector(1,1) 往右下移動 新增一個陣列 Array,裝所有的子彈 ``` var bullets = [] ``` 滑鼠點下去的時候,就 ``` let bullet = new Bullet() // 新增一個子彈 bullets.push(bullet) // 加入陣列 ``` !! B 記得大寫代表他是類別 把子彈畫出來 ``` for(let bullet of bullets) ``` 做一個類似堡壘的東西在中央 從中央開始射 這樣改起來很容易 位置: ``` x = width/2 y = height/2 mode = CENTER ``` 子彈碰到這個病毒的時候,希望他們兩個就消滅掉 mouse in range 修改成 Ball In Range 概念:每一個 ball 取出來之後呢,我們要檢查每一顆子彈 ``` for(let bullet of bullets) { ... } ``` 碰撞? ``` hitResult = ball.isBallInRange() // return True || False ``` 子彈的速度: bullet 產生的時候用 createVector 然後取中心點跟滑鼠之間之間的差距量 ``` createVector(mouseX-width/2,mouseY-height/2) ``` 限制長(速)度,後面接 ... ``` .limit(5) || limit(10) ``` 與其用 limit() 我們可以直接用 setMag() 固定速度 ``` setMag(10) ``` 移除物件 ``` hitResult ? ball.dead = true : ball.dead = fasle ``` ``` draw(){ if(this.dead) { return } } ``` 把剛剛的 rect 改成可操作的船? KeyPressed vs KeyisPressed KeyPressed 只觸發一次 KeyisPressed 持續觸發 ``` print(key) // 看按鍵的程式代號 ``` 作業: 船做成 Class 加入爆炸?