home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 16 / CD_ASCQ_16_0994.iso / news / 573 / 3dlab101 / l3dworld.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-26  |  20KB  |  438 lines

  1. {────────────────────────────────────────────────────────────────────────────}
  2. {───( C ) Copyright 1994 By Kimmo Fredriksson.───────────────────────────────}
  3. {────────────────────────────────────────────────────────────────────────────}
  4. {───You may use this unit freely in your programs, and distribute them,──────}
  5. {───but you are *NOT* allowed to distribute any modified form of this────────}
  6. {───unit, not source, nor the compiled TPU, TPP or whatsoever, *without*─────}
  7. {───my permission! In it's original form, this source is freeware.───────────}
  8. {────────────────────────────────────────────────────────────────────────────}
  9. {───Internet email: Kimmo.Fredriksson@Helsinki.FI────────────────────────────}
  10. {────────────────────────────────────────────────────────────────────────────}
  11.  
  12. {────────────────────────────────────────────────────────────────────────────}
  13. {───If you want the Turbo Pascal and assembler source code for the TxtMap────}
  14. {───Unit, register today. Send $20 (or 100 Fmk) to me, and I'll send all─────}
  15. {───the source to you.───────────────────────────────────────────────────────}
  16. {────────────────────────────────────────────────────────────────────────────}
  17. {─────────Kimmo Fredriksson──────────────────────────────────────────────────}
  18. {─────────Silvontie 38───────────────────────────────────────────────────────}
  19. {─────────37740 Haukila──────────────────────────────────────────────────────}
  20. {─────────FINLAND────────────────────────────────────────────────────────────}
  21. {────────────────────────────────────────────────────────────────────────────}
  22.  
  23. {$A+,B-,D-,E-,F-,G+,I-,L-,N-,O-,P+,Q-,R-,S-,T-,V-,X+}
  24.  
  25. UNIT    L3DWorld;
  26.  
  27.     INTERFACE
  28.  
  29. USES    TxtMap;
  30.  
  31. CONST   Copyright     = '(C) 1994 By Kimmo Fredriksson';
  32.  
  33.     ChkHit        : Boolean = TRUE;    { check hit-the-wall ?  }
  34.     HitDist        = 4 * WorldXZ DIV 3; { hits the wall at this dist. }
  35.  
  36. CONST    WXDim        = 256 DIV 2;        { Size of the world }
  37.     WZDim        = 256 DIV 2;
  38.  
  39.     MinWX        : Word = WXDim;        { These are updated when }
  40.     MinWZ        : Word = WZDim;         { building the world so, that }
  41.     MaxWX        : Word = 0;             { MinW? and MaxW? tell the }
  42.     MaxWZ        : Word = 0;        { upper-left and lower-right }
  43.                         { corners of world }
  44.  
  45. TYPE    IntARRAY    = ARRAY[ 0..16383 ] OF Integer; { used to casts }
  46.     ByteARRAY    = ARRAY[ 0..16383 ] OF Byte;
  47.  
  48.     IntAPtr        = ^IntARRAY;
  49.     ByteAPtr    = ^ByteARRAY;
  50.  
  51.     WallTableTYPE    = ARRAY[ 0..WXDim * 2 DIV 8 - 1, 0..WZDim * 2 - 1 ] OF Byte;
  52.  
  53.     { This data structure is used to hit-the-wall-check. }
  54.     { If the bit corresponding to players position is set, then }
  55.     { player has hit the wall }
  56.  
  57. VAR    WallTable    : ^WallTableTYPE;
  58.  
  59.  
  60. PROCEDURE SetWallTxtObjX( xF, xT, Zc : Integer; TI : Byte );
  61. PROCEDURE SetWallTxtObjZ( zF, zT, Xc : Integer; TI : Byte );
  62. PROCEDURE SetWallTxtObjBoxIn ( xF, zF, xT, zT : Integer; T0, T1, T2, T3 : Byte );
  63. PROCEDURE SetWallTxtObjBoxOut( xF, zF, xT, zT : Integer; T0, T1, T2, T3 : Byte );
  64. PROCEDURE SetWallTxtObjPoly( xc, zc : IntAPtr; TI : ByteAPtr; n : Word );
  65. FUNCTION  GetOneWall( xc, zc : Integer ) : Boolean;
  66. PROCEDURE MovePoint( VAR XP, ZP : LongInt; VAR X, Z : Integer; Xd, Zd, Angle : Integer );
  67. PROCEDURE MoveEye( Angle, Speed : Integer );
  68. PROCEDURE TurnEye( Angle : Integer );
  69. PROCEDURE SetEyePos( EyeX, EyeZ, Angle : Integer );
  70.  
  71.     IMPLEMENTATION
  72.  
  73. USES    AsmSys;
  74.  
  75. {
  76.  ╔═════════════════════════════════════════════════════════════════════════╗
  77.  ║ PROCEDURE Initilize                                                     ║
  78.  ╚═════════════════════════════════════════════════════════════════════════╝
  79. }
  80. PROCEDURE Initialize;
  81. BEGIN
  82.   NormX := WXDim;   { needed to convert user-points to porgrams own internal }
  83.   NormZ := WZDim;   { form }
  84.   New( WallTable );
  85.   FillChar( WallTable^, SizeOf( WallTableTYPE ), 0 ); { begin with no walls }
  86. END;
  87. {
  88.  ╔═════════════════════════════════════════════════════════════════════════╗
  89.  ║ PROCEDURE SetOneWall                                                    ║
  90.  ╟─────────────────────────────────────────────────────────────────────────╢
  91.  ║ Input  : Coordinates of the wall                                        ║
  92.  ╟─────────────────────────────────────────────────────────────────────────╢
  93.  ║ Set the bit on int the WallTable, corresponding the input wall          ║
  94.  ╚═════════════════════════════════════════════════════════════════════════╝
  95. }
  96. PROCEDURE SetOneWall( xc, zc : Integer );
  97. VAR msk : Byte;
  98. BEGIN
  99.   MinWX := MinIn( MinWX, xc ); { update the upper-left and lower-right }
  100.   MinWZ := MinIn( MinWZ, zc ); { coordinates of the world, }
  101.   MaxWX := MaxIn( MaxWX, xc ); { needed to draw the map }
  102.   MaxWZ := MaxIn( MaxWZ, zc );
  103.   msk := 1 SHL ( Abs( xc MOD 8 )); { 8-bits/byte --> 8 walls/byte }
  104.   xc := xc DIV 8;
  105.   WallTable^[ xc, zc ] := WallTable^[ xc, zc ] OR msk;
  106. END;
  107. {
  108.  ╔═════════════════════════════════════════════════════════════════════════╗
  109.  ║ FUNCTION GetOneWall                                                     ║
  110.  ╟─────────────────────────────────────────────────────────────────────────╢
  111.  ║ Input  : coordinates to check for wall                                  ║
  112.  ║ Output : TRUE, if wall found, FALSE otherwise                           ║
  113.  ╟─────────────────────────────────────────────────────────────────────────╢
  114.  ║ This function is needed to check if player walked against the wall.     ║
  115.  ║ Look also SetOneWall.                                                   ║
  116.  ╚═════════════════════════════════════════════════════════════════════════╝
  117. }
  118. FUNCTION GetOneWall( xc, zc : Integer ) : Boolean;
  119. VAR msk : Byte;
  120. BEGIN
  121.   msk := 1 SHL ( Abs( xc MOD 8 ));
  122.   xc := xc DIV 8;
  123.   GetOneWall := ( WallTable^[ xc, zc ] AND msk ) <> 0;
  124. END;
  125. {
  126.  ╔═════════════════════════════════════════════════════════════════════════╗
  127.  ║ FUNCTION HitTheWallX                                                    ║
  128.  ╟─────────────────────────────────────────────────────────────────────────╢
  129.  ║ Input  : moving point's x, z coordinates, and angle of direction        ║
  130.  ║ Output : TRUE, if point hit the wall in x-direction, FALSE otherwise    ║
  131.  ╟─────────────────────────────────────────────────────────────────────────╢
  132.  ║ xc, zc are 8-bit fixed-point numbers.                                   ║
  133.  ║ HitTheWallZ doas the same as this, but in Z-direction                   ║
  134.  ╚═════════════════════════════════════════════════════════════════════════╝
  135. }
  136. FUNCTION HitTheWallX( xc, zc : LongInt; Angle : Integer ) : Boolean;
  137. VAR z0, z1 : Integer;
  138. BEGIN
  139.   xc := xc * 2;  { walls was saved that way... }
  140.   zc := zc * 2;
  141.   IF ChkHit THEN  { do we care the hits of... }
  142.     BEGIN
  143.       z0 := ( zc DIV 256 ) DIV WorldXZ; { position in WallTable }
  144.       z1 := ( zc DIV 256 + WorldXZ DIV 2 ) DIV WorldXZ;
  145.       xc := xc DIV 256;
  146.       zc := zc DIV 256 DIV WorldXZ;
  147.       IF ( Angle >= 0 ) AND ( Angle < 180 ) THEN
  148.       xc := ( xc + WorldXZ + HitDist ) DIV WorldXZ
  149.     ELSE
  150.       xc := ( xc - HitDist ) DIV WorldXZ;
  151.       HitTheWallX := GetOneWall( xc, zc ) OR GetOneWall( xc, zc + 1 )
  152.     END
  153.   ELSE
  154.     HitTheWallX := FALSE
  155. END;
  156. {
  157.  ╔═════════════════════════════════════════════════════════════════════════╗
  158.  ║ FUNCTION HitTheWallZ                                                    ║
  159.  ╟─────────────────────────────────────────────────────────────────────────╢
  160.  ║ Input  : moving point's x, z coordinates, and angle of direction        ║
  161.  ║ Output : TRUE, if point hit the wall, FALSE otherwise                   ║
  162.  ╟─────────────────────────────────────────────────────────────────────────╢
  163.  ║ xc, zc are 8-bit fixed-point numbers.                                   ║
  164.  ║ HitTheWallX does the same as this, but in the X-direction.              ║
  165.  ╚═════════════════════════════════════════════════════════════════════════╝
  166. }
  167. FUNCTION HitTheWallZ( xc, zc : LongInt; Angle : Integer ) : Boolean;
  168. VAR x0, x1 : Integer;
  169. BEGIN
  170.   xc := xc * 2;
  171.   zc := zc * 2;
  172.   IF ChkHit THEN
  173.     BEGIN
  174.       x0 := ( xc DIV 256 ) DIV WorldXZ;
  175.       x1 := ( xc DIV 256 + WorldXZ DIV 2 ) DIV WorldXZ;
  176.       xc := xc DIV 256 DIV WorldXZ;
  177.       zc := zc DIV 256;
  178.       IF ( Angle >= 90 ) AND ( Angle < 270 ) THEN
  179.       zc := ( zc - HitDist ) DIV WorldXZ
  180.     ELSE
  181.       zc := ( zc + WorldXZ + HitDist ) DIV WorldXZ;
  182.       HitTheWallZ := GetOneWall( xc, zc ) OR GetOneWall( xc + 1, zc )
  183.     END
  184.   ELSE
  185.     HitTheWallZ := FALSE
  186. END;
  187. {
  188.  ╔═════════════════════════════════════════════════════════════════════════╗
  189.  ║ PROCEDURE MakeWall                                                      ║
  190.  ╟─────────────────────────────────────────────────────────────────────────╢
  191.  ║ Input  : Wall-tile's Left and Right coordinates, when viewing from Front║
  192.  ╟─────────────────────────────────────────────────────────────────────────╢
  193.  ║ Set the corresponding bits on in the WallTable, which we check out for  ║
  194.  ║ any walls after each step.                                              ║
  195.  ╚═════════════════════════════════════════════════════════════════════════╝
  196. }
  197. PROCEDURE MakeWall( x1, x2, z1, z2 : Integer );
  198. BEGIN
  199.   x1 := ( x1 + WXDim DIV 2 ) * 2;
  200.   x2 := ( x2 + WXDim DIV 2 ) * 2;
  201.   z1 := ( z1 + WZDim DIV 2 ) * 2;
  202.   z2 := ( z2 + WZDim DIV 2 ) * 2;
  203.   SetOneWall( x1, z1 );   { left edge }
  204.   SetOneWall(( x1 + x2 ) DIV 2, ( z1 + z2 ) DIV 2 ); { center }
  205.   SetOneWall( x2, z2 ); { right edge }
  206.   IF x1 = x2 THEN { where the slab faces to ? }
  207.     BEGIN
  208.       Inc( x1, Sgn( z1 - z2 ));
  209.       Inc( x2, Sgn( z1 - z2 ));
  210.     END
  211.   ELSE
  212.     BEGIN
  213.       Inc( z1, Sgn( x2 - x1 ));
  214.       Inc( z2, Sgn( x2 - x1 ));
  215.     END;
  216.   SetOneWall( x1, z1 ); { make double wall }
  217.   SetOneWall(( x1 + x2 ) DIV 2, ( z1 + z2 ) DIV 2 );
  218.   SetOneWall( x2, z2 );
  219. END;
  220. {
  221.  ╔═════════════════════════════════════════════════════════════════════════╗
  222.  ║ PROCEDURE InitWall                                                      ║
  223.  ╟─────────────────────────────────────────────────────────────────────────╢
  224.  ║ Input  : Wall-tile's Left and Right coordinates, when viewing from      ║
  225.  ║          Front, and index of desired texture                            ║
  226.  ╚═════════════════════════════════════════════════════════════════════════╝
  227. }
  228. PROCEDURE InitWall( x1, x2, z1, z2 : Integer; TI : Byte );
  229. BEGIN
  230.   MakeWall( x1, x2, z1, z2 );
  231.   InitWallTxtObj( x1, x2, z1, z2, TI );
  232. END;
  233. {
  234.  ╔═════════════════════════════════════════════════════════════════════════╗
  235.  ║ PROCEDURE SetWallTxtObjX                                                ║
  236.  ╟─────────────────────────────────────────────────────────────────────────╢
  237.  ║ Input  : Left and Right X-coordinates of the wall, when viewing from    ║
  238.  ║          Front side, and corresponding Z-coordinate and texture inexes. ║
  239.  ╟─────────────────────────────────────────────────────────────────────────╢
  240.  ║ Make a wall which consists of texture TI. Coordinates must be given in  ║
  241.  ║ right order (first left, then right, viewed from front), because if     ║
  242.  ║ vewed from wrong side, the wall is invisible.                           ║
  243.  ║ See also the SetWallTxtObjZ-procedure.                                  ║
  244.  ╚═════════════════════════════════════════════════════════════════════════╝
  245. }
  246. PROCEDURE SetWallTxtObjX( xF, xT, Zc : Integer; TI : Byte );
  247. VAR i : Integer;
  248. BEGIN
  249.   IF xF = xT THEN Exit;
  250.   IF xF < xT THEN
  251.     FOR i := xF TO Pred( xT ) DO InitWall( i, i + 1, Zc, Zc, TI )
  252.   ELSE
  253.     FOR i := xF DOWNTO Succ( xT ) DO InitWall( i, i - 1, Zc, Zc, TI );
  254.   InitLongWall( xF, xT, Zc, Zc );
  255. END;
  256. {
  257.  ╔═════════════════════════════════════════════════════════════════════════╗
  258.  ║ PROCEDURE SetWallTxtObjZ                                                ║
  259.  ╟─────────────────────────────────────────────────────────────────────────╢
  260.  ║ Input  : Left and Right Z-coordinates of the wall, when viewing from    ║
  261.  ║          Front side, and corresponding X-coordinate and texture inexes. ║
  262.  ╟─────────────────────────────────────────────────────────────────────────╢
  263.  ║ Make a wall which consists of texture TI. Coordinates must be given in  ║
  264.  ║ right order (first left, then right, viewed from front), because if     ║
  265.  ║ vewed from wrong side, the wall is invisible.                           ║
  266.  ║ See also the SetWallTxtObjX-procedure.                                  ║
  267.  ╚═════════════════════════════════════════════════════════════════════════╝
  268. }
  269. PROCEDURE SetWallTxtObjZ( zF, zT, Xc : Integer; TI : Byte );
  270. VAR i : Integer;
  271. BEGIN
  272.   IF zF = zT THEN Exit;
  273.   IF zF < zT THEN
  274.     FOR i := zF TO Pred( zT ) DO InitWall( Xc, Xc, i, i + 1, TI )
  275.   ELSE
  276.     FOR i := zF DOWNTO Succ( zT ) DO InitWall( Xc, Xc, i, i - 1, TI );
  277.   InitLongWall( Xc, Xc, zF, zT );
  278. END;
  279. {
  280.  ╔═════════════════════════════════════════════════════════════════════════╗
  281.  ║ PROCEDURE SetWallTxtObjBoxIn                                            ║
  282.  ╟─────────────────────────────────────────────────────────────────────────╢
  283.  ║ Input  : Coordinates of opposite corners, and texture indexes           ║
  284.  ║          corresponding to each side                                     ║
  285.  ╟─────────────────────────────────────────────────────────────────────────╢
  286.  ║ Make a box using walls. Viewer must be inside of this box, because it   ║
  287.  ║ will not be visible when viewed outside.                                ║
  288.  ╚═════════════════════════════════════════════════════════════════════════╝
  289. }
  290. PROCEDURE SetWallTxtObjBoxIn( xF, zF, xT, zT : Integer; T0, T1, T2, T3 : Byte );
  291. BEGIN
  292.   IF ( zF = zT ) OR ( xF = xT ) THEN Exit;
  293.   IF xF > xT THEN SwapInt( xF, xT );
  294.   IF zF < zT THEN SwapInt( zF, zT );
  295.   SetWallTxtObjX( xF, xT, zF, T0 );
  296.   SetWallTxtObjZ( zF, zT, xT, T1 );
  297.   SetWallTxtObjX( xT, xF, zT, T2 );
  298.   SetWallTxtObjZ( zT, zF, xF, T3 );
  299. END;
  300. {
  301.  ╔═════════════════════════════════════════════════════════════════════════╗
  302.  ║ PROCEDURE SetWallTxtObjBoxOut                                           ║
  303.  ╟─────────────────────────────────────────────────────────────────────────╢
  304.  ║ Input  : Coordinates of opposite corners, and texture indexes           ║
  305.  ║          corresponding to each side                                     ║
  306.  ╟─────────────────────────────────────────────────────────────────────────╢
  307.  ║ Make a box using walls. Viewer must be outside of this box, because it  ║
  308.  ║ will not be visible when viewed inside.                                 ║
  309.  ╚═════════════════════════════════════════════════════════════════════════╝
  310. }
  311. PROCEDURE SetWallTxtObjBoxOut( xF, zF, xT, zT : Integer; T0, T1, T2, T3 : Byte );
  312. BEGIN
  313.   IF ( zF = zT ) OR ( xF = xT ) THEN Exit;
  314.   IF xF > xT THEN SwapInt( xF, xT );
  315.   IF zF < zT THEN SwapInt( zF, zT );
  316.   SetWallTxtObjX( xT, xF, zF, T0 );
  317.   SetWallTxtObjZ( zT, zF, xT, T1 );
  318.   SetWallTxtObjX( xF, xT, zT, T2 );
  319.   SetWallTxtObjZ( zF, zT, xF, T3 );
  320. END;
  321. {
  322.  ╔═════════════════════════════════════════════════════════════════════════╗
  323.  ║ PROCEDURE SetWallTxtObjPoly                                             ║
  324.  ╟─────────────────────────────────────────────────────────────────────────╢
  325.  ║ Input  : Pointers to tables, that contai the x, z coordinates, and      ║
  326.  ║          corresponding texture indexes, and number of the points.       ║
  327.  ╟─────────────────────────────────────────────────────────────────────────╢
  328.  ║ Make n walls, which starting and ending points are found in the tables. ║
  329.  ║ You MUST specify the walls so, that first comes the Left edge, and then ║
  330.  ║ the Right edge, when viewing from Front.                                ║
  331.  ╚═════════════════════════════════════════════════════════════════════════╝
  332. }
  333. PROCEDURE SetWallTxtObjPoly( xc, zc : IntAPtr; TI : ByteAPtr; n : Word );
  334. VAR i, j : Integer;
  335. BEGIN
  336.   FOR i := 0 TO n - 1 DO
  337.     BEGIN
  338.       j := ( i + 1 ) MOD n; { make closed wall }
  339.       IF xc^[ i ] = xc^[ j ] THEN { where does it face to ? }
  340.     SetWallTxtObjZ( zc^[ i ], zc^[ j ], xc^[ i ], TI^[ i ] )
  341.       ELSE
  342.     SetWallTxtObjX( xc^[ i ], xc^[ j ], zc^[ i ], TI^[ i ] );
  343.     END
  344. END;
  345. {
  346.  ╔═════════════════════════════════════════════════════════════════════════╗
  347.  ║ PROCEDURE MovePoint                                                     ║
  348.  ╟─────────────────────────────────────────────────────────────────────────╢
  349.  ║ Input  : XP, ZP are 8-bit fixed-pooint coordinates; X, Z are their inte-║
  350.  ║          ger parts; Xd, Zd, movement in X and Z directions; Angle is    ║
  351.  ║          viewing angle, not necessarely to moving direction             ║
  352.  ╟─────────────────────────────────────────────────────────────────────────╢
  353.  ║ Move the point, and if it didn't hit the wall, return new position.     ║
  354.  ╚═════════════════════════════════════════════════════════════════════════╝
  355. }
  356. PROCEDURE MovePoint( VAR XP, ZP : LongInt; VAR X, Z : Integer; Xd, Zd, Angle : Integer );
  357. VAR Xtmp0, Ztmp0, Xtmp1, Ztmp1 : LongInt;
  358. BEGIN
  359.   Xtmp0 := XP + Xd;
  360.   Ztmp0 := ZP + Zd; { check X and Z directions separately }
  361.   IF NOT HitTheWallX( Xtmp0, ZP, Angle ) THEN Xtmp1 := Xtmp0 ELSE Xtmp1 := XP;
  362.   IF NOT HitTheWallZ( XP, Ztmp0, Angle ) THEN Ztmp1 := Ztmp0 ELSE Ztmp1 := ZP;
  363.   XP := Xtmp1; { if we didn't hit the wall, return new coordinates }
  364.   ZP := Ztmp1;
  365.   X := XP DIV 256;
  366.   Z := ZP DIV 256
  367. END;
  368. {
  369.  ╔═════════════════════════════════════════════════════════════════════════╗
  370.  ║ PROCEDURE MoveEye                                                       ║
  371.  ╟─────────────────────────────────────────────────────────────────────────╢
  372.  ║ Input  : Speed and direction of the movement                            ║
  373.  ╟─────────────────────────────────────────────────────────────────────────╢
  374.  ║ If you want to move backwards, for examble, you should use Angle of 180 ║
  375.  ║ degrees, and positive speed, and NOT angle of 0, and negative speed,    ║
  376.  ║ because that would corrupt the hit-the-wall checking.                   ║
  377.  ╚═════════════════════════════════════════════════════════════════════════╝
  378. }
  379. PROCEDURE MoveEye( Angle, Speed : Integer );
  380. VAR Xd, Zd : Integer;
  381. BEGIN
  382.   WITH EyePA DO
  383.     BEGIN
  384.       Angle := ( YAng + Angle ) MOD 360;  { make sure that the angle }
  385.       IF Angle < 0 THEN Inc( Angle, 360 ); { is between 0..359 }
  386.       Xd := Integer( DSin[ Angle ] ) * Speed;
  387.       Zd := Integer( DCos[ Angle ] ) * Speed;
  388.       MovePoint( XP, ZP, X, Z, Xd, Zd, Angle )
  389.     END
  390. END;
  391. {
  392.  ╔═════════════════════════════════════════════════════════════════════════╗
  393.  ║ PROCEDURE TurnEye                                                       ║
  394.  ╟─────────────────────────────────────────────────────────────────────────╢
  395.  ║ Input  : how many degrees to turn, and turning direction (sign)         ║
  396.  ╟─────────────────────────────────────────────────────────────────────────╢
  397.  ║ Angle is converted to between 0-359                                     ║
  398.  ╚═════════════════════════════════════════════════════════════════════════╝
  399. }
  400. PROCEDURE TurnEye( Angle : Integer );
  401. BEGIN
  402.   WITH EyePA DO
  403.     BEGIN
  404.       YAng := ( YAng + Angle ) MOD 360;
  405.       IF YAng < 0 THEN Inc( YAng, 360 )
  406.     END
  407. END;
  408. {
  409.  ╔═════════════════════════════════════════════════════════════════════════╗
  410.  ║ PROCEDURE SetEyePos                                                     ║
  411.  ╟─────────────────────────────────────────────────────────────────────────╢
  412.  ║ Input  : 'Eye's' coordinates in the XZ plane, and viewing angle         ║
  413.  ╟─────────────────────────────────────────────────────────────────────────╢
  414.  ║ Coordinates must be between -WXDim/2..WXDim/2 and -WZDim/2..WZDim/2.    ║
  415.  ║ Coordinates are trasformed to positive, or to range 0..WXDim, 0..WZDim, ║
  416.  ║ and then they will be multiplied by WorldXZ, in order to move little    ║
  417.  ║ smaller steps (using integer arithmetic, of cource).                    ║
  418.  ║ XP and ZP contains the coordinates in 8-bit fixed-point form.           ║
  419.  ╚═════════════════════════════════════════════════════════════════════════╝
  420. }
  421. PROCEDURE SetEyePos( EyeX, EyeZ, Angle : Integer );
  422. BEGIN
  423.   WITH EyePA DO
  424.     BEGIN
  425.       X := EyeX;
  426.       Z := EyeZ;
  427.       MakeWorldPoint( X, Z );
  428.       XP := LongInt( X ) * 256;
  429.       ZP := LongInt( Z ) * 256;
  430.       YAng := Angle;
  431.     END;
  432. END;
  433.  
  434. BEGIN
  435.   Initialize
  436. END.
  437.  
  438.