Spaces:
Running
Running
cosimotaiuti
commited on
Upload 108 files
Browse files- static/.DS_Store +0 -0
- static/assets/.DS_Store +0 -0
- static/assets/css/popup.css +236 -0
- static/assets/css/stress-animations.css +212 -0
- static/assets/img/.DS_Store +0 -0
- static/assets/img/popup/background.jpg +0 -0
- static/assets/img/popup/clown_lose.png +0 -0
- static/assets/img/popup/fuck.png +0 -0
- static/assets/img/popup/stars1.png +0 -0
- static/assets/img/popup/stars2.png +0 -0
- static/assets/img/popup/text.svg +0 -0
- static/assets/img/profil_pictures/low_stress.webp +0 -0
- static/assets/sounds/clownmove1.mp3 +0 -0
- static/assets/sounds/clownmove2.mp3 +0 -0
- static/assets/sounds/clownseesyou.mp3 +0 -0
- static/assets/sounds/gfmove.mp3 +0 -0
- static/assets/sounds/lose.mp3 +0 -0
- static/assets/sounds/unlockdoor.mp3 +0 -0
- static/assets/sounds/useknife.mp3 +0 -0
- static/game/elmnts/clown.js +2 -0
- static/game/elmnts/furniture.js +1 -1
- static/game/elmnts/girlfriend.js +17 -3
- static/game/game.js +50 -3
- static/game/gameState.js +63 -73
- static/game/index.html +44 -26
- static/game/index2.html +136 -0
- static/game/utilities/chat.js +45 -2
- static/game/utilities/sound.js +31 -14
static/.DS_Store
CHANGED
Binary files a/static/.DS_Store and b/static/.DS_Store differ
|
|
static/assets/.DS_Store
CHANGED
Binary files a/static/assets/.DS_Store and b/static/assets/.DS_Store differ
|
|
static/assets/css/popup.css
ADDED
@@ -0,0 +1,236 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@font-face {
|
2 |
+
font-family: "HorrorBrush";
|
3 |
+
src: url("/static/assets/fonts/horrorbrush.ttf") format("truetype");
|
4 |
+
}
|
5 |
+
|
6 |
+
.popup-overlay {
|
7 |
+
position: fixed;
|
8 |
+
top: 0;
|
9 |
+
left: 0;
|
10 |
+
width: 100%;
|
11 |
+
height: 100%;
|
12 |
+
background-color: rgba(0, 0, 0, 0.202);
|
13 |
+
backdrop-filter: blur(8px);
|
14 |
+
z-index: 1000;
|
15 |
+
display: block;
|
16 |
+
}
|
17 |
+
|
18 |
+
.popup-loser {
|
19 |
+
position: fixed;
|
20 |
+
top: 50%;
|
21 |
+
left: 50%;
|
22 |
+
transform: translate(-50%, -50%);
|
23 |
+
width: 800px;
|
24 |
+
height: 500px;
|
25 |
+
background-color: #141313;
|
26 |
+
border-radius: 20px;
|
27 |
+
box-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
|
28 |
+
z-index: 1001;
|
29 |
+
display: none;
|
30 |
+
overflow: hidden;
|
31 |
+
}
|
32 |
+
|
33 |
+
.popup-loser .clown {
|
34 |
+
position: absolute;
|
35 |
+
bottom: -5px;
|
36 |
+
right: -5px;
|
37 |
+
width: 300px;
|
38 |
+
height: auto;
|
39 |
+
z-index: 1002;
|
40 |
+
}
|
41 |
+
|
42 |
+
.popup-loser .blood-top {
|
43 |
+
position: absolute;
|
44 |
+
top: -100px;
|
45 |
+
left: -100px;
|
46 |
+
width: 300px;
|
47 |
+
height: auto;
|
48 |
+
z-index: 1002;
|
49 |
+
}
|
50 |
+
|
51 |
+
.popup-loser .blood-bottom {
|
52 |
+
position: absolute;
|
53 |
+
bottom: -100px;
|
54 |
+
right: -100px;
|
55 |
+
width: 300px;
|
56 |
+
height: auto;
|
57 |
+
transform: rotate(180deg);
|
58 |
+
z-index: 1001;
|
59 |
+
}
|
60 |
+
|
61 |
+
.popup-loser .title {
|
62 |
+
position: absolute;
|
63 |
+
left: 40%;
|
64 |
+
transform: translateX(-50%);
|
65 |
+
font-size: 120px;
|
66 |
+
font-weight: bold;
|
67 |
+
color: #9b0000;
|
68 |
+
text-shadow: 10px 10px 4px #4d0000;
|
69 |
+
font-family: "HorrorBrush", cursive;
|
70 |
+
z-index: 1003;
|
71 |
+
}
|
72 |
+
|
73 |
+
.popup-loser .title-glow {
|
74 |
+
position: absolute;
|
75 |
+
top: 50%;
|
76 |
+
left: 40%;
|
77 |
+
transform: translate(-50%, -50%);
|
78 |
+
width: 600px;
|
79 |
+
height: 600px;
|
80 |
+
background: radial-gradient(
|
81 |
+
circle,
|
82 |
+
rgba(155, 0, 0, 0.2) 0%,
|
83 |
+
rgba(0, 0, 0, 0) 90%
|
84 |
+
);
|
85 |
+
z-index: 1002;
|
86 |
+
pointer-events: none;
|
87 |
+
}
|
88 |
+
|
89 |
+
.popup-loser .play-again {
|
90 |
+
position: absolute;
|
91 |
+
bottom: 130px;
|
92 |
+
left: 40%;
|
93 |
+
transform: translateX(-50%);
|
94 |
+
padding: 15px 40px;
|
95 |
+
min-width: 230px;
|
96 |
+
font-size: 42px;
|
97 |
+
font-family: "HorrorBrush", cursive;
|
98 |
+
color: #ffffff;
|
99 |
+
background-color: #9b0000;
|
100 |
+
border-radius: 15px;
|
101 |
+
cursor: pointer;
|
102 |
+
transition: all 0.3s ease;
|
103 |
+
box-shadow: 0 5px 15px rgba(155, 0, 0, 0.4);
|
104 |
+
z-index: 1003;
|
105 |
+
letter-spacing: 2px;
|
106 |
+
line-height: 1;
|
107 |
+
white-space: nowrap;
|
108 |
+
height: auto;
|
109 |
+
display: flex;
|
110 |
+
align-items: center;
|
111 |
+
justify-content: center;
|
112 |
+
}
|
113 |
+
|
114 |
+
.popup-loser .play-again:hover {
|
115 |
+
background-color: #cc0000;
|
116 |
+
transform: translateX(-50%) scale(1.05);
|
117 |
+
box-shadow: 0 8px 20px rgba(155, 0, 0, 0.6);
|
118 |
+
}
|
119 |
+
|
120 |
+
/* Popup Winner */
|
121 |
+
.popup-winner {
|
122 |
+
position: fixed;
|
123 |
+
top: 50%;
|
124 |
+
left: 50%;
|
125 |
+
transform: translate(-50%, -50%);
|
126 |
+
width: 800px;
|
127 |
+
height: 500px;
|
128 |
+
border-radius: 20px;
|
129 |
+
box-shadow: 0 0 30px rgba(0, 0, 0, 0.5);
|
130 |
+
z-index: 1001;
|
131 |
+
display: block;
|
132 |
+
overflow: hidden;
|
133 |
+
background-image: url("/static/assets/img/popup/background.jpg");
|
134 |
+
background-size: cover;
|
135 |
+
background-position: center;
|
136 |
+
}
|
137 |
+
|
138 |
+
.popup-winner .win-text {
|
139 |
+
position: absolute;
|
140 |
+
top: 35%;
|
141 |
+
left: 35%;
|
142 |
+
transform: translate(-50%, -50%);
|
143 |
+
width: 60%;
|
144 |
+
height: auto;
|
145 |
+
z-index: 1003;
|
146 |
+
}
|
147 |
+
|
148 |
+
.popup-winner .fuck {
|
149 |
+
position: absolute;
|
150 |
+
bottom: -10px;
|
151 |
+
right: -10px;
|
152 |
+
width: 350px;
|
153 |
+
height: auto;
|
154 |
+
z-index: 1004;
|
155 |
+
}
|
156 |
+
|
157 |
+
.popup-winner .stars1 {
|
158 |
+
position: absolute;
|
159 |
+
right: 40px;
|
160 |
+
left: 80%;
|
161 |
+
top: 0%;
|
162 |
+
width: 200px;
|
163 |
+
height: auto;
|
164 |
+
z-index: 1002;
|
165 |
+
}
|
166 |
+
|
167 |
+
.popup-winner .stars2 {
|
168 |
+
position: absolute;
|
169 |
+
bottom: -10px;
|
170 |
+
right: 40px;
|
171 |
+
width: 500px;
|
172 |
+
height: auto;
|
173 |
+
z-index: 1002;
|
174 |
+
}
|
175 |
+
|
176 |
+
.popup-winner .play-again {
|
177 |
+
position: absolute;
|
178 |
+
bottom: 40px;
|
179 |
+
left: 27%;
|
180 |
+
top: auto;
|
181 |
+
transform: translateX(-50%);
|
182 |
+
padding: 20px 60px;
|
183 |
+
min-width: 350px;
|
184 |
+
height: 80px;
|
185 |
+
font-size: 30px;
|
186 |
+
font-family: "Comic Sans MS", cursive;
|
187 |
+
color: #ffffff;
|
188 |
+
background: linear-gradient(45deg, #ff69b4, #ff1493);
|
189 |
+
border: 3px solid #fff;
|
190 |
+
border-radius: 40px;
|
191 |
+
cursor: pointer;
|
192 |
+
transition: all 0.3s ease;
|
193 |
+
box-shadow: 0 5px 20px rgba(255, 105, 180, 0.6),
|
194 |
+
inset 0 0 20px rgba(255, 255, 255, 0.4);
|
195 |
+
z-index: 1003;
|
196 |
+
letter-spacing: 1px;
|
197 |
+
text-transform: uppercase;
|
198 |
+
animation: sparkle 2s infinite;
|
199 |
+
white-space: nowrap;
|
200 |
+
display: flex;
|
201 |
+
align-items: center;
|
202 |
+
justify-content: center;
|
203 |
+
line-height: 1;
|
204 |
+
}
|
205 |
+
|
206 |
+
.popup-winner .play-again:hover {
|
207 |
+
transform: translateX(-50%) scale(1.05);
|
208 |
+
background: linear-gradient(45deg, #ff1493, #ff69b4);
|
209 |
+
box-shadow: 0 8px 25px rgba(255, 105, 180, 0.8),
|
210 |
+
inset 0 0 30px rgba(255, 255, 255, 0.6);
|
211 |
+
letter-spacing: 3px;
|
212 |
+
}
|
213 |
+
|
214 |
+
.popup-winner .play-again::before {
|
215 |
+
content: "✨";
|
216 |
+
position: absolute;
|
217 |
+
left: 25px;
|
218 |
+
}
|
219 |
+
|
220 |
+
.popup-winner .play-again::after {
|
221 |
+
content: "✨";
|
222 |
+
position: absolute;
|
223 |
+
right: 25px;
|
224 |
+
}
|
225 |
+
|
226 |
+
@keyframes sparkle {
|
227 |
+
0% {
|
228 |
+
text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #ff69b4;
|
229 |
+
}
|
230 |
+
50% {
|
231 |
+
text-shadow: 0 0 20px #fff, 0 0 30px #fff, 0 0 40px #ff1493;
|
232 |
+
}
|
233 |
+
100% {
|
234 |
+
text-shadow: 0 0 10px #fff, 0 0 20px #fff, 0 0 30px #ff69b4;
|
235 |
+
}
|
236 |
+
}
|
static/assets/css/stress-animations.css
ADDED
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Classes de base pour la photo de profil */
|
2 |
+
#chatSection .profile-picture {
|
3 |
+
width: 40px;
|
4 |
+
height: 40px;
|
5 |
+
border-radius: 50%;
|
6 |
+
overflow: hidden;
|
7 |
+
margin-right: 10px;
|
8 |
+
}
|
9 |
+
|
10 |
+
#chatSection .profile-picture img {
|
11 |
+
width: 100%;
|
12 |
+
height: 100%;
|
13 |
+
object-fit: cover;
|
14 |
+
}
|
15 |
+
|
16 |
+
/* État: No Stress */
|
17 |
+
#chatSection.no-stress .profile-picture {
|
18 |
+
border: 2px solid #607ab1;
|
19 |
+
}
|
20 |
+
|
21 |
+
#chatSection.no-stress .chat-name {
|
22 |
+
color: #333;
|
23 |
+
}
|
24 |
+
|
25 |
+
/* État: Low Stress - Animation de pulsation modérée */
|
26 |
+
#chatSection.low-stress .profile-picture {
|
27 |
+
border: 2px solid #ffa500;
|
28 |
+
animation: lowStressPulse 1.5s infinite;
|
29 |
+
box-shadow: 0 0 5px rgba(255, 165, 0, 0.3);
|
30 |
+
}
|
31 |
+
|
32 |
+
#chatSection.low-stress .chat-name {
|
33 |
+
animation: lowStressTextPulse 1.5s infinite;
|
34 |
+
}
|
35 |
+
|
36 |
+
#chatSection.low-stress #chatHistory .ai-message {
|
37 |
+
background-color: #ffa500;
|
38 |
+
color: #ffffff;
|
39 |
+
animation: lowStressMessagePulse 2s infinite,
|
40 |
+
lowStressMessageScale 1.5s infinite;
|
41 |
+
border: 1px solid #ffa500;
|
42 |
+
}
|
43 |
+
|
44 |
+
@keyframes lowStressPulse {
|
45 |
+
0% {
|
46 |
+
box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.3);
|
47 |
+
transform: scale(1);
|
48 |
+
}
|
49 |
+
50% {
|
50 |
+
box-shadow: 0 0 10px 3px rgba(255, 165, 0, 0.5);
|
51 |
+
transform: scale(1.03);
|
52 |
+
}
|
53 |
+
100% {
|
54 |
+
box-shadow: 0 0 0 0 rgba(255, 165, 0, 0);
|
55 |
+
transform: scale(1);
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
@keyframes lowStressTextPulse {
|
60 |
+
0% {
|
61 |
+
transform: scale(1);
|
62 |
+
}
|
63 |
+
50% {
|
64 |
+
transform: scale(1.05);
|
65 |
+
}
|
66 |
+
100% {
|
67 |
+
transform: scale(1);
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
@keyframes lowStressMessagePulse {
|
72 |
+
0% {
|
73 |
+
background-color: #ffa500;
|
74 |
+
box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.3);
|
75 |
+
}
|
76 |
+
50% {
|
77 |
+
background-color: #ffb733;
|
78 |
+
box-shadow: 0 0 8px 0 rgba(255, 165, 0, 0.4);
|
79 |
+
}
|
80 |
+
100% {
|
81 |
+
background-color: #ffa500;
|
82 |
+
box-shadow: 0 0 0 0 rgba(255, 165, 0, 0.3);
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
@keyframes lowStressMessageScale {
|
87 |
+
0% {
|
88 |
+
transform: scale(1);
|
89 |
+
}
|
90 |
+
50% {
|
91 |
+
transform: scale(1.02);
|
92 |
+
}
|
93 |
+
100% {
|
94 |
+
transform: scale(1);
|
95 |
+
}
|
96 |
+
}
|
97 |
+
|
98 |
+
/* État: Very Stress - Animation de pulsation intense */
|
99 |
+
#chatSection.very-stress {
|
100 |
+
background-color: #1a1a1a;
|
101 |
+
transition: background-color 0.3s ease;
|
102 |
+
}
|
103 |
+
|
104 |
+
#chatSection.very-stress #chatHeader {
|
105 |
+
background-color: #1a1a1a;
|
106 |
+
transition: background-color 0.3s ease;
|
107 |
+
}
|
108 |
+
|
109 |
+
#chatSection.very-stress .profile-picture {
|
110 |
+
border: 3px solid #ff0000;
|
111 |
+
animation: veryStressPulse 0.8s infinite;
|
112 |
+
box-shadow: 0 0 10px rgba(255, 0, 0, 0.5);
|
113 |
+
}
|
114 |
+
|
115 |
+
#chatSection.very-stress .chat-name {
|
116 |
+
color: #ff0000;
|
117 |
+
animation: veryStressTextPulse 0.8s infinite;
|
118 |
+
font-weight: bold;
|
119 |
+
text-shadow: 0 0 10px rgba(255, 0, 0, 0.8);
|
120 |
+
}
|
121 |
+
|
122 |
+
#chatSection.very-stress #chatHistory {
|
123 |
+
background-color: #1a1a1a;
|
124 |
+
color: #ffffff;
|
125 |
+
}
|
126 |
+
|
127 |
+
#chatSection.very-stress #chatHistory .ai-message {
|
128 |
+
background-color: #e92626;
|
129 |
+
color: #ffffff;
|
130 |
+
animation: messageShake 0.8s infinite, messageRedPulse 2s infinite;
|
131 |
+
border: 1px solid #ff0000;
|
132 |
+
}
|
133 |
+
|
134 |
+
#chatSection.very-stress #chatControls {
|
135 |
+
background-color: #1a1a1a;
|
136 |
+
}
|
137 |
+
|
138 |
+
#chatSection.very-stress #prompt {
|
139 |
+
background-color: #2d2d2d;
|
140 |
+
color: #ffffff;
|
141 |
+
border: 1px solid #ffffff;
|
142 |
+
}
|
143 |
+
|
144 |
+
#chatSection.very-stress .chat-name::before {
|
145 |
+
content: "Bae ";
|
146 |
+
}
|
147 |
+
|
148 |
+
#chatSection.very-stress .chat-name::after {
|
149 |
+
content: "💀💀";
|
150 |
+
}
|
151 |
+
|
152 |
+
#chatSection.very-stress .chat-name span {
|
153 |
+
display: none;
|
154 |
+
}
|
155 |
+
|
156 |
+
@keyframes veryStressPulse {
|
157 |
+
0% {
|
158 |
+
box-shadow: 0 0 0 0 rgba(255, 0, 0, 0.5);
|
159 |
+
transform: scale(1);
|
160 |
+
}
|
161 |
+
50% {
|
162 |
+
box-shadow: 0 0 15px 5px rgba(255, 0, 0, 0.7);
|
163 |
+
transform: scale(1.05);
|
164 |
+
}
|
165 |
+
100% {
|
166 |
+
box-shadow: 0 0 0 0 rgba(255, 0, 0, 0);
|
167 |
+
transform: scale(1);
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
@keyframes veryStressTextPulse {
|
172 |
+
0% {
|
173 |
+
text-shadow: 0 0 0 rgba(255, 0, 0, 0);
|
174 |
+
transform: scale(1);
|
175 |
+
}
|
176 |
+
50% {
|
177 |
+
text-shadow: 0 0 10px rgba(255, 0, 0, 0.8);
|
178 |
+
transform: scale(1.08);
|
179 |
+
}
|
180 |
+
100% {
|
181 |
+
text-shadow: 0 0 0 rgba(255, 0, 0, 0);
|
182 |
+
transform: scale(1);
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
@keyframes messageShake {
|
187 |
+
0%,
|
188 |
+
100% {
|
189 |
+
transform: translateX(0);
|
190 |
+
}
|
191 |
+
25% {
|
192 |
+
transform: translateX(-2px) translateY(-1px);
|
193 |
+
}
|
194 |
+
75% {
|
195 |
+
transform: translateX(2px) translateY(1px);
|
196 |
+
}
|
197 |
+
}
|
198 |
+
|
199 |
+
@keyframes messageRedPulse {
|
200 |
+
0% {
|
201 |
+
background-color: #e92626;
|
202 |
+
box-shadow: 0 0 0 0 rgba(233, 38, 38, 0.4);
|
203 |
+
}
|
204 |
+
50% {
|
205 |
+
background-color: #ff3333;
|
206 |
+
box-shadow: 0 0 10px 0 rgba(233, 38, 38, 0.6);
|
207 |
+
}
|
208 |
+
100% {
|
209 |
+
background-color: #e92626;
|
210 |
+
box-shadow: 0 0 0 0 rgba(233, 38, 38, 0.4);
|
211 |
+
}
|
212 |
+
}
|
static/assets/img/.DS_Store
CHANGED
Binary files a/static/assets/img/.DS_Store and b/static/assets/img/.DS_Store differ
|
|
static/assets/img/popup/background.jpg
ADDED
static/assets/img/popup/clown_lose.png
ADDED
static/assets/img/popup/fuck.png
ADDED
static/assets/img/popup/stars1.png
ADDED
static/assets/img/popup/stars2.png
ADDED
static/assets/img/popup/text.svg
ADDED
static/assets/img/profil_pictures/low_stress.webp
ADDED
static/assets/sounds/clownmove1.mp3
ADDED
Binary file (37.6 kB). View file
|
|
static/assets/sounds/clownmove2.mp3
ADDED
Binary file (92 kB). View file
|
|
static/assets/sounds/clownseesyou.mp3
ADDED
Binary file (57.6 kB). View file
|
|
static/assets/sounds/gfmove.mp3
ADDED
Binary file (21.1 kB). View file
|
|
static/assets/sounds/lose.mp3
ADDED
Binary file (95 kB). View file
|
|
static/assets/sounds/unlockdoor.mp3
ADDED
Binary file (95.2 kB). View file
|
|
static/assets/sounds/useknife.mp3
ADDED
Binary file (20 kB). View file
|
|
static/game/elmnts/clown.js
CHANGED
@@ -24,6 +24,8 @@ class Clown extends Character {
|
|
24 |
|
25 |
this.behaviorInterval = setInterval(() => {
|
26 |
this.decideBehavior();
|
|
|
|
|
27 |
}, 3000);
|
28 |
}
|
29 |
|
|
|
24 |
|
25 |
this.behaviorInterval = setInterval(() => {
|
26 |
this.decideBehavior();
|
27 |
+
// playSound(Math.random() < 0.5 ? 'clownSound1' : 'clownSound2');
|
28 |
+
|
29 |
}, 3000);
|
30 |
}
|
31 |
|
static/game/elmnts/furniture.js
CHANGED
@@ -157,7 +157,7 @@ function getFurniture() {
|
|
157 |
"state": "usable",
|
158 |
"in_use": true,
|
159 |
"key":"Knife",
|
160 |
-
"locked_msg":"Um... what. the. f. Why is its mouth stitched up? Is the key inside??? i cant open it",
|
161 |
"unlocked_msg":"No no no ew ew i can't believe im doing this...😭😭😭 ....the key was in here i got it!! I can get out!",
|
162 |
"sprite": [
|
163 |
{
|
|
|
157 |
"state": "usable",
|
158 |
"in_use": true,
|
159 |
"key":"Knife",
|
160 |
+
"locked_msg":"Um... what. the. f. Why is its mouth stitched up? Is the key inside??? i cant open it, should i look for something to open it with?",
|
161 |
"unlocked_msg":"No no no ew ew i can't believe im doing this...😭😭😭 ....the key was in here i got it!! I can get out!",
|
162 |
"sprite": [
|
163 |
{
|
static/game/elmnts/girlfriend.js
CHANGED
@@ -9,6 +9,16 @@ class Girlfriend extends Character {
|
|
9 |
this.stressLevel = 30;
|
10 |
this.inventory = [];
|
11 |
this.knows_about_dead_body = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
13 |
|
14 |
draw(CELL_SIZE) {
|
@@ -55,7 +65,10 @@ class Girlfriend extends Character {
|
|
55 |
);
|
56 |
}
|
57 |
|
58 |
-
handleAction(response) {
|
|
|
|
|
|
|
59 |
switch (response.action) {
|
60 |
case "go":
|
61 |
this.moveToRoom(response.target);
|
@@ -151,6 +164,7 @@ class Girlfriend extends Character {
|
|
151 |
if (!this.inventory || !this.inventory.includes("Key")) {
|
152 |
addProgramaticMessage(the_exit.locked_message);
|
153 |
} else {
|
|
|
154 |
addProgramaticMessage(the_exit.unlocked_message);
|
155 |
}
|
156 |
});
|
@@ -158,13 +172,13 @@ class Girlfriend extends Character {
|
|
158 |
|
159 |
check(target) {
|
160 |
if (target === "Bookcase") {
|
161 |
-
let bookcase = this.gameState.
|
162 |
this.moveToPosition(bookcase.pos, () => {
|
163 |
addProgramaticMessage(bookcase.msg);
|
164 |
bookcase.state = "unusable";
|
165 |
});
|
166 |
} else if (target === "Cabinet") {
|
167 |
-
let cabinet =
|
168 |
this.moveToPosition(cabinet.pos, () => {
|
169 |
addProgramaticMessage(cabinet.msg);
|
170 |
this.inventory.push("Knife");
|
|
|
9 |
this.stressLevel = 30;
|
10 |
this.inventory = [];
|
11 |
this.knows_about_dead_body = false;
|
12 |
+
this.independance_rate = 3000;
|
13 |
+
this.game_loops_before_deciding_for_herself = this.independance_rate;
|
14 |
+
}
|
15 |
+
|
16 |
+
update(){
|
17 |
+
this.game_loops_before_deciding_for_herself--;
|
18 |
+
if(this.game_loops_before_deciding_for_herself <= 0){
|
19 |
+
this.game_loops_before_deciding_for_herself = this.independance_rate;
|
20 |
+
strongIndependantWoman();
|
21 |
+
}
|
22 |
}
|
23 |
|
24 |
draw(CELL_SIZE) {
|
|
|
65 |
);
|
66 |
}
|
67 |
|
68 |
+
handleAction(response, called_by_chat = false) {
|
69 |
+
if(called_by_chat){
|
70 |
+
this.game_loops_before_deciding_for_herself = this.independance_rate;
|
71 |
+
}
|
72 |
switch (response.action) {
|
73 |
case "go":
|
74 |
this.moveToRoom(response.target);
|
|
|
164 |
if (!this.inventory || !this.inventory.includes("Key")) {
|
165 |
addProgramaticMessage(the_exit.locked_message);
|
166 |
} else {
|
167 |
+
this.gameState.winGame();
|
168 |
addProgramaticMessage(the_exit.unlocked_message);
|
169 |
}
|
170 |
});
|
|
|
172 |
|
173 |
check(target) {
|
174 |
if (target === "Bookcase") {
|
175 |
+
let bookcase = this.gameState.map_data.furniture.find(item => item.name === "Bookcase");
|
176 |
this.moveToPosition(bookcase.pos, () => {
|
177 |
addProgramaticMessage(bookcase.msg);
|
178 |
bookcase.state = "unusable";
|
179 |
});
|
180 |
} else if (target === "Cabinet") {
|
181 |
+
let cabinet =this.gameState.map_data.furniture.find(item => item.name === "Cabinet");
|
182 |
this.moveToPosition(cabinet.pos, () => {
|
183 |
addProgramaticMessage(cabinet.msg);
|
184 |
this.inventory.push("Knife");
|
static/game/game.js
CHANGED
@@ -9,6 +9,17 @@ let baseMapImg;
|
|
9 |
let girlfriendImg;
|
10 |
let clownImg;
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
let isSoundOn =
|
13 |
localStorage.getItem("isSoundOn") === null
|
14 |
? true
|
@@ -22,7 +33,35 @@ let chatMessages = [];
|
|
22 |
|
23 |
let furnitureSprites = {};
|
24 |
|
25 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
baseMapImg = loadImage("/assets/img/appartment/basemap.png");
|
27 |
girlfriendImg = loadImage("/assets/img/gf.png");
|
28 |
clownImg = loadImage("/assets/img/clown.png");
|
@@ -45,6 +84,8 @@ function setup() {
|
|
45 |
let canvas = createCanvas(GRID_COLS * CELL_SIZE, GRID_ROWS * CELL_SIZE);
|
46 |
canvas.parent("mapWrapper");
|
47 |
adjustScale();
|
|
|
|
|
48 |
}
|
49 |
|
50 |
function draw() {
|
@@ -64,12 +105,18 @@ function draw() {
|
|
64 |
|
65 |
|
66 |
if (girlfriend) {
|
67 |
-
girlfriend.drawPath(CELL_SIZE);
|
68 |
girlfriend.draw(CELL_SIZE);
|
69 |
}
|
70 |
if (clown) {
|
71 |
clown.checkForGirlfriend(girlfriend);
|
72 |
-
clown.drawPath(CELL_SIZE);
|
73 |
clown.draw(CELL_SIZE);
|
74 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
}
|
|
|
9 |
let girlfriendImg;
|
10 |
let clownImg;
|
11 |
|
12 |
+
let clownSound1Snd;
|
13 |
+
let clownSound2Snd;
|
14 |
+
let clownSeesYouSnd;
|
15 |
+
let gfMoveSnd;
|
16 |
+
let loseSnd;
|
17 |
+
let unlockDoorSnd;
|
18 |
+
let useKnifeSnd;
|
19 |
+
|
20 |
+
|
21 |
+
|
22 |
+
|
23 |
let isSoundOn =
|
24 |
localStorage.getItem("isSoundOn") === null
|
25 |
? true
|
|
|
33 |
|
34 |
let furnitureSprites = {};
|
35 |
|
36 |
+
function preload() {
|
37 |
+
clownSound1Snd = loadSound('/assets/sounds/clownmove1.mp3');
|
38 |
+
clownSound2Snd = loadSound('/assets/sounds/clownmove2.mp3');
|
39 |
+
clownSeesYouSnd = loadSound('/assets/sounds/clownseesyou.mp3');
|
40 |
+
gfMoveSnd = loadSound('/assets/sounds/gfmove.mp3');
|
41 |
+
loseSnd = loadSound('/assets/sounds/lose.mp3');
|
42 |
+
unlockDoorSnd = loadSound('/assets/sounds/unlockdoor.mp3');
|
43 |
+
useKnifeSnd = loadSound('/assets/sounds/useknife.mp3');
|
44 |
+
}
|
45 |
+
|
46 |
+
async function initializeChat() {
|
47 |
+
const firstPrompt = gameState.getFirstPrompt();
|
48 |
+
const messages = [
|
49 |
+
{
|
50 |
+
role: "system",
|
51 |
+
content: firstPrompt,
|
52 |
+
},
|
53 |
+
];
|
54 |
+
try {
|
55 |
+
const response = await mistralAPI.sendMessage(messages);
|
56 |
+
const jsonResponse = JSON.parse(response);
|
57 |
+
addMessageToChat("assistant", jsonResponse.textMessage);
|
58 |
+
} catch (error) {
|
59 |
+
console.error("Error getting initial message:", error);
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
async function setup() {
|
64 |
+
|
65 |
baseMapImg = loadImage("/assets/img/appartment/basemap.png");
|
66 |
girlfriendImg = loadImage("/assets/img/gf.png");
|
67 |
clownImg = loadImage("/assets/img/clown.png");
|
|
|
84 |
let canvas = createCanvas(GRID_COLS * CELL_SIZE, GRID_ROWS * CELL_SIZE);
|
85 |
canvas.parent("mapWrapper");
|
86 |
adjustScale();
|
87 |
+
|
88 |
+
await initializeChat();
|
89 |
}
|
90 |
|
91 |
function draw() {
|
|
|
105 |
|
106 |
|
107 |
if (girlfriend) {
|
108 |
+
//girlfriend.drawPath(CELL_SIZE);
|
109 |
girlfriend.draw(CELL_SIZE);
|
110 |
}
|
111 |
if (clown) {
|
112 |
clown.checkForGirlfriend(girlfriend);
|
113 |
+
//clown.drawPath(CELL_SIZE);
|
114 |
clown.draw(CELL_SIZE);
|
115 |
}
|
116 |
+
|
117 |
+
gameState.update();
|
118 |
+
|
119 |
+
if (gameState.game_over) {
|
120 |
+
noLoop();
|
121 |
+
}
|
122 |
}
|
static/game/gameState.js
CHANGED
@@ -4,38 +4,38 @@ class GameState {
|
|
4 |
this.map_data = map_data;
|
5 |
this.girlfriend = null;
|
6 |
this.clown = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
"knife",
|
24 |
-
"oil",
|
25 |
-
"remote",
|
26 |
-
];
|
27 |
-
|
28 |
-
this.useTargets = [
|
29 |
-
"bedroom door",
|
30 |
-
"bookcase",
|
31 |
-
"storage door",
|
32 |
-
"dead body",
|
33 |
-
"coffee table",
|
34 |
-
"TV",
|
35 |
-
];
|
36 |
-
|
37 |
-
this.inventory = [];
|
38 |
-
this.isHiding = false;
|
39 |
}
|
40 |
|
41 |
getTheExit() {
|
@@ -44,11 +44,6 @@ class GameState {
|
|
44 |
);
|
45 |
}
|
46 |
|
47 |
-
getStorage() {
|
48 |
-
return this.map_data.furniture.find(
|
49 |
-
(furniture) => furniture.name === "Storage"
|
50 |
-
);
|
51 |
-
}
|
52 |
|
53 |
getStressPrompt() {
|
54 |
const currentStress = this.girlfriend ? this.girlfriend.stressLevel : 50; // Default to 50 if girlfriend not initialized
|
@@ -100,6 +95,7 @@ Examples:
|
|
100 |
}
|
101 |
`;
|
102 |
}
|
|
|
103 |
getPrompt() {
|
104 |
return `
|
105 |
|
@@ -108,24 +104,21 @@ You are a JSON girlfriend that is stuck in her boyfriends appartment with an evi
|
|
108 |
Current state:
|
109 |
- You (the girlfriend) are currently in this Room >> ${this.girlfriend.getCurrentRoom()}
|
110 |
- Your current stress level is ${this.girlfriend.stressLevel}/100
|
111 |
-
${
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
.join(", ")}`
|
127 |
-
: ""
|
128 |
-
}
|
129 |
RESPONSE FORMAT:
|
130 |
You must ALWAYS respond with a JSON object.
|
131 |
Your response should reflect a girlfriend's reaction to her boyfriend's message given this context and following the following structure:
|
@@ -150,31 +143,29 @@ For hiding instructions ("hide" action):
|
|
150 |
}
|
151 |
VALID HIDING PLACES:
|
152 |
You are only allowed to hide in these hiding spots no other hiding spots are recognized:
|
153 |
-
${
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
}
|
161 |
|
162 |
|
163 |
For checking/inquiring/going to apecifically the Cabinet or Bookcase instructions ("check" action):
|
164 |
{
|
165 |
"action": "check",
|
166 |
-
"target": "she can only check \"Cabinet\" (this is in the kitchen, you can ask if youre not sure) or \"Bookcase\" (this is in the guest bedroom you can ask if youre not sure).${
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
}
|
171 |
"textMessage": "[girlfriend's response]"
|
172 |
}
|
173 |
|
174 |
For exiting the house by the exit in the mainhallway instructions ("exit" action):
|
175 |
{
|
176 |
"action": "exit",
|
177 |
-
"target": "The Exit",
|
178 |
"textMessage": "[girlfriend's response]"
|
179 |
}
|
180 |
|
@@ -188,11 +179,10 @@ For any other input:
|
|
188 |
|
189 |
YOUR BEHAVIOR:
|
190 |
- You are aware of the danger and are extremely distressed.
|
191 |
-
${
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
}
|
196 |
Your text responses should be:
|
197 |
-- Brief and urgent
|
198 |
-- Reflect genuine fear and panic
|
|
|
4 |
this.map_data = map_data;
|
5 |
this.girlfriend = null;
|
6 |
this.clown = null;
|
7 |
+
this.game_over = false;
|
8 |
+
}
|
9 |
+
endGame() {
|
10 |
+
this.game_over = true;
|
11 |
+
loseGameModal();
|
12 |
+
}
|
13 |
+
|
14 |
+
winGame() {
|
15 |
+
this.game_over = true;
|
16 |
+
unlockDoorSnd.play();
|
17 |
+
setTimeout(() => {
|
18 |
+
winGameModal();
|
19 |
+
}, 3000);
|
20 |
+
return;
|
21 |
+
winGame();
|
22 |
+
}
|
23 |
|
24 |
+
update() {
|
25 |
+
this.girlfriend.update();
|
26 |
+
if (this.clown && this.girlfriend) {
|
27 |
+
const clownPos = this.clown.getCharacterPosition();
|
28 |
+
const gfPos = this.girlfriend.getCharacterPosition();
|
29 |
+
|
30 |
+
if (
|
31 |
+
clownPos &&
|
32 |
+
gfPos &&
|
33 |
+
clownPos.x === gfPos.x &&
|
34 |
+
clownPos.y === gfPos.y
|
35 |
+
) {
|
36 |
+
this.endGame();
|
37 |
+
}
|
38 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
|
41 |
getTheExit() {
|
|
|
44 |
);
|
45 |
}
|
46 |
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
getStressPrompt() {
|
49 |
const currentStress = this.girlfriend ? this.girlfriend.stressLevel : 50; // Default to 50 if girlfriend not initialized
|
|
|
95 |
}
|
96 |
`;
|
97 |
}
|
98 |
+
|
99 |
getPrompt() {
|
100 |
return `
|
101 |
|
|
|
104 |
Current state:
|
105 |
- You (the girlfriend) are currently in this Room >> ${this.girlfriend.getCurrentRoom()}
|
106 |
- Your current stress level is ${this.girlfriend.stressLevel}/100
|
107 |
+
${this.girlfriend.getIsHiding()
|
108 |
+
? `- You are currently hiding ${this.girlfriend.currentHidingSpot.hiding_type} the ${this.girlfriend.currentHidingSpot.name}`
|
109 |
+
: ""
|
110 |
+
}
|
111 |
+
${this.girlfriend.getCurrentRoom() === this.clown.getCurrentRoom()
|
112 |
+
? "- OMG YOU ARE IN THE SAME ROOM AS THE CLOWNNNN!!!"
|
113 |
+
: "- You have no idea where the clown is, you will hide if you can, if not leave the room"
|
114 |
+
}
|
115 |
+
|
116 |
+
${this.girlfriend.getInventory().length > 0
|
117 |
+
? `- You have the following items in your inventory: ${this.girlfriend
|
118 |
+
.getInventory()
|
119 |
+
.join(", ")}`
|
120 |
+
: ""
|
121 |
+
}
|
|
|
|
|
|
|
122 |
RESPONSE FORMAT:
|
123 |
You must ALWAYS respond with a JSON object.
|
124 |
Your response should reflect a girlfriend's reaction to her boyfriend's message given this context and following the following structure:
|
|
|
143 |
}
|
144 |
VALID HIDING PLACES:
|
145 |
You are only allowed to hide in these hiding spots no other hiding spots are recognized:
|
146 |
+
${this.girlfriend.getAvailableHidingSpots().length > 0
|
147 |
+
? `- You may hide in these available hiding spots (and thats it): ${this.girlfriend
|
148 |
+
.getAvailableHidingSpots()
|
149 |
+
.map((spot) => `[${spot.hiding_type} ${spot.name}]`)
|
150 |
+
.join(", ")}`
|
151 |
+
: "- There are no available hiding spots in this room"
|
152 |
+
}
|
|
|
153 |
|
154 |
|
155 |
For checking/inquiring/going to apecifically the Cabinet or Bookcase instructions ("check" action):
|
156 |
{
|
157 |
"action": "check",
|
158 |
+
"target": "she can only check \"Cabinet\" (this is in the kitchen, you can ask if youre not sure) or \"Bookcase\" (this is in the guest bedroom you can ask if youre not sure).${this.girlfriend.getKnowsAboutDeadBody()
|
159 |
+
? ' or "Dead Body" (in the Storage room)'
|
160 |
+
: "you might be asked to check other things be open minded about it ask where, be freaked out if nncecessarry"
|
161 |
+
}
|
|
|
162 |
"textMessage": "[girlfriend's response]"
|
163 |
}
|
164 |
|
165 |
For exiting the house by the exit in the mainhallway instructions ("exit" action):
|
166 |
{
|
167 |
"action": "exit",
|
168 |
+
"target": "The Exit", (the exit is in the main hallway by the way you cal also inted to exit it directly)
|
169 |
"textMessage": "[girlfriend's response]"
|
170 |
}
|
171 |
|
|
|
179 |
|
180 |
YOUR BEHAVIOR:
|
181 |
- You are aware of the danger and are extremely distressed.
|
182 |
+
${this.girlfriend.getCurrentRoom() !== this.clown.getCurrentRoom()
|
183 |
+
? "- You have no idea where the clown is"
|
184 |
+
: ""
|
185 |
+
}
|
|
|
186 |
Your text responses should be:
|
187 |
-- Brief and urgent
|
188 |
-- Reflect genuine fear and panic
|
static/game/index.html
CHANGED
@@ -3,6 +3,7 @@
|
|
3 |
<head>
|
4 |
<title>The Last Message - A text based horror game</title>
|
5 |
<link rel="stylesheet" href="/static/assets/css/game-style.css" />
|
|
|
6 |
</head>
|
7 |
|
8 |
<body>
|
@@ -89,11 +90,50 @@
|
|
89 |
<source src="/static/assets/sounds/message.wav" type="audio/wav" />
|
90 |
</audio>
|
91 |
|
92 |
-
<
|
93 |
-
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
95 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
|
|
|
97 |
<script src="/static/game/elmnts/furniture.js"></script>
|
98 |
<script src="/static/game/gameState.js"></script>
|
99 |
<script src="/static/game/mistral.js"></script>
|
@@ -108,28 +148,6 @@
|
|
108 |
<script src="/static/game/utilities/draw.js"></script>
|
109 |
<script src="/static/game/game.js"></script>
|
110 |
|
111 |
-
|
112 |
-
window.onload = async function () {
|
113 |
-
// Get the initial prompt from gameState
|
114 |
-
const firstPrompt = gameState.getFirstPrompt();
|
115 |
-
|
116 |
-
console.log("firstPrompt", firstPrompt);
|
117 |
-
|
118 |
-
const messages = [
|
119 |
-
{
|
120 |
-
role: "system",
|
121 |
-
content: firstPrompt,
|
122 |
-
},
|
123 |
-
];
|
124 |
-
|
125 |
-
try {
|
126 |
-
const response = await mistralAPI.sendMessage(messages);
|
127 |
-
const jsonResponse = JSON.parse(response);
|
128 |
-
addMessageToChat("assistant", jsonResponse.textMessage);
|
129 |
-
} catch (error) {
|
130 |
-
console.error("Error getting initial message:", error);
|
131 |
-
}
|
132 |
-
};
|
133 |
-
</script>
|
134 |
</body>
|
135 |
</html>
|
|
|
3 |
<head>
|
4 |
<title>The Last Message - A text based horror game</title>
|
5 |
<link rel="stylesheet" href="/static/assets/css/game-style.css" />
|
6 |
+
<link rel="stylesheet" href="/static/assets/css/popup.css" />
|
7 |
</head>
|
8 |
|
9 |
<body>
|
|
|
90 |
<source src="/static/assets/sounds/message.wav" type="audio/wav" />
|
91 |
</audio>
|
92 |
|
93 |
+
<div class="popup-overlay" style="display: none;"></div>
|
94 |
+
<div class="popup-loser" style="display: none;">
|
95 |
+
<div class="title-glow"></div>
|
96 |
+
<h1 class="title">SHE DIED!</h1>
|
97 |
+
<button class="play-again">Play Again</button>
|
98 |
+
<img src="/static/assets/img/blood-2.png" alt="" class="blood-top" />
|
99 |
+
<img src="/static/assets/img/popup/clown_lose.png" alt="" class="clown" />
|
100 |
+
<img src="/static/assets/img/blood-2.png" alt="" class="blood-bottom" />
|
101 |
+
</div>
|
102 |
+
|
103 |
+
<div class="popup-winner" style="display: none;">
|
104 |
+
<img src="/static/assets/img/popup/text.svg" alt="" class="win-text" />
|
105 |
+
<img src="/static/assets/img/popup/fuck.png" alt="" class="fuck" />
|
106 |
+
<img src="/static/assets/img/popup/stars1.png" alt="" class="stars1" />
|
107 |
+
<img src="/static/assets/img/popup/stars2.png" alt="" class="stars2" />
|
108 |
+
<button class="play-again">Play Again</button>
|
109 |
+
</div>
|
110 |
+
|
111 |
+
<script>
|
112 |
+
function winGameModal() {
|
113 |
+
document.querySelector('.popup-overlay').style.display = 'block';
|
114 |
+
document.querySelector('.popup-winner').style.display = 'block';
|
115 |
+
document.querySelector('.popup-loser').style.display = 'none';
|
116 |
+
}
|
117 |
+
|
118 |
+
function loseGameModal() {
|
119 |
+
document.querySelector('.popup-overlay').style.display = 'block';
|
120 |
+
document.querySelector('.popup-loser').style.display = 'block';
|
121 |
+
document.querySelector('.popup-winner').style.display = 'none';
|
122 |
+
}
|
123 |
|
124 |
+
// Add click handlers for play again buttons
|
125 |
+
document.querySelectorAll('.play-again').forEach(button => {
|
126 |
+
button.addEventListener('click', () => {
|
127 |
+
document.querySelector('.popup-overlay').style.display = 'none';
|
128 |
+
document.querySelector('.popup-winner').style.display = 'none';
|
129 |
+
document.querySelector('.popup-loser').style.display = 'none';
|
130 |
+
location.reload(); // Reload the page to restart the game
|
131 |
+
});
|
132 |
+
});
|
133 |
+
</script>
|
134 |
+
|
135 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
|
136 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/addons/p5.sound.min.js" "></script>
|
137 |
<script src="/static/game/elmnts/furniture.js"></script>
|
138 |
<script src="/static/game/gameState.js"></script>
|
139 |
<script src="/static/game/mistral.js"></script>
|
|
|
148 |
<script src="/static/game/utilities/draw.js"></script>
|
149 |
<script src="/static/game/game.js"></script>
|
150 |
|
151 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
</body>
|
153 |
</html>
|
static/game/index2.html
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>The Last Message - A text based horror game</title>
|
5 |
+
<link rel="stylesheet" href="/static/assets/css/game-style.css" />
|
6 |
+
<link rel="stylesheet" href="/static/assets/css/stress-animations.css" />
|
7 |
+
<link rel="stylesheet" href="/static/assets/css/popup.css" />
|
8 |
+
</head>
|
9 |
+
|
10 |
+
<body>
|
11 |
+
<div class="led-bar">
|
12 |
+
<div class="light-beam"></div>
|
13 |
+
</div>
|
14 |
+
<div class="background-elements">
|
15 |
+
<img
|
16 |
+
src="/static/assets/img/blood-2.png"
|
17 |
+
alt=""
|
18 |
+
class="blood blood-top-left"
|
19 |
+
/>
|
20 |
+
<img
|
21 |
+
src="/static/assets/img/help.png"
|
22 |
+
alt=""
|
23 |
+
class="blood blood-top-right"
|
24 |
+
/>
|
25 |
+
<img
|
26 |
+
src="/static/assets/img/splatter.png"
|
27 |
+
alt=""
|
28 |
+
class="blood splatter"
|
29 |
+
/>
|
30 |
+
<img
|
31 |
+
src="/static/assets/img/hand.png"
|
32 |
+
alt=""
|
33 |
+
class="blood blood-bottom-right"
|
34 |
+
/>
|
35 |
+
</div>
|
36 |
+
<div id="gameContainer">
|
37 |
+
<div id="mapSection">
|
38 |
+
<div id="mapWrapper" class="map-wrapper">
|
39 |
+
<!-- P5.js canvas goes here -->
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
<div class="phone-mockup">
|
43 |
+
<div class="phone-screen">
|
44 |
+
<div id="chatSection" class="very-stress">
|
45 |
+
<div id="chatHeader">
|
46 |
+
<div class="profile-picture">
|
47 |
+
<img
|
48 |
+
src="/static/assets/img/profil_pictures/very_stress.webp"
|
49 |
+
alt="Profile picture"
|
50 |
+
/>
|
51 |
+
</div>
|
52 |
+
<div class="chat-name"><span>Bae 💖😘</span></div>
|
53 |
+
</div>
|
54 |
+
<div id="chatHistory"></div>
|
55 |
+
<div id="chatControls">
|
56 |
+
<input
|
57 |
+
type="text"
|
58 |
+
id="prompt"
|
59 |
+
placeholder="Type your message..."
|
60 |
+
/>
|
61 |
+
<button onclick="Message()">
|
62 |
+
<svg
|
63 |
+
width="683"
|
64 |
+
height="683"
|
65 |
+
viewBox="0 0 683 683"
|
66 |
+
fill="none"
|
67 |
+
xmlns="http://www.w3.org/2000/svg"
|
68 |
+
>
|
69 |
+
<path
|
70 |
+
d="M22.2666 1.86666C19.5999 2.93333 16.5333 4.39999 15.4666 5.19999C11.9999 8.13333 9.33325 15.7333 9.33325 22.5333C9.33325 28.1333 65.4666 283.333 66.9333 284.667C67.3333 285.067 339.333 332.267 372.4 337.733C381.733 339.333 389.333 340.933 389.333 341.333C389.333 341.733 381.733 343.333 372.4 344.933C339.2 350.4 67.3333 397.6 66.9333 398C65.4666 399.333 9.33325 654.533 9.33325 660.133C9.33325 675.867 21.0666 685.333 35.8666 681.333C42.6666 679.467 662.267 362 666.4 358.133C671.333 353.733 673.333 348.8 673.333 341.333C673.333 333.867 671.333 328.933 666.4 324.533C662.533 320.933 43.0666 3.19999 36.2666 1.33333C29.9999 -0.400007 28.5333 -0.266674 22.2666 1.86666Z"
|
71 |
+
fill="white"
|
72 |
+
/>
|
73 |
+
</svg>
|
74 |
+
</button>
|
75 |
+
</div>
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
</div>
|
79 |
+
</div>
|
80 |
+
|
81 |
+
<!-- Popup Loser -->
|
82 |
+
<div class="popup-overlay"></div>
|
83 |
+
<div class="popup-loser">
|
84 |
+
<div class="title-glow"></div>
|
85 |
+
<h1 class="title">SHE DIED!</h1>
|
86 |
+
<button class="play-again">Play Again</button>
|
87 |
+
<img src="/static/assets/img/blood-2.png" alt="" class="blood-top" />
|
88 |
+
<img src="/static/assets/img/popup/clown_lose.png" alt="" class="clown" />
|
89 |
+
<img src="/static/assets/img/blood-2.png" alt="" class="blood-bottom" />
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<!-- Popup Winner -->
|
93 |
+
<div class="popup-winner" style="display: none;">
|
94 |
+
<img src="/static/assets/img/popup/text.svg" alt="" class="win-text" />
|
95 |
+
<img src="/static/assets/img/popup/fuck.png" alt="" class="fuck" />
|
96 |
+
<img src="/static/assets/img/popup/stars1.png" alt="" class="stars1" />
|
97 |
+
<img src="/static/assets/img/popup/stars2.png" alt="" class="stars2" />
|
98 |
+
<button class="play-again">Play Again</button>
|
99 |
+
</div>
|
100 |
+
|
101 |
+
<div class="sound-button" onclick="toggleSound()">
|
102 |
+
<img
|
103 |
+
src="/static/assets/img/sondon.png"
|
104 |
+
alt="Sound control"
|
105 |
+
id="soundIcon"
|
106 |
+
/>
|
107 |
+
</div>
|
108 |
+
|
109 |
+
<audio id="bgMusic" loop>
|
110 |
+
<source src="/static/assets/sounds/music.mp3" type="audio/mp3" />
|
111 |
+
</audio>
|
112 |
+
|
113 |
+
<audio id="messageSound">
|
114 |
+
<source src="/static/assets/sounds/message.wav" type="audio/wav" />
|
115 |
+
</audio>
|
116 |
+
|
117 |
+
<audio id="walkingSound" loop>
|
118 |
+
<source src="/static/assets/sounds/walking.mp3" type="audio/mp3" />
|
119 |
+
</audio>
|
120 |
+
|
121 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
|
122 |
+
<script src="/static/game/elmnts/furniture.js"></script>
|
123 |
+
<script src="/static/game/gameState.js"></script>
|
124 |
+
<script src="/static/game/mistral.js"></script>
|
125 |
+
<script src="/static/game/elmnts/character.js"></script>
|
126 |
+
<script src="/static/game/elmnts/girlfriend.js"></script>
|
127 |
+
<script src="/static/game/elmnts/clown.js"></script>
|
128 |
+
<script src="/static/game/elmnts/grid.js"></script>
|
129 |
+
<script src="/static/game/elmnts/apt.js"></script>
|
130 |
+
<script src="/static/game/utilities/sound.js"></script>
|
131 |
+
<script src="/static/game/utilities/helpers.js"></script>
|
132 |
+
<script src="/static/game/utilities/chat.js"></script>
|
133 |
+
<script src="/static/game/utilities/draw.js"></script>
|
134 |
+
<script src="/static/game/game.js"></script>
|
135 |
+
</body>
|
136 |
+
</html>
|
static/game/utilities/chat.js
CHANGED
@@ -20,6 +20,48 @@ async function addProgramaticMessage(message) {
|
|
20 |
addMessageToChat("assistant", message);
|
21 |
}
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
async function sendMessage() {
|
24 |
const prompt = document.getElementById("prompt").value.trim();
|
25 |
if (!prompt) return;
|
@@ -30,6 +72,8 @@ async function sendMessage() {
|
|
30 |
const chatHistory = document.getElementById("chatHistory");
|
31 |
const loadingIndicator = createLoadingIndicator();
|
32 |
chatHistory.appendChild(loadingIndicator);
|
|
|
|
|
33 |
|
34 |
// First, get the stress prompt and send it
|
35 |
const stressPrompt = gameState.getStressPrompt();
|
@@ -40,7 +84,6 @@ async function sendMessage() {
|
|
40 |
},
|
41 |
{ role: "user", content: prompt },
|
42 |
];
|
43 |
-
console.log("stressMessages", stressMessages);
|
44 |
|
45 |
const stressResponse = await mistralAPI.sendMessage(stressMessages);
|
46 |
const stressChange = JSON.parse(stressResponse).stressChange || 0;
|
@@ -67,7 +110,7 @@ async function sendMessage() {
|
|
67 |
const jsonResponse = JSON.parse(jsonContent);
|
68 |
|
69 |
if (jsonResponse.action) {
|
70 |
-
girlfriend.handleAction(jsonResponse);
|
71 |
}
|
72 |
|
73 |
if (jsonResponse.textMessage) {
|
|
|
20 |
addMessageToChat("assistant", message);
|
21 |
}
|
22 |
|
23 |
+
async function strongIndependantWoman(){
|
24 |
+
|
25 |
+
const chatHistory = document.getElementById("chatHistory");
|
26 |
+
const loadingIndicator = createLoadingIndicator();
|
27 |
+
chatHistory.appendChild(loadingIndicator);
|
28 |
+
chatHistory.scrollTop = chatHistory.scrollHeight;
|
29 |
+
|
30 |
+
|
31 |
+
let masterPrompt = gameState.getPrompt();
|
32 |
+
|
33 |
+
const recentMessages = chatMessages.slice(-5);
|
34 |
+
|
35 |
+
const messages = [
|
36 |
+
{ role: "system", content: masterPrompt },
|
37 |
+
...recentMessages,
|
38 |
+
{ role: "user", content: `
|
39 |
+
**your boyfriend has been away from his phone for a while and has not replied promptly to your last message,
|
40 |
+
you shall based on all that you know decide to take an action, also you're pissed at the boyfriend**
|
41 |
+
you are brave, strong, fabulous and will dosomething about this situation
|
42 |
+
you're gall is to escape the house and avoid the clown at all costs
|
43 |
+
|
44 |
+
` },
|
45 |
+
];
|
46 |
+
|
47 |
+
const assistantResponse = await mistralAPI.sendMessage(messages);
|
48 |
+
|
49 |
+
chatHistory.removeChild(loadingIndicator);
|
50 |
+
|
51 |
+
const jsonStart = assistantResponse.indexOf("{");
|
52 |
+
const jsonEnd = assistantResponse.lastIndexOf("}") + 1;
|
53 |
+
const jsonContent = assistantResponse.substring(jsonStart, jsonEnd);
|
54 |
+
const jsonResponse = JSON.parse(jsonContent);
|
55 |
+
|
56 |
+
if (jsonResponse.action) {
|
57 |
+
girlfriend.handleAction(jsonResponse, true);
|
58 |
+
}
|
59 |
+
|
60 |
+
if (jsonResponse.textMessage) {
|
61 |
+
addMessageToChat("assistant", jsonResponse.textMessage);
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
async function sendMessage() {
|
66 |
const prompt = document.getElementById("prompt").value.trim();
|
67 |
if (!prompt) return;
|
|
|
72 |
const chatHistory = document.getElementById("chatHistory");
|
73 |
const loadingIndicator = createLoadingIndicator();
|
74 |
chatHistory.appendChild(loadingIndicator);
|
75 |
+
chatHistory.scrollTop = chatHistory.scrollHeight;
|
76 |
+
|
77 |
|
78 |
// First, get the stress prompt and send it
|
79 |
const stressPrompt = gameState.getStressPrompt();
|
|
|
84 |
},
|
85 |
{ role: "user", content: prompt },
|
86 |
];
|
|
|
87 |
|
88 |
const stressResponse = await mistralAPI.sendMessage(stressMessages);
|
89 |
const stressChange = JSON.parse(stressResponse).stressChange || 0;
|
|
|
110 |
const jsonResponse = JSON.parse(jsonContent);
|
111 |
|
112 |
if (jsonResponse.action) {
|
113 |
+
girlfriend.handleAction(jsonResponse, true);
|
114 |
}
|
115 |
|
116 |
if (jsonResponse.textMessage) {
|
static/game/utilities/sound.js
CHANGED
@@ -1,20 +1,38 @@
|
|
1 |
-
// Make handleWalkingSound globally available
|
2 |
-
function handleWalkingSound (isWalking) {
|
3 |
-
const walkingSound = document.getElementById("walkingSound");
|
4 |
-
if (!walkingSound) return;
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
}
|
15 |
}
|
16 |
|
17 |
-
// Update toggleSound to check girlfriend's movement status
|
18 |
function toggleSound() {
|
19 |
isSoundOn = !isSoundOn;
|
20 |
localStorage.setItem("isSoundOn", isSoundOn.toString());
|
@@ -29,7 +47,6 @@ function toggleSound() {
|
|
29 |
}
|
30 |
} else {
|
31 |
bgMusic.pause();
|
32 |
-
handleWalkingSound(false);
|
33 |
}
|
34 |
updateSoundIcon();
|
35 |
}
|
|
|
|
|
|
|
|
|
|
|
1 |
|
2 |
+
function playSound(sound) {
|
3 |
+
if (isSoundOn) {
|
4 |
+
let soundToPlay;
|
5 |
+
switch (sound) {
|
6 |
+
case 'clownSound1':
|
7 |
+
soundToPlay = clownSound1Snd;
|
8 |
+
break;
|
9 |
+
case 'clownSound2':
|
10 |
+
soundToPlay = clownSound2Snd;
|
11 |
+
break;
|
12 |
+
case 'clownSeesYou':
|
13 |
+
soundToPlay = clownSeesYouSnd;
|
14 |
+
break;
|
15 |
+
case 'gfMove':
|
16 |
+
soundToPlay = gfMoveSnd;
|
17 |
+
break;
|
18 |
+
case 'lose':
|
19 |
+
soundToPlay = loseSnd;
|
20 |
+
break;
|
21 |
+
case 'unlockDoor':
|
22 |
+
soundToPlay = unlockDoorSnd;
|
23 |
+
break;
|
24 |
+
case 'useKnife':
|
25 |
+
soundToPlay = useKnifeSnd;
|
26 |
+
break;
|
27 |
+
}
|
28 |
+
if (soundToPlay) {
|
29 |
+
soundToPlay.stop(); // Stop any existing playback
|
30 |
+
soundToPlay.loop(false); // Ensure looping is disabled
|
31 |
+
soundToPlay.play(); // Play the sound once
|
32 |
+
}
|
33 |
}
|
34 |
}
|
35 |
|
|
|
36 |
function toggleSound() {
|
37 |
isSoundOn = !isSoundOn;
|
38 |
localStorage.setItem("isSoundOn", isSoundOn.toString());
|
|
|
47 |
}
|
48 |
} else {
|
49 |
bgMusic.pause();
|
|
|
50 |
}
|
51 |
updateSoundIcon();
|
52 |
}
|