Changeset 4 for trunk/UCore.pas


Ignore:
Timestamp:
Mar 6, 2011, 6:43:01 PM (13 years ago)
Author:
george
Message:
  • Added: Complete map visualizaiton.
  • Added: Generating map rock border.
  • Added: Tank movement colision detection.
  • Added: Some bullet shooting test.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UCore.pas

    r3 r4  
    88  Dialogs, Classes, SysUtils, Contnrs, Graphics, SpecializedMatrix, SpecializedList;
    99
     10const
     11  MaxBulletCount = 10;
     12
    1013type
    1114  TEngine = class;
    12 
    13   TSurfaceMatter = (smNothing, smDirt1, smDirt2, smRock,
    14     smPlayer1H, smPlayer1L, smPlayer2H, smPlayer2L, smCannon, smBullet);
     15  TPlayer = class;
     16
     17  TSurfaceMatter = (smNothing, smDirt1, smDirt2, smRock, smCannon, smBullet,
     18    smPlayer1H, smPlayer1L, smPlayer2H, smPlayer2L,
     19    smPlayer3H, smPlayer3L, smPlayer4H, smPlayer4L);
    1520
    1621  TPlayerKeys = record
     
    2227  end;
    2328
     29  TBullet = class
     30    Player: TPlayer;
     31    Position: TPoint;
     32    Direction: Integer;
     33  end;
     34
    2435  { TTank }
    2536
     
    3546  TPlayer = class
    3647  private
     48    NewDirection: Integer;
     49    NewPosition: TPoint;
     50    Dig: Boolean;
    3751    function ShowTankProc(Item1, Item2: Byte): Byte;
    3852    function HideTankProc(Item1, Item2: Byte): Byte;
     
    4660    Keys: TPlayerKeys;
    4761    Tanks: TListObject;
     62    Bullets: TListObject;
    4863    procedure Control;
    4964    procedure Paint;
    5065    procedure PlaceHouse;
    51     function CheckColision: Boolean;
     66    function CheckColision: TSurfaceMatter;
    5267    procedure ShowTank;
    5368    procedure HideTank;
     
    6984    constructor Create;
    7085    destructor Destroy; override;
     86    procedure DrawToBitmap(Bitmap: TBitmap);
    7187    property Size: TMatrixByteIndex read GetSize write SetSize;
    7288  end;
     
    7894    FBitmap: TBitmap;
    7995    FRedrawPending: Boolean;
     96    FBitmapLower: TBitmap;
    8097    function GetPlayerCount: Integer;
    8198    procedure SetBitmap(const AValue: TBitmap);
     
    90107    procedure ResizePlayerFrames;
    91108    procedure Tick;
     109    procedure Draw;
    92110    property PlayerCount: Integer read GetPlayerCount write SetPlayerCount;
    93111    property Bitmap: TBitmap read FBitmap write SetBitmap;
     
    97115const
    98116  SurfaceMatterColors: array[TSurfaceMatter] of TColor = (clBlack, $0756b0,
    99     $2170c3, TColor($9a9a9a), TColor($00ff00), TColor($00a000),
    100     TColor($ff2c2c), TColor($b60000), clYellow, clRed);
     117    $2170c3, TColor($9a9a9a), clYellow, clRed,
     118    TColor($00ff00), TColor($00a000), TColor($ff2c2c), TColor($b60000),
     119    TColor($0000ff), TColor($0000a0), TColor($ff2cff), TColor($b600b6));
     120  DirectionToDelta: array[0..7] of TPoint =
     121    ((X: 0; Y: -1), (X: 1; Y: -1), (X: 1; Y: 0), (X: 1; Y: 1),
     122    (X: 0; Y: 1), (X: -1; Y: 1), (X: -1; Y: 0), (X: -1; Y: -1));
    101123
    102124var
     
    136158var
    137159  X, Y: Integer;
     160  Distance: Double;
     161  Delta: Double;
    138162begin
    139163  for Y := 0 to Surface.Count.Y - 1 do
     
    143167        Surface.ItemsXY[Y, X] := Byte(smDirt2);
    144168    end;
     169
     170  Distance := 0.1 * Surface.Count.X;
     171  Delta := 0;
     172  for Y := 0 to Surface.Count.Y - 1 do begin
     173    for X := 0 to Round(Distance) - 1 do begin
     174      Surface.ItemsXY[Y, X] := Byte(smRock);
     175    end;
     176    Delta := (Random * 2 - 1) * 3 - (Distance / (0.1 * Surface.Count.X) * 2 - 1);
     177    Distance := Distance + Delta;
     178  end;
     179
     180  Distance := 0.1 * Surface.Count.X;
     181  Delta := 0;
     182  for Y := 0 to Surface.Count.Y - 1 do begin
     183    for X := 0 to Round(Distance) - 1 do begin
     184      Surface.ItemsXY[Y, Surface.Count.X - 1 - X] := Byte(smRock);
     185    end;
     186    Delta := (Random * 2 - 1) * 3 - (Distance / (0.1 * Surface.Count.X) * 2 - 1);
     187    Distance := Distance + Delta;
     188  end;
     189
     190  Distance := 0.1 * Surface.Count.Y;
     191  Delta := 0;
     192  for X := 0 to Surface.Count.X - 1 do begin
     193    for Y := 0 to Round(Distance) - 1 do begin
     194      Surface.ItemsXY[Y, X] := Byte(smRock);
     195    end;
     196    Delta := (Random * 2 - 1) * 3 - (Distance / (0.1 * Surface.Count.Y) * 2 - 1);
     197    Distance := Distance + Delta;
     198  end;
     199
     200  Distance := 0.1 * Surface.Count.Y;
     201  Delta := 0;
     202  for X := 0 to Surface.Count.X - 1 do begin
     203    for Y := 0 to Round(Distance) - 1 do begin
     204      Surface.ItemsXY[Surface.Count.Y - 1 - Y, X] := Byte(smRock);
     205    end;
     206    Delta := (Random * 2 - 1) * 3 - (Distance / (0.1 * Surface.Count.Y) * 2 - 1);
     207    Distance := Distance + Delta;
     208  end;
    145209end;
    146210
     
    150214begin
    151215  Surface := TMatrixByte.Create;
    152   NewSize.X := 100;
    153   NewSize.Y := 100;
     216  NewSize.X := 800;
     217  NewSize.Y := 300;
    154218  Size := NewSize;
    155219end;
     
    161225end;
    162226
     227procedure TWorld.DrawToBitmap(Bitmap: TBitmap);
     228var
     229  X, Y: Integer;
     230begin
     231  try
     232    Bitmap.BeginUpdate(True);
     233  for Y := 0 to Bitmap.Height - 1 do
     234    for X := 0 to Bitmap.Width - 1 do
     235      Bitmap.Canvas.Pixels[X, Y] := SurfaceMatterColors[TSurfaceMatter(
     236        Surface.ItemsXY[Trunc(Y / Bitmap.Height * Surface.Count.Y),
     237        Trunc(X / Bitmap.Width * Surface.Count.X)])];
     238  finally
     239    Bitmap.EndUpdate;
     240  end;
     241end;
     242
    163243{ TPlayer }
    164244
    165245procedure TPlayer.Control;
    166246var
    167   NewPosition: TPoint;
    168   NewDirection: Integer;
    169247  Delta: TPoint;
     248  Matter: TSurfaceMatter;
     249  NewBullet: TBullet;
     250  I: Integer;
    170251begin
    171252  Delta.X := 0;
    172253  Delta.Y := 0;
    173   if Engine.KeyState[Ord(Keys.Up)] then Delta.Y := Delta.Y + 1;
    174   if Engine.KeyState[Ord(Keys.Down)] then Delta.Y := Delta.Y - 1;
     254  if Engine.KeyState[Ord(Keys.Down)] then Delta.Y := Delta.Y + 1;
     255  if Engine.KeyState[Ord(Keys.Up)] then Delta.Y := Delta.Y - 1;
    175256  if Engine.KeyState[Ord(Keys.Right)] then Delta.X := Delta.X + 1;
    176257  if Engine.KeyState[Ord(Keys.Left)] then Delta.X := Delta.X - 1;
     
    186267    else if (Delta.X = -1) and (Delta.Y = 0) then NewDirection := 6
    187268    else if (Delta.X = -1) and (Delta.Y = -1) then NewDirection := 7;
    188   end;
    189 
    190   NewPosition := Point(Position.X + Delta.X, Position.Y + Delta.Y);
    191   if CheckColision then begin
     269
     270    if NewDirection = Direction then
     271      NewPosition := Point(Position.X + Delta.X, Position.Y + Delta.Y)
     272      else NewPosition := Position;
    192273    HideTank;
    193     Position := NewPosition;
    194     Direction := NewDirection;
     274    Matter := CheckColision;
     275    if (Matter = smDirt1) then Dig := not Dig;
     276    if (Matter = smNothing) or ((Matter = smDirt1) and (not Dig)) then begin
     277      Position := NewPosition;
     278      Direction := NewDirection;
     279      Engine.Redraw;
     280    end;
    195281    ShowTank;
    196     Engine.Redraw;
     282  end;
     283
     284
     285  if Engine.KeyState[Ord(Keys.Shoot)] then
     286    if Bullets.Count < MaxBulletCount then begin
     287      NewBullet := TBullet.Create;
     288      NewBullet.Player := Self;
     289      NewBullet.Position := Position;
     290      NewBullet.Direction := Direction;
     291      Bullets.Add(NewBullet);
     292    end;
     293
     294  for I := Bullets.Count - 1 downto 0 do
     295  with TBullet(Bullets[I]) do begin
     296    Engine.World.Surface.ItemsXY[Position.Y, Position.X] := Byte(smNothing);
     297
     298    Position.X := Position.X + DirectionToDelta[Direction].X;
     299    Position.Y := Position.Y + DirectionToDelta[Direction].Y;
     300
     301    with Engine.World.Surface do
     302    if (Position.X >= Count.X) or (Position.X < 0) or
     303      (Position.Y >= Count.Y) or (Position.Y < 0) then
     304      Bullets.Delete(I) else
     305      Engine.World.Surface.ItemsXY[Position.Y, Position.X] := Byte(smBullet);
    197306  end;
    198307end;
     
    203312  XX, YY: Integer;
    204313begin
    205   with Engine.Bitmap.Canvas do begin
     314  with Engine.FBitmapLower.Canvas do begin
    206315    Rectangle(ScreenFrame);
    207     //FillRect(ScreenFrame);
     316    Brush.Color := SurfaceMatterColors[smRock];
     317    FillRect(ScreenFrame);
    208318
    209319
     
    248358end;
    249359
    250 function TPlayer.CheckColision: Boolean;
    251 begin
    252 
     360function TPlayer.CheckColision: TSurfaceMatter;
     361var
     362  X, Y: Integer;
     363begin
     364  Result := smNothing;
     365  with Engine.World, TTank(Tanks[NewDirection]) do
     366  for Y := 0 to Image.Count.Y - 1 do
     367  for X := 0 to Image.Count.X - 1 do
     368    if (Image.ItemsXY[Y, X] > 0) and
     369    (Surface.ItemsXY[Y + NewPosition.Y, X + NewPosition.X] <> Byte(smNothing)) then
     370    begin
     371      Result := smDirt1;
     372      if (Surface.ItemsXY[Y + NewPosition.Y, X + NewPosition.X] <> Byte(smDirt1)) and
     373      (Surface.ItemsXY[Y + NewPosition.Y, X + NewPosition.X] <> Byte(smDirt2)) then
     374      begin
     375        Result := TSurfaceMatter(Surface.ItemsXY[Y + NewPosition.Y, X + NewPosition.X]);
     376        Exit;
     377      end;
     378    end;
    253379end;
    254380
     
    261387begin
    262388  with Engine.World do begin
    263     Surface.Merge(TMatrixByte.Point(Position.X, Position.Y), TTank(Tanks[Direction]).Image, ShowTankProc);
     389    Surface.Merge(Surface.CreateIndex(Position.X, Position.Y), TTank(Tanks[Direction]).Image, ShowTankProc);
    264390  end;
    265391end;
     
    273399begin
    274400  with Engine.World do begin
    275     Surface.Merge(TMatrixByte.Point(Position.X, Position.Y), TTank(Tanks[Direction]).Image, HideTankProc);
     401    Surface.Merge(Surface.CreateIndex(Position.X, Position.Y), TTank(Tanks[Direction]).Image, HideTankProc);
    276402  end;
    277403end;
     
    287413  NewTank := TTank.Create;
    288414  with NewTank do begin
    289     Image.Count := TMatrixByte.Point(7, 7);
     415    Image.Count := Image.CreateIndex(7, 7);
    290416    for I := 0 to 3 do
    291417      Image[I, 3] := Byte(smCannon);
     
    305431  NewTank := TTank.Create;
    306432  with NewTank do begin
    307     Image.Count := TMatrixByte.Point(7, 7);
     433    Image.Count := Image.CreateIndex(7, 7);
    308434    for I := 0 to 2 do
    309435      Image[3 - I, 3 + I] := Byte(smCannon);
     
    368494begin
    369495  Tanks := TListObject.Create;
     496  Bullets := TListObject.Create;
    370497end;
    371498
    372499destructor TPlayer.Destroy;
    373500begin
     501  Bullets.Free;
    374502  Tanks.Free;
    375503  inherited Destroy;
     
    422550  I: Integer;
    423551begin
    424   // TODO: Determine frames from player count
    425   if Assigned(Bitmap) then begin
    426     HorizFrameCount := 2;
    427     VertFrameCount := 1;
     552  if Assigned(FBitmapLower) then begin
     553    if Players.Count > 1 then begin
     554      if Players.Count > 2 then VertFrameCount := 2
     555        else VertFrameCount := 1;
     556      HorizFrameCount := Round(Players.Count / VertFrameCount);
     557    end else begin
     558      VertFrameCount := 1;
     559      HorizFrameCount := 1;
     560    end;
     561    FBitmapLower.SetSize(80 * HorizFrameCount, 60 * VertFrameCount);
    428562    for I := 0 to Players.Count - 1 do begin
    429563      TPlayer(Players[I]).ScreenFrame := Rect(
    430         (I mod HorizFrameCount) * (Bitmap.Width div HorizFrameCount),
    431         (I div HorizFrameCount) * (Bitmap.Height div VertFrameCount),
    432         ((I mod HorizFrameCount) + 1) * (Bitmap.Width div HorizFrameCount),
    433         ((I div HorizFrameCount) + 1) * (Bitmap.Height div VertFrameCount));
    434     end;
    435   end;
     564        (I mod HorizFrameCount) * (FBitmapLower.Width div HorizFrameCount),
     565        (I div HorizFrameCount) * (FBitmapLower.Height div VertFrameCount),
     566        ((I mod HorizFrameCount) + 1) * (FBitmapLower.Width div HorizFrameCount),
     567        ((I div HorizFrameCount) + 1) * (FBitmapLower.Height div VertFrameCount));
     568    end;
     569  end;
     570  Redraw;
    436571end;
    437572
    438573constructor TEngine.Create;
    439574begin
     575  FBitmapLower := TBitmap.Create;
    440576  Players := TObjectList.Create;
    441577  World := TWorld.Create;
    442578  World.Engine := Self;
     579  Redraw;
    443580end;
    444581
    445582destructor TEngine.Destroy;
    446583begin
     584  FBitmapLower.Free;
    447585  Players.Free;
    448586  World.Free;
     
    457595    TPlayer(Players[I]).Control;
    458596  end;
    459 
     597end;
     598
     599procedure TEngine.Draw;
     600var
     601  I: Integer;
     602begin
    460603  if FRedrawPending then begin
    461     if Assigned(Bitmap) then begin
    462       Bitmap.Canvas.FillRect(0, 0, Bitmap.Width, Bitmap.Height);
    463       for I := 0 to Players.Count - 1 do begin
    464         TPlayer(Players[I]).Control;
    465         TPlayer(Players[I]).Paint;
    466       end;
     604    FBitmapLower.Canvas.FillRect(0, 0, FBitmapLower.Width, FBitmapLower.Height);
     605    for I := 0 to Players.Count - 1 do begin
     606      TPlayer(Players[I]).Paint;
     607    end;
     608    if Assigned(FBitmap) then begin
     609      FBitmap.Canvas.StretchDraw(Rect(0, 0, FBitmap.Width, FBitmap.Height), FBitmapLower);
    467610    end;
    468611    FRedrawPending := False;
     
    481624  begin
    482625    // Reset position
    483     Position := Point(25 + Random(World.Surface.Count.X - 50),
    484       25 + Random(World.Surface.Count.Y - 50));
     626    Position := Point(Round(World.Surface.Count.X * 0.2) + Random(Round(World.Surface.Count.X * 0.6)),
     627      Round(World.Surface.Count.Y * 0.2) + Random(Round(World.Surface.Count.Y * 0.6)));
    485628
    486629    PlaceHouse;
    487630  end;
     631  Redraw;
    488632end;
    489633
Note: See TracChangeset for help on using the changeset viewer.