WarPie90

Random game stuff Simba 1.4

Oct 29th, 2023 (edited)
1,988
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 17.79 KB | None | 0 0
  1. program LapeGame123;
  2. {$I SRL/osr.simba}
  3.  
  4. const
  5.   WIDTH  = 720;
  6.   HEIGHT = 480;
  7.  
  8.   // Colors
  9.   C_SKY      = $FF9933;
  10.   C_WALL     = $33AA55;
  11.   C_LAVA     = $0000FF;
  12.   C_WATER    = $FF9900;
  13.   C_CRATE    = $003366;
  14.   C_PIPE     = $C0C0C0;
  15.   C_CLOUD    = $FFFFFF;
  16.   C_PROJ     = $0000AA;
  17.   C_OBSIDIAN = $000000;
  18.  
  19.   // Physics
  20.   GRAVITY_AIR   = 0.9;
  21.   GRAVITY_WATER = 0.15;
  22.   JUMP_FORCE    = -16.5;
  23.   JUMP_WATER    = -5.0;
  24.  
  25.   MOVE_SPEED    = 5.0;
  26.   DASH_SPEED    = 8.5;
  27.   WATER_DRAG    = 0.6;
  28.  
  29.   MAX_BREATH    = 1800;
  30.   MAX_DASH      = 120;
  31.   RESPAWN_TIME  = 300;
  32.  
  33. type
  34.   TEntityType = (etPlayer, etWalker, etThrower);
  35.  
  36.   TProjectile = record
  37.     Active: Boolean;
  38.     Pos, Vel: Vector2;
  39.     Size: Integer;
  40.   end;
  41.  
  42.   // Forward declaration so TEntity can reference TGame in methods
  43.   TGame = record
  44.     Buffer: TMufasaBitmap;
  45.     Camera: TPoint;
  46.   end;
  47.  
  48.   TEntity = record
  49.     Active: Boolean;
  50.     EType: TEntityType;
  51.  
  52.     // Physics
  53.     Pos: Vector2;
  54.     HomePos: Vector2;
  55.     Vel: Vector2;
  56.     Size: TBox;
  57.     Color: Int32;
  58.  
  59.     // State
  60.     Grounded: Boolean;
  61.     FaceRight: Boolean;
  62.     RespawnTimer: Integer;
  63.  
  64.     // Water Logic
  65.     InWater: Boolean;
  66.     WaterSurfaceY: Integer;
  67.  
  68.     // Player Specific
  69.     Breath: Integer;
  70.     DashTimer: Integer;
  71.     LastTapTime: UInt64;
  72.     LastKey: Byte;
  73.  
  74.     // NPC Specific
  75.     AttackCooldown: Integer;
  76.  
  77.     SpriteL, SpriteR: TMufasaBitmap;
  78.   end;
  79.  
  80.   // Actual TGame Definition
  81.   TGameFull = record
  82.     Buffer: TMufasaBitmap;
  83.     Camera: TPoint;
  84.     Player: TEntity;
  85.     Enemies: array of TEntity;
  86.     Projectiles: array of TProjectile;
  87.  
  88.     // World Layers
  89.     Walls, Crates, Pipes, Lava, Water, Clouds, Obsidian: TBoxArray;
  90.   end;
  91.  
  92. var
  93.   Game: TGameFull;
  94.  
  95. // -----------------------------------------------------------------------------
  96. // Helpers
  97. // -----------------------------------------------------------------------------
  98.  
  99. function MakeBox(x, y, w, h: Int32): TBox;
  100. begin
  101.   Result := [x, y, x + w, y + h];
  102. end;
  103.  
  104. function CheckCollision(A, B: TBox): Boolean;
  105. begin
  106.   Result := (A.X1 < B.X2) and (A.X2 > B.X1) and (A.Y1 < B.Y2) and (A.Y2 > B.Y1);
  107. end;
  108.  
  109. // Pass G as TGameFull
  110. function CheckSolidCollision(Bounds: TBox; var G: TGameFull; out HitBox: TBox): Boolean;
  111. var i: Integer;
  112. begin
  113.   Result := True;
  114.   for i := 0 to High(G.Walls) do if CheckCollision(Bounds, G.Walls[i]) then begin HitBox := G.Walls[i]; Exit; end;
  115.   for i := 0 to High(G.Crates) do if CheckCollision(Bounds, G.Crates[i]) then begin HitBox := G.Crates[i]; Exit; end;
  116.   for i := 0 to High(G.Pipes) do if CheckCollision(Bounds, G.Pipes[i]) then begin HitBox := G.Pipes[i]; Exit; end;
  117.   for i := 0 to High(G.Obsidian) do if CheckCollision(Bounds, G.Obsidian[i]) then begin HitBox := G.Obsidian[i]; Exit; end;
  118.   Result := False;
  119. end;
  120.  
  121. function PointInBoxes(Pt: TPoint; Boxes: TBoxArray): Boolean;
  122. var i: Integer;
  123. begin
  124.   Result := False;
  125.   for i := 0 to High(Boxes) do if Boxes[i].Contains(Pt) then Exit(True);
  126. end;
  127.  
  128. // -----------------------------------------------------------------------------
  129. // Entity Logic
  130. // -----------------------------------------------------------------------------
  131.  
  132. procedure TEntity.Init(StartX, StartY: Double; EType: TEntityType);
  133. begin
  134.   Self.Active := True;
  135.   Self.EType  := EType;
  136.   Self.Pos    := [StartX, StartY];
  137.   Self.HomePos:= [StartX, StartY];
  138.   Self.Vel    := [0, 0];
  139.   Self.FaceRight := True;
  140.   Self.Size   := [0, 0, 40, 40];
  141.   Self.RespawnTimer := 0;
  142.  
  143.   case EType of
  144.     etPlayer:
  145.     begin
  146.       Self.Color := $0000FF;
  147.       Self.Breath := MAX_BREATH;
  148.     end;
  149.     etWalker:
  150.     begin
  151.       Self.Color := $00FFFF;
  152.       Self.Vel.x := 2.0;
  153.     end;
  154.     etThrower:
  155.     begin
  156.       Self.Color := $800080;
  157.       Self.Vel.x := 1.5;
  158.     end;
  159.   end;
  160. end;
  161.  
  162. function TEntity.GetBounds(): TBox;
  163. begin
  164.   Result.X1 := Round(Self.Pos.X);
  165.   Result.Y1 := Round(Self.Pos.Y);
  166.   Result.X2 := Result.X1 + Self.Size.X2;
  167.   Result.Y2 := Result.Y1 + Self.Size.Y2;
  168. end;
  169.  
  170. function TEntity.ShouldTurnAround(var G: TGameFull): Boolean;
  171. var
  172.   Feeler: TPoint;
  173.   LookAhead: Integer;
  174. begin
  175.   if not Self.Grounded then Exit(False);
  176.   LookAhead := Round(Abs(Self.Vel.X) * 10) + 10;
  177.  
  178.   if Self.Vel.X > 0 then Feeler.X := Round(Self.Pos.X) + Self.Size.X2 + LookAhead
  179.   else Feeler.X := Round(Self.Pos.X) - LookAhead;
  180.  
  181.   // Cliff Check
  182.   Feeler.Y := Round(Self.Pos.Y) + Self.Size.Y2 + 5;
  183.   if (not PointInBoxes(Feeler, G.Walls)) and
  184.      (not PointInBoxes(Feeler, G.Obsidian)) and
  185.      (not PointInBoxes(Feeler, G.Crates)) and
  186.      (not PointInBoxes(Feeler, G.Pipes)) then Exit(True);
  187.  
  188.   // Hazard Check
  189.   Feeler.Y := Round(Self.Pos.Y) + Self.Size.Y2 - 10;
  190.   if PointInBoxes(Feeler, G.Lava) or PointInBoxes(Feeler, G.Water) then Exit(True);
  191.  
  192.   Result := False;
  193. end;
  194.  
  195. procedure SpawnProjectile(StartPos, TargetPos: Vector2; var G: TGameFull);
  196. var
  197.   Idx: Integer;
  198. begin
  199.   Idx := Length(G.Projectiles);
  200.   SetLength(G.Projectiles, Idx + 1);
  201.   G.Projectiles[Idx].Active := True;
  202.   G.Projectiles[Idx].Size := 10;
  203.   G.Projectiles[Idx].Pos := StartPos;
  204.   G.Projectiles[Idx].Vel.Y := -6.0;
  205.   if TargetPos.X > StartPos.X then G.Projectiles[Idx].Vel.X := 5.0
  206.   else G.Projectiles[Idx].Vel.X := -5.0;
  207. end;
  208.  
  209. procedure TEntity.UpdatePhysics(var G: TGameFull);
  210. var
  211.   Predicted, HitBox: TBox;
  212.   i: Integer;
  213.   DistToPlayer: Double;
  214. begin
  215.   if not Self.Active then
  216.   begin
  217.     if Self.EType = etPlayer then Exit;
  218.     if Self.RespawnTimer > 0 then
  219.     begin
  220.       Dec(Self.RespawnTimer);
  221.       if Self.RespawnTimer <= 0 then Self.Init(Self.HomePos.X, Self.HomePos.Y, Self.EType);
  222.     end;
  223.     Exit;
  224.   end;
  225.  
  226.   Self.Grounded := False;
  227.   Self.InWater := False;
  228.  
  229.   // --- Attack Logic ---
  230.   if (Self.EType = etThrower) and (Self.AttackCooldown > 0) then Dec(Self.AttackCooldown);
  231.   if (Self.EType = etThrower) and (Self.AttackCooldown <= 0) then
  232.   begin
  233.     DistToPlayer := Hypot(Self.Pos.X - G.Player.Pos.X, Self.Pos.Y - G.Player.Pos.Y);
  234.     if DistToPlayer < 350 then
  235.     begin
  236.       SpawnProjectile(Self.Pos, G.Player.Pos, G);
  237.       Self.AttackCooldown := 120;
  238.     end;
  239.   end;
  240.  
  241.   if (Self.EType = etPlayer) and (Self.DashTimer > 0) then Dec(Self.DashTimer);
  242.  
  243.   // --- Water Check ---
  244.   Predicted := Self.GetBounds();
  245.   for i := 0 to High(G.Water) do
  246.     if CheckCollision(Predicted, G.Water[i]) then
  247.     begin
  248.       Self.InWater := True;
  249.       Self.WaterSurfaceY := G.Water[i].Y1;
  250.       Break;
  251.     end;
  252.  
  253.   // --- Lava Check ---
  254.   for i := 0 to High(G.Lava) do
  255.     if CheckCollision(Predicted, G.Lava[i]) then
  256.     begin
  257.       if Self.EType = etPlayer then
  258.       begin
  259.          WriteLn('Burned!');
  260.          Self.Init(100, 300, etPlayer);
  261.          G.Camera := [0,0];
  262.          Exit;
  263.       end
  264.       else
  265.       begin
  266.         Self.Active := False;
  267.         Self.RespawnTimer := RESPAWN_TIME;
  268.       end;
  269.       Exit;
  270.     end;
  271.  
  272.   // --- Breath Logic ---
  273.   if Self.EType = etPlayer then
  274.   begin
  275.     if Self.InWater then
  276.     begin
  277.       Dec(Self.Breath);
  278.       if Self.Breath <= 0 then
  279.       begin
  280.         Self.Init(100, 300, etPlayer);
  281.         G.Camera := [0,0];
  282.         Exit;
  283.       end;
  284.     end
  285.     else
  286.       Self.Breath := MAX_BREATH;
  287.   end;
  288.  
  289.   // --- X Movement ---
  290.   if Self.InWater then Self.Vel.X := Self.Vel.X * WATER_DRAG;
  291.   Self.Pos.X := Self.Pos.X + Self.Vel.X;
  292.  
  293.   Predicted := Self.GetBounds();
  294.   if CheckSolidCollision(Predicted, G, HitBox) then
  295.   begin
  296.       if Self.Vel.X > 0 then Self.Pos.X := HitBox.X1 - Self.Size.X2
  297.       else if Self.Vel.X < 0 then Self.Pos.X := HitBox.X2;
  298.  
  299.       if Self.EType = etPlayer then Self.Vel.X := 0
  300.       else Self.Vel.X := -Self.Vel.X;
  301.   end;
  302.  
  303.   // --- Turn Logic ---
  304.   if (Self.EType <> etPlayer) and Self.Grounded and (Self.Vel.X <> 0) then
  305.   begin
  306.     if Self.ShouldTurnAround(G) then Self.Vel.X := -Self.Vel.X;
  307.   end;
  308.  
  309.   // --- Y Movement ---
  310.   Self.Pos.Y := Self.Pos.Y + Self.Vel.Y;
  311.   Predicted := Self.GetBounds();
  312.   if CheckSolidCollision(Predicted, G, HitBox) then
  313.   begin
  314.       if Self.Vel.Y > 0 then
  315.       begin
  316.         Self.Pos.Y := HitBox.Y1 - Self.Size.Y2;
  317.         Self.Grounded := True;
  318.       end
  319.       else if Self.Vel.Y < 0 then
  320.         Self.Pos.Y := HitBox.Y2;
  321.  
  322.       Self.Vel.Y := 0;
  323.   end;
  324.  
  325.   // --- Gravity ---
  326.   if Self.InWater then
  327.   begin
  328.     Self.Vel.Y := Self.Vel.Y + GRAVITY_WATER;
  329.     if Self.Vel.Y > 3 then Self.Vel.Y := 3;
  330.   end
  331.   else
  332.   begin
  333.     Self.Vel.Y := Self.Vel.Y + GRAVITY_AIR;
  334.     if Self.Vel.Y > 15 then Self.Vel.Y := 15;
  335.   end;
  336.  
  337.   if Self.Pos.Y > 1200 then
  338.   begin
  339.     if Self.EType = etPlayer then
  340.     begin
  341.        Self.Init(100, 300, etPlayer);
  342.        G.Camera := [0,0];
  343.     end else
  344.     begin
  345.        Self.Active := False;
  346.        Self.RespawnTimer := RESPAWN_TIME;
  347.     end;
  348.   end;
  349. end;
  350.  
  351. procedure TEntity.Draw(Buffer: TMufasaBitmap; Cam: TPoint);
  352. var
  353.   DrawBox: TBox;
  354.   Pct: Double;
  355.   BarW: Int32;
  356. begin
  357.   if not Self.Active then Exit;
  358.  
  359.   DrawBox := Self.GetBounds();
  360.   DrawBox := DrawBox.Offset(Point(-Cam.X, -Cam.Y));
  361.  
  362.   Buffer.DrawBoxFilled(DrawBox, False, Self.Color);
  363.  
  364.   if Self.EType = etPlayer then
  365.   begin
  366.     if Self.Breath < MAX_BREATH then
  367.     begin
  368.       Pct := Self.Breath / MAX_BREATH;
  369.       BarW := Round(40 * Pct);
  370.       Buffer.DrawBoxFilled([DrawBox.X1, DrawBox.Y1 - 10, DrawBox.X1 + 40, DrawBox.Y1 - 5], False, $000000);
  371.       Buffer.DrawBoxFilled([DrawBox.X1, DrawBox.Y1 - 10, DrawBox.X1 + BarW, DrawBox.Y1 - 5], False, $00FFFF);
  372.     end;
  373.     if Self.DashTimer > 0 then
  374.     begin
  375.       Pct := Self.DashTimer / MAX_DASH;
  376.       BarW := Round(40 * Pct);
  377.       Buffer.DrawBoxFilled([DrawBox.X1, DrawBox.Y1 - 16, DrawBox.X1 + 40, DrawBox.Y1 - 11], False, $000000);
  378.       Buffer.DrawBoxFilled([DrawBox.X1, DrawBox.Y1 - 16, DrawBox.X1 + BarW, DrawBox.Y1 - 11], False, $FFFF00);
  379.     end;
  380.   end;
  381. end;
  382.  
  383. // -----------------------------------------------------------------------------
  384. // Projectiles & Main
  385. // -----------------------------------------------------------------------------
  386.  
  387. procedure UpdateProjectiles(var G: TGameFull);
  388. var
  389.   i: Integer;
  390.   ProjBox, Hit, PlayerBox: TBox;
  391. begin
  392.   PlayerBox := G.Player.GetBounds();
  393.   for i := 0 to High(G.Projectiles) do
  394.   begin
  395.     if not G.Projectiles[i].Active then Continue;
  396.     G.Projectiles[i].Pos.X := G.Projectiles[i].Pos.X + G.Projectiles[i].Vel.X;
  397.     G.Projectiles[i].Pos.Y := G.Projectiles[i].Pos.Y + G.Projectiles[i].Vel.Y;
  398.     G.Projectiles[i].Vel.Y := G.Projectiles[i].Vel.Y + GRAVITY_AIR;
  399.  
  400.     ProjBox := [Round(G.Projectiles[i].Pos.X), Round(G.Projectiles[i].Pos.Y),
  401.                 Round(G.Projectiles[i].Pos.X) + G.Projectiles[i].Size,
  402.                 Round(G.Projectiles[i].Pos.Y) + G.Projectiles[i].Size];
  403.  
  404.     if CheckSolidCollision(ProjBox, G, Hit) or (ProjBox.Y1 > 1200) then
  405.     begin
  406.       G.Projectiles[i].Active := False;
  407.       Continue;
  408.     end;
  409.  
  410.     if CheckCollision(ProjBox, PlayerBox) then
  411.     begin
  412.       G.Player.Init(100, 300, etPlayer);
  413.       G.Camera := [0,0];
  414.       G.Projectiles[i].Active := False;
  415.     end;
  416.   end;
  417. end;
  418.  
  419. procedure TGameFull.Setup();
  420. var
  421.   i, x, GapType, PropRoll: Integer;
  422.   LastGapType: Integer;
  423. begin
  424.   Self.Buffer.Init();
  425.   Self.Buffer.SetSize(WIDTH, HEIGHT);
  426.   Self.Player.Init(100, 250, etPlayer);
  427.  
  428.   SetLength(Self.Enemies, 30);
  429.   for i := 0 to High(Self.Enemies) do
  430.   begin
  431.     if Random(3) = 0 then Self.Enemies[i].Init(500 + (i * 600), 100, etThrower)
  432.     else Self.Enemies[i].Init(500 + (i * 600), 100, etWalker);
  433.   end;
  434.  
  435.   Self.Walls += MakeBox(-100, 350, 600, 200);
  436.   x := 500;
  437.   LastGapType := 0;
  438.  
  439.   while x < 40000 do
  440.   begin
  441.     if Random(2) = 0 then
  442.       Self.Clouds += MakeBox(x + Random(200), Random(50, 200), Random(80, 150), Random(30, 50));
  443.  
  444.     GapType := Random(0, 5);
  445.  
  446.     // Obsidian Gen (Prevent Water touching Lava)
  447.     if ((LastGapType = 4) and (GapType = 5)) or ((LastGapType = 5) and (GapType = 4)) then
  448.     begin
  449.       Self.Obsidian += MakeBox(x, 350, 50, 200);
  450.       x := x + 50;
  451.     end;
  452.  
  453.     if GapType <= 3 then // Land
  454.     begin
  455.       Self.Walls += MakeBox(x, 350, Random(300, 700), 200);
  456.       PropRoll := Random(10);
  457.       if PropRoll <= 2 then Self.Pipes += MakeBox(x + 50, 300, 60, 50)
  458.       else if PropRoll = 3 then
  459.       begin
  460.          Self.Pipes += MakeBox(x + 100, 250, 60, 100);
  461.          Self.Crates += MakeBox(x + 40, 310, 40, 40);
  462.       end;
  463.       if PropRoll = 4 then
  464.       begin
  465.          Self.Crates += MakeBox(x + 150, 310, 40, 40);
  466.          Self.Crates += MakeBox(x + 190, 310, 40, 40);
  467.          Self.Crates += MakeBox(x + 170, 270, 40, 40);
  468.       end
  469.       else if PropRoll >= 8 then
  470.       begin
  471.          Self.Crates += MakeBox(x + 100, 200, 40, 40);
  472.          Self.Crates += MakeBox(x + 140, 200, 40, 40);
  473.       end;
  474.       x := Self.Walls[High(Self.Walls)].X2;
  475.       LastGapType := 0;
  476.     end
  477.     else if GapType = 4 then // Water
  478.     begin
  479.       Self.Water += MakeBox(x, 370, 300, 180);
  480.       x += 300;
  481.       LastGapType := 4;
  482.     end
  483.     else // Lava
  484.     begin
  485.       Self.Lava += MakeBox(x, 380, 200, 50);
  486.       Self.Crates += MakeBox(x + 80, 280, 40, 40);
  487.       x += 200;
  488.       LastGapType := 5;
  489.     end;
  490.   end;
  491.   DisplayDebugImgWindow(WIDTH, HEIGHT);
  492. end;
  493.  
  494. procedure TGameFull.UpdateInput();
  495. var
  496.   TargetSpeed: Double;
  497.   CurrTime: UInt64;
  498. begin
  499.   CurrTime := GetTickCount();
  500.   TargetSpeed := MOVE_SPEED;
  501.   if Self.Player.DashTimer > 0 then TargetSpeed := DASH_SPEED;
  502.  
  503.   Self.Player.Vel.X := Self.Player.Vel.X * 0.80;
  504.   if Abs(Self.Player.Vel.X) < 0.1 then Self.Player.Vel.X := 0;
  505.  
  506.   if IsKeyDown(VK_RIGHT) then
  507.   begin
  508.     if (Self.Player.LastKey <> VK_RIGHT) then
  509.     begin
  510.       if (CurrTime - Self.Player.LastTapTime < 250) and (Self.Player.LastKey = 0) then
  511.       begin
  512.          Self.Player.DashTimer := MAX_DASH;
  513.          TargetSpeed := DASH_SPEED;
  514.       end;
  515.       Self.Player.LastTapTime := CurrTime;
  516.     end;
  517.     Self.Player.LastKey := VK_RIGHT;
  518.     Self.Player.Vel.X := TargetSpeed;
  519.     Self.Player.FaceRight := True;
  520.   end
  521.   else if IsKeyDown(VK_LEFT) then
  522.   begin
  523.     if (Self.Player.LastKey <> VK_LEFT) then
  524.     begin
  525.       if (CurrTime - Self.Player.LastTapTime < 250) and (Self.Player.LastKey = 0) then
  526.       begin
  527.          Self.Player.DashTimer := MAX_DASH;
  528.          TargetSpeed := DASH_SPEED;
  529.       end;
  530.       Self.Player.LastTapTime := CurrTime;
  531.     end;
  532.     Self.Player.LastKey := VK_LEFT;
  533.     Self.Player.Vel.X := -TargetSpeed;
  534.     Self.Player.FaceRight := False;
  535.   end
  536.   else
  537.     Self.Player.LastKey := 0;
  538.  
  539.   if IsKeyDown(VK_SPACE) then
  540.   begin
  541.     if Self.Player.InWater then
  542.     begin
  543.       Self.Player.Vel.Y := Self.Player.Vel.Y - 1.5;
  544.       if Self.Player.Vel.Y < JUMP_WATER then Self.Player.Vel.Y := JUMP_WATER;
  545.  
  546.       // Water Exit Force
  547.       if Self.Player.Pos.Y <= (Self.Player.WaterSurfaceY + 15) then
  548.         Self.Player.Vel.Y := JUMP_FORCE * 0.85;
  549.     end
  550.     else if Self.Player.Grounded then
  551.       Self.Player.Vel.Y := JUMP_FORCE;
  552.   end;
  553. end;
  554.  
  555. procedure TGameFull.CheckCombat();
  556. var
  557.   i: Integer;
  558.   PBox, EBox: TBox;
  559. begin
  560.   PBox := Self.Player.GetBounds();
  561.   for i := 0 to High(Self.Enemies) do
  562.   begin
  563.     if not Self.Enemies[i].Active then Continue;
  564.     EBox := Self.Enemies[i].GetBounds();
  565.     if CheckCollision(PBox, EBox) then
  566.     begin
  567.       if (Self.Player.Vel.Y > 0) and (PBox.Y2 < EBox.Y2 - 10) then
  568.       begin
  569.         Self.Enemies[i].Active := False;
  570.         Self.Enemies[i].RespawnTimer := RESPAWN_TIME;
  571.         Self.Player.Vel.Y := -10.0;
  572.       end
  573.       else
  574.       begin
  575.         Self.Player.Init(100, 300, etPlayer);
  576.         Self.Camera := [0,0];
  577.       end;
  578.     end;
  579.   end;
  580. end;
  581.  
  582. procedure TGameFull.Update();
  583. var
  584.   i, PlayerScreenX, PlayerScreenY: Integer;
  585. begin
  586.   Self.UpdateInput();
  587.   Self.Player.UpdatePhysics(Self);
  588.   for i := 0 to High(Self.Enemies) do Self.Enemies[i].UpdatePhysics(Self);
  589.   UpdateProjectiles(Self);
  590.   Self.CheckCombat();
  591.  
  592.   PlayerScreenX := Round(Self.Player.Pos.X) - Self.Camera.X;
  593.   PlayerScreenY := Round(Self.Player.Pos.Y) - Self.Camera.Y;
  594.   if PlayerScreenX > 450 then Self.Camera.X := Round(Self.Player.Pos.X) - 450;
  595.   if PlayerScreenX < 200 then Self.Camera.X := Round(Self.Player.Pos.X) - 200;
  596.   if Self.Camera.X < 0 then Self.Camera.X := 0;
  597.   if PlayerScreenY < 150 then Self.Camera.Y := Round(Self.Player.Pos.Y) - 150;
  598.   if PlayerScreenY > 330 then Self.Camera.Y := Round(Self.Player.Pos.Y) - 330;
  599.   if Self.Camera.Y > 50 then Self.Camera.Y := 50;
  600. end;
  601.  
  602. procedure TGameFull.Render();
  603.   procedure DrawLayer(Boxes: TBoxArray; Col: Int32);
  604.   var b, dw: TBox;
  605.   begin
  606.     for b in Boxes do
  607.     begin
  608.       dw := b.Offset(Point(-Self.Camera.X, -Self.Camera.Y));
  609.       if (dw.X2 > 0) and (dw.X1 < WIDTH) and (dw.Y2 > 0) and (dw.Y1 < HEIGHT) then
  610.         Self.Buffer.DrawBoxFilled(dw, False, Col);
  611.     end;
  612.   end;
  613. var i: Integer;
  614. begin
  615.   Self.Buffer.DrawClear(C_SKY);
  616.   DrawLayer(Self.Clouds, C_CLOUD);
  617.   DrawLayer(Self.Walls,  C_WALL);
  618.   DrawLayer(Self.Obsidian, C_OBSIDIAN);
  619.   DrawLayer(Self.Crates, C_CRATE);
  620.   DrawLayer(Self.Pipes,  C_PIPE);
  621.   DrawLayer(Self.Lava,   C_LAVA);
  622.   DrawLayer(Self.Water,  C_WATER);
  623.  
  624.   for i := 0 to High(Self.Projectiles) do
  625.     if Self.Projectiles[i].Active then
  626.     begin
  627.        Self.Buffer.DrawBoxFilled([Round(Self.Projectiles[i].Pos.X)-Self.Camera.X, Round(Self.Projectiles[i].Pos.Y)-Self.Camera.Y,
  628.                                   Round(Self.Projectiles[i].Pos.X)+Self.Projectiles[i].Size-Self.Camera.X,
  629.                                   Round(Self.Projectiles[i].Pos.Y)+Self.Projectiles[i].Size-Self.Camera.Y], False, C_PROJ);
  630.     end;
  631.  
  632.   for i := 0 to High(Self.Enemies) do Self.Enemies[i].Draw(Self.Buffer, Self.Camera);
  633.   Self.Player.Draw(Self.Buffer, Self.Camera);
  634.   DrawBitmapDebugImg(Self.Buffer);
  635. end;
  636.  
  637. procedure TGameFull.Loop();
  638. begin
  639.   while True do
  640.   begin
  641.     Self.Update();
  642.     Self.Render();
  643.     Wait(16);
  644.   end;
  645. end;
  646.  
  647. begin
  648.   ClearDebug();
  649.   Game.Setup();
  650.   Game.Loop();
  651. end.
  652.  
Advertisement
Add Comment
Please, Sign In to add comment