|
1 /* |
|
2 Copyright (c) 2023 MCL Software |
|
3 |
|
4 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), |
|
5 to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
6 and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
|
7 |
|
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
|
9 |
|
10 THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
11 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|
12 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
13 */ |
|
14 |
|
15 #include "kbdinput.h" |
|
16 #include "draw.h" |
|
17 #include "texture.h" |
|
18 #include "intro.h" |
|
19 #include "level.h" |
|
20 #include "common.h" |
|
21 #include <stdio.h> |
|
22 |
|
23 SDL_Point offset; |
|
24 Player player; |
|
25 |
|
26 int stealProgress = 0; |
|
27 Uint64 now = 0; |
|
28 Uint64 then = 0; |
|
29 bool fireAlarmSystemActivated = 0; |
|
30 bool missionScreenShown = 1; |
|
31 |
|
32 float applyZoomFactor(float i) |
|
33 { |
|
34 if(zoomFactor > 0) |
|
35 { |
|
36 i *= zoomFactor; |
|
37 } |
|
38 else |
|
39 { |
|
40 i /= -zoomFactor; |
|
41 } |
|
42 |
|
43 return i; |
|
44 } |
|
45 |
|
46 void updateZoomFactor() |
|
47 { |
|
48 destRect.w = applyZoomFactor(TILE_WIDTH); |
|
49 destRect.h = applyZoomFactor(TILE_HEIGHT); |
|
50 } |
|
51 |
|
52 void drawTiles() |
|
53 { |
|
54 |
|
55 for(int y = 0; y < 4; y ++) |
|
56 { |
|
57 |
|
58 for(int i = (player.x < 64 ? 0 : player.x - 63); i < (player.x + 64 < LEVEL_WIDTH ? player.x + 64 : LEVEL_WIDTH); i ++) |
|
59 { |
|
60 for(int j = (player.y < 64 ? 0 : player.y - 63); j < (player.y + 64 < LEVEL_DEPTH ? player.y + 64 : LEVEL_DEPTH); j ++) |
|
61 { |
|
62 SDL_Point coords = tileToPixelCoordinates(i, j); |
|
63 destRect.x = applyZoomFactor(coords.x + offset.x) + applyZoomFactor(LEVEL_WIDTH); |
|
64 destRect.y = applyZoomFactor(coords.y + offset.y) - applyZoomFactor(LEVEL_HEIGHT);; |
|
65 destRect.y -= applyZoomFactor(TILE_HEIGHT / 2 * y); |
|
66 |
|
67 // Transform coordinates according to rotation formula |
|
68 SDL_Point trans = getLevelTransformation(i, j); |
|
69 |
|
70 // Check what tile is currently being drawn; this will later be needed |
|
71 // to determine how it should be drawn. |
|
72 Object object = getObjectFromIdent(levelTiles[trans.x * LEVEL_WIDTH + trans.y]); |
|
73 |
|
74 SDL_Point textureClip; |
|
75 |
|
76 // Get the tile's texture |
|
77 if(object.textureHeight == 2 && y == object.placementHeight + 1) |
|
78 // For tiles with a texture higher than TILE_HEIGHT |
|
79 textureClip = getTextureFromIndex(object.textureIndex - 16); |
|
80 else |
|
81 textureClip = getTextureFromIndex(object.textureIndex); |
|
82 |
|
83 // Multiply coordinates by tile width and height to get the real coordinates on the tilemap |
|
84 clip.x = textureClip.x * 89; |
|
85 clip.y = textureClip.y * 90; |
|
86 |
|
87 // This sets the destination rectangle's width and height |
|
88 // TODO: figure out a more efficient way to do this without calling this function for every tile |
|
89 updateZoomFactor(); |
|
90 |
|
91 if(y < object.placementHeight + object.height && y >= object.placementHeight) |
|
92 SDL_RenderCopyEx(renderer, tilemap, &clip, &destRect, 0, 0, SDL_FLIP_HORIZONTAL ? orientation % 2 == 0 ? object.flipTexture : !object.flipTexture : 0); |
|
93 else if(y == 0 && object.renderUnder) |
|
94 // Render tile at Y: 0 for tiles that are transparent and/or above the ground |
|
95 SDL_RenderCopy(renderer, tilemap, &(SDL_Rect){89, 0, 89, 90}, &destRect); |
|
96 else if(y == 3 && object.renderAbove) |
|
97 { |
|
98 SDL_RenderCopy(renderer, tilemap, &(SDL_Rect){356, 0, 89, 90}, &destRect); |
|
99 } |
|
100 |
|
101 //SDL_Point transPlayer = getTransformation(player.x, player.y); |
|
102 |
|
103 // Render player |
|
104 if(y == 1 && trans.x == player.x && trans.y == player.y) |
|
105 { |
|
106 textureClip = getTextureFromIndex(33); |
|
107 clip.x = textureClip.x * 89; |
|
108 clip.y = textureClip.y * 90; |
|
109 clip.w = 89; |
|
110 clip.h = 90; |
|
111 |
|
112 //SDL_Point newDestRect = getTransformation(applyZoomFactor(coords.x + offset.x) + applyZoomFactor(LEVEL_WIDTH), applyZoomFactor(coords.y + offset.y) - applyZoomFactor(LEVEL_HEIGHT)); |
|
113 |
|
114 //destRect.x = newDestRect.x; |
|
115 //destRect.y = newDestRect.y; |
|
116 //destRect.y -= applyZoomFactor(TILE_HEIGHT / 2 * y); |
|
117 SDL_RenderCopy(renderer, tilemap, &clip, &destRect); |
|
118 } |
|
119 } |
|
120 } |
|
121 } |
|
122 } |
|
123 |
|
124 |
|
125 |
|
126 Object getObjectProperties(char object) |
|
127 { |
|
128 Object objectProps; |
|
129 objectProps.textureIndex = 0; |
|
130 objectProps.stealable = true; |
|
131 objectProps.height = 2; |
|
132 objectProps.interactable = -1;; |
|
133 objectProps.passable = false; |
|
134 |
|
135 return objectProps; |
|
136 } |
|
137 |
|
138 int main(int argc, char *argv[]) |
|
139 { |
|
140 loadLevelFromFile(); |
|
141 |
|
142 initMissions(); |
|
143 |
|
144 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO); |
|
145 |
|
146 Mix_Init(MIX_INIT_OGG); |
|
147 |
|
148 Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048); |
|
149 |
|
150 alarmSound = Mix_LoadWAV("alarm.wav"); |
|
151 |
|
152 themeSong = Mix_LoadMUS("audio/music/DeviousLicks.ogg"); |
|
153 bgm1 = Mix_LoadMUS("audio/music/Class1.ogg"); |
|
154 bgm2 = Mix_LoadMUS("audio/music/Class2.ogg"); |
|
155 bgm3 = Mix_LoadMUS("audio/music/Class3.ogg"); |
|
156 bgm4 = Mix_LoadMUS("audio/music/ANewReality.ogg"); // todo: move this track further down |
|
157 bgm5 = Mix_LoadMUS("audio/music/Recollection.ogg"); |
|
158 bgm6 = Mix_LoadMUS("audio/music/TheSadReality1.ogg"); |
|
159 bgm7 = Mix_LoadMUS("audio/music/TheSadReality2.ogg"); |
|
160 bgm8 = Mix_LoadMUS("audio/music/TheXXXReality.ogg"); |
|
161 bgm9 = Mix_LoadMUS("audio/music/FirstDay.ogg"); |
|
162 bgm10 = Mix_LoadMUS("audio/music/FirstDayAlternateVersion.ogg"); |
|
163 bgm11 = Mix_LoadMUS("audio/music/Hallway1.ogg"); |
|
164 bgm12 = Mix_LoadMUS("audio/music/Hallway2.ogg"); |
|
165 bgm13 = Mix_LoadMUS("audio/music/Hallway3.ogg"); |
|
166 bgm14 = Mix_LoadMUS("audio/music/Hallway4.ogg"); |
|
167 //creditsTheme = Mix_LoadMUS("audio/music/Credits.ogg"); |
|
168 |
|
169 Mix_PlayMusic(themeSong, -1); |
|
170 |
|
171 SDL_Window* window = SDL_CreateWindow("Devious Licks", 170, 70, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); |
|
172 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); |
|
173 |
|
174 initGraphics(); |
|
175 |
|
176 SDL_Event event; |
|
177 bool quit = false; |
|
178 |
|
179 // Title Screen |
|
180 while(!gameRunning) |
|
181 { |
|
182 drawTitleScreen(); |
|
183 while(SDL_PollEvent(&event)) |
|
184 { |
|
185 handleKeyboard(event); |
|
186 |
|
187 if(!performMenuKeyActions() || event.type == SDL_QUIT) |
|
188 { |
|
189 gameRunning = 1; |
|
190 quit = true; |
|
191 } |
|
192 } |
|
193 } |
|
194 |
|
195 // Intro |
|
196 // 0 - enabled |
|
197 // 1 - disabled (skip) |
|
198 gameRunning = 0; |
|
199 |
|
200 Mix_PlayMusic(bgm7, -1); |
|
201 |
|
202 while(!gameRunning && !quit) |
|
203 { |
|
204 if(INTR_DrawIntro()) |
|
205 gameRunning = 1; |
|
206 |
|
207 while(SDL_PollEvent(&event)) |
|
208 { |
|
209 handleKeyboard(event); |
|
210 |
|
211 if(event.type == SDL_QUIT) |
|
212 { |
|
213 gameRunning = 1; |
|
214 quit = true; |
|
215 } |
|
216 } |
|
217 } |
|
218 |
|
219 Mix_HaltMusic(); |
|
220 |
|
221 srand(time(0)); // set seed for pseudoRNG with RTC |
|
222 |
|
223 /*int nextTrack = rand() % 16; |
|
224 |
|
225 Mix_PlayMusic(nextTrack == 0 ? bgm1 : nextTrack == 1 ? bgm2 : nextTrack == 2 ? bgm3 : nextTrack == 3 ? bgm4 : nextTrack == 4 ? bgm5 : nextTrack == 5 ? bgm6 : nextTrack == 6 ? bgm7 : nextTrack == 7 ? bgm8 : nextTrack == 8 ? bgm9 : nextTrack == 9 ? bgm10 : nextTrack == 10 ? bgm11 : nextTrack == 11 ? bgm12 : nextTrack == 12 ? bgm13 : bgm14, 1); |
|
226 */ |
|
227 clip = (SDL_Rect){89, 0, 89, 90}; |
|
228 |
|
229 destRect.x = 0; |
|
230 destRect.y = 0; |
|
231 updateZoomFactor(); |
|
232 |
|
233 offset.x = -2420; |
|
234 offset.y = -1870; |
|
235 |
|
236 player.x = 75; |
|
237 player.y = 25; |
|
238 |
|
239 while(!quit) |
|
240 { |
|
241 now = SDL_GetTicks(); |
|
242 |
|
243 SDL_RenderClear(renderer); |
|
244 |
|
245 //SDL_GetMouseState(&mouseX, &mouseY); |
|
246 |
|
247 drawTiles(); |
|
248 |
|
249 if(levelTiles[(player.x + 1) * LEVEL_WIDTH + player.y] == 'D' || levelTiles[(player.x - 1) * LEVEL_WIDTH + player.y] == 'D' || levelTiles[player.x * LEVEL_WIDTH + player.y + 1] == 'D' || levelTiles[player.x * LEVEL_WIDTH + player.y - 1] == 'D') |
|
250 { |
|
251 drawLeaveSchool(); |
|
252 player.leftCampus = performYesNo() ? true : false; |
|
253 } |
|
254 |
|
255 drawHUD(); |
|
256 |
|
257 if(missionScreenShown && drawMissionScreen()) |
|
258 { |
|
259 missionScreenShown = 0; |
|
260 } |
|
261 |
|
262 if(checkForMissionComplete(currentMission)) |
|
263 { |
|
264 drawGoToExit(); |
|
265 if(player.leftCampus) |
|
266 { |
|
267 offset.x = -2420; |
|
268 offset.y = -1870; |
|
269 player.x = 75; |
|
270 player.y = 25; |
|
271 if(drawMissionComplete()) |
|
272 { |
|
273 missionScreenShown = 1; |
|
274 } |
|
275 } |
|
276 } |
|
277 SDL_SetRenderDrawColor(renderer, 10, 180, 255, 255); |
|
278 SDL_RenderPresent(renderer); |
|
279 |
|
280 // Cycle music |
|
281 if(!Mix_PlayingMusic()) |
|
282 { |
|
283 int nextTrack = rand() % 16; |
|
284 |
|
285 Mix_PlayMusic(nextTrack == 0 ? bgm1 : nextTrack == 1 ? bgm2 : nextTrack == 2 ? bgm3 : nextTrack == 3 ? bgm4 : nextTrack == 4 ? bgm5 : nextTrack == 5 ? bgm6 : nextTrack == 6 ? bgm7 : nextTrack == 7 ? bgm8 : nextTrack == 8 ? bgm9 : nextTrack == 9 ? bgm10 : nextTrack == 10 ? bgm11 : nextTrack == 11 ? bgm12 : nextTrack == 12 ? bgm13 : bgm14, 1); |
|
286 } |
|
287 |
|
288 |
|
289 // Handle all queued events |
|
290 while(SDL_PollEvent(&event)) |
|
291 { |
|
292 handleKeyboard(event); |
|
293 |
|
294 if(event.type == SDL_QUIT) |
|
295 quit = true; |
|
296 } |
|
297 |
|
298 if(now - then > 100) |
|
299 { |
|
300 if(performPlayerMovement()) |
|
301 then = now; |
|
302 } |
|
303 } |
|
304 |
|
305 SDL_RemoveTimer(fireAlarmTimer); |
|
306 SDL_DestroyWindow(window); |
|
307 |
|
308 return ISOL_Terminate(); |
|
309 } |