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}
38 MARK_BLOCKED
= MARK_WALL
+ MARK_DOOR
;
39 MARK_LIQUID
= MARK_WATER
+ MARK_ACID
;
40 MARK_LIFT
= MARK_LIFTDOWN
+ MARK_LIFTUP
+ MARK_LIFTLEFT
+ MARK_LIFTRIGHT
;
42 procedure g_GFX_Init();
43 procedure g_GFX_Free();
45 procedure g_GFX_Blood(fX
, fY
: Integer; Count
: Word; vx
, vy
: Integer;
46 DevX
, DevY
: Word; CR
, CG
, CB
: Byte; Kind
: Byte = BLOOD_NORMAL
);
47 procedure g_GFX_Spark(fX
, fY
: Integer; Count
: Word; Angle
: SmallInt; DevX
, DevY
: Byte);
48 procedure g_GFX_Water(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DevX
, DevY
, Color
: Byte);
49 procedure g_GFX_SimpleWater(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DefColor
, CR
, CG
, CB
: Byte);
50 procedure g_GFX_Bubbles(fX
, fY
: Integer; Count
: Word; DevX
, DevY
: Byte);
51 procedure g_GFX_SetMax(Count
: Integer);
52 function g_GFX_GetMax(): Integer;
54 procedure g_GFX_OnceAnim(X
, Y
: Integer; Anim
: TAnimation
; AnimType
: Byte = 0);
56 procedure g_Mark(x
, y
, Width
, Height
: Integer; t
: Byte; st
: Boolean);
58 procedure g_GFX_Update();
59 procedure g_GFX_Draw();
63 gpart_dbg_enabled
: Boolean = true;
64 gpart_dbg_phys_enabled
: Boolean = true;
70 g_map
, g_basic
, Math
, e_graphics
, GL
, GLExt
,
71 g_options
, g_console
, SysUtils
, g_triggers
, MAPDEF
,
72 g_game
, g_language
, g_net
;
75 PParticle
= ^TParticle
;
79 AccelX
, AccelY
: Single;
80 Red
, Green
, Blue
: Byte;
85 offsetX
, offsetY
: ShortInt;
91 Animation
: TAnimation
;
104 Particles
: array of TParticle
;
105 OnceAnims
: array of TOnceAnim
;
106 MaxParticles
: Integer;
107 CurrentParticle
: Integer;
110 function isBlockedAt (x
, y
: Integer): Boolean; inline;
112 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
113 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, (PANEL_WALL
or PANEL_CLOSEDOOR
or PANEL_STEP
));
117 function isWallAt (x
, y
: Integer): Boolean; inline;
119 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
120 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, (PANEL_WALL
or PANEL_STEP
));
123 function isLiftUpAt (x
, y
: Integer): Boolean; inline;
125 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
126 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, PANEL_LIFTUP
);
129 function isLiftDownAt (x
, y
: Integer): Boolean; inline;
131 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
132 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, PANEL_LIFTDOWN
);
135 function isLiftLeftAt (x
, y
: Integer): Boolean; inline;
137 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
138 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, PANEL_LIFTLEFT
);
141 function isLiftRightAt (x
, y
: Integer): Boolean; inline;
143 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
144 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, PANEL_LIFTRIGHT
);
147 function isLiquidAt (x
, y
: Integer): Boolean; inline;
149 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
150 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, (PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
));
153 function isAnythingAt (x
, y
: Integer): Boolean; inline;
155 if not gpart_dbg_phys_enabled
then begin result
:= false; exit
; end;
156 result
:= g_Map_HasAnyPanelAtPoint(x
, y
, (PANEL_WALL
or PANEL_CLOSEDOOR
or PANEL_OPENDOOR
or PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
or PANEL_STEP
or PANEL_LIFTUP
or PANEL_LIFTDOWN
or PANEL_LIFTLEFT
or PANEL_LIFTRIGHT
));
160 procedure g_Mark(x
, y
, Width
, Height
: Integer; t
: Byte; st
: Boolean);
161 {$IF not DEFINED(HAS_COLLIDE_BITMAP)}
166 yy
, y2
, xx
, x2
: Integer;
179 Height
:= Height
+ y
;
186 if x
> gMapInfo
.Width
then
188 if y
> gMapInfo
.Height
then
191 y2
:= y
+ Height
- 1;
192 if y2
> gMapInfo
.Height
then
193 y2
:= gMapInfo
.Height
;
196 if x2
> gMapInfo
.Width
then
197 x2
:= gMapInfo
.Width
;
200 begin // Óñòàíîâèòü ïðèçíàê
203 gCollideMap
[yy
][xx
] := gCollideMap
[yy
][xx
] or t
;
206 begin // Óáðàòü ïðèçíàê
210 gCollideMap
[yy
][xx
] := gCollideMap
[yy
][xx
] and t
;
216 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
217 procedure CreateCollideMap();
221 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 1/6', 0, False);
222 SetLength(gCollideMap
, gMapInfo
.Height
+1);
223 for a
:= 0 to High(gCollideMap
) do
224 SetLength(gCollideMap
[a
], gMapInfo
.Width
+1);
226 if gWater
<> nil then
228 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 2/6', 0, True);
229 for a
:= 0 to High(gWater
) do
231 g_Mark(X
, Y
, Width
, Height
, MARK_WATER
, True);
234 if gAcid1
<> nil then
236 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 3/6', 0, True);
237 for a
:= 0 to High(gAcid1
) do
239 g_Mark(X
, Y
, Width
, Height
, MARK_ACID
, True);
242 if gAcid2
<> nil then
244 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 4/6', 0, True);
245 for a
:= 0 to High(gAcid2
) do
247 g_Mark(X
, Y
, Width
, Height
, MARK_ACID
, True);
250 if gLifts
<> nil then
252 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 5/6', 0, True);
253 for a
:= 0 to High(gLifts
) do
256 g_Mark(X
, Y
, Width
, Height
, MARK_LIFT
, False);
259 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTUP
, True)
260 else if LiftType
= 1 then
261 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTDOWN
, True)
262 else if LiftType
= 2 then
263 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTLEFT
, True)
264 else if LiftType
= 3 then
265 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTRIGHT
, True)
269 if gWalls
<> nil then
271 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 6/6', 0, True);
272 for a
:= 0 to High(gWalls
) do
274 if gWalls
[a
].Door
then
277 if gWalls
[a
].Enabled
then
279 g_Mark(X
, Y
, Width
, Height
, MARK_DOOR
, True)
280 else // Îòêðûòàÿ äâåðü:
281 if gWalls
[a
].Enabled
then
283 g_Mark(X
, Y
, Width
, Height
, MARK_DOOR
, False);
287 g_Mark(X
, Y
, Width
, Height
, MARK_WALL
, True);
294 procedure g_GFX_Init();
296 //CreateCollideMap();
300 procedure g_GFX_Free();
305 SetLength(Particles
, MaxParticles
);
306 for a
:= 0 to High(Particles
) do Particles
[a
].State
:= STATE_FREE
;
307 CurrentParticle
:= 0;
309 if OnceAnims
<> nil then
311 for a
:= 0 to High(OnceAnims
) do
312 OnceAnims
[a
].Animation
.Free();
319 procedure CorrectOffsets(id
: Integer);
323 part
:= @Particles
[id
];
326 // check for upper wall
327 if isBlockedAt(part
.X
, part
.Y
-1) then part
.offsetY
:= 1;
328 // check for left wall
329 if isBlockedAt(part
.X
-1, part
.Y
) then part
.offsetX
:= 1;
333 procedure g_GFX_SparkVel (fX
, fY
: Integer; Count
: Word; VX
, VY
: Integer; DevX
, DevY
: Byte);
340 l
:= Length(Particles
);
342 if Count
> l
then Count
:= l
;
349 for a
:= 1 to Count
do
351 with Particles
[CurrentParticle
] do
353 X
:= fX
-DevX1
+Random(DevX2
);
354 Y
:= fY
-DevY1
+Random(DevY2
);
356 VelX
:= VX
+ (Random
-Random
)*3;
357 VelY
:= VY
+ (Random
-Random
)*3;
365 AccelX
:= -Sign(VelX
)*Random
/100;
369 Green
:= 100+Random(155);
373 State
:= STATE_NORMAL
;
375 LiveTime
:= 30+Random(60);
376 ParticleType
:= PARTICLE_SPARK
;
378 CorrectOffsets(CurrentParticle
);
381 if CurrentParticle
+2 > MaxParticles
then
384 CurrentParticle
:= CurrentParticle
+1;
389 procedure g_GFX_Blood(fX
, fY
: Integer; Count
: Word; vx
, vy
: Integer;
390 DevX
, DevY
: Word; CR
, CG
, CB
: Byte; Kind
: Byte = BLOOD_NORMAL
);
399 if Kind
= BLOOD_SPARKS
then
401 g_GFX_SparkVel(fX
, fY
, 2 + Random(2), -VX
div 2, -VY
div 2, DevX
, DevY
);
404 l
:= Length(Particles
);
415 for a
:= 1 to Count
do
417 with Particles
[CurrentParticle
] do
419 X
:= fX
- DevX1
+ Random(DevX2
);
420 Y
:= fY
- DevY1
+ Random(DevY2
);
423 if (X < 0) or (X > gMapInfo.Width-1) or
424 (Y < 0) or (Y > gMapInfo.Height-1) or
425 ByteBool(gCollideMap[Y, X] and MARK_WALL) then
428 if isWallAt(X
, Y
) then continue
;
430 VelX
:= vx
+ (Random
-Random
)*3;
431 VelY
:= vy
+ (Random
-Random
)*3;
439 AccelX
:= -Sign(VelX
)*Random
/100;
442 CRnd
:= 20*Random(6);
445 CC
:= CR
+ CRnd
- 50;
446 if CC
< 0 then CC
:= 0;
447 if CC
> 255 then CC
:= 255;
453 CC
:= CG
+ CRnd
- 50;
454 if CC
< 0 then CC
:= 0;
455 if CC
> 255 then CC
:= 255;
461 CC
:= CB
+ CRnd
- 50;
462 if CC
< 0 then CC
:= 0;
463 if CC
> 255 then CC
:= 255;
470 State
:= STATE_NORMAL
;
472 LiveTime
:= 120+Random(40);
473 ParticleType
:= PARTICLE_BLOOD
;
475 CorrectOffsets(CurrentParticle
);
478 if CurrentParticle
>= MaxParticles
-1 then
481 CurrentParticle
:= CurrentParticle
+1;
486 procedure g_GFX_Spark(fX
, fY
: Integer; Count
: Word; Angle
: SmallInt; DevX
, DevY
: Byte);
492 BaseVelX
, BaseVelY
: Single;
495 l
:= Length(Particles
);
501 Angle
:= 360 - Angle
;
508 b
:= DegToRad(Angle
);
510 BaseVelY
:= 1.6*sin(b
);
511 if Abs(BaseVelX
) < 0.01 then
513 if Abs(BaseVelY
) < 0.01 then
515 for a
:= 1 to Count
do
517 with Particles
[CurrentParticle
] do
519 X
:= fX
-DevX1
+Random(DevX2
);
520 Y
:= fY
-DevY1
+Random(DevY2
);
522 VelX
:= BaseVelX
*Random
;
523 VelY
:= BaseVelY
-Random
;
528 Green
:= 100+Random(155);
532 State
:= STATE_NORMAL
;
534 LiveTime
:= 30+Random(60);
535 ParticleType
:= PARTICLE_SPARK
;
537 CorrectOffsets(CurrentParticle
);
540 if CurrentParticle
+2 > MaxParticles
then
543 CurrentParticle
:= CurrentParticle
+1;
547 procedure g_GFX_Water(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DevX
, DevY
, Color
: Byte);
554 l
:= Length(Particles
);
560 if Abs(fVelX
) < 3.0 then
561 fVelX
:= 3.0 - 6.0*Random
;
568 for a
:= 1 to Count
do
570 with Particles
[CurrentParticle
] do
572 X
:= fX
-DevX1
+Random(DevX2
);
573 Y
:= fY
-DevY1
+Random(DevY2
);
575 if Abs(fVelX
) < 0.5 then
576 VelX
:= 1.0 - 2.0*Random
578 VelX
:= fVelX
*Random
;
579 if Random(10) < 7 then
581 VelY
:= fVelY
*Random
;
588 Red
:= 155 + Random(9)*10;
589 Green
:= Trunc(150*Random
);
594 Red
:= Trunc(150*Random
);
595 Green
:= 175 + Random(9)*10;
600 Red
:= Trunc(200*Random
);
602 Blue
:= 175 + Random(9)*10;
606 Red
:= 90 + Random(12)*10;
614 State
:= STATE_NORMAL
;
616 LiveTime
:= 60+Random(60);
617 ParticleType
:= PARTICLE_WATER
;
619 CorrectOffsets(CurrentParticle
);
622 if CurrentParticle
+2 > MaxParticles
then
625 CurrentParticle
:= CurrentParticle
+1;
629 procedure g_GFX_SimpleWater(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DefColor
, CR
, CG
, CB
: Byte);
634 l
:= Length(Particles
);
640 for a
:= 1 to Count
do
642 with Particles
[CurrentParticle
] do
655 Red
:= 155 + Random(9)*10;
656 Green
:= Trunc(150*Random
);
661 Red
:= Trunc(150*Random
);
662 Green
:= 175 + Random(9)*10;
667 Red
:= Trunc(200*Random
);
669 Blue
:= 175 + Random(9)*10;
671 4: // Ñâîé öâåò, ñâåòëåå
673 Red
:= 20 + Random(19)*10;
676 Red
:= Min(Red
+ CR
, 255);
677 Green
:= Min(Green
+ CG
, 255);
678 Blue
:= Min(Blue
+ CB
, 255);
680 5: // Ñâîé öâåò, òåìíåå
682 Red
:= 20 + Random(19)*10;
685 Red
:= Max(CR
- Red
, 0);
686 Green
:= Max(CG
- Green
, 0);
687 Blue
:= Max(CB
- Blue
, 0);
691 Red
:= 90 + Random(12)*10;
699 State
:= STATE_NORMAL
;
701 LiveTime
:= 60+Random(60);
702 ParticleType
:= PARTICLE_WATER
;
704 CorrectOffsets(CurrentParticle
);
707 if CurrentParticle
+2 > MaxParticles
then
710 CurrentParticle
:= CurrentParticle
+1;
714 procedure g_GFX_Bubbles(fX
, fY
: Integer; Count
: Word; DevX
, DevY
: Byte);
721 l
:= Length(Particles
);
732 for a
:= 1 to Count
do
734 with Particles
[CurrentParticle
] do
736 X
:= fX
-DevX1
+Random(DevX2
);
737 Y
:= fY
-DevY1
+Random(DevY2
);
739 if (X
>= gMapInfo
.Width
) or (X
<= 0) or
740 (Y
>= gMapInfo
.Height
) or (Y
<= 0) then
743 if not isLiquidAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
756 State
:= STATE_NORMAL
;
759 ParticleType
:= PARTICLE_BUBBLES
;
761 CorrectOffsets(CurrentParticle
);
764 if CurrentParticle
+2 > MaxParticles
then
767 CurrentParticle
:= CurrentParticle
+1;
771 procedure g_GFX_SetMax(Count
: Integer);
775 if Count
> 50000 then Count
:= 50000;
776 if (Count
< 1) then Count
:= 1;
778 SetLength(Particles
, Count
);
779 for a
:= 0 to High(Particles
) do Particles
[a
].State
:= STATE_FREE
;
780 MaxParticles
:= Count
;
781 //if CurrentParticle >= Count then
782 CurrentParticle
:= 0;
785 function g_GFX_GetMax(): Integer;
787 Result
:= MaxParticles
;
790 function FindOnceAnim
: DWORD
;
794 if OnceAnims
<> nil then
795 for i
:= 0 to High(OnceAnims
) do
796 if OnceAnims
[i
].Animation
= nil then
802 if OnceAnims
= nil then
804 SetLength(OnceAnims
, 16);
809 Result
:= High(OnceAnims
) + 1;
810 SetLength(OnceAnims
, Length(OnceAnims
) + 16);
814 procedure g_GFX_OnceAnim(X
, Y
: Integer; Anim
: TAnimation
; AnimType
: Byte = 0);
821 find_id
:= FindOnceAnim();
823 OnceAnims
[find_id
].AnimType
:= AnimType
;
824 OnceAnims
[find_id
].Animation
:= TAnimation
.Create(Anim
.FramesID
, Anim
.Loop
, Anim
.Speed
);
825 OnceAnims
[find_id
].Animation
.Blending
:= Anim
.Blending
;
826 OnceAnims
[find_id
].Animation
.Alpha
:= Anim
.Alpha
;
827 OnceAnims
[find_id
].X
:= X
;
828 OnceAnims
[find_id
].Y
:= Y
;
831 procedure g_GFX_Update();
840 if not gpart_dbg_enabled
then exit
;
841 if Particles
<> nil then
844 h
:= gMapInfo
.Height
;
846 len
:= High(Particles
);
850 if Particles
[a
].State
<> STATE_FREE
then
854 if Time
= LiveTime
then State
:= STATE_FREE
;
855 if (X
+1 >= w
) or (Y
+1 >= h
) or (X
<= 0) or (Y
<= 0) then State
:= STATE_FREE
;
856 if State
= STATE_FREE
then Continue
;
857 //e_WriteLog(Format('particle #%d: %d', [State, ParticleType]), MSG_NOTIFY);
864 if (State
= STATE_STICK
) then
866 if (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and
867 (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) and
868 (not ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) and
869 (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED))
872 if (not isBlockedAt(X
, Y
-1)) and
873 (not isBlockedAt(X
, Y
+1)) and
874 (not isBlockedAt(X
-1, Y
)) and
875 (not isBlockedAt(X
+1, Y
))
877 begin // Îòëèïëà - êàïàåò
880 State
:= STATE_NORMAL
;
883 if Random(200) = 100 then
884 begin // Ïðèëåïëåíà - íî âîçìîæíî ñòåêàåò
890 if not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)} then
892 if isLiftUpAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTUP)} then
894 if VelY
> -4-Random(3) then
896 if Abs(VelX
) > 0.1 then
897 VelX
:= VelX
- VelX
/10.0;
898 VelX
:= VelX
+ (Random
-Random
)*0.2;
901 if isLiftLeftAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT)} then
903 if VelX
> -8-Random(3) then
907 if isLiftRightAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT)} then
908 begin // Ïîòîê âïðàâî
909 if VelX
< 8+Random(3) then
918 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) then
919 if (State
<> STATE_STICK
) and
920 (not isBlockedAt(X
, Y
-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and
921 (not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and
922 (not isBlockedAt(X
, Y
+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then
923 begin // Âèñèò â âîçäóõå - êàïàåò
926 State
:= STATE_NORMAL
;
940 if (X
+s
>= w
) or (X
+s
<= 0) then
946 //c := gCollideMap[Y, X+s];
948 if isBlockedAt(X
+s
, Y
) {ByteBool(c and MARK_BLOCKED)} then
954 State
:= STATE_STICK
;
973 if (Y
+s
>= h
) or (Y
+s
<= 0) then
979 //c := gCollideMap[Y+s, X];
981 if isBlockedAt(X
, Y
+s
) {ByteBool(c and MARK_BLOCKED)} then
987 if (s
> 0) and (State
<> STATE_STICK
) then
988 State
:= STATE_NORMAL
990 State
:= STATE_STICK
;
1003 if (X
+dX
>= w
) or (Y
+dY
>= h
) or
1004 (X
+dX
<= 0) or (Y
+dY
<= 0) or
1005 isBlockedAt(X
+dX
, Y
+dY
) {ByteBool(gCollideMap[Y+dY, X+dX] and MARK_BLOCKED)} then
1006 begin // Ñòåíà/äâåðü/ãðàíèöà
1007 State
:= STATE_FREE
;
1018 VelX
:= VelX
+ AccelX
;
1019 VelY
:= VelY
+ AccelY
;
1021 // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè:
1022 if isLiquidAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
1026 Alpha
:= 255 - Trunc((255.0 * Time
) / LiveTime
);
1035 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) and
1036 (not isBlockedAt(X
, Y
-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and
1037 (not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and
1038 (not isBlockedAt(X
, Y
+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then
1039 begin // Âèñèò â âîçäóõå
1055 if (X
+s
>= w
) or (X
+s
<= 0) then
1057 State
:= STATE_FREE
;
1061 //c := gCollideMap[Y, X+s];
1063 if isBlockedAt(X
+s
, Y
) {ByteBool(c and MARK_BLOCKED)} then
1064 begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî
1070 if not isAnythingAt(X
+s
, Y
) {c = MARK_FREE} then
1074 State
:= STATE_FREE
;
1091 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1093 State
:= STATE_FREE
;
1097 //c := gCollideMap[Y+s, X];
1099 if isBlockedAt(X
, Y
+s
) {ByteBool(c and MARK_BLOCKED)} then
1100 begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî
1104 AccelY
:= Abs(AccelY
);
1106 else // Èëè íå ïàäàåò
1117 if not isAnythingAt(X
, Y
+s
) {c = MARK_FREE} then
1121 State
:= STATE_FREE
;
1128 VelX
:= VelX
+ AccelX
;
1132 AccelY
:= AccelY
+ 0.08;
1133 VelY
:= VelY
+ AccelY
;
1141 if (State
= STATE_STICK
) and (Random(30) = 15) then
1142 begin // Ñòåêàåò/îòëèïàåò
1145 if (not isBlockedAt(X
-1, Y
) {ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)}) and
1146 (not isBlockedAt(X
+1, Y
) {ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED)}) then
1147 State
:= STATE_NORMAL
;
1151 if not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)} then
1153 if isLiftUpAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTUP)} then
1155 if VelY
> -4-Random(3) then
1157 if Abs(VelX
) > 0.1 then
1158 VelX
:= VelX
- VelX
/10.0;
1159 VelX
:= VelX
+ (Random
-Random
)*0.2;
1162 if isLiftLeftAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT)} then
1163 begin // Ïîòîê âëåâî
1164 if VelX
> -8-Random(3) then
1168 if isLiftRightAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT)} then
1169 begin // Ïîòîê âïðàâî
1170 if VelX
< 8+Random(3) then
1179 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) then
1180 if (State
<> STATE_STICK
) and
1181 (not isBlockedAt(X
, Y
-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and
1182 (not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and
1183 (not isBlockedAt(X
, Y
+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then
1184 begin // Âèñèò â âîçäóõå - êàïàåò
1187 State
:= STATE_NORMAL
;
1197 for b
:= 1 to Abs(dX
) do
1199 if (X
+s
>= w
) or (X
+s
<= 0) then
1200 begin // Ñáîêó ãðàíèöà
1201 State
:= STATE_FREE
;
1205 //c := gCollideMap[Y, X+s];
1207 if isLiquidAt(X
+s
, Y
) {ByteBool(c and MARK_LIQUID)} and (dY
> 0) then
1208 begin // Ñáîêó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
1209 State
:= STATE_FREE
;
1213 if isBlockedAt(X
+s
, Y
) {ByteBool(c and MARK_BLOCKED)} then
1214 begin // Ñòåíà/äâåðü
1219 State
:= STATE_STICK
;
1234 for b
:= 1 to Abs(dY
) do
1236 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1237 begin // Ñíèçó/ñâåðõó ãðàíèöà
1238 State
:= STATE_FREE
;
1242 //c := gCollideMap[Y+s, X];
1244 if isLiquidAt(X
, Y
+s
) {ByteBool(c and MARK_LIQUID)} and (dY
> 0) then
1245 begin // Ñíèçó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
1246 State
:= STATE_FREE
;
1250 if isBlockedAt(X
, Y
+s
) {ByteBool(c and MARK_BLOCKED)} then
1251 begin // Ñòåíà/äâåðü
1256 if (s
> 0) and (State
<> STATE_STICK
) then
1257 State
:= STATE_NORMAL
1259 State
:= STATE_STICK
;
1267 VelX
:= VelX
+ AccelX
;
1268 VelY
:= VelY
+ AccelY
;
1284 for b
:= 1 to Abs(dY
) do
1286 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1288 State
:= STATE_FREE
;
1292 if not isLiquidAt(X
, Y
+s
) {ByteBool(gCollideMap[Y+s, X] and MARK_LIQUID)} then
1293 begin // Óæå íå æèäêîñòü
1294 State
:= STATE_FREE
;
1303 VelY
:= VelY
+ AccelY
;
1313 end; // Particles <> nil
1315 if OnceAnims
<> nil then
1317 for a
:= 0 to High(OnceAnims
) do
1318 if OnceAnims
[a
].Animation
<> nil then
1320 case OnceAnims
[a
].AnimType
of
1323 if Random(3) = 0 then
1324 OnceAnims
[a
].X
:= OnceAnims
[a
].X
-1+Random(3);
1325 if Random(2) = 0 then
1326 OnceAnims
[a
].Y
:= OnceAnims
[a
].Y
-Random(2);
1330 if OnceAnims
[a
].Animation
.Played
then
1332 OnceAnims
[a
].Animation
.Free();
1333 OnceAnims
[a
].Animation
:= nil;
1336 OnceAnims
[a
].Animation
.Update();
1341 procedure g_GFX_Draw();
1345 if Particles
<> nil then
1347 glDisable(GL_TEXTURE_2D
);
1351 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1355 len
:= High(Particles
);
1357 for a
:= 0 to len
do
1358 with Particles
[a
] do
1359 if (State
<> STATE_FREE
) and (X
>= sX
) and (Y
>= sY
) and
1360 (X
<= sX
+sWidth
) and (sY
<= sY
+sHeight
) then
1362 glColor4ub(Red
, Green
, Blue
, Alpha
);
1363 glVertex2i(X
+ offsetX
, Y
+ offsetY
);
1368 glDisable(GL_BLEND
);
1371 if OnceAnims
<> nil then
1372 for a
:= 0 to High(OnceAnims
) do
1373 if OnceAnims
[a
].Animation
<> nil then
1374 with OnceAnims
[a
] do
1375 Animation
.Draw(X
, Y
, M_NONE
);