1 (* Copyright (C) DooM 2D:Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 {$INCLUDE ../shared/a_modes.inc}
17 {.$DEFINE HAS_COLLIDE_BITMAP}
39 MARK_BLOCKED
= MARK_WALL
+ MARK_DOOR
;
40 MARK_LIQUID
= MARK_WATER
+ MARK_ACID
;
41 MARK_LIFT
= MARK_LIFTDOWN
+ MARK_LIFTUP
+ MARK_LIFTLEFT
+ MARK_LIFTRIGHT
;
43 procedure g_GFX_Init();
44 procedure g_GFX_Free();
46 procedure g_GFX_Blood(fX
, fY
: Integer; Count
: Word; vx
, vy
: Integer;
47 DevX
, DevY
: Word; CR
, CG
, CB
: Byte; Kind
: Byte = BLOOD_NORMAL
);
48 procedure g_GFX_Spark(fX
, fY
: Integer; Count
: Word; Angle
: SmallInt; DevX
, DevY
: Byte);
49 procedure g_GFX_Water(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DevX
, DevY
, Color
: Byte);
50 procedure g_GFX_SimpleWater(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DefColor
, CR
, CG
, CB
: Byte);
51 procedure g_GFX_Bubbles(fX
, fY
: Integer; Count
: Word; DevX
, DevY
: Byte);
52 procedure g_GFX_SetMax(Count
: Integer);
53 function g_GFX_GetMax(): Integer;
55 procedure g_GFX_OnceAnim(X
, Y
: Integer; Anim
: TAnimation
; AnimType
: Byte = 0);
57 procedure g_Mark(x
, y
, Width
, Height
: Integer; t
: Byte; st
: Boolean);
59 procedure g_GFX_Update();
60 procedure g_GFX_Draw();
63 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
65 gCollideMap
: Array of Array of Byte;
72 g_map
, g_basic
, Math
, e_graphics
, GL
, GLExt
,
73 g_options
, g_console
, SysUtils
, g_triggers
, MAPDEF
,
74 g_game
, g_language
, g_net
;
80 AccelX
, AccelY
: Single;
81 Red
, Green
, Blue
: Byte;
86 offsetX
, offsetY
: ShortInt;
92 Animation
: TAnimation
;
105 Particles
: Array of TParticle
;
106 OnceAnims
: Array of TOnceAnim
;
107 MaxParticles
: Integer;
108 CurrentParticle
: Integer;
110 procedure g_Mark(x
, y
, Width
, Height
: Integer; t
: Byte; st
: Boolean);
111 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
113 yy
, y2
, xx
, x2
: Integer;
116 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
128 Height
:= Height
+ y
;
135 if x
> gMapInfo
.Width
then
137 if y
> gMapInfo
.Height
then
140 y2
:= y
+ Height
- 1;
141 if y2
> gMapInfo
.Height
then
142 y2
:= gMapInfo
.Height
;
145 if x2
> gMapInfo
.Width
then
146 x2
:= gMapInfo
.Width
;
149 begin // Óñòàíîâèòü ïðèçíàê
152 gCollideMap
[yy
][xx
] := gCollideMap
[yy
][xx
] or t
;
155 begin // Óáðàòü ïðèçíàê
159 gCollideMap
[yy
][xx
] := gCollideMap
[yy
][xx
] and t
;
164 procedure CreateCollideMap();
165 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
170 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
171 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 1/6', 0, False);
172 SetLength(gCollideMap
, gMapInfo
.Height
+1);
173 for a
:= 0 to High(gCollideMap
) do
174 SetLength(gCollideMap
[a
], gMapInfo
.Width
+1);
176 if gWater
<> nil then
178 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 2/6', 0, True);
179 for a
:= 0 to High(gWater
) do
181 g_Mark(X
, Y
, Width
, Height
, MARK_WATER
, True);
184 if gAcid1
<> nil then
186 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 3/6', 0, True);
187 for a
:= 0 to High(gAcid1
) do
189 g_Mark(X
, Y
, Width
, Height
, MARK_ACID
, True);
192 if gAcid2
<> nil then
194 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 4/6', 0, True);
195 for a
:= 0 to High(gAcid2
) do
197 g_Mark(X
, Y
, Width
, Height
, MARK_ACID
, True);
200 if gLifts
<> nil then
202 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 5/6', 0, True);
203 for a
:= 0 to High(gLifts
) do
206 g_Mark(X
, Y
, Width
, Height
, MARK_LIFT
, False);
209 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTUP
, True)
210 else if LiftType
= 1 then
211 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTDOWN
, True)
212 else if LiftType
= 2 then
213 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTLEFT
, True)
214 else if LiftType
= 3 then
215 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTRIGHT
, True)
219 if gWalls
<> nil then
221 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 6/6', 0, True);
222 for a
:= 0 to High(gWalls
) do
224 if gWalls
[a
].Door
then
227 if gWalls
[a
].Enabled
then
229 g_Mark(X
, Y
, Width
, Height
, MARK_DOOR
, True)
230 else // Îòêðûòàÿ äâåðü:
231 if gWalls
[a
].Enabled
then
233 g_Mark(X
, Y
, Width
, Height
, MARK_DOOR
, False);
237 g_Mark(X
, Y
, Width
, Height
, MARK_WALL
, True);
243 procedure g_GFX_Init();
248 procedure g_GFX_Free();
253 SetLength(Particles
, MaxParticles
);
254 CurrentParticle
:= 0;
256 if OnceAnims
<> nil then
258 for a
:= 0 to High(OnceAnims
) do
259 OnceAnims
[a
].Animation
.Free();
264 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
270 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
271 procedure CorrectOffsets(id
: Integer);
273 with Particles
[id
] do
275 if (X
>= 0) and (Y
> 0) and
276 (Y
< Length(gCollideMap
)) and (X
< Length(gCollideMap
[0])) and
277 (ByteBool(gCollideMap
[Y
-1, X
] and MARK_BLOCKED
)) then
278 offsetY
:= 1 // Ñòåíà ñâåðõó
282 if (X
> 0) and (Y
>= 0) and
283 (Y
< Length(gCollideMap
)) and (X
< Length(gCollideMap
[0])) and
284 (ByteBool(gCollideMap
[Y
, X
-1] and MARK_BLOCKED
)) then
285 offsetX
:= 1 // Ñòåíà ñëåâà
293 procedure g_GFX_SparkVel(fX
, fY
: Integer; Count
: Word; VX
, VY
: Integer; DevX
, DevY
: Byte);
294 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
302 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
303 l
:= Length(Particles
);
314 for a
:= 1 to Count
do
316 with Particles
[CurrentParticle
] do
318 X
:= fX
-DevX1
+Random(DevX2
);
319 Y
:= fY
-DevY1
+Random(DevY2
);
321 VelX
:= VX
+ (Random
-Random
)*3;
322 VelY
:= VY
+ (Random
-Random
)*3;
330 AccelX
:= -Sign(VelX
)*Random
/100;
334 Green
:= 100+Random(155);
338 State
:= STATE_NORMAL
;
340 LiveTime
:= 30+Random(60);
341 ParticleType
:= PARTICLE_SPARK
;
343 CorrectOffsets(CurrentParticle
);
346 if CurrentParticle
+2 > MaxParticles
then
349 CurrentParticle
:= CurrentParticle
+1;
354 procedure g_GFX_Blood(fX
, fY
: Integer; Count
: Word; vx
, vy
: Integer;
355 DevX
, DevY
: Word; CR
, CG
, CB
: Byte; Kind
: Byte = BLOOD_NORMAL
);
356 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
366 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
367 if Kind
= BLOOD_SPARKS
then
369 g_GFX_SparkVel(fX
, fY
, 2 + Random(2), -VX
div 2, -VY
div 2, DevX
, DevY
);
372 l
:= Length(Particles
);
383 for a
:= 1 to Count
do
385 with Particles
[CurrentParticle
] do
387 X
:= fX
- DevX1
+ Random(DevX2
);
388 Y
:= fY
- DevY1
+ Random(DevY2
);
390 if (X
< 0) or (X
> gMapInfo
.Width
-1) or
391 (Y
< 0) or (Y
> gMapInfo
.Height
-1) or
392 ByteBool(gCollideMap
[Y
, X
] and MARK_WALL
) then
395 VelX
:= vx
+ (Random
-Random
)*3;
396 VelY
:= vy
+ (Random
-Random
)*3;
404 AccelX
:= -Sign(VelX
)*Random
/100;
407 CRnd
:= 20*Random(6);
410 CC
:= CR
+ CRnd
- 50;
411 if CC
< 0 then CC
:= 0;
412 if CC
> 255 then CC
:= 255;
418 CC
:= CG
+ CRnd
- 50;
419 if CC
< 0 then CC
:= 0;
420 if CC
> 255 then CC
:= 255;
426 CC
:= CB
+ CRnd
- 50;
427 if CC
< 0 then CC
:= 0;
428 if CC
> 255 then CC
:= 255;
435 State
:= STATE_NORMAL
;
437 LiveTime
:= 120+Random(40);
438 ParticleType
:= PARTICLE_BLOOD
;
440 CorrectOffsets(CurrentParticle
);
443 if CurrentParticle
>= MaxParticles
-1 then
446 CurrentParticle
:= CurrentParticle
+1;
451 procedure g_GFX_Spark(fX
, fY
: Integer; Count
: Word; Angle
: SmallInt; DevX
, DevY
: Byte);
452 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
458 BaseVelX
, BaseVelY
: Single;
462 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
463 l
:= Length(Particles
);
469 Angle
:= 360 - Angle
;
476 b
:= DegToRad(Angle
);
478 BaseVelY
:= 1.6*sin(b
);
479 if Abs(BaseVelX
) < 0.01 then
481 if Abs(BaseVelY
) < 0.01 then
483 for a
:= 1 to Count
do
485 with Particles
[CurrentParticle
] do
487 X
:= fX
-DevX1
+Random(DevX2
);
488 Y
:= fY
-DevY1
+Random(DevY2
);
490 VelX
:= BaseVelX
*Random
;
491 VelY
:= BaseVelY
-Random
;
496 Green
:= 100+Random(155);
500 State
:= STATE_NORMAL
;
502 LiveTime
:= 30+Random(60);
503 ParticleType
:= PARTICLE_SPARK
;
505 CorrectOffsets(CurrentParticle
);
508 if CurrentParticle
+2 > MaxParticles
then
511 CurrentParticle
:= CurrentParticle
+1;
516 procedure g_GFX_Water(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DevX
, DevY
, Color
: Byte);
517 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
525 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
526 l
:= Length(Particles
);
532 if Abs(fVelX
) < 3.0 then
533 fVelX
:= 3.0 - 6.0*Random
;
540 for a
:= 1 to Count
do
542 with Particles
[CurrentParticle
] do
544 X
:= fX
-DevX1
+Random(DevX2
);
545 Y
:= fY
-DevY1
+Random(DevY2
);
547 if Abs(fVelX
) < 0.5 then
548 VelX
:= 1.0 - 2.0*Random
550 VelX
:= fVelX
*Random
;
551 if Random(10) < 7 then
553 VelY
:= fVelY
*Random
;
560 Red
:= 155 + Random(9)*10;
561 Green
:= Trunc(150*Random
);
566 Red
:= Trunc(150*Random
);
567 Green
:= 175 + Random(9)*10;
572 Red
:= Trunc(200*Random
);
574 Blue
:= 175 + Random(9)*10;
578 Red
:= 90 + Random(12)*10;
586 State
:= STATE_NORMAL
;
588 LiveTime
:= 60+Random(60);
589 ParticleType
:= PARTICLE_WATER
;
591 CorrectOffsets(CurrentParticle
);
594 if CurrentParticle
+2 > MaxParticles
then
597 CurrentParticle
:= CurrentParticle
+1;
602 procedure g_GFX_SimpleWater(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DefColor
, CR
, CG
, CB
: Byte);
603 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
609 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
610 l
:= Length(Particles
);
616 for a
:= 1 to Count
do
618 with Particles
[CurrentParticle
] do
631 Red
:= 155 + Random(9)*10;
632 Green
:= Trunc(150*Random
);
637 Red
:= Trunc(150*Random
);
638 Green
:= 175 + Random(9)*10;
643 Red
:= Trunc(200*Random
);
645 Blue
:= 175 + Random(9)*10;
647 4: // Ñâîé öâåò, ñâåòëåå
649 Red
:= 20 + Random(19)*10;
652 Red
:= Min(Red
+ CR
, 255);
653 Green
:= Min(Green
+ CG
, 255);
654 Blue
:= Min(Blue
+ CB
, 255);
656 5: // Ñâîé öâåò, òåìíåå
658 Red
:= 20 + Random(19)*10;
661 Red
:= Max(CR
- Red
, 0);
662 Green
:= Max(CG
- Green
, 0);
663 Blue
:= Max(CB
- Blue
, 0);
667 Red
:= 90 + Random(12)*10;
675 State
:= STATE_NORMAL
;
677 LiveTime
:= 60+Random(60);
678 ParticleType
:= PARTICLE_WATER
;
680 CorrectOffsets(CurrentParticle
);
683 if CurrentParticle
+2 > MaxParticles
then
686 CurrentParticle
:= CurrentParticle
+1;
691 procedure g_GFX_Bubbles(fX
, fY
: Integer; Count
: Word; DevX
, DevY
: Byte);
692 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
700 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
701 l
:= Length(Particles
);
712 for a
:= 1 to Count
do
714 with Particles
[CurrentParticle
] do
716 X
:= fX
-DevX1
+Random(DevX2
);
717 Y
:= fY
-DevY1
+Random(DevY2
);
719 if (X
>= gMapInfo
.Width
) or (X
<= 0) or
720 (Y
>= gMapInfo
.Height
) or (Y
<= 0) then
723 if not ByteBool(gCollideMap
[Y
, X
] and MARK_LIQUID
) then
736 State
:= STATE_NORMAL
;
739 ParticleType
:= PARTICLE_BUBBLES
;
741 CorrectOffsets(CurrentParticle
);
744 if CurrentParticle
+2 > MaxParticles
then
747 CurrentParticle
:= CurrentParticle
+1;
752 procedure g_GFX_SetMax(Count
: Integer);
754 if Count
> 50000 then
757 SetLength(Particles
, Count
);
758 MaxParticles
:= Count
;
759 if CurrentParticle
>= Count
then
760 CurrentParticle
:= 0;
763 function g_GFX_GetMax(): Integer;
765 Result
:= MaxParticles
;
768 function FindOnceAnim
: DWORD
;
772 if OnceAnims
<> nil then
773 for i
:= 0 to High(OnceAnims
) do
774 if OnceAnims
[i
].Animation
= nil then
780 if OnceAnims
= nil then
782 SetLength(OnceAnims
, 16);
787 Result
:= High(OnceAnims
) + 1;
788 SetLength(OnceAnims
, Length(OnceAnims
) + 16);
792 procedure g_GFX_OnceAnim(X
, Y
: Integer; Anim
: TAnimation
; AnimType
: Byte = 0);
799 find_id
:= FindOnceAnim();
801 OnceAnims
[find_id
].AnimType
:= AnimType
;
802 OnceAnims
[find_id
].Animation
:= TAnimation
.Create(Anim
.FramesID
, Anim
.Loop
, Anim
.Speed
);
803 OnceAnims
[find_id
].Animation
.Blending
:= Anim
.Blending
;
804 OnceAnims
[find_id
].Animation
.Alpha
:= Anim
.Alpha
;
805 OnceAnims
[find_id
].X
:= X
;
806 OnceAnims
[find_id
].Y
:= Y
;
809 procedure g_GFX_Update();
812 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
820 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
821 if Particles
<> nil then
824 h
:= gMapInfo
.Height
;
826 len
:= High(Particles
);
829 if Particles
[a
].State
<> 0 then
832 if Time
= LiveTime
then
834 if (X
+1 >= w
) or (Y
+1 >= h
) or (X
<= 0) or (Y
<= 0) then
836 if State
= STATE_FREE
then
844 if (State
= STATE_STICK
) then
845 if (not ByteBool(gCollideMap
[Y
-1, X
] and MARK_BLOCKED
)) and
846 (not ByteBool(gCollideMap
[Y
+1, X
] and MARK_BLOCKED
)) and
847 (not ByteBool(gCollideMap
[Y
, X
-1] and MARK_BLOCKED
)) and
848 (not ByteBool(gCollideMap
[Y
, X
+1] and MARK_BLOCKED
)) then
849 begin // Îòëèïëà - êàïàåò
852 State
:= STATE_NORMAL
;
855 if Random(200) = 100 then
856 begin // Ïðèëåïëåíà - íî âîçìîæíî ñòåêàåò
862 if not ByteBool(gCollideMap
[Y
, X
] and MARK_BLOCKED
) then
864 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIFTUP
) then
866 if VelY
> -4-Random(3) then
868 if Abs(VelX
) > 0.1 then
869 VelX
:= VelX
- VelX
/10.0;
870 VelX
:= VelX
+ (Random
-Random
)*0.2;
873 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIFTLEFT
) then
875 if VelX
> -8-Random(3) then
879 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIFTRIGHT
) then
880 begin // Ïîòîê âïðàâî
881 if VelX
< 8+Random(3) then
890 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) then
891 if (State
<> STATE_STICK
) and
892 (not ByteBool(gCollideMap
[Y
-1, X
] and MARK_BLOCKED
)) and
893 (not ByteBool(gCollideMap
[Y
, X
] and MARK_BLOCKED
)) and
894 (not ByteBool(gCollideMap
[Y
+1, X
] and MARK_BLOCKED
)) then
895 begin // Âèñèò â âîçäóõå - êàïàåò
898 State
:= STATE_NORMAL
;
912 if (X
+s
>= w
) or (X
+s
<= 0) then
918 c
:= gCollideMap
[Y
, X
+s
];
920 if ByteBool(c
and MARK_BLOCKED
) then
926 State
:= STATE_STICK
;
945 if (Y
+s
>= h
) or (Y
+s
<= 0) then
951 c
:= gCollideMap
[Y
+s
, X
];
953 if ByteBool(c
and MARK_BLOCKED
) then
959 if (s
> 0) and (State
<> STATE_STICK
) then
960 State
:= STATE_NORMAL
962 State
:= STATE_STICK
;
975 if (X
+dX
>= w
) or (Y
+dY
>= h
) or
976 (X
+dX
<= 0) or (Y
+dY
<= 0) or
977 ByteBool(gCollideMap
[Y
+dY
, X
+dX
] and MARK_BLOCKED
) then
978 begin // Ñòåíà/äâåðü/ãðàíèöà
990 VelX
:= VelX
+ AccelX
;
991 VelY
:= VelY
+ AccelY
;
993 // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè:
994 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIQUID
) then
998 Alpha
:= 255 - Trunc((255.0 * Time
) / LiveTime
);
1007 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) and
1008 (not ByteBool(gCollideMap
[Y
-1, X
] and MARK_BLOCKED
)) and
1009 (not ByteBool(gCollideMap
[Y
, X
] and MARK_BLOCKED
)) and
1010 (not ByteBool(gCollideMap
[Y
+1, X
] and MARK_BLOCKED
)) then
1011 begin // Âèñèò â âîçäóõå
1027 if (X
+s
>= w
) or (X
+s
<= 0) then
1029 State
:= STATE_FREE
;
1033 c
:= gCollideMap
[Y
, X
+s
];
1035 if ByteBool(c
and MARK_BLOCKED
) then
1036 begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî
1042 if c
= MARK_FREE
then
1046 State
:= STATE_FREE
;
1063 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1065 State
:= STATE_FREE
;
1069 c
:= gCollideMap
[Y
+s
, X
];
1071 if ByteBool(c
and MARK_BLOCKED
) then
1072 begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî
1076 AccelY
:= Abs(AccelY
);
1078 else // Èëè íå ïàäàåò
1089 if c
= MARK_FREE
then
1093 State
:= STATE_FREE
;
1100 VelX
:= VelX
+ AccelX
;
1104 AccelY
:= AccelY
+ 0.08;
1105 VelY
:= VelY
+ AccelY
;
1113 if (State
= STATE_STICK
) and (Random(30) = 15) then
1114 begin // Ñòåêàåò/îòëèïàåò
1117 if (not ByteBool(gCollideMap
[Y
, X
-1] and MARK_BLOCKED
)) and
1118 (not ByteBool(gCollideMap
[Y
, X
+1] and MARK_BLOCKED
)) then
1119 State
:= STATE_NORMAL
;
1123 if not ByteBool(gCollideMap
[Y
, X
] and MARK_BLOCKED
) then
1125 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIFTUP
) then
1127 if VelY
> -4-Random(3) then
1129 if Abs(VelX
) > 0.1 then
1130 VelX
:= VelX
- VelX
/10.0;
1131 VelX
:= VelX
+ (Random
-Random
)*0.2;
1134 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIFTLEFT
) then
1135 begin // Ïîòîê âëåâî
1136 if VelX
> -8-Random(3) then
1140 if ByteBool(gCollideMap
[Y
, X
] and MARK_LIFTRIGHT
) then
1141 begin // Ïîòîê âïðàâî
1142 if VelX
< 8+Random(3) then
1151 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) then
1152 if (State
<> STATE_STICK
) and
1153 (not ByteBool(gCollideMap
[Y
-1, X
] and MARK_BLOCKED
)) and
1154 (not ByteBool(gCollideMap
[Y
, X
] and MARK_BLOCKED
)) and
1155 (not ByteBool(gCollideMap
[Y
+1, X
] and MARK_BLOCKED
)) then
1156 begin // Âèñèò â âîçäóõå - êàïàåò
1159 State
:= STATE_NORMAL
;
1169 for b
:= 1 to Abs(dX
) do
1171 if (X
+s
>= w
) or (X
+s
<= 0) then
1172 begin // Ñáîêó ãðàíèöà
1173 State
:= STATE_FREE
;
1177 c
:= gCollideMap
[Y
, X
+s
];
1179 if ByteBool(c
and MARK_LIQUID
) and (dY
> 0) then
1180 begin // Ñáîêó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
1181 State
:= STATE_FREE
;
1185 if ByteBool(c
and MARK_BLOCKED
) then
1186 begin // Ñòåíà/äâåðü
1191 State
:= STATE_STICK
;
1206 for b
:= 1 to Abs(dY
) do
1208 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1209 begin // Ñíèçó/ñâåðõó ãðàíèöà
1210 State
:= STATE_FREE
;
1214 c
:= gCollideMap
[Y
+s
, X
];
1216 if ByteBool(c
and MARK_LIQUID
) and (dY
> 0) then
1217 begin // Ñíèçó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
1218 State
:= STATE_FREE
;
1222 if ByteBool(c
and MARK_BLOCKED
) then
1223 begin // Ñòåíà/äâåðü
1228 if (s
> 0) and (State
<> STATE_STICK
) then
1229 State
:= STATE_NORMAL
1231 State
:= STATE_STICK
;
1239 VelX
:= VelX
+ AccelX
;
1240 VelY
:= VelY
+ AccelY
;
1256 for b
:= 1 to Abs(dY
) do
1258 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1260 State
:= STATE_FREE
;
1264 if not ByteBool(gCollideMap
[Y
+s
, X
] and MARK_LIQUID
) then
1265 begin // Óæå íå æèäêîñòü
1266 State
:= STATE_FREE
;
1275 VelY
:= VelY
+ AccelY
;
1283 end; // Particles <> nil
1286 if OnceAnims
<> nil then
1288 for a
:= 0 to High(OnceAnims
) do
1289 if OnceAnims
[a
].Animation
<> nil then
1291 case OnceAnims
[a
].AnimType
of
1294 if Random(3) = 0 then
1295 OnceAnims
[a
].X
:= OnceAnims
[a
].X
-1+Random(3);
1296 if Random(2) = 0 then
1297 OnceAnims
[a
].Y
:= OnceAnims
[a
].Y
-Random(2);
1301 if OnceAnims
[a
].Animation
.Played
then
1303 OnceAnims
[a
].Animation
.Free();
1304 OnceAnims
[a
].Animation
:= nil;
1307 OnceAnims
[a
].Animation
.Update();
1312 procedure g_GFX_Draw();
1316 if Particles
<> nil then
1318 glDisable(GL_TEXTURE_2D
);
1322 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1326 len
:= High(Particles
);
1328 for a
:= 0 to len
do
1329 with Particles
[a
] do
1330 if (State
<> STATE_FREE
) and (X
>= sX
) and (Y
>= sY
) and
1331 (X
<= sX
+sWidth
) and (sY
<= sY
+sHeight
) then
1333 glColor4ub(Red
, Green
, Blue
, Alpha
);
1334 glVertex2i(X
+ offsetX
, Y
+ offsetY
);
1339 glDisable(GL_BLEND
);
1342 if OnceAnims
<> nil then
1343 for a
:= 0 to High(OnceAnims
) do
1344 if OnceAnims
[a
].Animation
<> nil then
1345 with OnceAnims
[a
] do
1346 Animation
.Draw(X
, Y
, M_NONE
);