<div class="title">TWINE</div>
<div class="content">
(text-style:"fade-in-out")[(text-color:#82edf7)+(text-size:0.8)[아래의 파란 글자를 클릭해 내용을 확인해보세요!]]
[[Twine이란?->설명]]
[[사용법]]
[[퀴즈<-퀴즈 풀어보기]]
</div><div class="explanation">**Twine**은 선택지에 따라 이야기가 달라지는 대화형 비선형 스토리를 쉽게 만들 수 있는 도구입니다.
결과물이 HTML 파일인 웹 페이지 형태로 저장돼서 누구나 쉽게 확인할 수 있습니다.
Twine은 Passage라는 작은 상자를 연결하여 스토리를 이어지는 것을 시각적으로 확인할 수 있어서 초보자도 쉽게 설계할 수 있습니다. 당신이 **서울 2033**을 플레이해본 적이 있다면, Twine의 플레이 방식을 더 쉽게 이해할 수 있을 것입니다.
또한 이 도구는 오픈 소스이며 매우 가벼워, 프로그램을 다운로드하지 않고도 크롬 같은 웹 브라우저에서 바로 게임을 제작할 수 있습니다.
따라서 코딩 지식이 없어도 가능하며, 그래픽 사용자 인터페이스 (GUI)가 직관적이기 때문에 빠르게 이해할 수 있습니다. 또한 완성 결과물을 웹 페이지로 배포할 수 있고, 간단한 코드 (변수나 조건문 등)을 사용할 수도 있습니다.
텍스트 게임 특성 상 화려한 시각적 효과보다 스토리가 더욱 중요합니다. 하지만 만약 당신이 HTML과 CSS, Markdown에 대해서 알고 있다면, 보다 화려한 텍스트 게임 제작이 가능합니다. 게다가 Java Script까지 알고 있다면 더 돋보이는 게임을 만들 수 있을 것이라고 생각합니다.
<a href="https://twinery.org" target="_blank">Twine.org</a>에서 직접 만들어볼 수 있습니다.
사용법이 궁금하다면 왼쪽의 화살표를 눌러 이전 화면으로 이동하거나, [[사용법]]을 눌러 바로 이동하세요.
</div><div class="title">목차</div>
<div class="content">
(text-color:#82edf7)+(text-size:0.8)[모든 설명의 스타일 포맷은 Harlowe 이며,
화면 왼쪽(text-size:0.6)[(모바일의 경우 화면 위쪽)]의 화살표를 클릭할 경우 바로 이전/이후에 선택한 Passage로 이동됩니다.]
[[링크 만들기]]
[[오디오 설정하기]]
[[텍스트 꾸미기 -기본편-]]
[[텍스트 꾸미기 -심화편-]]
[[텍스트 한 번에 꾸미기]]
[[배경 꾸미기]]
[[이미지 추가하기]]
[[변수와 조건 설정하기 -기본편-]]
[[변수와 조건 설정하기 -심화편- ->temp2]]
[[JavaScript와 Stylesheet 사용하기->jsAndCss]]
[[Story Formats]]
[[Error List]]
</div>
<div class="bottom"><span class="bottom_link">[[메인으로 이동하기->start]]</span></div><div>
Twine 문제를 풀어봅시다.
문제는 할로우를 기준으로 출제되었습니다.
</div><div class="use">Twine에서 링크는 플레어어가 클릭할 수 있는 **선택지** 역할을 합니다. 링크를 클릭하면 다른 Passage로 이동하거나, 텍스트를 변화시키는 등의 동작을 수행합니다.
<img src="./default_link.png" width="620" height="400" alt="연결된 모습"/>
이미지와 같이 링크를 만들 수 있습니다. 기억해야 할 점은, Twine은 빈칸이 존재할 경우 다른 Passage로 판단합니다. 즉, '예'와 ' 예'를 다른 Passage로, '아니오'와 '아니요'를 다른 Passage로 인식합니다.
텍스트 게임인만큼 선택지에는 대사가 들어갈 수도 있고 문장이 들어갈 수도 있습니다. 하지만 Passage의 이름이 긴 건 가독성에도 좋지 않고 오타 등의 이슈가 생길 확률이 높습니다. 이를 위해 Twine은 ->를 제공합니다. 화살표가 나가는 방향에는 화면에 띄울 내용을, 화살표가 가리키는 방향에는 Passage 이름으로 등록하고 싶은 내용을 입력하면 됩니다.
<img src="./linkd.png" width="620" height="400" alt="연결된 모습"/>
실제로 실행된 화면에서는 긴 문장이 보이겠지만, Passage 명은 등교와 실패로 간단하게 보입니다. 참고로, 앞서 말했듯 Twine는 공백이 포함된 단어와 공백이 포함되지 않은 단어를 다른 단어로 보기 때문에 [화면에 보일 문장 -> Passage이름]과 [화면에 보일 문장 ->Passage이름]은 서로 다른 Passage로 연결됩니다.
Passage 뿐만 아니라 외부 링크 연결이 필요할 때도 있습니다. 이 경우에는 HTML 태그 중 `<a>`를 사용해야 합니다. 사용법은 아래와 같습니다.
<p class="code_block">`<a href="https://example.com" target="_blank">링크에 대해 설명하는 내용</a>`</p>target을 위와 같이 설정할 경우 새로운 창에서 해당 링크 페이지가 열립니다.
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="use">보기 좋은 텍스트 게임을 만들고 싶다면 먼저 텍스트를 꾸며야 합니다.
텍스트의 색을 지정할 때는 CSS를 쓰는 방법 외에도 Harlowe에서 지원하는 **text-color**를 사용할 수 있습니다. text-color는 아래와 같이 사용할 수 있습니다.
`(text-color:purple)[보라색]
(text-color:red+green)[혼합색]
(text-color:#bbd175)[Hex code]
(text-color:(rgb: 0,0,0))[rgb]
(text-color:(rgba: 0,0,0,0.5))[투명도를 설정하는 rgb]
(text-color:(hsl:20,0.4,0.6))[hsl]
(text-color:(hsla:):20,0.4,0.6,0.5))[투명도를 설정하는 hsl]`
(text-color:purple)[보라색]
(text-color:red+green)[혼합색]
(text-color:#bbd175)[초록에 가까운 색]
(text-color:(rgb: 2,2,2))[검은색]
(text-color:(rgba: 2,2,2,0.5))[반투명하게 설정]
(text-color:(hsl:20,0.4,0.6))[임의의 색]
(text-color:(hsla:20,0.4,0.6,0.5))[반투명한 임의의 색]
단, rgb 혹은 hsl 등에 존재하지 않는 값을 입력하면 오류가 발생하니 주의해야 합니다.
다음은 배경색을 지정하는 방법입니다. **background:**는 Harlowe가 지원하는 글자 배경색 변경 명령어 입니다. 사용법은 text-color와 동일합니다.
`(background:blue)[파란색 배경]
(background:red+green+blue)[혼합색 배경]
(background:#fea59)[컬러 코드 배경]
(background:(rgb:250, 0, 0))[rgb 배경]
(background:(rgba:250, 0, 0, 0.7))[반투명한 rgb 배경]
(background:(hsl:120, 0.8, 0.8))[hsl 배경]
(background:(hsla:120, 0.8, 0.8, 0.3))[반투명한 hsl 배경]`
(background:blue)[파란색 배경]
(background:red+green+blue)[혼합색 배경]
(background:#f2ea59)[컬러 코드 배경]
(background:(rgb:250, 0, 0))[rgb 배경]
(background:(rgba:250, 0, 0, 0.1))[반투명한 rgb 배경]
(background:(hsl:120, 0.8, 0.8))[hsl 배경]
(background:(hsla:120, 0.8, 0.8, 0.3))[반투명한 hsl 배경]
참고로 투명도는 0~1 사이의 숫자값을 가지며 1에 가까울수록 불투명하게, 0에 가까울수록 투명하게 설정할 수 있습니다.
다음은 글꼴을 변경하는 방법입니다. 글꼴을 적용하는 데에는 두 가지 방법이 있습니다. 첫번째는 브라우저에 설치된 폰트를 적용하는 방법이고, 두 번째는 폰트를 import하는 방법입니다.
첫번째 방식으로 폰트를 적용할 때는 CSS 외에 Harlowe에서 지원하는 **font:**를 사용할 수 있습니다.
`(font:"궁서")[궁서체입니다.]
(font:"webdings")[webdings체입니다. abcdefghiJKLMNOP]
(font:"캘리그라피")[브라우저에 존재하지 않는 글씨체]`
(font:"궁서")[궁서체입니다. font test]
(font:"webdings")[webdings체입니다.. abcdABCD]
(font:"캘리그라피")[브라우저에 존재하지 않는 글씨체는 적용이 되지 않습니다.]
위와 같이 적용하기 위해서는 브라우저에 해당 폰트가 존재해야 합니다. 내 브라우저에 존재하는 폰트는 **브라우저 오른쪽 상단 점 세개 -> 설정 -> 모양 -> 글꼴 맞춤설정**에서 확인할 수 있습니다.
두번째 방식으로 폰트를 적용할 때는 스타일시트에 해당 폰트를 @import해야 합니다. 현재 이 스토리스에 전체적으로 적용된 폰트는 <p class="code_block">@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100..900&display=swap');</p> 으로 호출한 폰트입니다.
스타일시트에 대한 내용은 [[JavaScript와 Stylesheet 사용하기->jsAndCss]] 에서 자세하게 확인할 수 있습니다.
<hr>
폰트까지 적용했으니 이제는 텍스트에 효과를 적용해봅시다. 텍스트에 효과를 주는 방법은 세 가지가 있습니다. 1. 특수 기호를 사용하거나, 2. HTML 태그를 사용하거나, 3. text-style을 사용하는 방법입니다.
먼저 특수기호를 사용하는 방법입니다. 오류 박스가 나오지 않는 가장 단순한 방법이지만 사용할 수 있는 효과가 한정되어 있다는 한계가 존재합니다.
` ''작은 따옴표 두 개로 굵게 표시하기''
**별 두 개로 굵게 표시하기 (주로 사용하는 방법)**
^^위첨자^^
~~취소선~~`
''작은 따옴표 두 개로 굵게 표시하기''
**별 두 개로 굵게 표시하기 (주로 사용하는 방법)**
^^위첨자^^
~~취소선~~
참고로 백틱 ( ` `` ` )으로 감싸면 특수문자나 명령어, HTML이 적용되지 않습니다.
다음은 HTML 태그를 사용하는 방법입니다.
`<B>`와 `<strong>` 태그는 <b>글자</b>를 <strong>굵게</strong> 표시합니다.
`<i>`는 글자를 <i>기울여서</i> 표시합니다.
`<strike>`는 글자에 <strike>취소선</strike>를 표시합니다.
`<u>`는 글자에 <u>밑줄</u>을 그립니다.
`<sup>`을 사용하면 글자를 <sup>위 첨자</sup>로 표시합니다.
`<sub>`을 사용하면 글자를 <sub>아래 첨자</sub>로 표시합니다.
`<tt>`는 글자를 <tt>타자체</tt>로 만들어줍니다.
`<big>`은 글자를 주변보다 <big>크게</big> 만들고, `<small>`은 글자를 주변보다 <small>작게</small> 만듭니다.
마지막은 **text-style**을 사용하는 방법입니다. text-style은 Harlowe에서 지원하는 명령어로, HTML 태그나 특수기호보다 다채로운 효과를 적용할 수 있습니다. 사용법은 `(text-style:"효과 이름")[적용할 텍스트]` 입니다.
`(text-style:"none")[효과 없음]
(text-style:"bold")[글자 굵게 표시하기]
(text-style:"italic")[글자 기울여서 표시하기]
(text-style:"underline")[글자 밑에 밑줄 하나]
(text-style:"double-underline")[글자 밑에 밑줄 두 개]
(text-style:"wavy-underline")[글자 밑에 물결선]
(text-style:"strike")[취소선]
(text-style:"double-strike")[취소선 두 개]
(text-style:"wavy-strike")[물결형 취소선]
(text-style:"superscript")[위첨자]
(text-style:"subscript")[아래첨자]
(text-style:"mark")[형광펜 표시]
(text-style:"outline")[바깥쪽 글자 라인만 표시]
(text-style:"shadow")[그림자 표시]
(text-style:"emboss")[앰보싱-글자 부풀리기]
(text-style:"condense")[콘덴스-글자 응축하기]
(text-style:"expand")[글자 간격 띄우기]
(text-style:"blur")[블러처리]
(text-style:"blurrier")[더 진한 블러처리]
(text-style:"smear")[글자 퍼뜨리기]
(text-style:"mirror")[거울 모드]
(text-style:"upside-down")[글자 위 아래 뒤집기]
(text-style:"tall")[글자 위아래로 늘리기]
(text-style:"flat")[글자 위아래 줄이기]
(text-style:"blink")[글자가 나타났다가 사라지게 하기]
(text-style:"fade-in-out")[글자를 서서히 나타났다가 서서히 사라지게 하기]
(text-style:"rumble")[위아래 떨림]
(text-style:"shudder")[좌우 떨림]
(text-style:"sway")[좌우로 서서히 이동]
(text-style:"buoy")[위아래로 서서히 이동]
(text-style:"fidget")[글자를 작고 반복적으로 움직이게 함]`
(text-style:"none")[효과 없음]
(text-style:"bold")[글자 굵게 표시하기]
(text-style:"italic")[글자 기울여서 표시하기]
(text-style:"underline")[글자 밑에 밑줄 하나]
(text-style:"double-underline")[글자 밑에 밑줄 두 개]
(text-style:"wavy-underline")[글자 밑에 물결선]
(text-style:"strike")[취소선]
(text-style:"double-strike")[취소선 두 개]
(text-style:"wavy-strike")[물결형 취소선]
(text-style:"superscript")[위첨자]
(text-style:"subscript")[아래첨자]
(text-style:"mark")[형광펜 표시]
(text-style:"outline")[바깥쪽 글자 라인만 표시]
(text-style:"shadow")[그림자 표시]
(text-style:"emboss")[앰보싱-글자 부풀리기]
(text-style:"condense")[콘덴스-글자 응축하기]
(text-style:"expand")[글자 간격 띄우기]
(text-style:"blur")[블러처리]
(text-style:"blurrier")[더 진한 블러처리]
(text-style:"smear")[글자 퍼뜨리기]
(text-style:"mirror")[거울 모드]
(text-style:"upside-down")[글자 위 아래 뒤집기]
(text-style:"tall")[글자 위아래로 늘리기]
(text-style:"flat")[글자 위아래 줄이기]
(text-style:"blink")[글자가 나타났다가 사라지게 하기]
(text-style:"fade-in-out")[글자를 서서히 나타났다가 서서히 사라지게 하기]
(text-style:"rumble")[위아래 떨림]
(text-style:"shudder")[좌우 떨림]
(text-style:"sway")[좌우로 서서히 이동]
(text-style:"buoy")[위아래로 서서히 이동]
(text-style:"fidget")[글자를 작고 반복적으로 움직이게 함]
보다 자세한 내용은 <a href="https://twine2.neocities.org/#macro_text-style" target="_blank">Harlowe 매뉴얼 : 글자 효과</a>에서 확인할 수 있습니다.
<hr>
분위기를 환기할 겸 재미있는 문장을 하나 만들어보았습니다. **(text-color:"goldenrod")[이 문장 중 단어 <span class="special-link">[[하나는]]</span> 링크에 연결되어 있습니다.]**
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="use">텍스트 게임에는 가독성과 설명을 위해 사진이 필요한 경우가 존재합니다. 이미지를 첨부하기 위해서는 `<img>` 태그를 사용해야 합니다.
먼저 절대 경로와 상대 경로에 대해서 소개하겠습니다.
절대 경로는 최초의 시작점으로부터 경유한 모든 경로를 기입하는 방식입니다. 윈도우 운영체제를 사용한다면 기본적인 시작점은 **C:**가 됩니다. 기준점이 항상 일정하기 때문에 경로가 변하지 않으며, 호출하는 파일의 위치가 변경되어도 호출 받는 파일의 위치가 동일하다면 수정이 필요하지 않습니다. 하지만 시스템이 변경되면 시작점이 달라지기 때문에 전체 경로를 수정해야 할 수 있습니다.
상대 경로는 현재 위치를 기준으로 파일을 찾는 형태입니다. 시작점이 고정되어 있지 않기 때문에 폴더 구조가 변경되면 상대 경로도 함께 수정해야 하지만 경로가 짧고 단순하며, 이동성이 좋아서 전체 경로가 바뀌어도 구조만 같다면 별다른 수정이 필요하지 않습니다. 현재 위치는 **.**으로, 상위 폴더 위치는 **..**으로 표시합니다.
이미지 파일인 img.png와 HTML 파일인 test.html가 C 드라이브 -> 테스트 -> 경로 폴더 안에 있다고 가정해봅시다.
test.html에서 img.png를 절대 경로로 호출하려면 **C:/테스트/경로/img.png**를 입력해야 합니다. 상대 경로로 호출하면 **./img.png**만으로 간단하게 입력이 가능합니다.
따라서 상대 경로는 프로젝트 대부 파일을 연결하거나, 폴더 구조를 기준으로 한 이동이 필요하거나, Git 등으로 공유되는 프로그램이 환경이 달라도 동일하게 작동해야 할 때 사용합니다.
그리고 절대 경로는 위치가 변하지 않는 파일을 호출하거나, 서버에서 root를 기준으로 접근하거나, http 등으로 시작하는 외부 리소스를 불러올 때 사용합니다.
다음은 `<img>` 태그를 사용하는 방법에 대해서 소개하겠습니다. 기본적인 사용법은 아래와 같습니다. 참고로 `</img>`나 태그 닫기를 의미하는 /는 사용하지 않아도 됩니다.
`<img src="(절대 / 상대 / 네트워크 경로)"/>`
절대 혹은 상대 경로를 입력하면 이미지 파일이 해당 경로에 존재해야 합니다. 하지만 url을 입력해 이미지를 네트워크에서 가져오면 이미지 파일을 다운로드 하지 않아도 됩니다. 하지만 인터넷에서 가져오는 사진이기 때문에 저작권에 문제가 없는지 꼭 확인해야 합니다.
`<img>` 태그에는 여러가지 속성이 존재합니다. 자주 사용하는 속성이 추가된 이미지 태그는 아래와 같습니다.
`<img src="https://i.ibb.co/3493r17/cat.jpg" alt="고양이 사진" title="야옹" align="middle" border="5" height=100 width=100>`
<img src="https://i.ibb.co/3493r17/cat.jpg" alt="고양이 사진" title="야옹" align="middle" border="5" height=100 width=100 />
alt는 대체 텍스트를 지정합니다. 이미지가 존재하지 않거나, 불러올 수 없을 때 대신 노출됩니다.
title은 이미지 도움말을 지정합니다. 사진에 마우스를 가져다 대면 풍선 도움말에 문구나 나타납니다.
align은 이미지를 정렬하는 속성입니다. left는 왼쪽 정렬, right는 오른쪽 정렬, top, middle, bottom은 수직 정렬을 진행합니다. 다만 가운데 정렬을 하고 싶다면 따로 CSS를 사용해야 합니다.
border는 이미지 테두리를 지정하는 속성입니다. 숫자가 클수록 테두리가 넓어집니다.
height와 width는 이름 그대로 세로/가로 길이를 지정하는 속성입니다. 이는 HTLM 안에서 너비와 높이를 재설정하기 때문에 지정한 크기에 따라 이미지가 깨질 수 있습니다. 이 속성을 사용하지 않으면 원본 크기가 표시됩니다.
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="use">여기서는 Passage 배경을 꾸미는 방법을 설명하려고 합니다. 배경을 꾸미는 방법에는 두 가지가 있습니다.
1. HTML 태그만 사용해서 꾸미기
2. Passage에 Tags를 추가하기
먼저 HTML만 사용해서 배경을 꾸며보겠습니다. 이를 위해서는 CSS 스타일을 정의해야 합니다. **Story -> Stylesheet**를 열고 원하는 스타일을 지정합니다.
`.test {
background: red;
color: black;
line-height: 1em;
padding: 20px;
font-size: 1em;
}`
그리고 스타일을 HTML에 적용합니다.
`<div class="test">
이 영역은 HTML의 class만 사용해서 스타일이 적용된 부분입니다.
</div>`
결과 화면은 아래와 같습니다.
<img src="./html.png" width="580" height="300" alt="HTML 적용 화면"/>
다만, HTML을 사용한 방식은 태그로 감싸인 부분에만 적용이 된다는 한계가 존재합니다. 그렇다면, 바깥쪽까지 변경하려면 어떻게 해야 할까요?
<img src="./tags.png" alt="twinery의 passage 구조 소스"/>
Twine에 생성되는 각 Passage는 내부적으로 사진과 같은 구조를 가지고 있습니다. tw-story는 가장 최상위 요소이며 그 아래인 tw-passage에 Passage에 입력한 실제 내용이 들어가게 됩니다. Passage에 Tags를 추가하면, Twine는 tw-story와 tw-passage 요소에 자동으로 tags=".." 속성을 부여합니다.(text-size:0.6)[(더 정확히 말하면, Tags 설정을 하지 않았을 경우, 두 요소에는 tags 속성이 포함되어 있으나 아무런 값도 등록되지 않은 상태를 가지고 있습니다. 여기서 Tags를 등록함으로서 요소의 tags 속성에 등록한 Tags명이 Twine에 의해 부여되어, Passage가 브라우저에 렌더링할 때 위 사진처럼 변환됩니다.)]
`[tags="explanation"] {
background:#d1bfa7;
}`
이처럼 Passage에 Tags를 추가하고, 그 Tags명과 동일한 스타일을 생성하여 전체 배경색을 설정할 수 있습니다.
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="use">텍스트 게임을 구현하기 위해서 꼭 필요한 것이 있다면 바로 변수와 조건문입니다. 여기서는 Harlowe에서 지원하는 변수와 조건 설정 방법을 소개해보려고 합니다.
변수란, 값을 담는 상자로, Harlowe에서는 변수를 저장할 때 $ 기호를 사용합니다. 다음은 변수에 값을 할당하는 명령어입니다.
`(set: $gold to 20)`
이렇게 set 명령어를 사용해서 변수에 값을 할당할 수 있습니다. 위 명령어는 **gold** 변수에 ''20''을 설정합니다.
Harlowe에는 두 가지의 변수가 존재합니다. 바로 스토리 변수 ($)와 임시 변수 (_) 입니다.
Story variable은 게임 전체에 영향을 주는 변수를 의미합니다. 한 번 생성하면 다른 Passage에도 영향을 주기 때문에 플레이어의 상태나 인벤토리, 아이템 등에 사용됩니다.
Temporary variable은 현재 Passage 내부에서만 유지되는 변수를 의미합니다. 다른 Passage로 이동하면 사라지기 때문에 내부 반복문이나 계산용 임시값에 사용됩니다. (text-size:0.6)+(text-color:gray)[(참고로 각 변수값은 확인이 쉽도록 색상을 직접 지정했습니다. 변수를 호출한다고 해서 색상이 지정되는 것은 아닙니다!)]
`(set:$test to 100)`
`(set:_temp to true)`
`(set:$string to "테스트")`(set:$test to 100)(set:_temp to 100)(set:$string to "테스트")<p class="code_block">`test의 값은 $test입니다. 그리고 temp의 값은 _temp입니다. 마지막으로 string의 값은 $string입니다.`</p>를 백틱 없이 입력하면 아래와 같습니다.
test의 값은 (text-color:red)[$test] 입니다. 그리고 temp의 값은 (text-color:blue)[_temp] 입니다. 마지막으로 string의 값은 (text-color:green)[$string] 입니다.
그렇다면 [[여기]]서도 동일하게 반환되는지 확인해보겠습니다. **여기**를 클릭해서 다른 Passage로 넘어가봅시다.
변수로 들어갈 수 있는 값에는 숫자, 참/거짓, 문자뿐만이 아닙니다. 아래는 리스트와 맵을 설정한 예시입니다.
`(set:$list to (array:"숫자", 10, "문자", true))`(set:$list to (array:"숫자", 10, "문자", true))
새로 할당한 변수 list의 값은 (text-color:#289c11)[$list] 입니다.
`(set:$item to (datamap:"1", true, "2", "물약", "3", false, "4", 100, 5, "temp", 6, true))`(set:$item to (datamap:"1", true, "2", "물약", "3", false, "4", 100, 5, "temp", 6, true))
새로 할당한 변수 item의 값은 (text-color:#289c11)[$item]입니다.
set은 다른 명령어와 달리 한 줄을 차지합니다. 때문에 set 명령어를 많이 작성하면 그만큼 칸이 비어보이게 됩니다. 이때, datamap을 사용할 수 있습니다. datamap은 하나의 변수에 하위 목록을 만들어주는 기능으로, 키와 값의 형태로 구성되어 있습니다. 위 출력문과 같이 앞에 있는 게 키, 뒤에 있는 게 값이 됩니다. 키-값쌍을 맞춰주지 않는다면 오류가 발생하기 때문에 반드시 내부 값은 짝수여야 합니다. 일부 값만 출력하고 싶다면 **print** 명령어를 사용해야 합니다. (text-size:0.6)+(text-color:gray)[(추가로, 키를 호출할 때는 지정한 타입을 그대로 사용해야 합니다. datamap에는 100으로 키가 등록되어 있는데 출력 혹은 if문에서 "100"과 같이 호출한다면 오류가 발생합니다.)]
`(print:$item's 5)`
item 중 키가 5인 값은 : (text-color:#289c11)[(print:$item's 5)]
이런 식으로 중첩도 가능합니다.
`(set:$inner_item to (datamap:"key",(datamap: "innerKey", "value")))`
(set:$inner_item to (datamap:"key",(datamap: "innerKey", "value")))
datamap에는 print 명령어를 사용하여 접근할 수 있습니다.
`(print: $inner_item's key's "innerKey")` -> 출력 결과 : (print: $inner_item's key's "innerKey")
`(print: $inner_item's "key")` -> 출력 결과 : (print: $inner_item's "key")
아래와 같이 새로운 변수에 innerKey의 값을 할당해 아래와 같이 출력할 수도 있습니다.
`(set: $inner to $inner_item's key)
(print: "key: [innerKey: " + $inner's "innerKey" + "]")`
(set: $inner to $inner_item's key)
(print: "key: [innerKey: " + $inner's "innerKey" + "]")
<hr>
다음은 조건문입니다. 가장 많이 사용될 명령어 중 하나이고, ''게임''같은 느낌을 주는 중요한 친구입니다.
조건문은 if와 else로 이루어져있습니다. **if**는 특정한 조건을 부여하고 그 조건이 **참**이면 [대괄호]의 내용을 출력합니다. 반대로 **else**는 if 조건이 **거짓**인 모든 경우에 출력됩니다. 만약 if 뒤에 else가 없고, 조건이 거짓이라면 빈 화면이 출력되기 때문에 보통은 if와 else가 하나의 짝으로 이루어집니다.
아래는 단일 if-else 예시입니다.
`(if:$item's "2" is "물약")
[자세히 보니 물약이 아니라 성수인 것 같다.]
(else:)
[아무것도 없다.]`
위와 같이 조건을 작성할 경우 **(text-color:#26119c)+(text-size:1)[(if:$item's "2" is "물약")
[자세히 보니 물약이 아니라 성수인 것 같다.]
(else:)
[아무것도 없다.]]**가 출력됩니다.
이번에는 if와 else 사이에 새로운 조건을 추가하는 명령어인 **else-if**를 사용해보겠습니다. if 조건이 거짓일 때 else보다 먼저 실행되며, else-if도 거짓이어야 else가 실행됩니다.
`(if:$item's "3" is true)
[3번은 참입니다.]
(else-if:$item's "3" is false)
[3번은 거짓입니다.]
(else:)
[거짓도 참도 아닙니다.]`
위 조건의 결과는 **(text-color:#26119c)+(text-size:1)[(if:$item's "3" is true)
[3번은 참입니다.]
(else-if:$item's "3" is false)
[3번은 거짓입니다.]
(else:)
[거짓도 참도 아닙니다.]]**입니다.
if문 사이에는 **or**나 **and**를 추가할 수 있습니다. **or**는 좌우의 값 중 하나라도 참이면 참으로 반환됩니다. **and**는 쉼표 ( , )로도 사용할 수 있으며, 좌우의 값이 모두 참이어야 참으로 반환됩니다.
`(if:$item's "1" is true and $item's "2" is "물약")[true]
(else:)[false]`
-> (if:$item's "1" is true and $item's "2" is "물약")[true](else:)[false]
`(if:$item's "1" is false or $item's "2" is "물약")[true]
(else:)[false]`
-> (if:$item's "1" is false or $item's "2" is "물약")[true]
(else:)[false]
만약 and 의 비교값이 모두 참/거짓이라면 아래와 같이 줄여서 사용할 수도 있습니다.
`(if:$item's "1" and $item's 6 is true)[true](else:)[false]`
-> (if:$item's "1" and $item's 6 is true)[true](else:)[false]
다음은 **중첩 if**를 소개해보려고 합니다. **중첩 IF문**은 if문 안에 if문이 있는 형식입니다. 중첩은 무한히 가능하지만 코드가 매우 (text-size:0.5)+(text-color:gray)[(더러워)]복잡해질 수 있기 때문에 최소한의 중첩 IF를 사용하는 것을 추천합니다.
`(if:$item's "1" is true)
[ datamap의 키 중 "1"이 true면 이 텍스트가 표시됩니다.
(if:$item's "4" is 100)
[ 그리고 datamap의 키 중 "4"의 값이 100이면 이 텍스트가 표시됩니다.]
(else:)
[ 아니면 이 텍스트가 표시됩니다. (아무런 값 없이 공백만 입력해도 됩니다.)]
]
(else:)
[datamap의 키 중 "1"이 true가 아닙니다.]`
-> **(if:$item's "1" is true)
[ datamap의 키 중 "1"이 true면 이 텍스트가 표시됩니다.
(if:$item's "4" is 100)
[ 그리고 datamap의 키 중 "4"의 값이 100이면 이 텍스트가 표시됩니다.]
(else:)
[ 아니면 이 텍스트가 표시됩니다. (아무런 값 없이 공백만 입력해도 됩니다.)]
]
(else:)
[datamap의 키 중 "1"이 true가 아닙니다.]**
위와 같이 중첩 IF문은 괄호를 제대로 닫는 것이 가장 중요합니다. 만약 내가 괄호를 닫았는지 헷갈린다면, 닫는 괄호 앞에 커서를 가져다 대보세요. 커서가 있는 괄호의 범위를 확인할 수 있습니다.
다음은 **unless** 입니다. 이 명령어는 IF와 다르게 조건이 거짓이면 참으로 판단합니다.
`(unless:$item's "1" is false)["1"의 값은 true임에도 이 텍스트가 출력됩니다.]
(else:)[여기는 출력되지 않습니다.]`
-> **(unless:$item's "1" is false)["1"의 값은 true임에도 이 텍스트가 출력됩니다.]
(else:)[여기는 출력되지 않습니다.]**
참고로, set 명령어만 사용해서 IF의 효과를 낼 수도 있습니다. 위에서 사용한 `$test` 변수를 사용해보겠습니다.
`(set:$isTest to $test is 100)
$isGold[isGold가 true면 대괄호 안의 내용이 출력됩니다.]`
(set:$isTest to $test is 100)
=> $isTest[isTest가 true면 대괄호 안의 내용이 출력됩니다.]
찬찬히 설명해보겠습니다.
먼저 test 변수는 위에서 100으로 설정되어 있었습니다. 따라서 (text-color:gray)[`$test` is 100]은 100 is 100 즉, 100 = 100과 동일한 의미를 가집니다. 이로서 `$isTest`는 true가 되기 때문에 대괄호의 내용이 출력됩니다.
다만, `$isTest`를 print한다고 해서 true가 출력되지 않습니다!
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="use">"goldenrod" isn't valid Harlowe syntax for the inside of a macro call. Maybe you misspelled something? Also, as of 3.3.0, Javascript syntax is not allowed inside macro calls.
: 색상을 " " 없이 입력했을 때 표시됩니다. 예를 들면 `(text-color:red)`와 같은 식으로 말이에요. 위 오류를 해결하려면 `(text-color:"red")` 처럼 red 를 쌍따옴표로 감싸주어야 합니다.
<hr class="err-hr">
The number 100 can't have changers like `(text-colour:)` attached.
Changers placed just before hooks, links and commands will attempt to attach, but in this case it didn't work.
: 어떤 명령어든, 괄호의 명령어에 해당하는 부분을 대괄호로 감싸주지 않았을 경우 발생하는 오류입니다. 위 오류를 해결하려면 명령어를 사용할 부분을 대괄호로 감싸주어야 합니다.
<hr class="err-hr">
dkdkdk
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="use">
Twine에는 Story Formats라고 불리는 다양한 규칙과 스타일 옵션 모음이 존재합니다.
기본 스토리 형식은 Harlowe 3.3.9이며, **Twine -> Story Formats**에서 변경 가능합니다.
각 스토리 형식의 특징에 대해 간략하게 설명하겠습니다.
**Harlowe**
초보자를 위해 설계된 스토리 포맷입니다. 초보자도 쉽게 사용할 수 있을만큼 문법이 간단하며 변수, 조건, 반복, 링크 등 스토리 중심 로직에 최적화되어 있습니다. 또한 샌드박스 환경이라서 작성한 코드에 오류가 있어도 브라우저나 컴퓨터에 영향을 주지 못합니다. 다만 샌드박스 환경이기 때문에 DOM을 직접 조작하거나 외부 JS 라이브러리를 호출하거나 브라우저 이벤트를 처리하는 등 대부분의 JS 기능을 활용할 수 없다는 단점이 존재합니다.
**SugarCube**
초기 Twine인 Twine1의 후속 버전으로, 초보자도 어느 정도 다룰 수 있도록 설계된 스토리 포맷입니다. Harolwe보다는 JavaScript를 자유롭게 사용할 수 있으며 세션/로컬 저장, 이벤트, UI 커스터마이징이 가능합니다. 따라서 복잡한 게임 로직이나 시뮬레이션 구현에 적합합니다. 다만 문법이 복잡해서 학습에 시간이 걸릴 수 있습니다.
**Snowman**
가장 진입 장벽이 높은 스토리 포맷입니다. 표준 HTML과 JS를 기반으로 거의 제한 없이 Twine을 HTML/JS 프레임워크처럼 사용할 수 있습니다. 또한 DOM과 JS를 자유롭게 조작할 수 있어 Twine를 사용해 웹 개발이 가능합니다. 다만 Twine의 간단한 매크로 문법을 활용하기 어렵고 자바스크립트를 학습한 사용자가 아니라면 개발이 쉽지 않습니다.
**Chapbook**
가장 최근에 나온 스토리 포맷입니다. CSS와 HTML로 스타일링을 유연하게 할 수 있으며 마크다운에 친화적입니다. 다만 최근 포맷인만큼 문서나 자료가 적고 고급 이벤트 처리가 제한되어 있습니다.
보통 가장 차이를 많이 느끼는 부분은 명령어 사용법입니다. 각 스토리 포맷마다 제공되는 명령어와 사용법이 다르기 때문입니다.
Harlowe는 `(명령어:"")[대상]`과 같이 사용했다면 SugarCube는 `<<>>`를 사용하고, Snowman은 `<% %>`을 사용합니다. 마지막으로 Chapbook은 `[ ]`외에도 다양한 삽입/수정자가 존재합니다.
더 자세한 내용은 <a href="https://twinery.org/cookbook/terms/terms_storyformats.html" target="_blank"/>에서 확인할 수 있습니다.
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div class="title">Java Script와 Stylesheet 활용하기</div>
<div class="content">
(text-color:#82edf7)+(text-size:0.8)[아래의 파란 글자를 클릭해 원하는 내용을 학습해보세요!]
[[CSS 적용하기]]
[[키보드/마우스 이벤트]]
[[외부 라이브러리 사용하기]]
[[세션 사용하기]]
[[외부 API 호출하기]]
[[타이머 / 애니메이션 제어하기]]
[[콘솔 활용하기]]
</div>
<div class="bottom"><span class="bottom_link">[[목차로 이동하기->사용법]]</span></div><div>
=><=
<img src="https://c.pxhere.com/images/d7/b5/425c16391d9e058a1df90b25313c-1637325.jpg!d" width="400" height="400" title="찾았다!"><br>
<=
정답은 '하나는' 이었습니다!
실제로 게임을 만들 때 활용하기 좋은 텍스트 꾸미기 방법이라고 생각합니다. 방법은 아래와 같습니다.
우선 Stylesheet에 아래의 내용을 추가합니다.
<p class="code_block">
`.special-link tw-link {
color: goldenrod;
}
.special-link tw-link:hover {
color: goldenrod;
}`
</p>
그리고 Passage에서 숨기고 싶은 링크 문장 혹은 단어를 `<span>` 태그로 감싸고 위에서 만들었던 class를 지정해줍니다. 링크로 지정된 단어는 굵게 표시되기 때문에 주변 단어도 동일하게 보이도록 설정합니다.
<p class="code_block">`**(text-color:"goldenrod")[이 문장 중 <span class="special-link">[[하나는]]</span> 링크에 연결되어 있습니다.]**`</p>
스타일시트에 대한 자세한 내용은 [[JavaScript와 Stylesheet 사용하기->jsAndCss]]에서 확인할 수 있습니다.
</div>
<div class="bottom"><span class="bottom_link">[[이전으로->텍스트 꾸미기 -기본편-]]</span></div>(특정 문자 전체 변경 enchant: "문자")
(페이지 전체에 지정 enchant: ?Passage)
(정렬)
{대괄호
야호}(여기는 매크로랑 tn8 소개)<div class="use">
이곳은 다른 Passage입니다.
test의 값은 (text-color:purple)[$test] 입니다. 그리고 temp의 값은 (text-color:yellow)[_temp] 입니다. 마지막으로 string의 값은 (text-color:aqua)[$string] 입니다.
여기서 temp의 값을 호출하면 오류가 나는 것이 정상입니다. temp는 현재 Passage에는 할당되지 않았고, 이전 Passage에서만 할당된 임시 변수이기 때문입니다.
</div>
<div class="bottom"><span class="bottom_link">[[이전으로->변수와 조건 설정하기 -기본편-]]</span></div><div class="use">변수와 조건 설정하기 심화편</div><div class="js">게임에 필요한 부분은 텍스트뿐만이 아닙니다. 배경과 문단 디자인 또한 중요한 요소입니다.
(text-color:gray)+(text-size:0.6)+(text-style:"superscript")[이 Passage에서는 기본적인 HTML 구조를 알고 있다는 가정 하에 작성되었습니다.]
가장 간단한 방법은 아래와 같이 태그에 style을 직접 작성하는 것입니다.
`<div style="background-color:blue"> 파란 배경 </div>`
이런 식으로 태그마다 서로 다른 속성을 부여할 수 있습니다. 하지만 속성이 매우 많고, 동일한 속성을 여러 Passage에 적용해야 한다면 위와 같은 방식은 매우 번거로울 것입니다.
그래서 사용하는 것이 바로 **Stylesheet** 입니다. Stylesheet는 **Story -> Stylesheet**로 접근할 수 있으며 작성법 또한 CSS와 동일합니다.
`.test {
background-color: red
}
<div class="test"> 빨간 배경 </div>`
이런 식으로 하나의 속성을 정의하여 여러 태그에서 호출해 사용할 수 있습니다. 앞에 .을 붙이면 class, 앞에 #을 붙이면 id 속성임을 의미합니다.
다양한 CSS 속성과 요소는 <a href="https://www.codestates.com/blog/content/html-css-%EA%B8%B0%EC%B4%88" target="_blank"/> 에서 확인할 수 있습니다.
</div>
<div class="bottom"><span class="bottom_link">[[다른 활용법 확인하기->jsAndCss]]</span></div><div class="use">게임의 몰입감을 위해서는 배경음악이 필요합니다. 여기서는 오디오를 설정하는 방법에 대해서 알아보겠습니다.
HTML에는 `<audio>` 태그가 존재합니다. Passage 안에 오디오 태그를 사용하면 오디오를 재생할 수 있습니다. 경로는 이미지와 같이 절대 / 상대 경로로 입력해야 하고 type은 오디오 파일의 타입으로 입력해주어야 합니다. src에 입력한 경로에 오디오 파일이 존재하지 않으면 노출되지 않습니다.
`<audio autoplay loop>
<source src="test.mp3" type="audio/mpeg">
<source src="test.ogg" type="audio/ogg">
<source src="test.wav" type="audio/wav">
</audio>`
<audio controls autoplay loop>
<source src=".\test.mp3" type="audio/mpeg">
<source src=".\test.ogg" type="audio/ogg">
<source src=".\test.wav" type="audio/wav">
</audio>
다만 브라우저 라이선스 차이로 인해 일부 오디오 형식이 지원되지 않을 수 있습니다. 때문에 오디오를 최상의 성능으로 사용하려면 여러 형식을 사용하는 것이 좋습니다. 현재 크롬 브라우저에서는 mp3를 지원하기 때문에 정상적으로 오디오 소스가 노출되지만, 만약 mp3를 지원하지 않는다면 오디오 소스는 표시되지 않기 때문입니다.
추가로 사용된 각 속성에 대해서 간략하게 소개하겠습니다.
autoplay 속성은 오디오가 실행될 준비가 끝나는대로 자동으로 실행하는 속성입니다. 다만 일부 브라우저의 경우, muted 속성을 함께 사용해야만 하기도 합니다. muted는 오디오는 재생하지만 소리는 음소거하기 때문에 사용자가 소리를 키우거나 하는 추가 동작이 필요합니다.
loop 속성은 오디오를 반복해서 재생하도록 하며, controls는 웹 화면에 컨트롤 막대를 표시합니다. 추가로, preload라는 속성이 있는데, 이 속성은 재생 버튼을 누르기 전에 오디오 파일을 미리 다운로드해 준비시키는 속성입니다. 만약 오디오를 외부에서 가져와 사용한다면 preload 속성을 사용해서 준비시켜두어야 로딩이 걸릴 확률이 낮습니다.
다만, 위와 같이 설정할 경우 이 파일이 설정된 Passage에서만 음악이 재생된다는 단점이 존재합니다. 그렇다면, 어떻게 해야 모든 Passage에서 음악을 실행시키도록 설정할 수 있을까요?
이때 JavaScript가 필요합니다.