summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/game.h15
-rw-r--r--src/main.cpp2
-rw-r--r--src/muxer.cpp12
-rw-r--r--src/muxer.h2
-rw-r--r--src/renderer.cpp96
-rw-r--r--src/renderer.h57
-rw-r--r--src/sign.cpp130
-rw-r--r--src/sign.h45
20 files changed, 675 insertions, 38 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f07e97..a40e14f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -8,10 +8,12 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Ether_SOURCE_DIR}/cmake")
8 8
9find_package(SDL2 REQUIRED) 9find_package(SDL2 REQUIRED)
10find_package(SDL2_Image REQUIRED) 10find_package(SDL2_Image REQUIRED)
11find_package(SDL2_TTF REQUIRED)
11 12
12set(ALL_LIBS 13set(ALL_LIBS
13 ${SDL2_LIBRARY} 14 ${SDL2_LIBRARY}
14 ${SDL2_IMAGE_LIBRARIES} 15 ${SDL2_IMAGE_LIBRARIES}
16 ${SDL2_TTF_LIBRARIES}
15 fmodstudio 17 fmodstudio
16 fmod 18 fmod
17) 19)
@@ -19,6 +21,7 @@ set(ALL_LIBS
19include_directories( 21include_directories(
20 ${SDL2_INCLUDE_DIR} 22 ${SDL2_INCLUDE_DIR}
21 ${SDL2_IMAGE_INCLUDE_DIRS} 23 ${SDL2_IMAGE_INCLUDE_DIRS}
24 ${SDL2_TTF_INCLUDE_DIRS}
22 src 25 src
23 vendor 26 vendor
24 vendor/fmod/inc 27 vendor/fmod/inc
@@ -34,6 +37,7 @@ add_executable(Ether
34 src/muxer.cpp 37 src/muxer.cpp
35 src/animation.cpp 38 src/animation.cpp
36 src/game.cpp 39 src/game.cpp
40 src/sign.cpp
37 vendor/fov.c 41 vendor/fov.c
38) 42)
39 43
diff --git a/cmake/FindSDL2_TTF.cmake b/cmake/FindSDL2_TTF.cmake new file mode 100644 index 0000000..8b2edcb --- /dev/null +++ b/cmake/FindSDL2_TTF.cmake
@@ -0,0 +1,98 @@
1# Locate SDL_ttf library
2#
3# This module defines:
4#
5# ::
6#
7# SDL2_TTF_LIBRARIES, the name of the library to link against
8# SDL2_TTF_INCLUDE_DIRS, where to find the headers
9# SDL2_TTF_FOUND, if false, do not try to link against
10# SDL2_TTF_VERSION_STRING - human-readable string containing the version of SDL_ttf
11#
12#
13#
14# For backward compatibility the following variables are also set:
15#
16# ::
17#
18# SDLTTF_LIBRARY (same value as SDL2_TTF_LIBRARIES)
19# SDLTTF_INCLUDE_DIR (same value as SDL2_TTF_INCLUDE_DIRS)
20# SDLTTF_FOUND (same value as SDL2_TTF_FOUND)
21#
22#
23#
24# $SDLDIR is an environment variable that would correspond to the
25# ./configure --prefix=$SDLDIR used in building SDL.
26#
27# Created by Eric Wing. This was influenced by the FindSDL.cmake
28# module, but with modifications to recognize OS X frameworks and
29# additional Unix paths (FreeBSD, etc).
30
31#=============================================================================
32# Copyright 2005-2009 Kitware, Inc.
33# Copyright 2012 Benjamin Eikel
34#
35# Distributed under the OSI-approved BSD License (the "License");
36# see accompanying file Copyright.txt for details.
37#
38# This software is distributed WITHOUT ANY WARRANTY; without even the
39# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
40# See the License for more information.
41#=============================================================================
42# (To distribute this file outside of CMake, substitute the full
43# License text for the above reference.)
44
45find_path(SDL2_TTF_INCLUDE_DIR SDL_ttf.h
46 HINTS
47 ENV SDL2TTFDIR
48 ENV SDL2DIR
49 PATH_SUFFIXES SDL2
50 # path suffixes to search inside ENV{SDLDIR}
51 include/SDL2 include
52 PATHS ${SDL2_TTF_PATH}
53 )
54
55if (CMAKE_SIZEOF_VOID_P EQUAL 8)
56 set(VC_LIB_PATH_SUFFIX lib/x64)
57else ()
58 set(VC_LIB_PATH_SUFFIX lib/x86)
59endif ()
60
61find_library(SDL2_TTF_LIBRARY
62 NAMES SDL2_ttf
63 HINTS
64 ENV SDL2TTFDIR
65 ENV SDL2DIR
66 PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX}
67 PATHS ${SDL2_TTF_PATH}
68 )
69
70if (SDL2_TTF_INCLUDE_DIR AND EXISTS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h")
71 file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+[0-9]+$")
72 file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+[0-9]+$")
73 file(STRINGS "${SDL2_TTF_INCLUDE_DIR}/SDL_ttf.h" SDL2_TTF_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+[0-9]+$")
74 string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MAJOR "${SDL2_TTF_VERSION_MAJOR_LINE}")
75 string(REGEX REPLACE "^#define[ \t]+SDL_TTF_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_MINOR "${SDL2_TTF_VERSION_MINOR_LINE}")
76 string(REGEX REPLACE "^#define[ \t]+SDL_TTF_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_TTF_VERSION_PATCH "${SDL2_TTF_VERSION_PATCH_LINE}")
77 set(SDL2_TTF_VERSION_STRING ${SDL2_TTF_VERSION_MAJOR}.${SDL2_TTF_VERSION_MINOR}.${SDL2_TTF_VERSION_PATCH})
78 unset(SDL2_TTF_VERSION_MAJOR_LINE)
79 unset(SDL2_TTF_VERSION_MINOR_LINE)
80 unset(SDL2_TTF_VERSION_PATCH_LINE)
81 unset(SDL2_TTF_VERSION_MAJOR)
82 unset(SDL2_TTF_VERSION_MINOR)
83 unset(SDL2_TTF_VERSION_PATCH)
84endif ()
85
86set(SDL2_TTF_LIBRARIES ${SDL2_TTF_LIBRARY})
87set(SDL2_TTF_INCLUDE_DIRS ${SDL2_TTF_INCLUDE_DIR})
88
89include(FindPackageHandleStandardArgs)
90
91FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_ttf
92 REQUIRED_VARS SDL2_TTF_LIBRARIES SDL2_TTF_INCLUDE_DIRS
93 VERSION_VAR SDL2_TTF_VERSION_STRING)
94
95# for backward compatibility
96set(SDLTTF_LIBRARY ${SDL2_TTF_LIBRARIES})
97set(SDLTTF_INCLUDE_DIR ${SDL2_TTF_INCLUDE_DIRS})
98set(SDLTTF_FOUND ${SDL2_TTF_FOUND})
diff --git a/res/childoflight.txt b/res/childoflight.txt index d65796d..72cc037 100644 --- a/res/childoflight.txt +++ b/res/childoflight.txt
@@ -1,26 +1,12 @@
1"Your life, and the lives of those who believe in you. Are you willing to put it all on the line?" 1"Your life, and the lives of those who believe in you. Are you willing to put it all on the line?"\nThose words echoed in the child's head more than any other as he put his hands on the lamp. Through it, he could feel the sun's enormous presence far below him. Its power was palpable; a gentle thrumming that tickled his fingers. It was strong -- stronger and nearer than it had been with the other lamps. Up close, it felt like all there was.
2Those words echoed in the child's head more than any other as he put his hands on the lamp. Through it, he could feel the sun's enormous presence far below him. Its power was palpable; a gentle thrumming that tickled his fingers. It was strong -- stronger and nearer than it had been with the other temples. Up close, it felt like all there was.
3The lamp was light in his hands. Without a word he pulled, and light poured out. He closed his eyes and all he saw was light. 2The lamp was light in his hands. Without a word he pulled, and light poured out. He closed his eyes and all he saw was light.
4The child was nowhere when he awoke. Bright, white emptiness stretched out in all directions. He gulped as he looked around -- felt that emptiness resonate in his chest. 3The child was nowhere when he awoke. Bright, white emptiness stretched out in all directions. He gulped as he looked around, and felt that emptiness resonate in his chest.\n"Hello?" he called out. No one answered.
5"Hello?" he called out. No one answered. 4Trembling, the child pushed himself to his feet. He'd been through countless battles, been spat on by people he used to trust, and even took down the immortal ruler of the world. He told himself he could handle whatever this was.\nHe hadn't had to do those things by himself, though.
6Trembling, he pushed himself to his feet. He'd been through countless battles, been spat on by people he used to trust, and even took down the immortal ruler of the world. He told himself he could handle whatever this was. 5The child took a step. His bare foot thudded against an invisible ground. When nothing further happened, he kept going. "Choose a direction and just walk," he thought. There was nothing else to do.\n"Is anyone out there?"
7He hadn't had to do those things by himself, though. 6The child's steps turned inside out. The ground flipped over and curved in on itself. He saw figures in the distance but when he approached he realized it was himself he was seeing. He felt a headache start to come on, and it only grew when something finally did appear.\nA black spiral, twisting out from beneath him. He climbed and climbed, and his feet hurt and his chest ached and his arms twisted but it wasn't enough to take him down. Somehow he felt like nothing would ever be able to stop him again. One foot after another he climbed and watched the matter splay out before him. This thing he'd found, it was immense. It was infinite.\nIt was the Sun.
8The child took a step. His bare foot thudded against an invisible ground. When nothing further happened, he kept going. Choose a direction and just walk, he thought. There was nothing else to do. 7"Pure hearted one," the Sun said without saying, not a roaring voice but a subtle understanding planted in the child's mind. "We meet at last."\nThe child gulped. Throughout all that time searching for and lighting the lamps, he hadn't considered what would actually happen if he won. But now here he was, facing infinity itself, and it dawned on him the Sun had probably been sealed away for a good reason.\nWould saving the world be worth the consequences?
9"Is anyone out there?" 8"H-hello?" the child stammered. It came out as nothing more than a squeak, but a shift in the Sun's surface -- starry as the night sky -- told him that it heard.\nIt spoke: "For thousands of years I have slept here, ever since the world grew past the need for my power."\nAn eye -- incomprehensibly large -- regarded the boy who'd raised it from its slumber. An eye which had seen countless things: births, deaths, loves, wars. A being who'd caused so many of them, and had to be shut away to contain its limitless power. A power that was once again free.
10His steps turned inside out. The ground flipped over and curved in on itself. He saw figures in the distance but when he approached he realized it was himself he was seeing. He felt a headache start to come on, and it only grew when something finally did appear. 9The child took a deep breath. "I'm sorry I woke you up," he said, voice wobbling like a teeter totter. "I had to light the lamps to stop someone else from doing it. He wanted to end the world. But I want to save it."\nThat deep, immaterial voice continued: "I've seen visions in my dreams of your world crumbling. I've felt your despair. I've heard your cries for help. I've seen your strength, clear as day, in the pieces of your heart that you shared."
11A black spiral, twisting out from beneath him. He climbed and climbed, and his feet hurt and his chest ached and his arms twisted but it wasn't enough to take him down. Somehow he felt like nothing would ever be able to stop him again. One foot after another he climbed and watched the matter splay out before him. This thing he'd found, it was immense. It was infinite. 10The child saw himself reflected in that eye. Saw his feet lift off the ground, pulled by some invisible force. Saw the sparks of magic flying around his hands, felt his being churning out of control as something dark, something horrible, something unfathomably ancient poured into his mind, squeezing and pulling it like taffy, tearing it apart and putting it back together.\n"Now my power is needed once again," the Sun said. "As you have shared with me, I will share it in return."
12It was the Sun. 11The child tried to ask what that meant, but his throat squeezed tight and choked the words to death. Sweat poured from his brow as the worst fever he'd ever felt took hold. His head was being thrust beneath the surface of the water, his torso was being struck by lightning from a machine.\nThe Sun watched him float there, writhing and sweating and sparking with violent electricity. It closed its eye.\n"I promise you that I will not miss it."
13"Pure hearted one," it said without saying, not a roaring voice but a subtle understanding planted in the child's mind. "We meet at last."
14The child gulped. Throughout all that time searching for and sanctifying the lamps, he hadn't considered what would actually happen if he won. But now here he was, facing infinity itself, and it dawned on him the Sun had probably been sealed away for a good reason.
15Would saving the world be worth the consequences?
16"H-hello?" he stammered. It came out as nothing more than a squeak, but a shift in the Sun's surface -- starry as the night sky -- told him that it heard.
17"For thousands of years I have slept here, ever since the world grew past the need for my power."
18An eye -- incomprehensibly large -- regarded the boy who'd raised it from its slumber. An eye which had seen countless things: births, deaths, loves, wars. A being who'd caused so many of them, and had to be shut away to contain its limitless power. A power that was once again free.
19The child took a deep breath. "I'm sorry I woke you up," he said, voice wobbling like a teeter totter. "I had to light the lamps to stop someone else from doing it. He wanted to end the world. But I want to save it."
20"I've seen visions in my dreams of your world crumbling. I've felt your despair. I've heard your cries for help. I've seen your strength, clear as day, in the pieces of your heart that you shared."
21The child saw himself reflected in that eye. Saw his feet lift off the ground, pulled by some invisible force. Saw the sparks of magic flying around his hands, felt his being churning out of control as something dark, something horrible, something unfathomably ancient poured into his mind, squeezing and pulling it like taffy, tearing it apart and putting it back together.
22"Now my power is needed once again. As you have shared with me, I will share it in return."
23"Wh-" he tried to ask, but his throat squeezed tight and choked the words to death. Sweat poured from his brow as the worst fever he'd ever felt took hold. His head was being thrust beneath the surface of the water, his torso was being struck by lightning from a machine.
24The Sun watched him float there, writhing and sweating and sparking with violent electricity. It closed its eye.
25"I promise you that I will not miss it."
26The thrumming from before was inside of him now. The Sun's heartbeat was gone -- it was his own. The child opened his mouth to scream, and what came out was light. \ No newline at end of file 12The thrumming from before was inside of him now. The Sun's heartbeat was gone -- it was his own. The child opened his mouth to scream, and what came out was light. \ No newline at end of file
diff --git a/res/fmod/.cache/fsbcache/Desktop/71C77FCD.fobj b/res/fmod/.cache/fsbcache/Desktop/71C77FCD.fobj new file mode 100644 index 0000000..ee4f169 --- /dev/null +++ b/res/fmod/.cache/fsbcache/Desktop/71C77FCD.fobj
Binary files differ
diff --git a/res/fmod/.cache/{9eeec59c-fe90-499a-a390-6175f2fa58e8}.pdc b/res/fmod/.cache/{9eeec59c-fe90-499a-a390-6175f2fa58e8}.pdc new file mode 100644 index 0000000..3fa7826 --- /dev/null +++ b/res/fmod/.cache/{9eeec59c-fe90-499a-a390-6175f2fa58e8}.pdc
Binary files differ
diff --git a/res/fmod/.user/Metadata/Event/{68372a81-e8b2-4b54-b8a4-93de302bcc94}.user.xml b/res/fmod/.user/Metadata/Event/{68372a81-e8b2-4b54-b8a4-93de302bcc94}.user.xml new file mode 100644 index 0000000..8deeed0 --- /dev/null +++ b/res/fmod/.user/Metadata/Event/{68372a81-e8b2-4b54-b8a4-93de302bcc94}.user.xml
@@ -0,0 +1,34 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<objects serializationModel="Studio.01.10.00">
3 <object class="Event" id="{68372a81-e8b2-4b54-b8a4-93de302bcc94}">
4 <relationship name="uiLastParameterSelection">
5 <destination>{8d0e479a-a12b-473f-93aa-de133b6c288c}</destination>
6 </relationship>
7 </object>
8 <object class="MasterTrack" id="{4073a972-7eb2-4ce6-a745-f479d895c198}"/>
9 <object class="MixerInput" id="{ece72a71-313f-4e2e-8cde-1b45205bc439}"/>
10 <object class="EventAutomatableProperties" id="{c0b89761-f8b7-4fff-a63e-7acc097ef1a9}"/>
11 <object class="MarkerTrack" id="{afc86c14-4856-4b21-b002-e2c236e1c00a}"/>
12 <object class="GroupTrack" id="{f93105f9-338b-4be2-bb3b-38b7a54a95da}"/>
13 <object class="Timeline" id="{8d0e479a-a12b-473f-93aa-de133b6c288c}">
14 <property name="uiLastRulerScaleRatio">
15 <value>0.016137708445400752</value>
16 </property>
17 </object>
18 <object class="EventMixerMaster" id="{d6928c43-7ad8-4ac8-afde-404be9c3c3c9}">
19 <relationship name="input">
20 <destination>{cfc8b7fd-e863-413e-89e8-c6f0bc5db7a8}</destination>
21 </relationship>
22 </object>
23 <object class="MixerBusEffectChain" id="{a7a25c5a-074d-490a-a50a-8b3b839f6a14}"/>
24 <object class="MixerBusPanner" id="{b33c4429-f286-4505-a998-52b4c752c162}"/>
25 <object class="SingleSound" id="{905db4d4-3f09-4a71-a981-772aa96e7ff4}"/>
26 <object class="EventMixerGroup" id="{cfc8b7fd-e863-413e-89e8-c6f0bc5db7a8}"/>
27 <object class="MixerBusEffectChain" id="{df7fd3ea-e7fd-4672-ac38-319471cf4416}"/>
28 <object class="MixerBusPanner" id="{105a5683-47eb-4d70-a553-adc2b2040fb7}"/>
29 <object class="MixerBusFader" id="{bf2399fd-38f7-45cf-8404-ce25844a23da}"/>
30 <object class="MixerBusEffectChain" id="{fe3c2b3a-f423-48c0-b918-ea3064331c9c}"/>
31 <object class="MixerBusPanner" id="{100a8e0f-32d5-424a-8453-f03c784c8e0f}"/>
32 <object class="MixerBusFader" id="{ffb4df86-9426-45b8-b3c2-b12e3b5ff447}"/>
33 <object class="MixerBusFader" id="{cc649c59-cd4c-4d44-9941-66792be28cb9}"/>
34</objects>
diff --git a/res/fmod/Assets/Attack02.wav b/res/fmod/Assets/Attack02.wav new file mode 100644 index 0000000..ddd9127 --- /dev/null +++ b/res/fmod/Assets/Attack02.wav
Binary files differ
diff --git a/res/fmod/Metadata/AudioFile/{9eeec59c-fe90-499a-a390-6175f2fa58e8}.xml b/res/fmod/Metadata/AudioFile/{9eeec59c-fe90-499a-a390-6175f2fa58e8}.xml new file mode 100644 index 0000000..7330e45 --- /dev/null +++ b/res/fmod/Metadata/AudioFile/{9eeec59c-fe90-499a-a390-6175f2fa58e8}.xml
@@ -0,0 +1,20 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<objects serializationModel="Studio.01.10.00">
3 <object class="AudioFile" id="{9eeec59c-fe90-499a-a390-6175f2fa58e8}">
4 <property name="assetPath">
5 <value>Attack02.wav</value>
6 </property>
7 <property name="frequencyInKHz">
8 <value>44.0999985</value>
9 </property>
10 <property name="channelCount">
11 <value>1</value>
12 </property>
13 <property name="length">
14 <value>0.30798185941043082</value>
15 </property>
16 <relationship name="masterAssetFolder">
17 <destination>{4c4e21c6-cc51-4a2c-b05e-fb67da4f7ed1}</destination>
18 </relationship>
19 </object>
20</objects>
diff --git a/res/fmod/Metadata/Event/{68372a81-e8b2-4b54-b8a4-93de302bcc94}.xml b/res/fmod/Metadata/Event/{68372a81-e8b2-4b54-b8a4-93de302bcc94}.xml new file mode 100644 index 0000000..18db19f --- /dev/null +++ b/res/fmod/Metadata/Event/{68372a81-e8b2-4b54-b8a4-93de302bcc94}.xml
@@ -0,0 +1,128 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<objects serializationModel="Studio.01.10.00">
3 <object class="Event" id="{68372a81-e8b2-4b54-b8a4-93de302bcc94}">
4 <property name="name">
5 <value>textbeep</value>
6 </property>
7 <property name="outputFormat">
8 <value>0</value>
9 </property>
10 <relationship name="folder">
11 <destination>{b10a4c1b-72f0-4676-bbef-b450aaa46cb6}</destination>
12 </relationship>
13 <relationship name="mixer">
14 <destination>{4928b913-a336-4aff-b192-a452d9e20bdd}</destination>
15 </relationship>
16 <relationship name="masterTrack">
17 <destination>{4073a972-7eb2-4ce6-a745-f479d895c198}</destination>
18 </relationship>
19 <relationship name="mixerInput">
20 <destination>{ece72a71-313f-4e2e-8cde-1b45205bc439}</destination>
21 </relationship>
22 <relationship name="automatableProperties">
23 <destination>{c0b89761-f8b7-4fff-a63e-7acc097ef1a9}</destination>
24 </relationship>
25 <relationship name="markerTracks">
26 <destination>{afc86c14-4856-4b21-b002-e2c236e1c00a}</destination>
27 </relationship>
28 <relationship name="groupTracks">
29 <destination>{f93105f9-338b-4be2-bb3b-38b7a54a95da}</destination>
30 </relationship>
31 <relationship name="timeline">
32 <destination>{8d0e479a-a12b-473f-93aa-de133b6c288c}</destination>
33 </relationship>
34 <relationship name="banks">
35 <destination>{a23d2b1c-914e-48d4-8df9-80f6edad6c28}</destination>
36 </relationship>
37 </object>
38 <object class="EventMixer" id="{4928b913-a336-4aff-b192-a452d9e20bdd}">
39 <relationship name="masterBus">
40 <destination>{d6928c43-7ad8-4ac8-afde-404be9c3c3c9}</destination>
41 </relationship>
42 </object>
43 <object class="MasterTrack" id="{4073a972-7eb2-4ce6-a745-f479d895c198}">
44 <relationship name="mixerGroup">
45 <destination>{d6928c43-7ad8-4ac8-afde-404be9c3c3c9}</destination>
46 </relationship>
47 </object>
48 <object class="MixerInput" id="{ece72a71-313f-4e2e-8cde-1b45205bc439}">
49 <relationship name="effectChain">
50 <destination>{a7a25c5a-074d-490a-a50a-8b3b839f6a14}</destination>
51 </relationship>
52 <relationship name="panner">
53 <destination>{b33c4429-f286-4505-a998-52b4c752c162}</destination>
54 </relationship>
55 <relationship name="output">
56 <destination>{a028aeaa-4166-48ea-881f-bb967c81e6f1}</destination>
57 </relationship>
58 </object>
59 <object class="EventAutomatableProperties" id="{c0b89761-f8b7-4fff-a63e-7acc097ef1a9}"/>
60 <object class="MarkerTrack" id="{afc86c14-4856-4b21-b002-e2c236e1c00a}"/>
61 <object class="GroupTrack" id="{f93105f9-338b-4be2-bb3b-38b7a54a95da}">
62 <relationship name="modules">
63 <destination>{905db4d4-3f09-4a71-a981-772aa96e7ff4}</destination>
64 </relationship>
65 <relationship name="mixerGroup">
66 <destination>{cfc8b7fd-e863-413e-89e8-c6f0bc5db7a8}</destination>
67 </relationship>
68 </object>
69 <object class="Timeline" id="{8d0e479a-a12b-473f-93aa-de133b6c288c}">
70 <relationship name="modules">
71 <destination>{905db4d4-3f09-4a71-a981-772aa96e7ff4}</destination>
72 </relationship>
73 </object>
74 <object class="EventMixerMaster" id="{d6928c43-7ad8-4ac8-afde-404be9c3c3c9}">
75 <relationship name="effectChain">
76 <destination>{df7fd3ea-e7fd-4672-ac38-319471cf4416}</destination>
77 </relationship>
78 <relationship name="panner">
79 <destination>{105a5683-47eb-4d70-a553-adc2b2040fb7}</destination>
80 </relationship>
81 <relationship name="mixer">
82 <destination>{4928b913-a336-4aff-b192-a452d9e20bdd}</destination>
83 </relationship>
84 </object>
85 <object class="MixerBusEffectChain" id="{a7a25c5a-074d-490a-a50a-8b3b839f6a14}">
86 <relationship name="effects">
87 <destination>{bf2399fd-38f7-45cf-8404-ce25844a23da}</destination>
88 </relationship>
89 </object>
90 <object class="MixerBusPanner" id="{b33c4429-f286-4505-a998-52b4c752c162}"/>
91 <object class="SingleSound" id="{905db4d4-3f09-4a71-a981-772aa96e7ff4}">
92 <property name="length">
93 <value>0.30798185941043082</value>
94 </property>
95 <relationship name="audioFile">
96 <destination>{9eeec59c-fe90-499a-a390-6175f2fa58e8}</destination>
97 </relationship>
98 </object>
99 <object class="EventMixerGroup" id="{cfc8b7fd-e863-413e-89e8-c6f0bc5db7a8}">
100 <property name="name">
101 <value>Audio 1</value>
102 </property>
103 <relationship name="effectChain">
104 <destination>{fe3c2b3a-f423-48c0-b918-ea3064331c9c}</destination>
105 </relationship>
106 <relationship name="panner">
107 <destination>{100a8e0f-32d5-424a-8453-f03c784c8e0f}</destination>
108 </relationship>
109 <relationship name="output">
110 <destination>{d6928c43-7ad8-4ac8-afde-404be9c3c3c9}</destination>
111 </relationship>
112 </object>
113 <object class="MixerBusEffectChain" id="{df7fd3ea-e7fd-4672-ac38-319471cf4416}">
114 <relationship name="effects">
115 <destination>{ffb4df86-9426-45b8-b3c2-b12e3b5ff447}</destination>
116 </relationship>
117 </object>
118 <object class="MixerBusPanner" id="{105a5683-47eb-4d70-a553-adc2b2040fb7}"/>
119 <object class="MixerBusFader" id="{bf2399fd-38f7-45cf-8404-ce25844a23da}"/>
120 <object class="MixerBusEffectChain" id="{fe3c2b3a-f423-48c0-b918-ea3064331c9c}">
121 <relationship name="effects">
122 <destination>{cc649c59-cd4c-4d44-9941-66792be28cb9}</destination>
123 </relationship>
124 </object>
125 <object class="MixerBusPanner" id="{100a8e0f-32d5-424a-8453-f03c784c8e0f}"/>
126 <object class="MixerBusFader" id="{ffb4df86-9426-45b8-b3c2-b12e3b5ff447}"/>
127 <object class="MixerBusFader" id="{cc649c59-cd4c-4d44-9941-66792be28cb9}"/>
128</objects>
diff --git a/res/softsquare.ttf b/res/softsquare.ttf new file mode 100644 index 0000000..fb0ee06 --- /dev/null +++ b/res/softsquare.ttf
Binary files differ
diff --git a/src/consts.h b/src/consts.h index 78312c0..ecb2306 100644 --- a/src/consts.h +++ b/src/consts.h
@@ -12,5 +12,8 @@ constexpr int CHUNK_WIDTH = 80;
12constexpr int CHUNK_HEIGHT = 80; 12constexpr int CHUNK_HEIGHT = 80;
13constexpr int RADIUS = 8; 13constexpr int RADIUS = 8;
14constexpr int NUM_TITLES = 1; 14constexpr int NUM_TITLES = 1;
15constexpr int MESSAGE_MARGIN = 64;
16constexpr int MESSAGE_TEXT_WIDTH = GAME_WIDTH - MESSAGE_MARGIN * 2;
17constexpr int CHARS_PER_BEEP = 8;
15 18
16#endif /* end of include guard: CONSTS_H_152EBF56 */ 19#endif /* end of include guard: CONSTS_H_152EBF56 */
diff --git a/src/game.cpp b/src/game.cpp index 301447f..5838528 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -7,9 +7,10 @@
7#include "renderer.h" 7#include "renderer.h"
8#include "consts.h" 8#include "consts.h"
9 9
10Game::Game(std::mt19937& rng, Muxer& muxer) : 10Game::Game(std::mt19937& rng, Muxer& muxer, Renderer& renderer) :
11 rng(rng), 11 rng(rng),
12 muxer(muxer) 12 muxer(muxer),
13 sign(renderer.getFont())
13{ 14{
14 losePopLampTimer.accumulate(losePopLampTimer.getDt()); 15 losePopLampTimer.accumulate(losePopLampTimer.getDt());
15 16
@@ -631,7 +632,7 @@ void Game::performDash() {
631 } 632 }
632} 633}
633 634
634void Game::update(size_t frameTime) { 635void Game::updatePlaying(size_t frameTime) {
635 SDL_Event e; 636 SDL_Event e;
636 637
637 while (SDL_PollEvent(&e)) 638 while (SDL_PollEvent(&e))
@@ -666,8 +667,22 @@ void Game::update(size_t frameTime) {
666 { 667 {
667 if (losing == LoseState::None) 668 if (losing == LoseState::None)
668 { 669 {
670 auto [lookX, lookY] = coordInDirection(player_x, player_y, playerAnim.getDirection());
671 MapData& lookTile = map.at(lookX, lookY);
669 if (moving) { 672 if (moving) {
670 queueDash = true; 673 if (!lookTile.sign) {
674 queueDash = true;
675 }
676 } else if (lookTile.sign) {
677 if (lookTile.text.empty()) {
678 int lineToRead = nextSignIndex++;
679 if (nextSignIndex >= signTexts.size()) {
680 nextSignIndex = 0;
681 }
682 lookTile.text = signTexts[lineToRead];
683 }
684
685 sign.displayMessage(lookTile.text);
671 } else { 686 } else {
672 performDash(); 687 performDash();
673 } 688 }
@@ -815,7 +830,7 @@ void Game::update(size_t frameTime) {
815 switch (signInstructionState) { 830 switch (signInstructionState) {
816 case SignInstructionState::Hidden: { 831 case SignInstructionState::Hidden: {
817 auto [lookX, lookY] = coordInDirection(player_x, player_y, playerAnim.getDirection()); 832 auto [lookX, lookY] = coordInDirection(player_x, player_y, playerAnim.getDirection());
818 if (map.at(lookX, lookY).sign) { 833 if (losing == LoseState::None && map.at(lookX, lookY).sign) {
819 signInstructionState = SignInstructionState::FadingIn; 834 signInstructionState = SignInstructionState::FadingIn;
820 signFade.start(1000); 835 signFade.start(1000);
821 } 836 }
@@ -913,3 +928,11 @@ void Game::update(size_t frameTime) {
913 928
914 playerAnim.update(frameTime); 929 playerAnim.update(frameTime);
915} 930}
931
932void Game::update(size_t frameTime) {
933 if (sign.signDisplayState != SignInstructionState::Hidden) {
934 sign.update(frameTime, *this);
935 } else {
936 updatePlaying(frameTime);
937 }
938}
diff --git a/src/game.h b/src/game.h index 71685e6..637a033 100644 --- a/src/game.h +++ b/src/game.h
@@ -11,6 +11,9 @@
11#include "animation.h" 11#include "animation.h"
12#include "interpolation.h" 12#include "interpolation.h"
13#include "consts.h" 13#include "consts.h"
14#include "sign.h"
15
16class Renderer;
14 17
15constexpr int TilesetIndex(int x, int y) { 18constexpr int TilesetIndex(int x, int y) {
16 return x + y * 25; 19 return x + y * 25;
@@ -23,13 +26,6 @@ enum class LoseState {
23 Outro 26 Outro
24}; 27};
25 28
26enum class SignInstructionState {
27 Hidden,
28 FadingIn,
29 Visible,
30 FadingOut
31};
32
33struct Input { 29struct Input {
34 bool left = false; 30 bool left = false;
35 bool right = false; 31 bool right = false;
@@ -58,7 +54,7 @@ struct Kickup {
58class Game { 54class Game {
59public: 55public:
60 56
61 Game(std::mt19937& rng, Muxer& muxer); 57 Game(std::mt19937& rng, Muxer& muxer, Renderer& render);
62 58
63 void update(size_t dt); 59 void update(size_t dt);
64 60
@@ -111,6 +107,7 @@ public:
111 int nextSignIndex = 0; 107 int nextSignIndex = 0;
112 SignInstructionState signInstructionState = SignInstructionState::Hidden; 108 SignInstructionState signInstructionState = SignInstructionState::Hidden;
113 Interpolation signFade; 109 Interpolation signFade;
110 Sign sign;
114 111
115private: 112private:
116 113
@@ -144,6 +141,8 @@ private:
144 141
145 void performDash(); 142 void performDash();
146 143
144 void updatePlaying(size_t frameTime);
145
147}; 146};
148 147
149#endif /* end of include guard: GAME_H_7D2B65AE */ 148#endif /* end of include guard: GAME_H_7D2B65AE */
diff --git a/src/main.cpp b/src/main.cpp index 49f5ff2..2bd8f3c 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -21,7 +21,7 @@ int main(int, char**)
21 Renderer renderer; 21 Renderer renderer;
22 Muxer muxer; 22 Muxer muxer;
23 23
24 Game game(rng, muxer); 24 Game game(rng, muxer, renderer);
25 25
26 constexpr int titleFadeLen = 2000; 26 constexpr int titleFadeLen = 2000;
27 bool doneTitles = false; 27 bool doneTitles = false;
diff --git a/src/muxer.cpp b/src/muxer.cpp index 3450187..c93c45a 100644 --- a/src/muxer.cpp +++ b/src/muxer.cpp
@@ -42,6 +42,18 @@ void Muxer::setPlayerLoc(int x, int y) {
42 ERRCHECK(system_->setListenerAttributes(0, &attributes)); 42 ERRCHECK(system_->setListenerAttributes(0, &attributes));
43} 43}
44 44
45void Muxer::playSound(std::string name) {
46 std::string eventPath = std::string("event:/") + name;
47
48 FMOD::Studio::EventDescription* eventDescription = nullptr;
49 ERRCHECK(system_->getEvent(eventPath.c_str(), &eventDescription));
50
51 FMOD::Studio::EventInstance* eventInstance = nullptr;
52 ERRCHECK(eventDescription->createInstance(&eventInstance));
53 ERRCHECK(eventInstance->start());
54 ERRCHECK(eventInstance->release());
55}
56
45void Muxer::playSoundAtPosition(std::string name, float x, float y) { 57void Muxer::playSoundAtPosition(std::string name, float x, float y) {
46 std::string eventPath = std::string("event:/") + name; 58 std::string eventPath = std::string("event:/") + name;
47 59
diff --git a/src/muxer.h b/src/muxer.h index b1a5b26..9750808 100644 --- a/src/muxer.h +++ b/src/muxer.h
@@ -28,6 +28,8 @@ public:
28 28
29 void setPlayerLoc(int x, int y); 29 void setPlayerLoc(int x, int y);
30 30
31 void playSound(std::string name);
32
31 void playSoundAtPosition(std::string name, float x, float y); 33 void playSoundAtPosition(std::string name, float x, float y);
32 34
33 void setMusicLevel(int level); 35 void setMusicLevel(int level);
diff --git a/src/renderer.cpp b/src/renderer.cpp index 2be36ae..c8c1746 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -1,4 +1,5 @@
1#include "renderer.h" 1#include "renderer.h"
2#include <iostream>
2#include "game.h" 3#include "game.h"
3 4
4Renderer::Renderer() 5Renderer::Renderer()
@@ -113,6 +114,11 @@ Renderer::Renderer()
113 114
114 loadTextureFromFile("../res/title0.png", titles_[0]); 115 loadTextureFromFile("../res/title0.png", titles_[0]);
115 SDL_QueryTexture(titles_[0].get(), nullptr, nullptr, &titleWidths_[0], &titleHeights_[0]); 116 SDL_QueryTexture(titles_[0].get(), nullptr, nullptr, &titleWidths_[0], &titleHeights_[0]);
117
118 font_ = font_ptr(TTF_OpenFont("../res/softsquare.ttf", 45));
119 if (!font_) {
120 throw ttf_error();
121 }
116} 122}
117 123
118void Renderer::renderGame( 124void Renderer::renderGame(
@@ -389,6 +395,55 @@ void Renderer::renderGame(
389 SDL_RenderCopy(ren_.get(), readInstruction_.get(), nullptr, nullptr); 395 SDL_RenderCopy(ren_.get(), readInstruction_.get(), nullptr, nullptr);
390 } 396 }
391 397
398 if (game.sign.signDisplayState != SignInstructionState::Hidden) {
399 int opacity = 255;
400 if (game.sign.signDisplayState == SignInstructionState::FadingIn) {
401 opacity = game.sign.signDisplayFade.getProgress(0, 255);
402 } else if (game.sign.signDisplayState == SignInstructionState::FadingOut) {
403 opacity = game.sign.signDisplayFade.getProgress(255, 0);
404 }
405
406 SDL_Rect signRect {
407 0,
408 GAME_HEIGHT / 2 - (45 * 2 + 1 + MESSAGE_MARGIN * 2) / 2,
409 GAME_WIDTH,
410 45 * 2 + 1 + MESSAGE_MARGIN * 2
411 };
412
413 SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_BLEND);
414 SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, opacity);
415 SDL_RenderFillRect(ren_.get(), &signRect);
416
417 if (game.sign.signDisplayState == SignInstructionState::Visible) {
418 int lineIndex = 0;
419 for (const SignLine& line : game.sign.linesToShow) {
420 if (messageLines_[lineIndex].line != line.text) {
421 renderMessageLine(messageLines_[lineIndex], line.text, game);
422 }
423
424 if (line.charsRevealed > 0) {
425 {
426 SDL_Rect srcRect {
427 0, 0, messageLines_[lineIndex].charIndexToWidth[line.charsRevealed],
428 TTF_FontHeight(font_.get())
429 };
430 SDL_Rect destRect {
431 MESSAGE_MARGIN,
432 GAME_HEIGHT / 2 - (45 * 2 + 1 + MESSAGE_MARGIN * 2) / 2 + MESSAGE_MARGIN + (45 + 1) * lineIndex,
433 srcRect.w,
434 srcRect.h };
435
436 SDL_SetRenderTarget(ren_.get(), nullptr);
437 SDL_RenderCopy(ren_.get(), messageLines_[lineIndex].renderedTex.get(), &srcRect, &destRect);
438 //std::cout << line.charsRevealed << " (" << messageLines_[lineIndex].charIndexToWidth[line.charsRevealed] << "): " << messageLines_[lineIndex].line.substr(0,line.charsRevealed) << std::endl;
439 }
440 }
441
442 lineIndex++;
443 }
444 }
445 }
446
392 SDL_RenderPresent(ren_.get()); 447 SDL_RenderPresent(ren_.get());
393} 448}
394 449
@@ -443,3 +498,44 @@ void Renderer::loadTextureFromFile(std::string_view path, texture_ptr& texture)
443 texture = texture_ptr(SDL_CreateTextureFromSurface(ren_.get(), pfs.get())); 498 texture = texture_ptr(SDL_CreateTextureFromSurface(ren_.get(), pfs.get()));
444 SDL_SetTextureBlendMode(texture.get(), SDL_BLENDMODE_BLEND); 499 SDL_SetTextureBlendMode(texture.get(), SDL_BLENDMODE_BLEND);
445} 500}
501
502void Renderer::renderMessageLine(MessageCache& line, const std::string& text, const Game& game) {
503 line.line = text;
504
505 line.renderedTex.reset(
506 SDL_CreateTexture(
507 ren_.get(),
508 SDL_PIXELFORMAT_RGBA8888,
509 SDL_TEXTUREACCESS_TARGET,
510 MESSAGE_TEXT_WIDTH,
511 TTF_FontHeight(font_.get())));
512
513 SDL_SetTextureBlendMode(line.renderedTex.get(), SDL_BLENDMODE_BLEND);
514
515 SDL_SetRenderTarget(ren_.get(), line.renderedTex.get());
516 SDL_SetRenderDrawBlendMode(ren_.get(), SDL_BLENDMODE_BLEND);
517 SDL_SetRenderDrawColor(ren_.get(), 0, 0, 0, 0);
518 SDL_RenderClear(ren_.get());
519
520 line.charIndexToWidth.clear();
521 line.charIndexToWidth.push_back(0);
522
523 for (int i=0; i<line.line.size(); i++) {
524 if (line.line[i] != ' ') {
525 int width = 0;
526 std::string substr = line.line.substr(0, i+1);
527 TTF_SizeText(font_.get(), substr.c_str(), &width, nullptr);
528 line.charIndexToWidth.push_back(width);
529 } else {
530 line.charIndexToWidth.push_back(line.charIndexToWidth.back());
531 }
532 }
533
534 SDL_Color fgColor {.r = 255, .g = 255, .b = 255, .a = 255};
535 SDL_Color bgColor {.r = 0, .g = 0, .b = 0, .a = 255};
536 SDL_Rect rect {0, 0, line.charIndexToWidth.back(), TTF_FontHeight(font_.get())};
537 surface_ptr lineSurf = surface_ptr(TTF_RenderText_Shaded(font_.get(), line.line.c_str(), fgColor, bgColor));
538 texture_ptr lineTex = texture_ptr(SDL_CreateTextureFromSurface(ren_.get(), lineSurf.get()));
539 SDL_RenderCopy(ren_.get(), lineTex.get(), nullptr, &rect);
540}
541
diff --git a/src/renderer.h b/src/renderer.h index de1e125..ce2e7e1 100644 --- a/src/renderer.h +++ b/src/renderer.h
@@ -3,10 +3,13 @@
3 3
4#include <SDL.h> 4#include <SDL.h>
5#include <SDL_image.h> 5#include <SDL_image.h>
6#include <SDL_ttf.h>
6#include <stdexcept> 7#include <stdexcept>
7#include <memory> 8#include <memory>
8#include <array> 9#include <array>
9#include <string_view> 10#include <string_view>
11#include <vector>
12#include <string>
10#include "consts.h" 13#include "consts.h"
11 14
12class Game; 15class Game;
@@ -27,6 +30,14 @@ public:
27 } 30 }
28}; 31};
29 32
33class ttf_error : public std::logic_error {
34public:
35
36 ttf_error() : std::logic_error(TTF_GetError())
37 {
38 }
39};
40
30class sdl_wrapper { 41class sdl_wrapper {
31public: 42public:
32 43
@@ -67,6 +78,26 @@ public:
67 } 78 }
68}; 79};
69 80
81class ttf_wrapper {
82public:
83
84 ttf_wrapper()
85 {
86 if (TTF_Init() != 0)
87 {
88 ttf_error ex;
89 TTF_Quit();
90
91 throw ex;
92 }
93 }
94
95 ~ttf_wrapper()
96 {
97 TTF_Quit();
98 }
99};
100
70class window_deleter { 101class window_deleter {
71public: 102public:
72 103
@@ -111,6 +142,16 @@ public:
111 142
112using texture_ptr = std::unique_ptr<SDL_Texture, texture_deleter>; 143using texture_ptr = std::unique_ptr<SDL_Texture, texture_deleter>;
113 144
145class font_deleter {
146public:
147
148 void operator()(TTF_Font* ptr) {
149 TTF_CloseFont(ptr);
150 }
151};
152
153using font_ptr = std::unique_ptr<TTF_Font, font_deleter>;
154
114class Renderer { 155class Renderer {
115public: 156public:
116 157
@@ -122,14 +163,18 @@ public:
122 163
123 void renderTitle(int num, double fade); 164 void renderTitle(int num, double fade);
124 165
166 TTF_Font* getFont() { return font_.get(); }
167
125private: 168private:
126 169
127 void loadTextureFromFile(std::string_view path, texture_ptr& texture); 170 void loadTextureFromFile(std::string_view path, texture_ptr& texture);
128 171
129 sdl_wrapper sdl_; 172 sdl_wrapper sdl_;
130 img_wrapper img_; 173 img_wrapper img_;
174 ttf_wrapper ttf_;
131 window_ptr win_; 175 window_ptr win_;
132 renderer_ptr ren_; 176 renderer_ptr ren_;
177 font_ptr font_;
133 178
134 texture_ptr playerFade_; 179 texture_ptr playerFade_;
135 texture_ptr lampFade_; 180 texture_ptr lampFade_;
@@ -142,6 +187,18 @@ private:
142 std::array<texture_ptr, NUM_TITLES> titles_; 187 std::array<texture_ptr, NUM_TITLES> titles_;
143 std::array<int, NUM_TITLES> titleWidths_; 188 std::array<int, NUM_TITLES> titleWidths_;
144 std::array<int, NUM_TITLES> titleHeights_; 189 std::array<int, NUM_TITLES> titleHeights_;
190
191 // Text rendering
192 struct MessageCache {
193 texture_ptr renderedTex;
194 std::vector<int> charIndexToWidth;
195 std::string line;
196 std::string overflow;
197 };
198
199 void renderMessageLine(MessageCache& line, const std::string& text, const Game& game);
200
201 MessageCache messageLines_[2];
145}; 202};
146 203
147#endif /* end of include guard: RENDERER_H_6A58EC30 */ 204#endif /* end of include guard: RENDERER_H_6A58EC30 */
diff --git a/src/sign.cpp b/src/sign.cpp new file mode 100644 index 0000000..992ac3d --- /dev/null +++ b/src/sign.cpp
@@ -0,0 +1,130 @@
1#include "sign.h"
2#include <list>
3#include "util.h"
4#include "consts.h"
5#include "game.h"
6
7void Sign::displayMessage(std::string text) {
8 signDisplayState = SignInstructionState::FadingIn;
9 lines.clear();
10
11 auto lineChunks = splitStr<std::list<std::string>>(text, "\\n");
12 for (std::string lineChunk : lineChunks) {
13 auto words = splitStr<std::list<std::string>>(lineChunk, " ");
14 std::string prev = words.front();
15 words.pop_front();
16 std::string cur = prev;
17 bool pauseLine = false;
18
19 while (!words.empty()) {
20 cur = prev + " " + words.front();
21
22 int width = 0;
23 TTF_SizeText(font_, cur.c_str(), &width, nullptr);
24 if (width > MESSAGE_TEXT_WIDTH) {
25 lines.push_back({.text = prev, .pause = pauseLine});
26 pauseLine = !pauseLine;
27 cur = words.front();
28 } else if (words.size() == 1) {
29 lines.push_back({.text = cur, .pause = true});
30 }
31
32 prev = cur;
33 words.pop_front();
34 }
35 }
36
37 lines.back().pause = true;
38 linesToShow.push_back(lines.front());
39 lines.pop_front();
40
41 if (!linesToShow.back().pause) {
42 linesToShow.push_back(lines.front());
43 lines.pop_front();
44 }
45}
46
47void Sign::update(size_t dt, Game& game) {
48 SDL_Event e;
49
50 while (SDL_PollEvent(&e)) {
51 if (e.type == SDL_QUIT) {
52 game.quit = true;
53 }
54 }
55
56 switch (signDisplayState) {
57 case SignInstructionState::Hidden: {
58 // Shouldn't happen.
59 break;
60 }
61 case SignInstructionState::FadingIn: {
62 signDisplayFade.tick(dt);
63 if (signDisplayFade.isComplete()) {
64 signDisplayState = SignInstructionState::Visible;
65 }
66
67 break;
68 }
69 case SignInstructionState::FadingOut: {
70 signDisplayFade.tick(dt);
71 if (signDisplayFade.isComplete()) {
72 signDisplayState = SignInstructionState::Hidden;
73 }
74
75 break;
76 }
77 case SignInstructionState::Visible: {
78 const Uint8* state = SDL_GetKeyboardState(NULL);
79 if (state[SDL_SCANCODE_SPACE]) {
80 bool fullyRevealed = true;
81 for (const SignLine& line : linesToShow) {
82 if (line.charsRevealed != line.text.size()) {
83 fullyRevealed = false;
84 break;
85 }
86 }
87
88 if (fullyRevealed) {
89 if (linesToShow.back().pause) {
90 linesToShow.back().pause = false;
91 // Play a sound
92 }
93 if (lines.empty()) {
94 linesToShow.clear();
95 signDisplayState = SignInstructionState::FadingOut;
96 signDisplayFade.start(1000);
97 break;
98 }
99 }
100 }
101
102 textAdvTimer_.accumulate(dt);
103 while (textAdvTimer_.step()) {
104 bool advancedChars = false;
105 for (SignLine& line : linesToShow) {
106 if (line.charsRevealed < line.text.size()) {
107 if (line.charsRevealed % CHARS_PER_BEEP == 0) {
108 // Play a sound
109 game.muxer.playSound("textbeep");
110 }
111 line.charsRevealed++;
112 advancedChars = true;
113 break;
114 }
115 }
116 if (!advancedChars) {
117 if (!lines.empty() && !linesToShow.back().pause) {
118 if (linesToShow.size() == 2) {
119 linesToShow.pop_front();
120 }
121 linesToShow.push_back(lines.front());
122 lines.pop_front();
123 }
124 }
125 }
126
127 break;
128 }
129 }
130}
diff --git a/src/sign.h b/src/sign.h new file mode 100644 index 0000000..c90a8fd --- /dev/null +++ b/src/sign.h
@@ -0,0 +1,45 @@
1#ifndef SIGN_H_B0491849
2#define SIGN_H_B0491849
3
4#include <string>
5#include <list>
6#include <SDL_ttf.h>
7#include "interpolation.h"
8#include "timer.h"
9
10class Game;
11
12enum class SignInstructionState {
13 Hidden,
14 FadingIn,
15 Visible,
16 FadingOut
17};
18
19struct SignLine {
20 std::string text;
21 bool pause = false;
22 int charsRevealed = 0;
23};
24
25class Sign {
26public:
27
28 explicit Sign(TTF_Font* font) : font_(font) {}
29
30 void displayMessage(std::string text);
31
32 void update(size_t dt, Game& game);
33
34 SignInstructionState signDisplayState = SignInstructionState::Hidden;
35 Interpolation signDisplayFade;
36 std::list<SignLine> lines;
37 std::list<SignLine> linesToShow;
38
39private:
40
41 TTF_Font* font_;
42 Timer textAdvTimer_ { 15 };
43};
44
45#endif /* end of include guard: SIGN_H_B0491849 */