0725

2026년 7월 25일


6월 말에 한번 해봐야겠다 한

미니 프로젝트가 마무리되었다.

내가 옛날에 개발하고, 완성되지 못한 채 방치되어 있던

노벨 스크립터를 내 최신 엔진에 추가하는 것.

그리고 그 노벨 엔진 구현체로

AIR 의 한 장면을 만들어 보는 것.

이 두 개가 이번 프로젝트의 핵심이었다.

구겨진 말뭉치들 의 7월 5일 글을 보면 알겠지만

실질적으로 프로젝트 시작한 날은 20일 전이고 -

순수 개발시간만 측정해 보면

대략 일주일정도 들었던 것 같다.


그러면 먼저, 내 엔진의 변경점부터 소개해 보겠다.

첫 번째, 텍스트렌더링을 갈아엎었다.

원래는, 내가 몇 년 전부터

Freetype 표준을 지키지 않은,

눈대중으로 만든 텍스트 셰이핑 알고리즘을 썼었다.

내가 직접 검증한 ttf 파일은 괜찮지만,

"아무 폰트나 가져와도 잘 작동(=셰이핑이 잘 된다)한다"

라는 보장이 없었다.

(실제로 H / V 정렬 관련해서 문제가 굉장히 많았다)

그런데, 비주얼 노벨 엔진에

텍스트 렌더링이 매우 중요한 요소인데

이렇게 대충 만들면 안되겠다 싶어서

glyph / font metrics 관련 표준 사양을 추가해 주었다.

0725.gif

위 GIF를 보면, 이제 글리프 CPU 컬링 & GPU 클리핑도 완벽하게 동작한다.

이것도 언젠가는 꼭 갈아 엎어야지 하던 기능이다.


두 번째, 스크립터를 위한 기능 및 TransitionSprite2D 추가되었다.

위 영상을 보면, Window slice나 Alpha Blending같은 효과로

트랜지션을 적용하는 걸 볼 수 있다.

이는 새로 만든 TransitionSprite2D 로 구현되었다.

또, GUI 단에 mouse_passthrough 라는 필터 속성을 달아서

IControl 이 기본적으로 hovered_object를 잡고,

저 속성에 따라서 입력을 아예 못 받게 만들 수 있게 했다.


세 번째, 비동기 에셋 로더가 클래스화되었다.

원래는 동기적으로 몇 개의 이미지만 로딩했지만

엔진을 어느정도 올렸다면 필수적인 기능인,

비동기 에셋 로딩을 구현했다.

그냥 스레드풀 쓰는 걸 클래스화 시켜주었다.


스크립터를 소개해보겠다.

전체적인 구조는, 전에 쓴 글에서 소개한

옛날 구조와 똑같다.

다른 점이 있다면,

리소스 로딩 부분에서

res 라는 키워드를 만들어서

이미지 / 오디오 / 보이스 팩을

직렬화시켰다.

또 global_state 랑 save_state 를 만들어서,

각각 전역 변수(세이브파일과 상관X)와 세이브파일 변수를

저장할 수 있게 했다.

가장 크고, 혁신적인 변경점이라고 하면

파이썬을 적극 도입했다는 것이다.

옛날에는 setvar 라는 명령이 있어서

a 라는 변수에 값 리터럴을 지정하는 방식이었는데,

그때는 내가 인터프리터를 직접 만들다 보니까

기본적인 산술연산은 물론

배열, 함수, 클래스, 메서드 같은 걸

전부 구현해야 했다.

(너무 귀찮았다)

이번 구현에는, 옛날부터 알고 있던

pocketpy 라는 C++ 용 파이썬 인터프리터를 추가해서

(pkpy의 최신 버전은 이식성 때문에 C로 다시 쓰인 듯 하다)

@ "파이썬 코드"

이렇게 문자열을 넘기면

그대로 파이썬을 쓸 수 있게 하였다.

이게 좋은 점이,

파이썬 문법으로 변수를 만들어 두면

조건문이나 대사에서도

"a >= 10 and a % 2 == 0"

이런 조건을 그대로 쓰거나

"변수 a의 값은 {a}입니다"

이렇게 대사 안에다가 변수를 출력할 수 있다.

(실제로 전부 지원하는 기능이다)


이전 글에서도 언급했지만,

'어느 시점에서라도' 게임을 저장하고

불러오는 기능은

완벽하게 구현되었다.

또, persistent 파일이 존재해서

global_state 소속 변수를 영구적으로 저장하고

현재 대사를 '한 번이라도 보았는지' 여부를 저장해 두어서

'읽은 곳까지 넘기기' 기능을 만들 수 있다.


위 영상에서 쓴 스크립트는 다음과 같다.

스크립트 펼치기

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
res bg {
    미스즈첫만남 : image = "bg/미스즈첫만남.png",
    제방         : image = "bg/제방.png",
    상점         : image = "bg/상점.png",
    검정         : image = "bg/검정.png",
}

res stand {
    m_a기본 : image = "stand/A_기본.png",
    m_a권유 : image = "stand/A_권유.png",
    m_a눈웃음 : image = "stand/A_눈웃음.png",
    m_a울상 : image = "stand/A_울상.png",
    m_b기본 : image = "stand/B_기본.png",
    m_b놀람 : image = "stand/B_놀람.png",
    m_b눈웃음 : image = "stand/B_눈웃음.png",
    m_b아쉬움 : image = "stand/B_아쉬움.png",
    m_b어색 : image = "stand/B_어색.png",
    m_b주스 : image = "stand/B_주스.png",
}

res voice {
    // voicepack 이란?
    // 폴더를 받고,
    // 그 안의 모든 오디오 파일의 이름이 '숫자' 라고 가정.
    // 그 모든 오디오를 로딩한 후 - 
    // 
    // setvoiceenabled true
    // 
    // setvoicepack "voice.AIR_VoicePack"
    // 
    // setvoiceindex 64
    // ...
    // setvoiceindex 130
    // 
    //      이런 식으로 써준다.

    AIR : voicepack = "koe/",
}



label main {

    // ···
    // ⋯
    // •••
    // 
    // 총 63부터 156까지 필요.
    // 
    // 63 ~ 88
    // 
    //      89 ~ 114
    // 
    //      115 ~ 150
    // 
    // 151 ~ 156

    @ "
class Align:
    pass

Align.CENTER = (800.0, 540.0)

MISUZU_STAND_SIZE = (1024, 768)
    "

    setchar "m" "목소리"
    setchar "y" "유키토"

    setbg "bg.제방"

    setvoiceenabled True
    setvoicepack "voice.AIR"
    setvoiceindex 63

    // 63
    m "으음···"

    hideui 1.0
    transbg "bg.미스즈첫만남" "windowslice" 2.0
    showui 1.0

    "바로 옆에 서서, 몸으로 바람을 쐬고 있는 소녀가 있었다."

    setvoiceenabled False
    y "··· ··· ···"
    setvoiceenabled True


    "그것은 흡사, 하늘을 나는 듯한 모습."
    "나는 숨을 멈춘 채 바라보았다."
    "하지만 그것은 한순간이었다."
    "그녀의 발밑을 보았다."
    "그녀는 내가 앉아있는 제방 콘크리트 위에 분명하게 서 있다."
    "그래서 곧 흥미를 잃었다."

    setchar "m" "소녀"

    // 64
    m "음~"

    hideui 1.0
    transbg "bg.제방" "blendalpha" 2.0
    showui 1.0

    // 65
    m "핫···"

    "소녀는 긴 기지개를 끝내고, 나를 향해 돌아서서 방긋 웃었다."
    "나는 소녀를 무시하고 정면을 바라보았다."

    showstand "misuzu" "stand.m_a기본" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

    // 66
    m "안녕하세요~"

    transstand "misuzu" "stand.m_a눈웃음" 0.5

    // 67
    m "주먹밥이 커다랗네요"
    // 68
    m "음료수 없어도, 괜찮아요?"
    "말을 걸고 있는 듯하다."
    // 69
    m "사올게요"

    hidestand "misuzu" 0.5

    "제방에서 휙 뛰어내리곤, 내 눈앞을 지나서 다다다 뛰어갔다."
    "점심시간에 잠시 빠져나왔나?"
    "교복도 입고 있으니, 그녀는 틀림없이 저 학교 학생이다."
    "자판기에서 종이팩 주스를 산 뒤, 다시 뛰어오고 있다."
    "···뛰어오는 도중에, 넘어졌다."
    "주스가, 제각기 다른 방향으로 굴러갔다."
    "울상을 지은 채 일어나서는, 열심히 돌아다니며 주스를 주워서 겨우 내가 있는 곳까지 돌아온다."

    showstand "misuzu" "stand.m_a눈웃음" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

    // 70
    m "받아요"
    "한껏 웃는 얼굴로 아무 일도 없었다는 듯이, 나에게 주스 하나를 내민다."
    // 71
    y "수고했어"

    transstand "misuzu" "stand.m_a울상" 0.5

    // 72
    m "가, 가오···"
    "곧장 울상이 된다."
    // 73
    y "다쳤으면, 돌아가"
    // 74
    m "괜찮아요···"

    hidestand "misuzu" 0.5

    "그렇게 말하면서, 내 옆에 앉는다."



    "신경 써주는 게 아니라, 그냥 귀찮았다."
    "주스 용기 옆면에, 붙어있던 빨대를 꽃는다."
    "후루루룩."
    "목으로 흘러넘긴다."
    "물컹···"

    // 75
    y "푸웁···!"
    "예상도 하지 못한 이상한 감각이 들어, 곧장 내용물을 뱉어낸다."
    y "뭐야, 이건···"
    "나는 주스 라벨을 본다."
    "··· \"물컹물컹 걸쭉, 복숭아맛\""
    setvoiceenabled False
    y "··· ··· ···"
    setvoiceenabled True
    "나는 종이팩을 거꾸로 뒤집어서는 쥐어짠다."
    "뚝   뚝···"
    "뚝뚝뚝···"

    showstand "misuzu" "stand.m_b놀람" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

    m "와···"
    "그것을 본 소녀가 황급히 내 손을 잡고는, 말린다."

    transstand "misuzu" "stand.m_a울상" 0.5

    m "어째서, 그런 짓을 하는 걸까···"
    "다시 또 울상."
    // 79
    y "날 놀리는 거잖아"
    m "그런 거 아니에요"
    "보니까, 소녀가 마신 주스도, 같은 라벨이었다."

    transstand "misuzu" "stand.m_a권유" 0.5

    // 81
    m "맛있어요, 이거"

    "놀리는 기색 하나 없이, 내게 진심으로 권하는 것이었다."
    m "필요 없어요?"
    y "필요 없어"

    transstand "misuzu" "stand.m_b아쉬움" 0.5

    m "음~·· 그럼, 내가 두 개 다 마실게요···"
    y "엉, 애시당초 네 거잖아"
    setvoiceenabled False
    m "··· ··· ···"
    setvoiceenabled True
    "서운한 듯한 표정이다."

    transstand "misuzu" "stand.m_b어색" 0.5

    // 86
    m "기뻐서 그래요~"
    "그런 듯하군."


    hidestand "misuzu" 0.5

    "나는 후딱 끼니를 때우고 이 장소를 떠나고 싶다."
    "하지만 거대한 주먹밥은 아직 절반도 줄지 않았다."
    setvoiceenabled False
    m "··· ··· ···"
    setvoiceenabled True
    "똑."

    showstand "misuzu" "stand.m_b주스" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

    "··· ··· ···"
    "꼬록꼬록꼬록···"
    "진한 액체가 목을 타고 지나가는 소리가 들려온다."
    "꿀꺽꿀꺽꿀꺽···같은 상쾌한 소리와는 상당히 멀다."
    "그 소리를 듣기만 해도 체할 것 같다."
    "얼른 주먹밥을 해치우기로 한다."
    "우물우물···"

    transstand "misuzu" "stand.m_a기본" 0.5

    // 87
    m "목이 메이면, 말해요"
    // 88
    y "너도"

    hidestand "misuzu" 0.5

    "나는 주먹밥을 다 먹고, 제방에서 뛰어내린다."
    "이제부터 어떻게 할까?"
    "물론 인형을 찾아야 하겠지만, 우선 기분 나쁜 주스를 마시는 녀석에게서 떨어지고 싶다."

    choice {
    case "걸어간다" {

        setvoiceindex 89

        hideui 1.0
        transbg "bg.상점" "windowslice" 2.0
        showui 1.0


        "나는 걷기 시작했다."
        "뒤에서 발소리가 난다."
        "총총총···"
        "뒤를 돌아보자 아니나 다를까, 소녀가 따라오고 있다."
        "나와 눈이 마주치자, 미소를 짓는다."
        "내가 빠르게 걷자, 이번에는 다다다다 뛰어서 따라온다."
        "나는 걸음을 멈추고, 뒤돌아 본다."

        showstand "misuzu" "stand.m_a기본" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

        setvoiceenabled False
        m "··· ··· ···"
        setvoiceenabled True
        // 89
        y "··· ··· ?"
        setvoiceenabled False
        m "··· ··· ···"
        setvoiceenabled True

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        m "··· 쓰레기, 쓰레기"
        "가까이 있던 쓰레기통에, 빈 종이팩을 버린다."
        y "그럼 이만"

        transstand "misuzu" "stand.m_a권유" 0.5

        m "잠깐만요"
        y "뭐야"

        transstand "misuzu" "stand.m_a기본" 0.5

        // 94
        m "해변에 가요"

        // 95   
        y "어째서?"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        // 96   
        m "놀고 싶으니까요"
        // 97   
        y "뭐···?"
        // 98   
        m "어제, 아이들이 거기서 놀았어요."

        transstand "misuzu" "stand.m_a기본" 0.5

        // 99    
        m "계속 바라보고 있었어요."
        // 100   
        m "즐거워 보이네, 나도 놀고 싶어~하고"
        // 101    
        m "계속 그렇게 생각했어요"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        // 102     
        m "곤히 잠든 당신 곁에서요"
        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        // 103     
        m "어제 저녁에 잤죠? 아까 거기에서"

        transstand "misuzu" "stand.m_b눈웃음" 0.5

        // 104     
        m "한가하나 싶어서, 계속 찔러봤어요."
        // 105      
        m "배나 등을 쿡쿡 말예요"
        // 106      
        m "그래도 전혀 일어날 기미가 안 보여서, 포기했어요"
        // 107 
        m "아주 지쳤었나 봐요"

        transstand "misuzu" "stand.m_a기본" 0.5

        // 108
        m "피로는 풀렸어요?"
        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True

        transstand "misuzu" "stand.m_a눈웃음" 0.5
        // 109
        m "오늘은 한가해요?"


        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        "··· 이상한 녀석이다."
        "설마 내가 그렇게 착한 청년처럼 보이는 걸까?"
        "혹은 뭔가, 다른 꿍꿍이를 갖고 행동하는 걸까?"
        "돈은 갖고 있으려나?"
        "마침 집에 방이 하나 비어있지는 않을까?"
        "마침 아버지가 일이 많아서 늦게 귀가하시면, 저녁밥을 얻어먹을 수 있지 않을까···?"
        "여러 가지 생각이 소용돌이쳤다."
        "아니야, 하고 그것들을 전부 지워버렸다."
        "아무리 우호적이라도, 이런 녀석과는 엮이지 않는 것이 무난하다."
        "타박상 입은 발목으로 걸음을 돌리면서 나는 그렇게 생각한다."

        transstand "misuzu" "stand.m_b기본" 0.5

        // 110
        m "자, 가요!"
        "어느샌가 내 앞에 서서 팔을 끌어당기고 있다."
        // 111
        y "아니··· 나는 바빠"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        // 112
        m "하지만 어제도 잤고, 오늘도 주먹밥을 먹었잖아요"
        // 113
        y "그건 휴식이야. 휴식도 필요하잖아"

        transstand "misuzu" "stand.m_a울상" 0.5

        // 114        (걸어간다)
        m "그동안은 한가···"

    }
    case "달려간다" {

        setvoiceindex 115

        showstand "misuzu" "stand.m_a기본" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        "빤히~"
        "눈이 마주치고 있다···"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        // 115
        m "니하하"
        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        y "대시!"
        "즉각 자세를 잡고 달려간다."

        hidestand "misuzu" 0.2

        hideui 0.6
        transbg "bg.검정" "windowslice" 1.6
        showui 0.6



        m "와···"
        "소녀가 깜짝 놀라며 소리를 질렀지만, 나는 뒤돌아 보지 않는다."


        hideui 0.6
        transbg "bg.상점" "windowslice" 1.6
        showui 0.6


        "그대로 정통으로···"
        // 이때 스크린셰이크가 있음.
        "퍽!"
        y "크억···"
        "방치되어 있던 세발자전거에 내 다리를 박았다."
        y "(누구냐! 빌어먹을 자식)"
        "근처 아이가 이쪽을 가만히 보며 우뚝 서 있다."
        y "젠장···"
        "다리가 아파서, 제대로 달릴 수 없다."
        "한 쪽 발로 스카이콩콩 타듯이 뛴다."
        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        "엉망진창 꼴사납다."
        "문득 바보 같아져서, 달리기를 멈춘다."

        // 121
        m "저기··· 안 아파요?"
        "내 뒤에서 말을 건네고 있다."
        y "엉, 이 정도 쯤이야"

        showstand "misuzu" "stand.m_a기본" "(Align.CENTER, MISUZU_STAND_SIZE)" 0.5

        m "··· 그치만 총총거리며 한 쪽 다리로 뛰었는걸요"
        y "애들이 있으니까 좀 익살스럽게 행동해봤어"

        transstand "misuzu" "stand.m_b눈웃음" 0.5

        m "웃겼어요. 생각만 해도 웃음이 나와요"
        m "니하하"
        "최악이다···"
        "소녀는 웃는 얼굴로, 아직 덜 마신 주스 빨대에 입을 댄다."
        y "···그래서 나한테 뭐 용건 있어?"

        transstand "misuzu" "stand.m_b주스" 0.5

        "소녀가 주스를 후루룩거리며 끝까지 마시고서 고개를 든다."

        transstand "misuzu" "stand.m_a기본" 0.5

        // 128
        m "해변에 가요"
        y "뭐?"
        // 130
        m "해변, 저기"
        "뒤를 가르킨다."

        // 131
        y "어째서?"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        // 132
        m "놀고 싶으니까요"
        //  133
        y "뭐···?"
        // 134
        m "어제, 아이들이 거기서 놀았어요."

        transstand "misuzu" "stand.m_a기본" 0.5

        // 135
        m "계속 바라보고 있었어요."
        // 136
        m "즐거워 보이네, 나도 놀고 싶어~하고"
        //  137
        m "계속 그렇게 생각했어요"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        //  138
        m "곤히 잠든 당신 곁에서요"
        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        // 139
        m "어제 저녁에 잤죠? 아까 거기에서"

        transstand "misuzu" "stand.m_b눈웃음" 0.5

        // 140
        m "한가하나 싶어서, 계속 찔러봤어요."
        // 141
        m "배나 등을 쿡쿡 말예요"
        // 142
        m "그래도 전혀 일어날 기미가 안 보여서, 포기했어요"
        // 143
        m "아주 지쳤었나 봐요"

        transstand "misuzu" "stand.m_a기본" 0.5

        // 144
        m "피로는 풀렸어요?"
        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True

        transstand "misuzu" "stand.m_a눈웃음" 0.5
        // 145
        m "오늘은 한가해요?"

        setvoiceenabled False
        y "··· ··· ···"
        setvoiceenabled True
        "··· 이상한 녀석이다."
        "설마 내가 그렇게 착한 청년처럼 보이는 걸까?"
        "혹은 뭔가, 다른 꿍꿍이를 갖고 행동하는 걸까?"
        "돈은 갖고 있으려나?"
        "마침 집에 방이 하나 비어있지는 않을까?"
        "마침 아버지가 일이 많아서 늦게 귀가하시면, 저녁밥을 얻어먹을 수 있지 않을까···?"
        "여러 가지 생각이 소용돌이쳤다."
        "아니야, 하고 그것들을 전부 지워버렸다."
        "아무리 우호적이라도, 이런 녀석과는 엮이지 않는 것이 무난하다."
        "타박상 입은 발목으로 걸음을 돌리면서 나는 그렇게 생각한다."

        transstand "misuzu" "stand.m_b기본" 0.5

        // 146
        m "자, 가요!"
        "어느샌가 내 앞에 서서 팔을 끌어당기고 있다."
        // 147
        y "아니··· 나는 바빠"

        transstand "misuzu" "stand.m_a눈웃음" 0.5

        // 148
        m "하지만 어제도 잤고, 오늘도 주먹밥을 먹었잖아요"
        // 149
        y "그건 휴식이야. 휴식도 필요하잖아"

        transstand "misuzu" "stand.m_a울상" 0.5

        // 150     (달려간다)
        m "애들도 웃겨줬고···"
    }
    }


    setvoiceindex 151

    setvoiceenabled False
    y "··· ··· ···"
    setvoiceenabled True

    // 151
    y "물건을 찾고 있어. 언제나 그 일로 머릿속이 꽉 차있다구"

    transstand "misuzu" "stand.m_a기본" 0.5

    // 152
    y "그래서 놀아줄 수 없어"

    transstand "misuzu" "stand.m_a눈웃음" 0.5

    // 153
    m "그러면 같이 찾아요~"
    // 154
    m "이 근처에요?"
    // 155
    y "북극이나 남극이나 둘 중 한 곳이라고 생각해"

    transstand "misuzu" "stand.m_a기본" 0.5

    // 156
    m "그럼, 다녀올게요~"

    hidestand "misuzu" 0.5

    "다다다···"
    setvoiceenabled False
    y "··· ··· ···"
    setvoiceenabled True
    "달려가고 말았다."
    "상당히 머리가 나쁜 녀석일지도 모른다."


    hideui 1.0
    transbg "bg.제방" "windowslice" 2.0
    showui 1.0

    "나는 인형찾기를 재개한다."

}

스크립트를 적으면서 신기했던 건,

저 장면에

걸어간다 / 달려간다 분기가 있는데,

처음에는 해변에 가자고 하는 대사까지 나뉜 줄 알았던 게

약간씩 다른 보이스파일로

더 길게 나뉘어 있었다는 점이다.


오랜만에 진행한 미니 프로젝트다 보니

잘 끝나서 뿌듯하다.

마지막 글이 3달 전이어서

속도낸 것도 있는듯


++ 추가

System Tween에, 모든 트위닝이 끝나면 resume하는 WaitForAll 도 추가해주었다.

co_await WaitForAll(...)