Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | rem Nightmare Forest by Daniel Marschall |
2 | rem Revision: 31 May 2018 |
||
3 | |||
4 | rem --------------------- |
||
5 | |||
6 | rem SPRUNG-PHYSIK: |
||
7 | rem - wenn man auf einem baum landet, kann man von dort aus nicht springen, und glitched manchmal auf dem boden |
||
8 | rem - im baum wird man trotzdem von skorpionen angefressen |
||
9 | rem ... scheinbar ist die jumpheight = 0 dann! |
||
10 | |||
11 | rem Der Himmel ist zu niedrig. Die Tannen sieht man nicht bis ganz oben |
||
12 | |||
13 | rem TODO: clone -> INSTANCE |
||
14 | |||
15 | rem TODO: scorpion schiebt stehenden spieler nicht weg |
||
16 | |||
17 | rem TODO: scorpion soll nicht so nah rankommen, sodass er im spieler stehen würde, wenn der spieler eingeklemmt ist |
||
18 | |||
19 | rem TODO: ambient light wird falsch verwendet. es ist viel zu blau, und alle objekte haben es deaktiviert, weil es die farben zerstört |
||
20 | |||
21 | rem TODO: screen or desktop? |
||
22 | rem TODO: mehr konfigurierbar machen |
||
23 | rem TODO: alles einrücken |
||
24 | |||
25 | rem TODO: lahm? |
||
26 | rem TODO: map außenlinie ist nicht gesperrt mit bäumen |
||
27 | rem TODO: überall float verwenden |
||
28 | |||
29 | rem TODO |
||
30 | rem - HUD |
||
31 | rem - schwimmen |
||
32 | rem - im wasser langsamer |
||
33 | rem - menü am anfang und pause mit maus bedienen |
||
34 | rem - rascheln im busch |
||
35 | rem - die gegner kommen erst nach einer bestimmten zeit. spawnen weit weg vom spieler |
||
36 | rem - tag und nachtzeiten? |
||
37 | |||
38 | rem NICE TO HAVE |
||
39 | rem - radar breitbild |
||
40 | rem - wassermatrix bewegt sich nur in 1 richtung |
||
41 | rem - mausumkehrung einstellbar |
||
42 | rem - stars.bmp (5000px) braucht lange zum laden. 1000px ist verpixelt |
||
43 | rem - besserer bluteffekt |
||
44 | |||
45 | rem ToDo: |
||
46 | rem Radar wackelt |
||
47 | rem :startgame weglassen |
||
48 | rem Streifen am Boden und am Himmel... |
||
49 | rem Baum teiltransparenz |
||
50 | rem Radar lieber als Matrix. Viele Probleme wie z.B. mit Skorpion transparenz |
||
51 | rem Unscharfes Radar, Radar ganz dyn. zeichnen? Rader stay on top |
||
52 | rem Menü: musik aus --> an: loop von position 0! |
||
53 | |||
54 | // -------------------------------- |
||
55 | // Numerical Resources |
||
56 | // -------------------------------- |
||
57 | rem TODO: vervollständigen |
||
58 | rem TODO: auch dateinamen als konstanten |
||
59 | |||
60 | #constant IMG_ForestFloor 1 |
||
61 | #constant IMG_Stars 2 |
||
62 | #constant IMG_Water 3 |
||
63 | #constant IMG_Tree 4 |
||
64 | #constant IMG_MapBackground 5 |
||
65 | #constant IMG_PauseScreen 95 |
||
66 | #constant IMG_TitleScreen 96 |
||
67 | #constant IMG_BLOOD 97 |
||
68 | |||
69 | #constant OBJ_Skybox 2 |
||
70 | #constant OBJ_Tent 10 |
||
71 | #constant OBJ_MapGhostObject 51 |
||
72 | #constant OBJ_TreeTemplate 52 |
||
73 | #constant OBJ_CollissionDummy 53 |
||
74 | #constant OBJ_BloodParticle_Base 100 |
||
75 | #constant OBJ_Monster_Base 1000 |
||
76 | #constant OBJ_Tree_Base 1500 |
||
77 | |||
78 | #constant MSH_TreeTemplate 52 |
||
79 | |||
80 | #constant MAT_Ground 1 |
||
81 | #constant MAT_Water 3 |
||
82 | |||
83 | #constant SFX_ForestBG 1 |
||
84 | #constant SFX_PauseMusic 5 |
||
85 | #constant SFX_Walk_Earth 10 |
||
86 | #constant SFX_Walk_Water 11 |
||
87 | #constant SFX_Attack_Base 20 |
||
88 | #constant SFX_Monster_Base 1000 |
||
89 | |||
90 | #constant DLL_MapGen 1 |
||
91 | #constant DLL_DBIni 2 |
||
92 | #constant DLL_Resize32 3 |
||
93 | |||
94 | #constant MEM_Map 1 |
||
95 | #constant MEM_ResizeSrc 2 |
||
96 | #constant MEM_ResizeDest 3 |
||
97 | |||
98 | // -------------------------------- |
||
99 | // File names |
||
100 | // -------------------------------- |
||
101 | |||
102 | #constant FN_DLL_Resize32 "dll_resize\Resize32.dll" |
||
103 | #constant FN_DLL_MapGen32 "mapgen\mapgen32.dll" |
||
104 | #constant FN_DLL_DBIni "cfgread\dbini32.dll" |
||
105 | |||
106 | #constant FN_SFX_ForestBG "sound\forestbg.wav" |
||
107 | #constant FN_SFX_PauseMusic "music\pause.wav" |
||
108 | #constant FN_SFX_Walk_Earth "sound\walk.wav" |
||
109 | #constant FN_SFX_Walk_Water "sound\walk_water.wav" |
||
110 | #constant FN_SFX_ScorpWalk "test.wav" |
||
111 | #constant FN_SFX_ScorpionAttack1 "sound\scorpionAttack\attack1.wav" |
||
112 | #constant FN_SFX_ScorpionAttack2 "sound\scorpionAttack\attack2.wav" |
||
113 | #constant FN_SFX_ScorpionAttack3 "sound\scorpionAttack\attack3.wav" |
||
114 | #constant FN_SFX_ScorpionAttack4 "sound\scorpionAttack\attack4.wav" |
||
115 | |||
116 | #constant FN_OBJ_ScorpIdle "obj\scorpion\ScorpIdle.x" |
||
117 | #constant FN_OBJ_ScorpWalk "obj\scorpion\ScorpWalk.x" |
||
118 | #constant FN_OBJ_Tent "obj\tent\Tent.x" |
||
119 | #constant FN_GFX_PauseScreen "bitmap\titlescreen.jpg" |
||
120 | |||
121 | #constant FN_GFX_MapBackground "map\ST01L01a.bmp" |
||
122 | #constant FN_GFX_TitleScreen "bitmap\titlescreen.jpg" |
||
123 | #constant FN_GFX_FloorTexture "bitmap\forest_floor_texture.jpg" |
||
124 | #constant FN_GFX_Stars "bitmap\stars.bmp" |
||
125 | #constant FN_GFX_Water "bitmap\water.bmp" |
||
126 | #constant FN_GFX_Tree "bitmap\tree.bmp" |
||
127 | #constant FN_GFX_BLOOD "bitmap\blood.png" |
||
128 | |||
129 | // -------------------------------- |
||
130 | // Language specific |
||
131 | // -------------------------------- |
||
132 | |||
133 | rem TODO: vervollständigen. multilang per DLL |
||
134 | #constant LNG_StartingGame "Starting game..." |
||
135 | |||
136 | // -------------------------------- |
||
137 | // Read configuration |
||
138 | // -------------------------------- |
||
139 | |||
140 | load dll FN_DLL_DBIni, DLL_DBIni |
||
141 | call dll DLL_DBIni, "LoadINI", "forest.ini" |
||
142 | framerate = call dll(DLL_DBIni, "ReadInt", "Game", "framerate", 0) |
||
143 | clockSpeedFactor = call dll(DLL_DBIni, "ReadInt", "Game", "clockSpeedFactor", 0) |
||
144 | clockBlinksPerSecond = call dll(DLL_DBIni, "ReadInt", "Game", "clockBlinksPerSecond", 0) |
||
145 | clockShowSeconds = call dll(DLL_DBIni, "ReadInt", "Game", "clockShowSeconds", 0) |
||
146 | beginClockSeconds = call dll(DLL_DBIni, "ReadInt", "Game", "beginClockSeconds", 0) |
||
147 | enemyRotateSmoothness = call dll(DLL_DBIni, "ReadInt", "Game", "enemyRotateSmoothness", 0) |
||
148 | maxRunEnergy = call dll(DLL_DBIni, "ReadInt", "Game", "maxRunEnergy", 0) |
||
149 | waterLevel = call dll(DLL_DBIni, "ReadInt", "Game", "waterLevel", 0) |
||
150 | sound3dVolumeCor = call dll(DLL_DBIni, "ReadInt", "Game", "sound3dVolumeCor", 0) |
||
151 | invertMouse = call dll(DLL_DBIni, "ReadInt", "Game", "invertMouse", 0) |
||
152 | test = call dll(DLL_DBIni, "ReadInt", "Game", "test", 0) |
||
153 | camerarange = call dll(DLL_DBIni, "ReadInt", "Game", "camerarange", 0) |
||
154 | fogdistance = call dll(DLL_DBIni, "ReadInt", "Game", "fogdistance", 0) |
||
155 | waterMovementMaxDistance = call dll(DLL_DBIni, "ReadInt", "Game", "waterMovementMaxDistance", 0) |
||
156 | gravity# = call dll(DLL_DBIni, "ReadFloat", "Game", "gravity", 0.0) |
||
157 | JumpStartVelocity# = call dll(DLL_DBIni, "ReadFloat", "Game", "JumpStartVelocity", 0.0) |
||
158 | MinFallVelocity# = call dll(DLL_DBIni, "ReadFloat", "Game", "MinFallVelocity", 0.0) |
||
159 | collissionboxsize# = call dll(DLL_DBIni, "ReadFloat", "Game", "collissionboxsize", 0.0) |
||
160 | playerEyeHeight# = call dll(DLL_DBIni, "ReadFloat", "Game", "playerEyeHeight", 0.0) |
||
161 | cMaxTrees = call dll(DLL_DBIni, "ReadInt", "Game", "cMaxTrees", 0) |
||
162 | cMapSizeX = call dll(DLL_DBIni, "ReadInt", "Game", "cMapSizeX", 0) |
||
163 | cMapSizeZ = call dll(DLL_DBIni, "ReadInt", "Game", "cMapSizeZ", 0) |
||
164 | cTreeRadius = call dll(DLL_DBIni, "ReadInt", "Game", "cTreeRadius", 0) |
||
165 | cMaxEnemies = call dll(DLL_DBIni, "ReadInt", "Game", "cMaxEnemies", 0) |
||
166 | HitInterval = call dll(DLL_DBIni, "ReadInt", "Game", "HitInterval", 0) |
||
167 | initialEnemySafezone# = call dll(DLL_DBIni, "ReadFloat", "Game", "InitialEnemySafezone", 0.0) |
||
168 | cEnemySpawnMapBorderPadding = call dll(DLL_DBIni, "ReadInt", "Game", "EnemySpawnMapBorderPadding", 0) |
||
169 | call dll DLL_DBIni, "UnloadINI" |
||
170 | delete dll DLL_DBIni |
||
171 | |||
172 | rem Setup & Startbildschirm |
||
173 | if check display mode( desktop width(), desktop height(), screen depth() ) |
||
174 | set display mode desktop width(), desktop height(), screen depth() |
||
175 | endif |
||
176 | hide mouse |
||
177 | |||
178 | Sync On |
||
179 | Sync Rate framerate |
||
180 | |||
181 | LoadImageFullscreen(FN_GFX_TitleScreen, IMG_TitleScreen) |
||
182 | |||
183 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
184 | |||
185 | rem Sync twice at application start for friendliness with dbpro's double buffering |
||
186 | rem (Required for newer versions of DB Pro) |
||
187 | sync : sync |
||
188 | |||
189 | gosub _menu |
||
190 | |||
191 | _startgame: |
||
192 | |||
193 | ink rgb(255, 230, 0), 0 |
||
194 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
195 | text 28, 550, LNG_StartingGame |
||
196 | |||
197 | sync |
||
198 | |||
199 | randomize timer() |
||
200 | |||
201 | rem Working variables ONLY |
||
202 | JumpKeyStatePrev = 0 |
||
203 | JumpPosition# = 0.0 |
||
204 | onGround = 1 |
||
205 | velocityY# = 0.0 |
||
206 | runEnergy# = maxRunEnergy |
||
207 | clockSeconds = beginClockSeconds |
||
208 | collcounter = 0 |
||
209 | hits = 0 |
||
210 | LastAttackSound = 0 |
||
211 | |||
212 | draw to front |
||
213 | |||
214 | gosub _setup_camera |
||
215 | gosub _create_floor |
||
216 | gosub _setup_player_position |
||
217 | gosub _create_sky |
||
218 | gosub _create_trees |
||
219 | gosub _draw_trees |
||
220 | gosub _create_water |
||
221 | gosub _create_radar |
||
222 | |||
223 | rem Bildschirm neu aufbauen |
||
224 | cls |
||
225 | sync |
||
226 | |||
227 | rem Lichtversuch |
||
228 | make light 1 |
||
229 | |||
230 | rem Radar vorbereiten |
||
231 | radarpointcolor = 150 |
||
232 | |||
233 | gosub _create_enemies |
||
234 | gosub _setupClock |
||
235 | gosub _setup_blood |
||
236 | |||
237 | Rem Forest atmo |
||
238 | load sound FN_SFX_ForestBG, SFX_ForestBG |
||
239 | load sound FN_SFX_PauseMusic, SFX_PauseMusic |
||
240 | load sound FN_SFX_Walk_Earth, SFX_Walk_Earth |
||
241 | load sound FN_SFX_Walk_Water, SFX_Walk_Water |
||
242 | |||
243 | #constant NumberOfAttackSounds 4 |
||
244 | load sound FN_SFX_ScorpionAttack1, SFX_Attack_Base+0 |
||
245 | load sound FN_SFX_ScorpionAttack2, SFX_Attack_Base+1 |
||
246 | load sound FN_SFX_ScorpionAttack3, SFX_Attack_Base+2 |
||
247 | load sound FN_SFX_ScorpionAttack4, SFX_Attack_Base+3 |
||
248 | |||
249 | LoadImageFullscreen(FN_GFX_PauseScreen, IMG_PauseScreen) |
||
250 | |||
251 | #constant SPREAD1_MAX 10 |
||
252 | #constant SPREAD2_MAX 15 |
||
253 | |||
254 | Disable EscapeKey |
||
255 | |||
256 | loop sound SFX_ForestBG |
||
257 | |||
258 | rem Hauptschleife |
||
259 | do |
||
260 | gosub _handle_weather |
||
261 | gosub _handle_player |
||
262 | gosub _update_trees |
||
263 | gosub _handle_radar |
||
264 | gosub _handle_enemies |
||
265 | gosub _handleClock |
||
266 | gosub _handle_blood |
||
267 | |||
268 | rem TODO: does not work. There is always an attack! |
||
269 | set object collision on OBJ_CollissionDummy |
||
270 | position object OBJ_CollissionDummy, camera position x(), camera position y(), camera position z() |
||
271 | for t = 0 to cMaxEnemies-1 |
||
272 | if object collision(OBJ_CollissionDummy, OBJ_Monster_Base+t) = 1 |
||
273 | collcounter = collcounter + 1 |
||
274 | print "Attacking enemy: ", t |
||
275 | endif |
||
276 | NEXT |
||
277 | print "Collision counter: ", collcounter |
||
278 | set object collision off OBJ_CollissionDummy |
||
279 | |||
280 | if collcounter >= HitInterval |
||
281 | collcounter = 0 |
||
282 | inc hits, 1 |
||
283 | gosub _play_attack_sound |
||
284 | gosub _splat_blood |
||
285 | endif |
||
286 | print "Hits: ", hits |
||
287 | |||
288 | if EscapeKey() = 1 |
||
289 | repeat |
||
290 | sync |
||
291 | until not (EscapeKey() = 1) |
||
292 | gosub _pausemenu |
||
293 | endif |
||
294 | sceneInitialized=1 |
||
295 | sync |
||
296 | loop |
||
297 | |||
298 | _pausemenu: |
||
299 | gosub _stop_game_sounds |
||
300 | loop sound SFX_PauseMusic |
||
301 | show mouse |
||
302 | |||
303 | repeat |
||
304 | cls |
||
305 | |||
306 | paste image IMG_PauseScreen, 0, 0 |
||
307 | |||
308 | rem Text |
||
309 | ink rgb(255,255,255),1 |
||
310 | text 100,100,"text" |
||
311 | |||
312 | text 28, 550, "Pause. ESC=Weiter. Runter=Ende." |
||
313 | sync |
||
314 | |||
315 | if DownKey() = 1 |
||
316 | goto _exit |
||
317 | ENDIF |
||
318 | UNTIL EscapeKey() = 1 |
||
319 | repeat |
||
320 | sync |
||
321 | until not (EscapeKey() = 1) |
||
322 | hide mouse |
||
323 | stop sound SFX_PauseMusic |
||
324 | loop sound SFX_ForestBG |
||
325 | |||
326 | rem TODO: das bringt nix. wenn man die maus bewegt, wird nach der pause die kamera gescrollt |
||
327 | set cursor 0, 0 |
||
328 | return |
||
329 | |||
330 | _setup_camera: |
||
331 | Set camera range 1, camerarange |
||
332 | AUTOMATIC CAMERA COLLISION 0,collissionboxsize#,0 : rem scorpione stoßen den spieler nicht weg, wenn keine taste gedrückt wird? syntax mit 4 parametern funktioniert im neuen dbpro free nicht! |
||
333 | Autocam off |
||
334 | |||
335 | rem TODO: zylinder |
||
336 | MAKE OBJECT SPHERE OBJ_CollissionDummy, collissionboxsize# |
||
337 | rem hide object OBJ_CollissionDummy |
||
338 | set object collision off OBJ_CollissionDummy |
||
339 | return |
||
340 | |||
341 | _setup_player_position: |
||
342 | X# = cMapSizeX / 2 |
||
343 | Y# = floorHeight#(X#, Z#) + playerEyeHeight |
||
344 | Z# = cMapSizeZ / 2 |
||
345 | position camera X#, Y#, Z# |
||
346 | |||
347 | rem TODO zelt ist winzig klein! |
||
348 | rem TODO zelt ist schwarz schattiert |
||
349 | rem TODO zelt beleuchten |
||
350 | Load object FN_OBJ_Tent, OBJ_Tent |
||
351 | show object OBJ_Tent |
||
352 | scale object OBJ_Tent, 10000, 5000, 5000 |
||
353 | position object OBJ_Tent, X#-20, Y#, Z#-10 |
||
354 | return |
||
355 | |||
356 | _handle_weather: |
||
357 | rem Wetter |
||
358 | |||
359 | color ambient light rgb(64,64,128) |
||
360 | rem set ambient light 1 |
||
361 | set ambient light 50 |
||
362 | if fog available() = 1 |
||
363 | fog on |
||
364 | fog distance fogdistance |
||
365 | fog color rgb(0, 0, 0) |
||
366 | endif |
||
367 | |||
368 | if test = 1 |
||
369 | SET MATRIX WIREFRAME ON MAT_Ground |
||
370 | SET MATRIX WIREFRAME ON MAT_Water |
||
371 | endif |
||
372 | |||
373 | rem Stars are moving |
||
374 | scroll object texture OBJ_Skybox, 0.00002, 0 |
||
375 | |||
376 | rem Water movement |
||
377 | rem TODO: wasser soll sich langsamer bewegen, aber das ist schwierig. wenn man die bewegung nur zu bestimmten ticks |
||
378 | rem durchführt, dann ruckelt es. |
||
379 | waterdir = (waterdir + 1) mod 360; |
||
380 | watermov = 0 + cos(waterdir)*waterMovementMaxDistance |
||
381 | position matrix MAT_Water, watermov, waterLevel, watermov |
||
382 | return |
||
383 | |||
384 | _handle_enemies: |
||
385 | pX# = Camera Position X() |
||
386 | pZ# = Camera Position Z() |
||
387 | |||
388 | rem TODO: gegner sollen sich nicht überschneiden |
||
389 | |||
390 | for t = 0 to cMaxEnemies-1 |
||
391 | eX# = Object Position X(OBJ_Monster_Base+t) |
||
392 | eY# = Object Position Y(OBJ_Monster_Base+t) |
||
393 | eZ# = Object Position Z(OBJ_Monster_Base+t) |
||
394 | |||
395 | eRX# = Object Angle X(OBJ_Monster_Base+t) |
||
396 | eRY# = Object Angle Y(OBJ_Monster_Base+t) |
||
397 | eRZ# = Object Angle Z(OBJ_Monster_Base+t) |
||
398 | |||
399 | deltaX# = pX#-eX# |
||
400 | deltaZ# = pZ#-eZ# |
||
401 | |||
402 | rem TODO: cor file |
||
403 | yPosOffset# = 20 |
||
404 | |||
405 | dist# = sqrt( deltaX#*deltaX# + deltaZ#*deltaZ# ) |
||
406 | |||
407 | if clockSeconds > 1 |
||
408 | if not sound playing(SFX_Monster_Base+t) |
||
409 | set sound volume SFX_Monster_Base+t, 0 |
||
410 | |||
411 | rem TODO: beliebiges startoffset? |
||
412 | loop sound SFX_Monster_Base+t |
||
413 | endif |
||
414 | endif |
||
415 | |||
416 | rem The mixing of 3dsound is bullshit (too loud from far distance, and not very loud on close distance), |
||
417 | rem so we mix the volume ourself |
||
418 | if sound3dVolumeCor>0 and dist#<sound3dVolumeCor then set sound volume SFX_Monster_Base+t, (1-(dist#/sound3dVolumeCor))*100 |
||
419 | |||
420 | rem TODO: 100 dynamisch machen |
||
421 | rem at least a distance of 10 so that atanfull() does not bug, when deltas becomes 0 |
||
422 | rem Verhindern, dass der Skorpion in einem "drin" steht. Er soll mit den Scheren angreifen |
||
423 | scorpMinDistance = 100 |
||
424 | |||
425 | if dist# > scorpMinDistance |
||
426 | if dist# < enemy(t).AwarenessRadius |
||
427 | enemy(t).Angle = atanfull(deltaX#, deltaZ#) |
||
428 | enemy(t).Angle = WrapValue(enemy(t).Angle+180) |
||
429 | enemy(t).CurSpeed = enemy(t).MaxSpeed |
||
430 | else |
||
431 | if enemy(t).WalkTimeout <= 0 |
||
432 | enemy(t).WalkTimeout = RndBetween(enemy(t).WalkTimeoutMin, enemy(t).WalkTimeoutMax) |
||
433 | enemy(t).Angle = RndBetween(0,359) |
||
434 | enemy(t).CurSpeed = RndBetween(0, enemy(t).MaxSpeed) |
||
435 | ENDIF |
||
436 | enemy(t).WalkTimeout = enemy(t).WalkTimeout - 1 |
||
437 | endif |
||
438 | |||
439 | if enemy(t).CurSpeed = 0 |
||
440 | gosub scorpChangeToIdle |
||
441 | else |
||
442 | gosub scorpChangeToWalk |
||
443 | rem TODO: also make animation slower/faster |
||
444 | endif |
||
445 | |||
446 | a# = WrapValue(enemy(t).Angle + 180) |
||
447 | XTest# = Newxvalue(eX#, a#, enemy(t).CurSpeed) |
||
448 | ZTest# = Newzvalue(eZ#, a#, enemy(t).CurSpeed) |
||
449 | if XTest# > 0 and XTest# < cMapSizeX then eX# = XTest# |
||
450 | if ZTest# > 0 and ZTest# < cMapSizeZ then eZ# = ZTest# |
||
451 | if XTest# <= 0 or XTest# >= cMapSizeX or ZTest# <= 0 or ZTest# >= cMapSizeZ |
||
452 | rem Kehrtwende, um den Kartenrand zu verlassen |
||
453 | enemy(t).Angle = WrapValue(enemy(t).Angle+180) |
||
454 | enemy(t).WalkTimeout = RndBetween(enemy(t).WalkTimeoutMin, enemy(t).WalkTimeoutMax) |
||
455 | enemy(t).CurSpeed = RndBetween(0, enemy(t).MaxSpeed) |
||
456 | endif |
||
457 | |||
458 | eY# = floorHeight#(eX#, eZ#) + yPosOffset# |
||
459 | Position Object OBJ_Monster_Base+t, eX#, eY#, eZ# |
||
460 | Position Sound SFX_Monster_Base+t, eX#, eY#, eZ# |
||
461 | |||
462 | eRY# = smoothRotate#(eRY#, enemy(t).Angle, enemyRotateSmoothness) |
||
463 | rotate object OBJ_Monster_Base+t, eRX#, eRY#, eRZ# |
||
464 | endif |
||
465 | next |
||
466 | return |
||
467 | |||
468 | #constant GROUNDTYPE_AIR 0 |
||
469 | #constant GROUNDTYPE_EARTH 1 |
||
470 | #constant GROUNDTYPE_WATER 2 |
||
471 | rem #constant GROUNDTYPE_DEEPWATER 3 |
||
472 | function groundType(onGround, waterLevel) |
||
473 | if onGround = 0 |
||
474 | ret = GROUNDTYPE_AIR |
||
475 | else |
||
476 | X# = camera position x() |
||
477 | Z# = camera position z() |
||
478 | if floorHeight#(X#,Z#) > waterLevel |
||
479 | ret = GROUNDTYPE_EARTH |
||
480 | else |
||
481 | ret = GROUNDTYPE_WATER |
||
482 | endif |
||
483 | endif |
||
484 | endfunction ret |
||
485 | |||
486 | _handle_player: |
||
487 | set cursor 0, 0 |
||
488 | oldcAY# = cAY# |
||
489 | oldcAX# = cAX# |
||
490 | |||
491 | X# = camera position x() |
||
492 | Y# = camera position y() |
||
493 | Z# = camera position z() |
||
494 | |||
495 | if invertMouse = 1 |
||
496 | cAX# = WrapValue(cAX# - MousemoveY() * 0.2) |
||
497 | else |
||
498 | cAX# = WrapValue(cAX# + MousemoveY() * 0.2) |
||
499 | endif |
||
500 | cAY# = WrapValue(cAY# + MousemoveX() * 0.2) |
||
501 | cAZ# = Camera angle Z() |
||
502 | |||
503 | rem Sprungroutine |
||
504 | rem TODO: + Anlaufsprung |
||
505 | |||
506 | JumpKeyStateNow=jumpPressed() |
||
507 | if (JumpKeyStatePrev=0) and (JumpKeyStateNow=1) |
||
508 | gosub PressJumpKey |
||
509 | ENDIF |
||
510 | if (JumpKeyStatePrev=1) and (JumpKeyStateNow=0) |
||
511 | gosub ReleaseJumpKey |
||
512 | ENDIF |
||
513 | JumpKeyStatePrev = JumpKeyStateNow |
||
514 | gosub JumpUpdate |
||
515 | |||
516 | rem Laufen |
||
517 | speedboost# = 1 |
||
518 | |||
519 | gt = groundType(onGround, waterLevel) |
||
520 | |||
521 | if upPressed()+downPressed()+leftPressed()+rightPressed() = 0 |
||
522 | runEnergy# = runEnergy# + 2 |
||
523 | stop sound SFX_Walk_Earth |
||
524 | stop sound SFX_Walk_Water |
||
525 | else |
||
526 | if gt = GROUNDTYPE_EARTH |
||
527 | stop sound SFX_Walk_Water |
||
528 | if not sound playing(SFX_Walk_Earth) |
||
529 | loop sound SFX_Walk_Earth |
||
530 | endif |
||
531 | endif |
||
532 | if gt = GROUNDTYPE_WATER |
||
533 | stop sound SFX_Walk_Earth |
||
534 | if not sound playing(SFX_Walk_Water) |
||
535 | loop sound SFX_Walk_Water |
||
536 | endif |
||
537 | endif |
||
538 | if gt = GROUNDTYPE_AIR |
||
539 | stop sound SFX_Walk_Earth |
||
540 | stop sound SFX_Walk_Water |
||
541 | endif |
||
542 | energyChanged = 0 |
||
543 | if ShiftKey()+ControlKey() = 1 : rem shift+control at the same time = walk normal |
||
544 | rem TODO: es ruckelt trotzdem noch |
||
545 | if ControlKey()=1 and runEnergy#>0 : rem Energy >1 , damit es nicht ruckelt (run-walk-run-walk-run-walk) . 3 = walk regain |
||
546 | speedboost# = 2 |
||
547 | runEnergy# = runEnergy# - 1 |
||
548 | energyChanged = 1 |
||
549 | endif |
||
550 | if ShiftKey()=1 |
||
551 | speedboost# = 0.5 |
||
552 | runEnergy# = runEnergy# + 0.5 |
||
553 | energyChanged = 1 |
||
554 | endif |
||
555 | endif |
||
556 | if not energyChanged then runEnergy# = runEnergy# + 1 |
||
557 | if upPressed() |
||
558 | XTest# = Newxvalue(X#, cAY#, 7*speedboost#) |
||
559 | ZTest# = Newzvalue(Z#, cAY#, 7*speedboost#) |
||
560 | gosub _WorldBoundCheck |
||
561 | endif |
||
562 | if downPressed() |
||
563 | XTest# = Newxvalue(X#, Wrapvalue(cAY# - 180), 5*(speedboost#/2)) |
||
564 | ZTest# = Newzvalue(Z#, Wrapvalue(cAY# - 180), 5*(speedboost#/2)) |
||
565 | gosub _WorldBoundCheck |
||
566 | endif |
||
567 | if leftPressed() |
||
568 | XTest# = Newxvalue(X#, Wrapvalue(cAY# - 90), 5*(speedboost#/1.3)) |
||
569 | ZTest# = Newzvalue(Z#, Wrapvalue(cAY# - 90), 5*(speedboost#/1.3)) |
||
570 | gosub _WorldBoundCheck |
||
571 | endif |
||
572 | if rightPressed() |
||
573 | XTest# = Newxvalue(X#, Wrapvalue(cAY# + 90), 5*(speedboost#/1.3)) |
||
574 | ZTest# = Newzvalue(Z#, Wrapvalue(cAY# + 90), 5*(speedboost#/1.3)) |
||
575 | gosub _WorldBoundCheck |
||
576 | endif |
||
577 | endif |
||
578 | if runEnergy# > maxRunEnergy then runEnergy# = maxRunEnergy |
||
579 | print "Run energy: ", runEnergy# |
||
580 | |||
581 | Rem Rotate camera |
||
582 | cTestX# = WrapValue(cAX# - 180) |
||
583 | if cTestX# > 225 then cAX# = 45 |
||
584 | if cTestX# < 135 then cAX# = 315 |
||
585 | YRotate camera CurveAngle(cAY#, oldcAY#, 24) |
||
586 | XRotate camera CurveAngle(cAX#, oldcAX#, 24) |
||
587 | |||
588 | Rem Position Camera |
||
589 | if onGround=1 |
||
590 | Y#=floorHeight#(X#, Z#) |
||
591 | else |
||
592 | Y#=JumpPosition# |
||
593 | ENDIF |
||
594 | inc Y#, playerEyeHeight# |
||
595 | Position Camera X#, Y#, Z# |
||
596 | |||
597 | Rem Position Listener |
||
598 | Position Listener X#, Y#, Z# |
||
599 | Rotate Listener 0, cAY#, 0 : rem todo warum 0 statt cAZ# etc ? |
||
600 | |||
601 | rem Sky sphere follows player |
||
602 | rem position object OBJ_Skybox, X#, Y#, Z# |
||
603 | position object OBJ_Skybox, X#, FloorHeight#(X#,Z#), Z# |
||
604 | |||
605 | |||
606 | |||
607 | rem Sollte man aus irgendeinem Grund die Skybox verlassen, soll man trotzdem zur Erde schauen können |
||
608 | backdrop on |
||
609 | color backdrop rgb(0,0,128) : rem TODO: schwarz + auslagern |
||
610 | set object cull OBJ_Skybox, 1 |
||
611 | |||
612 | rem texture backdrop IMG_Stars |
||
613 | rem hide object OBJ_Skybox |
||
614 | rem set object fog OBJ_Skybox, 0 |
||
615 | |||
616 | rem TEST: extend skybox if player jumps |
||
617 | if onGround = 0 |
||
618 | jumpheight#=Y#-FloorHeight#(X#,Z#) |
||
619 | else |
||
620 | jumpheight#=0 |
||
621 | endif |
||
622 | |||
623 | rem TODO: beim springen sieht man am boden den backdrop |
||
624 | |||
625 | rem 500 = die originalgröße der box, vor der ersten scalisierung (setup sky) |
||
626 | rem 600,120,600 = die originale skalierung als referenz |
||
627 | rem *2 , da es von beiden seiten erweitert wird |
||
628 | scalX# = 100.0*(500.0*6.00 + jumpheight#*2)/500.0 |
||
629 | scalY# = 100.0*(500.0*1.20 + jumpheight#*2)/500.0 |
||
630 | scalZ# = 100.0*(500.0*6.00 + jumpheight#*2)/500.0 |
||
631 | scale object OBJ_Skybox, scalX#, scalY#, scalZ# |
||
632 | return |
||
633 | |||
634 | _WorldBoundCheck: |
||
635 | if XTest# > 0 and XTest# < cMapSizeX then X# = XTest# |
||
636 | if ZTest# > 0 and ZTest# < cMapSizeZ then Z# = ZTest# |
||
637 | return |
||
638 | |||
639 | _update_trees: |
||
640 | if (ceil(X#) mod 10 = 0) or (ceil(Z#) mod 10 = 0) or (sceneInitialized=0) |
||
641 | for t = 0 to cMaxTrees-1 |
||
642 | rx = tree(t).x |
||
643 | rz = tree(t).z |
||
644 | incircle = IsInCircle(rx, rz, X#, Z#, camerarange) |
||
645 | rem incircle = IsInCircle(rx, rz, X#, Z#, fogdistance) |
||
646 | if incircle <> tree(t).drawn |
||
647 | if incircle = 1 |
||
648 | if object exist(OBJ_Tree_Base+t) |
||
649 | show object OBJ_Tree_Base+t |
||
650 | else |
||
651 | make object OBJ_Tree_Base+t, MSH_TreeTemplate, IMG_Tree |
||
652 | position object OBJ_Tree_Base+t, rx, floorHeight#(rx, rz)+190, rz |
||
653 | set object OBJ_Tree_Base+t, 1, 1, 0 |
||
654 | rotate object OBJ_Tree_Base+t, 0, RndBetween(0,359), 0 |
||
655 | endif |
||
656 | else |
||
657 | delete object OBJ_Tree_Base+t |
||
658 | rem hide object OBJ_Tree_Base+t |
||
659 | endif |
||
660 | ENDIF |
||
661 | tree(t).drawn = incircle |
||
662 | next t |
||
663 | endif |
||
664 | return |
||
665 | |||
666 | _fademenu: |
||
667 | if fade# > 100 then fadedir = 0 |
||
668 | if fade# < 50 then fadedir = 1 |
||
669 | if fadedir = 1 |
||
670 | fade# = fade# + 2.5 |
||
671 | else |
||
672 | fade# = fade# - 2.5 |
||
673 | endif |
||
674 | rem Beleuchtet |
||
675 | ink rgb(255, fade#, 0), 0 |
||
676 | set text font "Tahoma" |
||
677 | set text size 26 |
||
678 | if menu = 1 |
||
679 | if pos = 1 then text 260, 255, "Neues Spiel starten" |
||
680 | if pos = 2 then text 260, 285, "Spiel laden" |
||
681 | if pos = 3 then text 260, 315, "Einstellungen" |
||
682 | if pos = 4 then text 260, 345, "Spiel beenden" |
||
683 | endif |
||
684 | if menu = 3 |
||
685 | if pos = 1 |
||
686 | if sound = 1 then text 260, 255, "Ton: An" |
||
687 | if sound = 0 then text 260, 255, "Ton: Aus" |
||
688 | endif |
||
689 | if pos = 2 |
||
690 | if music = 1 then text 260, 285, "Musik: An" |
||
691 | if music = 0 then text 260, 285, "Musik: Aus" |
||
692 | endif |
||
693 | if pos = 3 then text 260, 315, "Hauptmenü" |
||
694 | endif |
||
695 | rem Normal |
||
696 | ink rgb(255, 230, 0), 0 |
||
697 | if menu = 1 |
||
698 | if pos <> 1 then text 260, 255, "Neues Spiel starten" |
||
699 | if pos <> 2 then text 260, 285, "Spiel laden" |
||
700 | if pos <> 3 then text 260, 315, "Einstellungen" |
||
701 | if pos <> 4 then text 260, 345, "Spiel beenden" |
||
702 | endif |
||
703 | if menu = 3 |
||
704 | if pos <> 1 |
||
705 | if sound = 1 then text 260, 255, "Ton: An" |
||
706 | if sound = 0 then text 260, 255, "Ton: Aus" |
||
707 | endif |
||
708 | if pos <> 2 |
||
709 | if music = 1 then text 260, 285, "Musik: An" |
||
710 | if music = 0 then text 260, 285, "Musik: Aus" |
||
711 | endif |
||
712 | if pos <> 3 then text 260, 315, "Hauptmenü" |
||
713 | endif |
||
714 | sync |
||
715 | return |
||
716 | |||
717 | _handle_radar: |
||
718 | rem TODO: the player dot should always stay at the same position |
||
719 | rem TODO: don't show far away enemies |
||
720 | |||
721 | rem Leuchtpunkt |
||
722 | if radarpointrev = 0 |
||
723 | inc radarpointcolor, 3 |
||
724 | else |
||
725 | dec radarpointcolor, 3 |
||
726 | endif |
||
727 | if radarpointcolor > 255 |
||
728 | radarpointrev = 1 |
||
729 | radarpointcolor = 254 |
||
730 | endif |
||
731 | if radarpointcolor < 150 |
||
732 | radarpointrev = 0 |
||
733 | radarpointcolor = 149 |
||
734 | endif |
||
735 | rem Bäume |
||
736 | for t = 0 to cMaxTrees-1 |
||
737 | if tree(t).drawn |
||
738 | x = tree(t).x |
||
739 | y = tree(t).z |
||
740 | |||
741 | x0 = camera position x() |
||
742 | y0 = camera position z() |
||
743 | ang = camera angle y() |
||
744 | tx = x0 + (x-x0)*cos(ang) - (y-y0)*sin(ang) |
||
745 | ty = y0 + (x-x0)*sin(ang) + (y-y0)*cos(ang) |
||
746 | x = tx |
||
747 | y = ty |
||
748 | |||
749 | x = (x / 62.5) + 7.5 |
||
750 | y = screen height() - 7.5 - (y / 62.5) |
||
751 | |||
752 | rem ink rgb(0, radarpointcolor, 0), 0 |
||
753 | ink rgb(0, 50, 0), 0 |
||
754 | circle x, y, 1 |
||
755 | circle x, y, 0 |
||
756 | endif |
||
757 | next i |
||
758 | rem Player |
||
759 | x = (X# / 62.5) + 7.5 |
||
760 | y = screen height() - 7.5 - (Z# / 62.5) |
||
761 | ink rgb(0, 0, radarpointcolor), 0 |
||
762 | circle x, y, 1 |
||
763 | circle x, y, 0 |
||
764 | rem Enemies |
||
765 | for t = 0 to cMaxEnemies-1 |
||
766 | x = object position x(OBJ_Monster_Base+t) |
||
767 | y = object position z(OBJ_Monster_Base+t) |
||
768 | |||
769 | x0 = camera position x() |
||
770 | y0 = camera position z() |
||
771 | ang = camera angle y() |
||
772 | tx = x0 + (x-x0)*cos(ang) - (y-y0)*sin(ang) |
||
773 | ty = y0 + (x-x0)*sin(ang) + (y-y0)*cos(ang) |
||
774 | x = tx |
||
775 | y = ty |
||
776 | |||
777 | x = (x / 62.5) + 7.5 |
||
778 | y = screen height() - 7.5 - (y / 62.5) |
||
779 | |||
780 | ink rgb(radarpointcolor, 0, 0), 0 |
||
781 | circle x, y, 1 |
||
782 | circle x, y, 0 |
||
783 | next |
||
784 | return |
||
785 | |||
786 | _draw_trees: |
||
787 | rem TODO: da ist ein baum an offset 0,0,0 |
||
788 | load image FN_GFX_Tree, IMG_Tree |
||
789 | |||
790 | make object plain OBJ_TreeTemplate, 2*cTreeRadius, 400 |
||
791 | make mesh from object MSH_TreeTemplate, OBJ_TreeTemplate |
||
792 | add limb OBJ_TreeTemplate, 1, MSH_TreeTemplate |
||
793 | rotate limb OBJ_TreeTemplate, 1, 0, 90, 0 |
||
794 | make mesh from object MSH_TreeTemplate, OBJ_TreeTemplate |
||
795 | delete object OBJ_TreeTemplate |
||
796 | return |
||
797 | |||
798 | _create_trees: |
||
799 | dim tree(cMaxTrees-1) as treeType |
||
800 | |||
801 | remstart |
||
802 | for t = 0 to cMaxTrees-1 |
||
803 | tree(t).x = RndBetween(0, cMapSizeX) |
||
804 | tree(t).z = RndBetween(0, cMapSizeZ) |
||
805 | tree(t).drawn = 0 |
||
806 | NEXT |
||
807 | remend |
||
808 | |||
809 | rem TODO: wegbreite definieren |
||
810 | load dll FN_DLL_MapGen32, DLL_MapGen |
||
811 | call dll DLL_MapGen, "LoadParametersFromINI", "forest.ini" |
||
812 | |||
813 | load dll FN_DLL_DBIni, DLL_DBIni |
||
814 | call dll DLL_DBIni, "LoadINI", "seed.ini" |
||
815 | onetimeseed = call dll(DLL_DBIni, "ReadInt", "Seed", "onetime", 0) |
||
816 | staticseed = call dll(DLL_DBIni, "ReadInt", "Seed", "value", 0) |
||
817 | seedactive = call dll(DLL_DBIni, "ReadInt", "Seed", "active", 0) |
||
818 | IF (onetimeseed = 1) AND (seedactive = 1) |
||
819 | call dll DLL_DBIni, "WriteInt", "Seed", "active", 0 |
||
820 | ENDIF |
||
821 | IF seedactive |
||
822 | call dll DLL_MapGen, "UseSeed", staticseed |
||
823 | ELSE |
||
824 | call dll DLL_MapGen, "RandomSeed" |
||
825 | ENDIF |
||
826 | call dll DLL_DBIni, "UnloadINI" |
||
827 | delete dll DLL_DBIni |
||
828 | |||
829 | make memblock MEM_Map, cMaxTrees*8 |
||
830 | call dll DLL_MapGen, "GenerateMap", cMaxTrees, cTreeRadius, cMapSizeX, cMapSizeZ, get memblock ptr(MEM_Map), 0 |
||
831 | for t = 0 to cMaxTrees-1 |
||
832 | tree(t).x = memblock dword(MEM_Map, t*8) |
||
833 | tree(t).z = memblock dword(MEM_Map, t*8+4) |
||
834 | tree(t).drawn = 0 |
||
835 | NEXT |
||
836 | delete memblock MEM_Map |
||
837 | delete dll DLL_MapGen |
||
838 | return |
||
839 | |||
840 | _menu: |
||
841 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
842 | set text font "times" |
||
843 | set text size 27 |
||
844 | fade = 100 |
||
845 | pos = 1 |
||
846 | menu = 1 |
||
847 | sound = 1 |
||
848 | do |
||
849 | gosub _fademenu |
||
850 | if ( downkey() = 1 and pos < 4 and menu = 1 ) or ( downkey() = 1 and pos < 3 and menu = 3 ) |
||
851 | inc pos |
||
852 | while downkey() = 1 |
||
853 | gosub _fademenu |
||
854 | endwhile |
||
855 | endif |
||
856 | if upkey() = 1 and pos > 1 |
||
857 | dec pos |
||
858 | while upkey() = 1 |
||
859 | gosub _fademenu |
||
860 | endwhile |
||
861 | endif |
||
862 | if returnkey() = 1 |
||
863 | if menu = 1 |
||
864 | if pos = 1 then gosub _startgame |
||
865 | if pos = 2 |
||
866 | rem PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
867 | rem menu = 2 |
||
868 | rem pos = 1 |
||
869 | endif |
||
870 | if pos = 3 |
||
871 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
872 | menu = 3 |
||
873 | pos = 1 |
||
874 | endif |
||
875 | if pos = 4 then end |
||
876 | else |
||
877 | if menu = 3 |
||
878 | if pos = 1 |
||
879 | if sound = 1 |
||
880 | sound = 0 |
||
881 | else |
||
882 | sound = 1 |
||
883 | endif |
||
884 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
885 | endif |
||
886 | if pos = 2 |
||
887 | if music = 1 |
||
888 | music = 0 |
||
889 | else |
||
890 | music = 1 |
||
891 | endif |
||
892 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
893 | endif |
||
894 | if pos = 3 |
||
895 | PASTE IMAGE IMG_TitleScreen, 0, 0 |
||
896 | menu = 1 |
||
897 | pos = 1 |
||
898 | endif |
||
899 | endif |
||
900 | endif |
||
901 | while returnkey() = 1 |
||
902 | gosub _fademenu |
||
903 | endwhile |
||
904 | endif |
||
905 | loop |
||
906 | return |
||
907 | |||
908 | _create_enemies: |
||
909 | dim enemy(cMaxEnemies-1) as enemyType |
||
910 | for t = 0 to cMaxEnemies-1 |
||
911 | if t=0 |
||
912 | Load 3Dsound FN_SFX_ScorpWalk,SFX_Monster_Base+t |
||
913 | else |
||
914 | Clone Sound SFX_Monster_Base+t, SFX_Monster_Base |
||
915 | endif |
||
916 | |||
917 | pX# = Camera Position X() |
||
918 | pY# = Camera Position Y() |
||
919 | pZ# = Camera Position Z() |
||
920 | |||
921 | repeat |
||
922 | eX# = RndBetween(cEnemySpawnMapBorderPadding, cMapSizeX-cEnemySpawnMapBorderPadding) |
||
923 | eZ# = RndBetween(cEnemySpawnMapBorderPadding, cMapSizeZ-cEnemySpawnMapBorderPadding) |
||
924 | deltaX# = pX#-eX# |
||
925 | deltaZ# = pZ#-eZ# |
||
926 | dist# = sqrt( deltaX#*deltaX# + deltaZ#*deltaZ# ) |
||
927 | rem Prevent that the enemies spawn right at the player (5000/5000) |
||
928 | until dist# >= initialEnemySafezone# |
||
929 | enemy(t).AwarenessRadius = RndBetween(600, 1300) |
||
930 | enemy(t).MaxSpeed = RndBetween(1, 4) |
||
931 | enemy(t).WalkTimeoutMin = 200 |
||
932 | enemy(t).WalkTimeoutMax = 300 |
||
933 | |||
934 | if t = 0 |
||
935 | animScorpIdleStart = 0 |
||
936 | Load object FN_OBJ_ScorpIdle, OBJ_Monster_Base+t |
||
937 | animScorpIdleEnd = total object frames(OBJ_Monster_Base+t) |
||
938 | |||
939 | animScorpWalkStart = animScorpIdleEnd+1 |
||
940 | Append object FN_OBJ_ScorpWalk, OBJ_Monster_Base+t, animScorpWalkStart |
||
941 | animScorpWalkEnd = total object frames(OBJ_Monster_Base+t) |
||
942 | else |
||
943 | Clone Object OBJ_Monster_Base+t, OBJ_Monster_Base |
||
944 | endif |
||
945 | |||
946 | eY# = floorHeight#(eX#, eZ#) : rem TODO + yPosOffset# |
||
947 | position object OBJ_Monster_Base+t, eX#, eY#, eZ# |
||
948 | Position Sound SFX_Monster_Base+t, eX#, eY#, eZ# |
||
949 | |||
950 | fix object pivot OBJ_Monster_Base+t |
||
951 | gosub scorpChangeToWalk |
||
952 | set object collision on OBJ_Monster_Base+t |
||
953 | NEXT |
||
954 | return |
||
955 | |||
956 | scorpChangeToIdle: |
||
957 | rem TODO: smoothness (interpolation) |
||
958 | if enemy(t).CurrentAnim <> 1 |
||
959 | loop object OBJ_Monster_Base+t, animScorpIdleStart, animScorpIdleEnd |
||
960 | enemy(t).CurrentAnim = 1 |
||
961 | endif |
||
962 | return |
||
963 | |||
964 | scorpChangeToWalk: |
||
965 | rem TODO: smoothness (interpolation) |
||
966 | if enemy(t).CurrentAnim <> 2 |
||
967 | loop object OBJ_Monster_Base+t, animScorpWalkStart, animScorpWalkEnd |
||
968 | enemy(t).CurrentAnim = 2 |
||
969 | endif |
||
970 | return |
||
971 | |||
972 | _setupClock: |
||
973 | set text font "arial" : set text size 30 : set text transparent |
||
974 | |||
975 | // Session variables |
||
976 | clockTickCounter=0 |
||
977 | clockCurrentMidDot=0 |
||
978 | clockTicksPerSecond = framerate |
||
979 | return |
||
980 | |||
981 | _handleClock: |
||
982 | if mod(clockTickCounter*clockBlinksPerSecond, clockTicksPerSecond) = 0 |
||
983 | clockCurrentMidDot = 1 - clockCurrentMidDot |
||
984 | endif |
||
985 | |||
986 | if mod(clockTickCounter*clockSpeedFactor, clockTicksPerSecond) = 0 |
||
987 | clockSeconds = clockSeconds + 1 |
||
988 | endif |
||
989 | |||
990 | gosub _printClock |
||
991 | |||
992 | clockTickCounter = clockTickCounter + 1 |
||
993 | RETURN |
||
994 | |||
995 | _create_water: |
||
996 | make matrix MAT_Water, cMapSizeX+2*waterMovementMaxDistance, cMapSizeZ+2*waterMovementMaxDistance, 15, 15 |
||
997 | load image FN_GFX_Water, IMG_Water |
||
998 | prepare matrix texture MAT_Water, IMG_Water, 1, 1 |
||
999 | fill matrix MAT_Water, 0, 1 |
||
1000 | position matrix MAT_Water, 0, waterLevel, 0 |
||
1001 | ghost matrix on MAT_Water |
||
1002 | set matrix MAT_Water, 0, 0, 1, 1, 1, 1, 1 |
||
1003 | update matrix MAT_Water |
||
1004 | return |
||
1005 | |||
1006 | _create_floor: |
||
1007 | rem Boden |
||
1008 | make matrix MAT_Ground, cMapSizeX, cMapSizeZ, 15, 15 |
||
1009 | |||
1010 | load image FN_GFX_FloorTexture, IMG_ForestFloor |
||
1011 | prepare matrix texture MAT_Ground, IMG_ForestFloor, 1, 1 |
||
1012 | fill matrix MAT_Ground, 0, 1 |
||
1013 | set matrix MAT_Ground, 0, 0, 1, 1, 1, 1, 1 |
||
1014 | randomize matrix MAT_Ground, 130 |
||
1015 | |||
1016 | rem TEST |
||
1017 | rem TODO: aber man kann 40,40 nicht updaten?! |
||
1018 | set matrix height MAT_Ground, 10, 10, 1000 |
||
1019 | |||
1020 | update matrix MAT_Ground |
||
1021 | |||
1022 | remstart |
||
1023 | currentmatrix=1 |
||
1024 | for z=1 to 20 |
||
1025 | for x=1 to 20 |
||
1026 | |||
1027 | rem Get matrix heights |
||
1028 | rem print x, " - ", z |
||
1029 | rem sync |
||
1030 | rem sleep 100 |
||
1031 | |||
1032 | h8#=get matrix height(currentmatrix,x,z-1) |
||
1033 | h4#=get matrix height(currentmatrix,x-1,z) |
||
1034 | h#=get matrix height(currentmatrix,x,z) |
||
1035 | h2#=get matrix height(currentmatrix,x,z) |
||
1036 | |||
1037 | rem Calculate projected angle X using heights |
||
1038 | x1#=(x-1)*25.0 : y1#=h# |
||
1039 | x2#=(x+0)*25.0 : y2#=h4# |
||
1040 | dx#=x2#-x1# |
||
1041 | dy#=y2#-y1# |
||
1042 | ax#=atanfull(dx#,dy#) |
||
1043 | ax#=wrapvalue(90-ax#) |
||
1044 | |||
1045 | rem Calculate projected angle Z using heights |
||
1046 | z1#=(z-1)*25.0 : y1#=h2# |
||
1047 | z2#=(z+0)*25.0 : y2#=h8# |
||
1048 | dz#=z2#-z1# |
||
1049 | dy#=y2#-y1# |
||
1050 | az#=atanfull(dz#,dy#) |
||
1051 | az#=wrapvalue(90-az#) |
||
1052 | |||
1053 | rem Make normal from projected angle |
||
1054 | nx#=sin(ax#) |
||
1055 | ny#=cos(ax#) |
||
1056 | nz#=sin(az#) |
||
1057 | |||
1058 | rem Setting matrix normal for smoothness |
||
1059 | set matrix normal currentmatrix,x,z,nx#,ny#,nz# |
||
1060 | |||
1061 | next x |
||
1062 | next z |
||
1063 | update matrix currentmatrix |
||
1064 | remend |
||
1065 | return |
||
1066 | |||
1067 | _create_sky: |
||
1068 | if test = 1 |
||
1069 | load image FN_GFX_Tree, IMG_Stars : rem Any small picture - it doesn't matter since we only show wireframe |
||
1070 | else |
||
1071 | load image FN_GFX_Stars, IMG_Stars |
||
1072 | endif |
||
1073 | |||
1074 | rem TODO: landsize undefined |
||
1075 | make object sphere OBJ_Skybox, (landsize * 2) - 500 |
||
1076 | |||
1077 | rem make object sphere OBJ_Skybox, -4000 |
||
1078 | |||
1079 | set object collision off OBJ_Skybox |
||
1080 | rem scale object OBJ_Skybox, 2000, 750, 2000 |
||
1081 | scale object OBJ_Skybox, 600, 120, 600 |
||
1082 | set object OBJ_Skybox, 1, 0, 0, 0, 0, 1, 1 |
||
1083 | texture object OBJ_Skybox, IMG_Stars |
||
1084 | rem fade object OBJ_Skybox, 0 |
||
1085 | |||
1086 | if test = 1 |
||
1087 | backdrop on |
||
1088 | set object wireframe OBJ_Skybox, 1 |
||
1089 | else |
||
1090 | backdrop off |
||
1091 | endif |
||
1092 | return |
||
1093 | |||
1094 | _create_radar: |
||
1095 | rem Karte - Abstand zur Kamera: 1.1 |
||
1096 | remstart |
||
1097 | load image FN_GFX_MapBackground, IMG_MapBackground |
||
1098 | make object plain OBJ_MapGhostObject, 0.352, 0.352 |
||
1099 | lock object on OBJ_MapGhostObject |
||
1100 | position object OBJ_MapGhostObject, -0.6908, -0.4675, 1.1 |
||
1101 | ghost object on OBJ_MapGhostObject |
||
1102 | texture object OBJ_MapGhostObject, IMG_MapBackground |
||
1103 | remend |
||
1104 | |||
1105 | rem Karte - Abstand zur Kamera: 1.5 |
||
1106 | load image FN_GFX_MapBackground, IMG_MapBackground |
||
1107 | make object plain OBJ_MapGhostObject, 0.48, 0.48 |
||
1108 | lock object on OBJ_MapGhostObject |
||
1109 | position object OBJ_MapGhostObject, -0.942, -0.6375, 1.5 |
||
1110 | ghost object on OBJ_MapGhostObject |
||
1111 | texture object OBJ_MapGhostObject, IMG_MapBackground |
||
1112 | return |
||
1113 | |||
1114 | _printClock: |
||
1115 | if clockCurrentMidDot = 0 |
||
1116 | middle$ = " " |
||
1117 | else |
||
1118 | middle$ = ":" |
||
1119 | endif |
||
1120 | mind = clockSeconds/60 |
||
1121 | hours = mind/60 |
||
1122 | if clockShowSeconds |
||
1123 | secsText$ = middle$+TwoDigit$(mod(clockSeconds,60)) |
||
1124 | else |
||
1125 | secsText$ = "" |
||
1126 | endif |
||
1127 | print "Time: ", TwoDigit$(mod(hours,24)), middle$, TwoDigit$(mod(mind,60)), secsText$ |
||
1128 | return |
||
1129 | |||
1130 | rem Rotate smooth, and rotate in the direction with the lowest distance |
||
1131 | rem "turn object left" ist das kommando |
||
1132 | function smoothRotate#(von#, nach#, smoothness) |
||
1133 | if (von# > 270) and (nach# < 90) |
||
1134 | ret# = WrapValue(von# + (360 - von# + nach#)/smoothness) |
||
1135 | else |
||
1136 | if (von# < 90) and (nach# > 270) |
||
1137 | ret# = WrapValue(von# - (360 - nach# + von#)/smoothness) |
||
1138 | else |
||
1139 | ret# = von# + (nach# - von#)/smoothness |
||
1140 | endif |
||
1141 | endif |
||
1142 | endfunction ret# |
||
1143 | |||
1144 | function floorHeight#(X#, Z#) |
||
1145 | rem TODO: implement water |
||
1146 | ret# = Get Ground Height(MAT_Ground, X#, Z#) |
||
1147 | ENDFUNCTION ret# |
||
1148 | |||
1149 | function upPressed() |
||
1150 | ret = UpKey()=1 or keystate(17)=1 or joystick up()=1 |
||
1151 | ENDFUNCTION ret |
||
1152 | |||
1153 | function leftPressed() |
||
1154 | ret = LeftKey()=1 or keystate(30)=1 or joystick left()=1 |
||
1155 | ENDFUNCTION ret |
||
1156 | |||
1157 | function rightPressed() |
||
1158 | ret = RightKey()=1 or keystate(32)=1 or joystick right()=1 |
||
1159 | ENDFUNCTION ret |
||
1160 | |||
1161 | function downPressed() |
||
1162 | ret = DownKey()=1 or keystate(31)=1 or joystick down()=1 |
||
1163 | ENDFUNCTION ret |
||
1164 | |||
1165 | function jumpPressed() |
||
1166 | ret = keystate(57)=1 or JOYSTICK FIRE A()=1 |
||
1167 | ENDFUNCTION ret |
||
1168 | |||
1169 | function TwoDigit$(value) |
||
1170 | if value < 10 |
||
1171 | ret$ = "0"+STR$(value) |
||
1172 | else |
||
1173 | ret$ = STR$(value) |
||
1174 | ENDIF |
||
1175 | ENDFUNCTION ret$ |
||
1176 | |||
1177 | function mod(num,modulus) |
||
1178 | value=num-((num/modulus)*modulus) |
||
1179 | endfunction value |
||
1180 | |||
1181 | function fileReadInt(fileNum) |
||
1182 | read string 1, s$ |
||
1183 | ret=val(s$) |
||
1184 | ENDFUNCTION ret |
||
1185 | |||
1186 | function fileReadFloat#(fileNum) |
||
1187 | read string 1, s$ |
||
1188 | ret#=val(s$) |
||
1189 | ENDFUNCTION ret# |
||
1190 | |||
1191 | function RndBetween(a,b) |
||
1192 | ret = a+Rnd(b-a) |
||
1193 | ENDFUNCTION ret |
||
1194 | |||
1195 | function isInCircle(pX#,pY#,cX#,cY#,cR#) |
||
1196 | ret = sqrt( (pX#-cX#)*(pX#-cX#) + (pY#-cY#)*(pY#-cY#) ) <= cR# |
||
1197 | ENDFUNCTION ret |
||
1198 | |||
1199 | _stop_game_sounds: |
||
1200 | Stop Sound SFX_ForestBG |
||
1201 | Stop Sound SFX_PauseMusic |
||
1202 | Stop Sound SFX_Walk_Earth |
||
1203 | Stop Sound SFX_Walk_Water |
||
1204 | for t = 0 to cMaxEnemies-1 |
||
1205 | Stop Sound SFX_Monster_Base+t |
||
1206 | next t |
||
1207 | return |
||
1208 | |||
1209 | type treeType |
||
1210 | x as float |
||
1211 | z as float |
||
1212 | drawn as boolean |
||
1213 | endtype |
||
1214 | |||
1215 | type enemyType |
||
1216 | Speed as float |
||
1217 | WalkTimeout as float |
||
1218 | WalkTimeoutMin as float |
||
1219 | WalkTimeoutMax as float |
||
1220 | AwarenessRadius as float |
||
1221 | CurSpeed as float |
||
1222 | MaxSpeed as float |
||
1223 | Angle as float |
||
1224 | CurrentAnim as float |
||
1225 | endtype |
||
1226 | |||
1227 | PressJumpKey: |
||
1228 | if onGround=1 |
||
1229 | rem TODO: absprungsound |
||
1230 | JumpPosition#=floorHeight#(X#,Z#) |
||
1231 | velocityY# = JumpStartVelocity# |
||
1232 | onGround = 0 |
||
1233 | endif |
||
1234 | return |
||
1235 | |||
1236 | ReleaseJumpKey: |
||
1237 | if velocityY# > MinFallVelocity# |
||
1238 | velocityY# = MinFallVelocity# |
||
1239 | endif |
||
1240 | return |
||
1241 | |||
1242 | JumpUpdate: |
||
1243 | if onGround=0 |
||
1244 | dec velocityY#, gravity# |
||
1245 | inc JumpPosition#, velocityY# |
||
1246 | |||
1247 | rem TODO: man kann sich dann durch die decke glitchen |
||
1248 | curFloorHeight# = floorHeight#(X#,Z#) |
||
1249 | if JumpPosition# < curFloorHeight# |
||
1250 | rem TODO: aufprallsound |
||
1251 | JumpPosition# = curFloorHeight# |
||
1252 | velocityY# = 0.0 |
||
1253 | onGround = 1 |
||
1254 | endif |
||
1255 | endif |
||
1256 | return |
||
1257 | |||
1258 | function resizeImage(image as dword, width as dword, height as dword) |
||
1259 | if DLL EXIST(DLL_Resize32) = 0 |
||
1260 | load dll FN_DLL_Resize32, DLL_Resize32 |
||
1261 | endif |
||
1262 | |||
1263 | make memblock from image MEM_ResizeSrc, image |
||
1264 | size = call dll(DLL_Resize32, "DestSize", get memblock ptr(MEM_ResizeSrc), width, height) |
||
1265 | |||
1266 | make memblock MEM_ResizeDest, size |
||
1267 | |||
1268 | call dll DLL_Resize32, "Resize", get memblock ptr(MEM_ResizeSrc), get memblock ptr(MEM_ResizeDest), width, height |
||
1269 | |||
1270 | |||
1271 | make image from memblock image, MEM_ResizeDest |
||
1272 | |||
1273 | delete memblock MEM_ResizeSrc |
||
1274 | delete memblock MEM_ResizeDest |
||
1275 | |||
1276 | REM delete dll DLL_Resize |
||
1277 | |||
1278 | endfunction |
||
1279 | |||
1280 | function LoadImageFullscreen(imgFN as string, imgID) |
||
1281 | Load Image imgFN, imgID |
||
1282 | width = desktop width() |
||
1283 | height = image height(imgID)*desktop width()/1.0/image width(imgID); |
||
1284 | resizeImage(imgID, width, height) |
||
1285 | ENDFUNCTION |
||
1286 | |||
1287 | _play_attack_sound: |
||
1288 | repeat |
||
1289 | r=RndBetween(0,NumberOfAttackSounds-1) |
||
1290 | UNTIL (r <> LastAttackSound) or (NumberOfAttackSounds = 1) |
||
1291 | LastAttackSound=r |
||
1292 | play sound SFX_Attack_Base+r |
||
1293 | return |
||
1294 | |||
1295 | _setup_blood: |
||
1296 | // Make 100 particle objects |
||
1297 | particleIndex = 0 |
||
1298 | #constant PARTICLEMAX = 500 |
||
1299 | dim particle(PARTICLEMAX) as particleType |
||
1300 | |||
1301 | rem TODO: mehr |
||
1302 | rem http://nobacks.com/blood-splatter-eighty-eight/ |
||
1303 | load image FN_GFX_BLOOD, IMG_BLOOD |
||
1304 | |||
1305 | for i = 0 to PARTICLEMAX-1 |
||
1306 | make object plain OBJ_BloodParticle_Base+i, 2, 2 |
||
1307 | set object ambient OBJ_BloodParticle_Base+i, 0 |
||
1308 | set object collision off OBJ_BloodParticle_Base+i |
||
1309 | |||
1310 | rem color object OBJ_BloodParticle_Base+i, rgb(128, 0, 0) |
||
1311 | texture object OBJ_BloodParticle_Base+i, IMG_BLOOD |
||
1312 | set object cull OBJ_BloodParticle_Base+i, 0 |
||
1313 | set object transparency OBJ_BloodParticle_Base+i, 6 |
||
1314 | |||
1315 | rem TEST |
||
1316 | rem rotate object OBJ_BloodParticle_Base+i, RndBetween(0,359), RndBetween(0,359), RndBetween(0,359) |
||
1317 | |||
1318 | exclude object on OBJ_BloodParticle_Base+i |
||
1319 | next i |
||
1320 | return |
||
1321 | |||
1322 | _handle_blood: |
||
1323 | // Update particles |
||
1324 | for i = 0 to PARTICLEMAX-1 |
||
1325 | UpdateParticle(i) |
||
1326 | next i |
||
1327 | return |
||
1328 | |||
1329 | _splat_blood: |
||
1330 | rem https://forum.thegamecreators.com/thread/160210#msg1886513 , modified |
||
1331 | |||
1332 | rem TODO: sieht einfach nur scheiße aus. außerdem ist der strahl in 2 himmelsrichtungen schmal (seitlich) |
||
1333 | |||
1334 | rem yoff = rnd(SPREAD1_MAX*2)-SPREAD1_MAX; |
||
1335 | |||
1336 | // Activate blood particles around box |
||
1337 | for i = 0 to PARTICLEMAX-1 |
||
1338 | // The angle particles should fly |
||
1339 | a#=camera angle y() |
||
1340 | rem yAng# = a#+rnd(SPREAD2_MAX*2)-SPREAD2_MAX+yoff |
||
1341 | yAng#=a# |
||
1342 | |||
1343 | // Calculate directions |
||
1344 | xSpeed# = sin(yAng#) |
||
1345 | zSpeed# = cos(yAng#) |
||
1346 | |||
1347 | // Calculate speeds |
||
1348 | xSpeed# = xSpeed# * (rnd(20)/5.0) |
||
1349 | ySpeed# = ((rnd(20)-rnd(20))/10.0) |
||
1350 | zSpeed# = zSpeed# * (rnd(20)/5.0) |
||
1351 | // Activate particle |
||
1352 | |||
1353 | x# = camera position x() |
||
1354 | y# = camera position y() |
||
1355 | z# = camera position z() |
||
1356 | |||
1357 | life = 30+rnd(30) |
||
1358 | |||
1359 | particleIndex = ActivateParticle(particleIndex, life, x#, y#, z#, xSpeed#, ySpeed#, zSpeed#) |
||
1360 | next i |
||
1361 | return |
||
1362 | |||
1363 | // Activate the specified particle and give it an initial position/velocity |
||
1364 | function ActivateParticle(i, life, x#, y#, z#, xSpeed#, ySpeed#, zSpeed#) |
||
1365 | // Cycle through the particle objects to use |
||
1366 | inc i |
||
1367 | if i > PARTICLEMAX-1 then dec i, PARTICLEMAX-1 |
||
1368 | |||
1369 | // Set particle variables |
||
1370 | particle(i).life = life |
||
1371 | particle(i).x = x# |
||
1372 | particle(i).y = y# |
||
1373 | particle(i).z = z# |
||
1374 | particle(i).xSpeed = xSpeed# |
||
1375 | particle(i).ySpeed = ySpeed# |
||
1376 | particle(i).zSpeed = zSpeed# |
||
1377 | |||
1378 | // Show particle object |
||
1379 | exclude object off OBJ_BloodParticle_Base+i |
||
1380 | endfunction i |
||
1381 | |||
1382 | // Update positioning for specified particle |
||
1383 | function UpdateParticle(i) |
||
1384 | // Only update particles that are alive |
||
1385 | if particle(i).life > 0 |
||
1386 | // Apply gravity |
||
1387 | rem dec particle(i).ySpeed, 0.098 |
||
1388 | dec particle(i).ySpeed, 0.200 |
||
1389 | |||
1390 | // Move the particle |
||
1391 | inc particle(i).x, particle(i).xSpeed |
||
1392 | inc particle(i).y, particle(i).ySpeed |
||
1393 | inc particle(i).z, particle(i).zSpeed |
||
1394 | |||
1395 | // Position particle |
||
1396 | position object OBJ_BloodParticle_Base+i, particle(i).x, particle(i).y, particle(i).z |
||
1397 | rem point object OBJ_BloodParticle_Base+i, camera position x(), camera position y(), camera position z() |
||
1398 | |||
1399 | |||
1400 | |||
1401 | // Lower particle's life |
||
1402 | dec particle(i).life |
||
1403 | |||
1404 | // Hide particles when they die |
||
1405 | if particle(i).life <= 0 |
||
1406 | exclude object on OBJ_BloodParticle_Base+i |
||
1407 | endif |
||
1408 | endif |
||
1409 | endfunction |
||
1410 | |||
1411 | // Data type used by particles |
||
1412 | type particleType |
||
1413 | life as integer // Remaining life of particle (0=Dead) |
||
1414 | x as float // Position |
||
1415 | y as float // ... |
||
1416 | z as float // ... |
||
1417 | xSpeed as float // Velocity |
||
1418 | ySpeed as float // ... |
||
1419 | zSpeed as float // ... |
||
1420 | endtype |
||
1421 | |||
1422 | rem -- MUST STAY AT THE END OF THE PROGRAM -- |
||
1423 | _exit: |
||
1424 | exit |