4fcd318df451b0abdf0f4ab2177d3b71118aa281
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();
65 g_map
, g_basic
, Math
, e_graphics
, GL
, GLExt
,
66 g_options
, g_console
, SysUtils
, g_triggers
, MAPDEF
,
67 g_game
, g_language
, g_net
;
70 PParticle
= ^TParticle
;
74 AccelX
, AccelY
: Single;
75 Red
, Green
, Blue
: Byte;
80 offsetX
, offsetY
: ShortInt;
86 Animation
: TAnimation
;
99 Particles
: Array of TParticle
;
100 OnceAnims
: Array of TOnceAnim
;
101 MaxParticles
: Integer;
102 CurrentParticle
: Integer;
105 function isBlockedAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
107 result
:= g_Map_CollidePanel(x
, y
, w
, h
, (PANEL_WALL
or PANEL_CLOSEDOOR
or PANEL_STEP
));
112 function isWallAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
114 result
:= g_Map_CollidePanel(x
, y
, w
, h
, (PANEL_WALL
or PANEL_STEP
));
118 function isLiftUpAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
120 result
:= g_Map_CollidePanel(x
, y
, w
, h
, PANEL_LIFTUP
);
123 function isLiftDownAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
125 result
:= g_Map_CollidePanel(x
, y
, w
, h
, PANEL_LIFTDOWN
);
128 function isLiftLeftAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
130 result
:= g_Map_CollidePanel(x
, y
, w
, h
, PANEL_LIFTLEFT
);
133 function isLiftRightAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
135 result
:= g_Map_CollidePanel(x
, y
, w
, h
, PANEL_LIFTRIGHT
);
139 function isLiquidAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
141 result
:= g_Map_CollidePanel(x
, y
, w
, h
, (PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
));
145 function isAnythingAt (x
, y
: Integer; w
: Integer=1; h
: Integer=1): Boolean; inline;
147 result
:= g_Map_CollidePanel(x
, y
, w
, h
, (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
));
151 procedure g_Mark(x
, y
, Width
, Height
: Integer; t
: Byte; st
: Boolean);
152 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
154 yy
, y2
, xx
, x2
: Integer;
157 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
169 Height
:= Height
+ y
;
176 if x
> gMapInfo
.Width
then
178 if y
> gMapInfo
.Height
then
181 y2
:= y
+ Height
- 1;
182 if y2
> gMapInfo
.Height
then
183 y2
:= gMapInfo
.Height
;
186 if x2
> gMapInfo
.Width
then
187 x2
:= gMapInfo
.Width
;
190 begin // Óñòàíîâèòü ïðèçíàê
193 gCollideMap
[yy
][xx
] := gCollideMap
[yy
][xx
] or t
;
196 begin // Óáðàòü ïðèçíàê
200 gCollideMap
[yy
][xx
] := gCollideMap
[yy
][xx
] and t
;
205 procedure CreateCollideMap();
206 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
211 {$IF DEFINED(HAS_COLLIDE_BITMAP)}
212 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 1/6', 0, False);
213 SetLength(gCollideMap
, gMapInfo
.Height
+1);
214 for a
:= 0 to High(gCollideMap
) do
215 SetLength(gCollideMap
[a
], gMapInfo
.Width
+1);
217 if gWater
<> nil then
219 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 2/6', 0, True);
220 for a
:= 0 to High(gWater
) do
222 g_Mark(X
, Y
, Width
, Height
, MARK_WATER
, True);
225 if gAcid1
<> nil then
227 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 3/6', 0, True);
228 for a
:= 0 to High(gAcid1
) do
230 g_Mark(X
, Y
, Width
, Height
, MARK_ACID
, True);
233 if gAcid2
<> nil then
235 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 4/6', 0, True);
236 for a
:= 0 to High(gAcid2
) do
238 g_Mark(X
, Y
, Width
, Height
, MARK_ACID
, True);
241 if gLifts
<> nil then
243 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 5/6', 0, True);
244 for a
:= 0 to High(gLifts
) do
247 g_Mark(X
, Y
, Width
, Height
, MARK_LIFT
, False);
250 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTUP
, True)
251 else if LiftType
= 1 then
252 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTDOWN
, True)
253 else if LiftType
= 2 then
254 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTLEFT
, True)
255 else if LiftType
= 3 then
256 g_Mark(X
, Y
, Width
, Height
, MARK_LIFTRIGHT
, True)
260 if gWalls
<> nil then
262 g_Game_SetLoadingText(_lc
[I_LOAD_COLLIDE_MAP
]+' 6/6', 0, True);
263 for a
:= 0 to High(gWalls
) do
265 if gWalls
[a
].Door
then
268 if gWalls
[a
].Enabled
then
270 g_Mark(X
, Y
, Width
, Height
, MARK_DOOR
, True)
271 else // Îòêðûòàÿ äâåðü:
272 if gWalls
[a
].Enabled
then
274 g_Mark(X
, Y
, Width
, Height
, MARK_DOOR
, False);
278 g_Mark(X
, Y
, Width
, Height
, MARK_WALL
, True);
284 procedure g_GFX_Init();
289 procedure g_GFX_Free();
294 SetLength(Particles
, MaxParticles
);
295 CurrentParticle
:= 0;
297 if OnceAnims
<> nil then
299 for a
:= 0 to High(OnceAnims
) do
300 OnceAnims
[a
].Animation
.Free();
307 procedure CorrectOffsets(id
: Integer);
311 part
:= @Particles
[id
];
314 // check for upper wall
315 if isBlockedAt(part
.X
, part
.Y
-1) then part
.offsetY
:= 1;
316 // check for left wall
317 if isBlockedAt(part
.X
-1, part
.Y
) then part
.offsetX
:= 1;
321 procedure g_GFX_SparkVel (fX
, fY
: Integer; Count
: Word; VX
, VY
: Integer; DevX
, DevY
: Byte);
328 l
:= Length(Particles
);
330 if Count
> l
then Count
:= l
;
337 for a
:= 1 to Count
do
339 with Particles
[CurrentParticle
] do
341 X
:= fX
-DevX1
+Random(DevX2
);
342 Y
:= fY
-DevY1
+Random(DevY2
);
344 VelX
:= VX
+ (Random
-Random
)*3;
345 VelY
:= VY
+ (Random
-Random
)*3;
353 AccelX
:= -Sign(VelX
)*Random
/100;
357 Green
:= 100+Random(155);
361 State
:= STATE_NORMAL
;
363 LiveTime
:= 30+Random(60);
364 ParticleType
:= PARTICLE_SPARK
;
366 CorrectOffsets(CurrentParticle
);
369 if CurrentParticle
+2 > MaxParticles
then
372 CurrentParticle
:= CurrentParticle
+1;
377 procedure g_GFX_Blood(fX
, fY
: Integer; Count
: Word; vx
, vy
: Integer;
378 DevX
, DevY
: Word; CR
, CG
, CB
: Byte; Kind
: Byte = BLOOD_NORMAL
);
387 if Kind
= BLOOD_SPARKS
then
389 g_GFX_SparkVel(fX
, fY
, 2 + Random(2), -VX
div 2, -VY
div 2, DevX
, DevY
);
392 l
:= Length(Particles
);
403 for a
:= 1 to Count
do
405 with Particles
[CurrentParticle
] do
407 X
:= fX
- DevX1
+ Random(DevX2
);
408 Y
:= fY
- DevY1
+ Random(DevY2
);
411 if (X < 0) or (X > gMapInfo.Width-1) or
412 (Y < 0) or (Y > gMapInfo.Height-1) or
413 ByteBool(gCollideMap[Y, X] and MARK_WALL) then
416 if isWallAt(X
, Y
) then continue
;
418 VelX
:= vx
+ (Random
-Random
)*3;
419 VelY
:= vy
+ (Random
-Random
)*3;
427 AccelX
:= -Sign(VelX
)*Random
/100;
430 CRnd
:= 20*Random(6);
433 CC
:= CR
+ CRnd
- 50;
434 if CC
< 0 then CC
:= 0;
435 if CC
> 255 then CC
:= 255;
441 CC
:= CG
+ CRnd
- 50;
442 if CC
< 0 then CC
:= 0;
443 if CC
> 255 then CC
:= 255;
449 CC
:= CB
+ CRnd
- 50;
450 if CC
< 0 then CC
:= 0;
451 if CC
> 255 then CC
:= 255;
458 State
:= STATE_NORMAL
;
460 LiveTime
:= 120+Random(40);
461 ParticleType
:= PARTICLE_BLOOD
;
463 CorrectOffsets(CurrentParticle
);
466 if CurrentParticle
>= MaxParticles
-1 then
469 CurrentParticle
:= CurrentParticle
+1;
474 procedure g_GFX_Spark(fX
, fY
: Integer; Count
: Word; Angle
: SmallInt; DevX
, DevY
: Byte);
480 BaseVelX
, BaseVelY
: Single;
483 l
:= Length(Particles
);
489 Angle
:= 360 - Angle
;
496 b
:= DegToRad(Angle
);
498 BaseVelY
:= 1.6*sin(b
);
499 if Abs(BaseVelX
) < 0.01 then
501 if Abs(BaseVelY
) < 0.01 then
503 for a
:= 1 to Count
do
505 with Particles
[CurrentParticle
] do
507 X
:= fX
-DevX1
+Random(DevX2
);
508 Y
:= fY
-DevY1
+Random(DevY2
);
510 VelX
:= BaseVelX
*Random
;
511 VelY
:= BaseVelY
-Random
;
516 Green
:= 100+Random(155);
520 State
:= STATE_NORMAL
;
522 LiveTime
:= 30+Random(60);
523 ParticleType
:= PARTICLE_SPARK
;
525 CorrectOffsets(CurrentParticle
);
528 if CurrentParticle
+2 > MaxParticles
then
531 CurrentParticle
:= CurrentParticle
+1;
535 procedure g_GFX_Water(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DevX
, DevY
, Color
: Byte);
542 l
:= Length(Particles
);
548 if Abs(fVelX
) < 3.0 then
549 fVelX
:= 3.0 - 6.0*Random
;
556 for a
:= 1 to Count
do
558 with Particles
[CurrentParticle
] do
560 X
:= fX
-DevX1
+Random(DevX2
);
561 Y
:= fY
-DevY1
+Random(DevY2
);
563 if Abs(fVelX
) < 0.5 then
564 VelX
:= 1.0 - 2.0*Random
566 VelX
:= fVelX
*Random
;
567 if Random(10) < 7 then
569 VelY
:= fVelY
*Random
;
576 Red
:= 155 + Random(9)*10;
577 Green
:= Trunc(150*Random
);
582 Red
:= Trunc(150*Random
);
583 Green
:= 175 + Random(9)*10;
588 Red
:= Trunc(200*Random
);
590 Blue
:= 175 + Random(9)*10;
594 Red
:= 90 + Random(12)*10;
602 State
:= STATE_NORMAL
;
604 LiveTime
:= 60+Random(60);
605 ParticleType
:= PARTICLE_WATER
;
607 CorrectOffsets(CurrentParticle
);
610 if CurrentParticle
+2 > MaxParticles
then
613 CurrentParticle
:= CurrentParticle
+1;
617 procedure g_GFX_SimpleWater(fX
, fY
: Integer; Count
: Word; fVelX
, fVelY
: Single; DefColor
, CR
, CG
, CB
: Byte);
622 l
:= Length(Particles
);
628 for a
:= 1 to Count
do
630 with Particles
[CurrentParticle
] do
643 Red
:= 155 + Random(9)*10;
644 Green
:= Trunc(150*Random
);
649 Red
:= Trunc(150*Random
);
650 Green
:= 175 + Random(9)*10;
655 Red
:= Trunc(200*Random
);
657 Blue
:= 175 + Random(9)*10;
659 4: // Ñâîé öâåò, ñâåòëåå
661 Red
:= 20 + Random(19)*10;
664 Red
:= Min(Red
+ CR
, 255);
665 Green
:= Min(Green
+ CG
, 255);
666 Blue
:= Min(Blue
+ CB
, 255);
668 5: // Ñâîé öâåò, òåìíåå
670 Red
:= 20 + Random(19)*10;
673 Red
:= Max(CR
- Red
, 0);
674 Green
:= Max(CG
- Green
, 0);
675 Blue
:= Max(CB
- Blue
, 0);
679 Red
:= 90 + Random(12)*10;
687 State
:= STATE_NORMAL
;
689 LiveTime
:= 60+Random(60);
690 ParticleType
:= PARTICLE_WATER
;
692 CorrectOffsets(CurrentParticle
);
695 if CurrentParticle
+2 > MaxParticles
then
698 CurrentParticle
:= CurrentParticle
+1;
702 procedure g_GFX_Bubbles(fX
, fY
: Integer; Count
: Word; DevX
, DevY
: Byte);
709 l
:= Length(Particles
);
720 for a
:= 1 to Count
do
722 with Particles
[CurrentParticle
] do
724 X
:= fX
-DevX1
+Random(DevX2
);
725 Y
:= fY
-DevY1
+Random(DevY2
);
727 if (X
>= gMapInfo
.Width
) or (X
<= 0) or
728 (Y
>= gMapInfo
.Height
) or (Y
<= 0) then
731 if not isLiquidAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
744 State
:= STATE_NORMAL
;
747 ParticleType
:= PARTICLE_BUBBLES
;
749 CorrectOffsets(CurrentParticle
);
752 if CurrentParticle
+2 > MaxParticles
then
755 CurrentParticle
:= CurrentParticle
+1;
759 procedure g_GFX_SetMax(Count
: Integer);
761 if Count
> 50000 then
764 SetLength(Particles
, Count
);
765 MaxParticles
:= Count
;
766 if CurrentParticle
>= Count
then
767 CurrentParticle
:= 0;
770 function g_GFX_GetMax(): Integer;
772 Result
:= MaxParticles
;
775 function FindOnceAnim
: DWORD
;
779 if OnceAnims
<> nil then
780 for i
:= 0 to High(OnceAnims
) do
781 if OnceAnims
[i
].Animation
= nil then
787 if OnceAnims
= nil then
789 SetLength(OnceAnims
, 16);
794 Result
:= High(OnceAnims
) + 1;
795 SetLength(OnceAnims
, Length(OnceAnims
) + 16);
799 procedure g_GFX_OnceAnim(X
, Y
: Integer; Anim
: TAnimation
; AnimType
: Byte = 0);
806 find_id
:= FindOnceAnim();
808 OnceAnims
[find_id
].AnimType
:= AnimType
;
809 OnceAnims
[find_id
].Animation
:= TAnimation
.Create(Anim
.FramesID
, Anim
.Loop
, Anim
.Speed
);
810 OnceAnims
[find_id
].Animation
.Blending
:= Anim
.Blending
;
811 OnceAnims
[find_id
].Animation
.Alpha
:= Anim
.Alpha
;
812 OnceAnims
[find_id
].X
:= X
;
813 OnceAnims
[find_id
].Y
:= Y
;
816 procedure g_GFX_Update();
825 if Particles
<> nil then
828 h
:= gMapInfo
.Height
;
830 len
:= High(Particles
);
833 if Particles
[a
].State
<> 0 then
836 if Time
= LiveTime
then
838 if (X
+1 >= w
) or (Y
+1 >= h
) or (X
<= 0) or (Y
<= 0) then
840 if State
= STATE_FREE
then
848 if (State
= STATE_STICK
) then
850 if (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and
851 (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) and
852 (not ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) and
853 (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED))
856 if (not isBlockedAt(X
, Y
-1)) and
857 (not isBlockedAt(X
, Y
+1)) and
858 (not isBlockedAt(X
-1, Y
)) and
859 (not isBlockedAt(X
+1, Y
))
861 begin // Îòëèïëà - êàïàåò
864 State
:= STATE_NORMAL
;
867 if Random(200) = 100 then
868 begin // Ïðèëåïëåíà - íî âîçìîæíî ñòåêàåò
874 if not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)} then
876 if isLiftUpAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTUP)} then
878 if VelY
> -4-Random(3) then
880 if Abs(VelX
) > 0.1 then
881 VelX
:= VelX
- VelX
/10.0;
882 VelX
:= VelX
+ (Random
-Random
)*0.2;
885 if isLiftLeftAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT)} then
887 if VelX
> -8-Random(3) then
891 if isLiftRightAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT)} then
892 begin // Ïîòîê âïðàâî
893 if VelX
< 8+Random(3) then
902 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) then
903 if (State
<> STATE_STICK
) and
904 (not isBlockedAt(X
, Y
-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and
905 (not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and
906 (not isBlockedAt(X
, Y
+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then
907 begin // Âèñèò â âîçäóõå - êàïàåò
910 State
:= STATE_NORMAL
;
924 if (X
+s
>= w
) or (X
+s
<= 0) then
930 //c := gCollideMap[Y, X+s];
932 if isBlockedAt(X
+s
, Y
) {ByteBool(c and MARK_BLOCKED)} then
938 State
:= STATE_STICK
;
957 if (Y
+s
>= h
) or (Y
+s
<= 0) then
963 //c := gCollideMap[Y+s, X];
965 if isBlockedAt(X
, Y
+s
) {ByteBool(c and MARK_BLOCKED)} then
971 if (s
> 0) and (State
<> STATE_STICK
) then
972 State
:= STATE_NORMAL
974 State
:= STATE_STICK
;
987 if (X
+dX
>= w
) or (Y
+dY
>= h
) or
988 (X
+dX
<= 0) or (Y
+dY
<= 0) or
989 isBlockedAt(X
+dX
, Y
+dY
) {ByteBool(gCollideMap[Y+dY, X+dX] and MARK_BLOCKED)} then
990 begin // Ñòåíà/äâåðü/ãðàíèöà
1002 VelX
:= VelX
+ AccelX
;
1003 VelY
:= VelY
+ AccelY
;
1005 // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè:
1006 if isLiquidAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
1010 Alpha
:= 255 - Trunc((255.0 * Time
) / LiveTime
);
1019 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) and
1020 (not isBlockedAt(X
, Y
-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and
1021 (not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and
1022 (not isBlockedAt(X
, Y
+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then
1023 begin // Âèñèò â âîçäóõå
1039 if (X
+s
>= w
) or (X
+s
<= 0) then
1041 State
:= STATE_FREE
;
1045 //c := gCollideMap[Y, X+s];
1047 if isBlockedAt(X
+s
, Y
) {ByteBool(c and MARK_BLOCKED)} then
1048 begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî
1054 if not isAnythingAt(X
+s
, Y
) {c = MARK_FREE} then
1058 State
:= STATE_FREE
;
1075 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1077 State
:= STATE_FREE
;
1081 //c := gCollideMap[Y+s, X];
1083 if isBlockedAt(X
, Y
+s
) {ByteBool(c and MARK_BLOCKED)} then
1084 begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî
1088 AccelY
:= Abs(AccelY
);
1090 else // Èëè íå ïàäàåò
1101 if not isAnythingAt(X
, Y
+s
) {c = MARK_FREE} then
1105 State
:= STATE_FREE
;
1112 VelX
:= VelX
+ AccelX
;
1116 AccelY
:= AccelY
+ 0.08;
1117 VelY
:= VelY
+ AccelY
;
1125 if (State
= STATE_STICK
) and (Random(30) = 15) then
1126 begin // Ñòåêàåò/îòëèïàåò
1129 if (not isBlockedAt(X
-1, Y
) {ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)}) and
1130 (not isBlockedAt(X
+1, Y
) {ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED)}) then
1131 State
:= STATE_NORMAL
;
1135 if not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)} then
1137 if isLiftUpAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTUP)} then
1139 if VelY
> -4-Random(3) then
1141 if Abs(VelX
) > 0.1 then
1142 VelX
:= VelX
- VelX
/10.0;
1143 VelX
:= VelX
+ (Random
-Random
)*0.2;
1146 if isLiftLeftAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT)} then
1147 begin // Ïîòîê âëåâî
1148 if VelX
> -8-Random(3) then
1152 if isLiftRightAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT)} then
1153 begin // Ïîòîê âïðàâî
1154 if VelX
< 8+Random(3) then
1163 if (Abs(VelX
) < 0.1) and (Abs(VelY
) < 0.1) then
1164 if (State
<> STATE_STICK
) and
1165 (not isBlockedAt(X
, Y
-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and
1166 (not isBlockedAt(X
, Y
) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and
1167 (not isBlockedAt(X
, Y
+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then
1168 begin // Âèñèò â âîçäóõå - êàïàåò
1171 State
:= STATE_NORMAL
;
1181 for b
:= 1 to Abs(dX
) do
1183 if (X
+s
>= w
) or (X
+s
<= 0) then
1184 begin // Ñáîêó ãðàíèöà
1185 State
:= STATE_FREE
;
1189 //c := gCollideMap[Y, X+s];
1191 if isLiquidAt(X
+s
, Y
) {ByteBool(c and MARK_LIQUID)} and (dY
> 0) then
1192 begin // Ñáîêó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
1193 State
:= STATE_FREE
;
1197 if isBlockedAt(X
+s
, Y
) {ByteBool(c and MARK_BLOCKED)} then
1198 begin // Ñòåíà/äâåðü
1203 State
:= STATE_STICK
;
1218 for b
:= 1 to Abs(dY
) do
1220 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1221 begin // Ñíèçó/ñâåðõó ãðàíèöà
1222 State
:= STATE_FREE
;
1226 //c := gCollideMap[Y+s, X];
1228 if isLiquidAt(X
, Y
+s
) {ByteBool(c and MARK_LIQUID)} and (dY
> 0) then
1229 begin // Ñíèçó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò
1230 State
:= STATE_FREE
;
1234 if isBlockedAt(X
, Y
+s
) {ByteBool(c and MARK_BLOCKED)} then
1235 begin // Ñòåíà/äâåðü
1240 if (s
> 0) and (State
<> STATE_STICK
) then
1241 State
:= STATE_NORMAL
1243 State
:= STATE_STICK
;
1251 VelX
:= VelX
+ AccelX
;
1252 VelY
:= VelY
+ AccelY
;
1268 for b
:= 1 to Abs(dY
) do
1270 if (Y
+s
>= h
) or (Y
+s
<= 0) then
1272 State
:= STATE_FREE
;
1276 if not isLiquidAt(X
, Y
+s
) {ByteBool(gCollideMap[Y+s, X] and MARK_LIQUID)} then
1277 begin // Óæå íå æèäêîñòü
1278 State
:= STATE_FREE
;
1287 VelY
:= VelY
+ AccelY
;
1295 end; // Particles <> nil
1297 if OnceAnims
<> nil then
1299 for a
:= 0 to High(OnceAnims
) do
1300 if OnceAnims
[a
].Animation
<> nil then
1302 case OnceAnims
[a
].AnimType
of
1305 if Random(3) = 0 then
1306 OnceAnims
[a
].X
:= OnceAnims
[a
].X
-1+Random(3);
1307 if Random(2) = 0 then
1308 OnceAnims
[a
].Y
:= OnceAnims
[a
].Y
-Random(2);
1312 if OnceAnims
[a
].Animation
.Played
then
1314 OnceAnims
[a
].Animation
.Free();
1315 OnceAnims
[a
].Animation
:= nil;
1318 OnceAnims
[a
].Animation
.Update();
1323 procedure g_GFX_Draw();
1327 if Particles
<> nil then
1329 glDisable(GL_TEXTURE_2D
);
1333 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1337 len
:= High(Particles
);
1339 for a
:= 0 to len
do
1340 with Particles
[a
] do
1341 if (State
<> STATE_FREE
) and (X
>= sX
) and (Y
>= sY
) and
1342 (X
<= sX
+sWidth
) and (sY
<= sY
+sHeight
) then
1344 glColor4ub(Red
, Green
, Blue
, Alpha
);
1345 glVertex2i(X
+ offsetX
, Y
+ offsetY
);
1350 glDisable(GL_BLEND
);
1353 if OnceAnims
<> nil then
1354 for a
:= 0 to High(OnceAnims
) do
1355 if OnceAnims
[a
].Animation
<> nil then
1356 with OnceAnims
[a
] do
1357 Animation
.Draw(X
, Y
, M_NONE
);