嵌入代碼
這一節需要用到各種代碼。
嵌入Python
Librian的嵌入Python可以用於實現劇本的邏輯,也可以成爲獨立的擴展功能。
這些代碼運行在同一個虛擬環境裏,在各處嵌入的代碼都會共享全局變量。如果你不希望這樣,也可以把你的代碼寫成Python文件然後 import
。
當然你可以用一些Python的黑魔法直接操作Librian(雖然我不會教你)。
全局函數參考
fusion(s)
- 將字符串
s
編譯後顯示到ADV畫面中。
樣例:
潘大爺 「我試試這樣說話……」
```
hp = 150
hp -= 50
fusion(f'潘大爺 「我還有{hp}點生命值!」')
```
潘大爺 「感覺不錯。」
goto(path=None, lable=None)
- 跳轉到另一個路徑爲
path
的劇本的一個躍點tag
的位置。
path
爲默認值將跳轉到當前劇本,lable
爲默認值將跳到那個劇本的開頭。
樣例:
```
hp -= 10
if hp < 0:
goto('gameover.liber')
```
潘大爺 「看來我還活着。」
call(path=None, lable=None)
- 與
goto
跳轉相同,此外目標劇本演出結束後回到調用處。
choice(*li)
- 產生一組選項。每個參數爲一個選項,包含一個選項名和一個函數。
在 劇本寫法 中的跳轉語句 ? 〇〇 -> 〇〇
,實際上是 choice
和 call
的語法糖。
? 接受治療 -> 壞結局.liber
? 放棄治療 -> 好結局.liber
? 蘿莉治療 -> 一章.liber, 原點
相當於
```
choice(
('接受治療', lambda: call('壞結局.liber')),
('放棄治療', lambda: call('好結局.liber')),
('蘿莉治療', lambda: call('一章.liber', '原點'))
)
```
adv_end()
- 使ADV演出結束。
别名
你也可以用中文來寫這些函數——
fusion
=同化
(沒錯這個不是「融合」而是「假魂的同化」)goto
=跳轉
|跳转
call
=調用
|调用
choice
=產生選項
|产生选项
adv_end
=演出終了
|演出终了
樣例
一點也不好玩的RPG遊戲——
```
from random import randint
def 攻擊(a, b):
傷害 = int(randint(8, 12) / 10 * a['攻擊力'])
b['當前生命'] -= 傷害
fusion(f"{a['名']}攻擊{b['名']}!造成{傷害}點傷害!{b['名']}的生命值{b['當前生命']}/{b['生命上限']}。")
def 淘汰之刃(a, b):
b['當前生命'] = 0
fusion(f"{a['名']}對{b['名']}使用淘汰之刃!{b['名']}的生命值{b['當前生命']}/{b['生命上限']}。")
大爺 = {'名': '大爺', '速度': 10, '攻擊力': 30, '當前生命': 100, '生命上限': 100}
敵人 = {'名': '敵人', '速度': 5, '攻擊力': 9, '當前生命': 80, '生命上限': 80}
```
```
if 大爺['速度'] > 敵人['速度']:
大爺的回合 = True
fusion('潘大爺 「智者先攻!」')
else:
大爺的回合 = False
```
*決鬥開始
```
if 大爺的回合:
choice(
('攻擊', lambda: 攻擊(大爺, 敵人)),
('淘汰之刃', lambda: 淘汰之刃(大爺, 敵人))
)
else:
攻擊(敵人, 大爺)
大爺的回合 = not 大爺的回合
```
```
if 敵人['當前生命'] <= 0 or 大爺['當前生命'] <= 0:
adv_end()
else:
goto(lable='決鬥開始')
```
一些坑
每次的代碼段總是會執行到底, goto
, call
, fusion
並不是即時的,他們真正的作用只是改變了劇本棧的順序,這導致在一個塊中多次調用會产生出乎意料的演出順序。
(我雖然想將讀者的實例改爲遞歸的來解決這個問題,但是卻發現這樣存在一個不能存檔的問題。)
舉這樣一個例子:
```
call('第一章.liber')
call('第二章.liber')
```
作家的想法是想要先演出第一章,第一章結束之後返回調用點,然後演出第二章。
但實際上的執行順序是 call('第一章.liber')
-> call('第二章.liber')
-> 演出第二章 -> 演出第一章。
因爲在 call
時候劇本的棧頂被先後壓入了第一章和第二章,成爲 (.., 當前劇本, 第一章, 第二章)
,第二章在棧頂導致先演出。
我想過的解決辦法是在每一次 call
的時候直接重建一個讀者實例,然後直接進入這個新實例執行,在這個實例執行完畢之後就可以回到調用點執行之後的語句了……但問題是存檔時只能儲存劇本棧不能儲存調用棧,也就是無法在新劇本執行完畢之後返回調用點。
也就是說,由於這個問題,這個做法暫時只能寫成:
```
call('第一章.liber')
```
```
call('第二章.liber')
```
嵌入JavaScript
如果你想要直接操作前端來做一些很酷的事情,也可以試着嵌入JavaScript代碼。
樣例:
alert('你好呀!')
不行我想不出來,以後再補吧(笑)。
嵌入HTML
在前端有一個層 <div id='html疊加'>
,你可以直接往其中寫入HTML代碼。
每次使用HTML代碼段,都會將上次的代碼覆蓋。
總表
語言類型 | 重複使用 | 作用域 | 存檔 |
---|---|---|---|
Python | 疊加 | 共享 | 存檔 |
JavaScript | 疊加,但在停滯點之間會覆蓋 | 全局 | 不存檔 |
HTML | 覆蓋 | - | 存檔 |
CSS | 覆蓋 | - | 存檔 |
SASS/SCSS | 覆蓋 | - | 存檔 |
現在 HTML / CSS / SASS / SCSS 共用同一個空間,它們也會互相覆蓋。