• 沒有找到結果。

Stream 套件,讓運行此領域專屬語言的引擎引入參與者模型 (actor model),高效 率管理分散式環境下的各個參與裝置(感應器、Unity 程式)。

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

52

最後,我們透過程式化展演規則,實現了讓實體展演者與虛擬環境的角色或 場景之間互動得以更程式化的支援,我們另外設計了一款輕量級的圖形化編輯器,

提供不具程式設計經驗的 DIPS 腳本撰寫者一個直覺與快速的開發工具,且能夠 輕易擴充或客製化,達到降低使用與學習該語言的門檻之目的。

置,如此一來,導演的描述便可擴充如下:『when(actor body state) { action1 } otherwise {action2}』,本系統便可具更多個演員或多個虛擬角色、場景互動的能 力,語言能力也更強,此外這樣還更一個優點,導演可以組合演員與肢體,再由 演員與肢體的組合來產生對應的狀態與動作,提高導演編寫的自由度,函式庫的 可擴充性也更高。

結束,例如我們註冊了一個展演規則為『when(leftHandUp){ noseRaise }』,則該 表演過程中,左手舉起規則便完全綁定鼻子舉起的動作效果,但是一個表演節目

DemoDevice 與 DemoBody 兩部分,以提高不同裝置的辨識度。

由於本研究旨在虛實環境與DIPS 執行引擎的整合,因此我們保留該實作的 彈性空間給予未來的實作。

通訊資料格式的改善

目前解譯實體裝置送來的感應器資料時,研究計畫中定義的資料格式為

『{"device": {"x" : "...", "y": "...", "z": "..."}} 』,例如收到來自左手的訊號,其資 料內容為『{"LeftHand": {"x":"25.364231", "y":"54.123158", "z":"0.546548"}} 』,

這樣的資料格式在解析 JSON 內容時會遇到無法直接取得裝置名稱的狀況,因為 多數的解析器(parser)實作不會提供存取『key』名稱(此例 key 名稱是 LeftHand) 的方法,本實作目前是透過另外解析資料字串以取出裝置名稱。

多數的 JSON 解析器實作都更個慣例,就是不會把資料存放在 key 中,理 想上的資料格式建議遵守『Micha's Golden Rule』,Mike Dewar [15]提出使用該資 料格式來處理 JSON,可以提高 D3.js 在資料選取上的便利與效率,因此目前的 資料格式建議改成『{"body": "DeviceName", "position": {"x" : "...", "y": "...", "z":

"..."}}』這樣的格式 ( key [field] : value [data] )。

陣列內容為:[ number_of_device, value_of_x, value_of_y, value_of_z ],其中第一 項 number_of_device 為定義好的裝置編號(客製化時通訊各方統一好更哪些裝置,

便可定義出裝置編號),可以整數來編號,其它為座標值,精確度為單精度浮點 數,其長度為 4 位元組,如此則各欄位長度皆為 4 位元組(byte),共 16 位元組,

相較現行格式之最短可能內容:『{"A":{"x":"0.0","y":"0.0","z":"0.0"}}』長度為 37 位元組,(裝置名稱長度不一,因此長度可能更長,且可能性很高,此亦增加解

1 val leftHandUpRule: Rule = when (leftHandUp) { 2 noseRaise

3 } 以及

1 val handsUpRule: Rule = when (leftHandUp and rightHandUp) {

2 noseLay

[1] Hsin Huang, Hsin-Chien Huang, Chun-Feng Liao, Ting-Chun Li, Tzzu-Chieh Tsai, Li-jia Teng, Future Circus: A Performer-Guided Mixed-reality Performance Art, 2015, International Symposium on Wearable Computers

[2] Sorensen, Andrew(2005) , Impromptu : an interactive programming environment for composition and performance. In: Proceedings of the Australasian Computer Music Conference 2009, 2-4 July 2009, Queensland University of Technology, Brisbane.

[3] Ingo Maier Martin Odersky., Deprecating the Observer Pattern with Scala.React, EPFL-REPORT-176887

[4] P. Hudak., Modular domain specific languages and tools., In P. Devanbu and J.

Poulin, editors, Proceeding of the 5th International Conference on Software Reuse (ICSR'98), pages 134-142. IEEE, 1998.

[5] Martin Fowler., Domain specific languages., Addison-Wesley Professional, 2010 [6] H. Conrad Cunningham., A Little Language for Surveys: Constructing an Internal

DSL in Ruby.

[7] Daan Leijen and Erik Meijer, Domain Specific Embedded Compilers, Proceedings of DSL'99: The 2nd Conference on Domain-Specific Languages, Austin, Texas, USA, October 3–6, 1999

[8] Carl Hewitt; Peter Bishop and Richard Steiger., A Universal Modular Actor For-malism for Artificial Intelligence., IJCAI. 1973.

[9] Gul A. Agha, Actors: A Model of Concurrent Computation In Distributed Sys-tems., 1985

[10] Akka Scala Documentation, Release 2.4-SNAPSHOT, Typesafe Inc.

[11] Evan Czaplicki, Elm: Concurrent FRP for Functional GUIs, 2012

[12] Zhanyong Wan, Paul Hudak, Functional Reactive Programming from First Principles, PLDI '00 Proceedings of the ACM SIGPLAN 2000 conference on Programming language design and implementation Pages 242-252

[13] Debasish Ghosh, Anshinsoft , DSL for the Uninitiated, June 1, 2011 [14] Mike Dewar, Getting Start with D3, O'Reilly, 2012

[15] 謝忠和, 全民做遊戲 Unity 3D 跨平台遊戲開發寶典, 2012 [16] DIPS DSL, https://github.com/NCCUCS-PLSM/scala-dsl [17] DIPS Demo, https://github.com/NCCUCS-PLSM/dsl-demo

[18] DIPS Demo Unity Part, https://github.com/NCCUCS-PLSM/dsl-engine-unity [19] Martin Fowler, Work in progress, http://martinfowler.com/dslwip/, 2007.

[20] Reactive Streams, http://www.reactive-streams.org

[21] vFavbric team , Choosing Your Messaging Protocol: AMQP, MQTT, or STOMP, http://blogs.vmware.com/vfabric/2013/02/choosing-your-messaging-protocol-amq p-mqtt-or-stomp.html

[22] Phidgets 1056 user guide, http://www.phidgets.com/docs/1056_User_Guide [23] MIT Scratch extension, http://wiki.scratch.mit.edu/wiki/Scratch_Extension [24] Google Blockly, https://github.com/google/blockly

[25] Arvin Hsieh, [Design Pattern] 觀察者模式 (Observer Pattern) 我也能夠辦報 社, http://www.dotblogs.com.tw/joysdw12/archiver/2013/03/13/96531.aspx

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

59

[26] 邓际锋, 函数式反应型编程(FRP) — 实时互动应用开发的新思路, InfoQ, 2013, http://www.infoq.com/cn/articles/functional-reactive-programming [27] CC 數位學習網, Unity 3D 教學, http://www.cg.com.tw/Unity

- implicit class SyntaxHelper(t: T) - def *(int: Int) = ev times (t, int) - def /(int: Int) = ev divide (t, int)

- def +(t2: T) = ev plus (t, t2) - def foldFun(s: Option[(T, Int)], t: T)

- def or(signal: Signal[Boolean])(implicit evidence: Signal[T] =:= Condition): Condition - def and(signal: Signal[Boolean])(implicit evidence: Signal[T] =:= Condition): Condition

- def _1[U](implicit evidence: Signal[T] =:= Signal[(U, _)]): Signal[U]

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

62

- def x(implicit evidence: Signal[T] =:= Signal[Pos]): Signal[Int]

- def y(implicit evidence: Signal[T] =:= Signal[Pos]): Signal[Int]

- def _2[U](implicit evidence: Signal[T] =:= Signal[(_, U)]): Signal[U]

case class FilterSignal[T](s: Signal[T], f: T => Boolean) extends Signal[T]

case class IntervalSignal[T](s: Signal[T], interval: Duration) extends Signal[T]

case class FoldSignal[T, U](s: Signal[T], start: U, f: (U, T) => U) extends Signal[U]

case class MappedSignal[T, U](s: Signal[T], f: T => U) extends Signal[U]

case class ZippedSignal[U, V](signal1: Signal[U], signal2: Signal[V], initialL: Op-tion[U] = None, initialR: Option[V] = None) extends Signal[(U, V)]

- def withDefaults(left: Option[U] = None, right: Option[V] = None):

ZippedSignal[U, V]

- private def choose[T](c1: Option[T], c2: Option[T])

case class Property[T](query: DeviceQuery, key: String) extends Signal[T]

case class SignalData[T](s: Signal[T], data: T)

case class Or(c1: Condition, c2: Condition) extends Condition case class And(c1: Condition, c2: Condition) extends Condition case class Not(condition: Condition) extends Condition

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

63

附錄二

Syntax.scala 類別與方法結構 object Syntax

- implicit class Ruler(actorRef: ActorRef) - def instruct(rule: Rule)

- object Location

- def inside(location: Location): LocationQuery - def not(query: LocationQuery): LocationQuery - object L

- def apply(s: String)

- implicit def functionToFunctionAction(f: () => Any)

- def zip[T, U](signal1: Signal[T], signal2: Signal[U]): Signal[(T, U)]

- def when(condition: Condition)(action: Action) - def not(condition: Condition)

- def not[T](f: T => Boolean) - def apply(t: T): Boolean

Rule.scala 類別與方法結構 object `package`

trait Rule

- def condition: Condition - def action: Action

- def elseAction: Option[Action]

case class IfRule(condition: Condition, action: Action) extends Rule - def otherwise(elseAction: Action)

case class IfElseRule(condition: Condition, action: Action, elseAct: Action) extends Rule

- override def elseAction case class ActorMessageAction[T](query: De-viceQuery, command: T) extends Action

case class ShowSignalAction[T](query: DeviceQuery, signal: Signal[T]) extends Action

case class FunctionAction(function: () => Any) extends Action case class Show[T](signal: Signal[T])

trait Action

- def and(action2: Action)

case class Then(action1: Action, action2: Action) extends Action case object DeleteRules

Device.scala 類別與方法結構 case class DeviceDescriptor(

case class NamedDeviceQuery(name: String) extends DeviceQuery - def matchesDescriptor(descriptor: DeviceDescriptor)

case class TypeDeviceQuery(typ: String) extends DeviceQuery - def matchesDescriptor(descriptor: DeviceDescriptor)

case class LocationDeviceQuery(query: LocationQuery) extends DeviceQuery - def matchesDescriptor(descriptor: DeviceDescriptor)

case class UUIDDeviceQuery(uuid: String) extends DeviceQuery - def matchesDescriptor(descriptor: DeviceDescriptor)

case class OutputsDeviceQuery(outputs: List[(String, Class[_])]) extends DeviceQuery - def matchesDescriptor(descriptor: DeviceDescriptor)

case class InputsDeviceQuery(inputs: List[(String, Class[_])]) extends DeviceQuery - def matchesDescriptor(descriptor: DeviceDescriptor)

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

66

trait GenericDeviceQuery extends DeviceQuery with Dynamic - def property[T](propertyName: String)

- def is(propertyName: String)

- def selectDynamic[T](propertyName: String) trait DeviceQuery

- def matchesDescriptor(descriptor: DeviceDescriptor): Boolean - def should[T](message: T)

- def shouldShow[T](signal: Signal[T]) object Device - def named(name: String)

- def ofType(type: String) - def inside(location: Location) - def withUUID(uuid: String)

- def thatOutputs(list: List[(String, Class[_])]) - def thatInputs(list: List[(String, Class[_])])

DemoDevice.scala 之類別實作

/**** Define supported physic devices. ****/

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

71

} }

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

72

附錄六

DemoState.scala 之狀態定義實作

/* x-axis state definition of left hand sensor */

val leftHandx: Signal[Float] = leftHand.property[Float]("LeftHandx") val lx: Signal[Float] = leftHandx.atRate(1 second)

val leftHandUp: Condition = lx < (-10).toFloat val leftHandDown: Condition = lx > 10.toFloat

/* x-axis state definition of right hand sensor */

val rightHandx: Signal[Float] = rightHand.property[Float]("RightHandx") val rx: Signal[Float] = rightHandx.atRate(1 second)

val rightHandUp: Condition = rx < (-10).toFloat val rightHandDown: Condition = rx > 10.toFloat

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

73

附錄七

DemoAction.scala 之動作命令實作

val noseRaise: Action = elephant should "noseRaise"

val noseLay: Action = elephant should "noseDown"

val bodyRaise: Action = elephant should "bodyRaise"

val bodyLay: Action = elephant should "bodyDown"

val keepElephantAction: Action = elephant should "keepAction"

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

74

附錄八

DemoEffect.scala 之特效命令實作 val lightOn: Action = light should "on"

val lightOff: Action = light should "off"

val keepLightAction: Action = light should "keepAction"

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

75

附錄九

Engine.scala 腳本執行引擎主程式 object Engine {

def main(args: Array[String]): Unit = { /* loading SDL script */

val filename = getClass.getResource("/DemoDSLScript.scala") val script = Source.fromURL(filename).mkString

/* parse and eval script */

val tb = currentMirror.mkToolBox() tb.eval(tb.parse(script))

} }

EngineDIPSCreator.scala 接收圖形化編輯器介面的執行引擎主程式 object EngineDIPSCreator {

var times = 0 var script = ""

def main(args: Array[String]): Unit = { val serverSock = new ServerSocket(12345)

// listening to socket request from DIPS creator while (true) {

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

77

} }

// Handle request from Scratch

def handleRequest(sockIn: InputStream): Unit = { val buf = new Array[Byte](5000)

val bytes_read = sockIn.read(buf, 0, buf.length)

val header = new String(Arrays.copyOf(buf, bytes_read)) val url = header.substring(header.indexOf("/?rule=")+7, head-er.indexOf("HTTP/1"))

val script = URLDecoder.decode(url, "UTF-8")

val tb = currentMirror.mkToolBox() tb.eval(tb.parse(script))

} }

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

78

附錄十一

展示動作的對應 DSL 腳本

1. 魔術師的左手向上舉起,做出指示大象鼻子舉起來的動作,魔術師的左手放 下,做出指示大象鼻子放下來的動作

1 val leftHandUpRule: Rule = when(leftHandUp){

2 noseRaise 3 } otherwise {

4 keepElephantAction 5 }

6 val leftHandDownRule: Rule = when(leftHandDown){

7 noseLay 8 } otherwise {

9 keepElephantAction 10 }

11 listener.instruct(leftHandUpRule) 12 listener.instruct(leftHandDownRule)

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

79

2. 魔術師的右手向上舉起,做出指示大象身體抬起來的動作,魔術師的右手放 下,做出指示大象身體放下來的動作

1 val rightHandUpRule: Rule = when(rightHandUp){

2 bodyRaise 3 } otherwise {

4 keepElephantAction 5 }

6 val rightHandDownRule: Rule = when(rightHandDown){

7 bodyLay 8 } otherwise {

9 keepElephantAction 10 }

11 listener.instruct(rightHandUpRule) 12 listener.instruct(rightHandDownRule)

‧ 國

立 政 治 大 學

N a tio na

l C h engchi U ni ve rs it y

80

3. 魔術師的雙手舉起,燈亮起來,魔術師的雙手放下,燈暗下來 1 val handsUpRule: Rule = when(leftHandUp and rightHandUp){

2 lightOn 3 } otherwise { 4 keepLightAction 5 }

6 val handsDownRule: Rule = when(leftHandDown and rightHandDown){

7 lightOff 8 } otherwise { 9 keepLightAction 10 }

11 listener.instruct(handsUpRule) 12 listener.instruct(handsDownRule)

相關文件