Subversion Repositories forest

Rev

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