Changeset 19 for trunk/UCore.pas
- Timestamp:
- Sep 27, 2011, 10:16:41 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UCore.pas
r17 r19 7 7 uses 8 8 Dialogs, Classes, SysUtils, Contnrs, Graphics, SpecializedMatrix, SpecializedList, 9 IntfGraphics, FPImage, LCLType, SpecializedBitmap, GraphType, Math, URectangle; 9 IntfGraphics, FPImage, LCLType, SpecializedBitmap, GraphType, Math, URectangle, 10 Syncobjs, UThreading; 10 11 11 12 const … … 126 127 end; 127 128 129 { TSystemThread } 130 131 TSystemThread = class(TListedThread) 132 Engine: TEngine; 133 procedure Execute; override; 134 end; 135 136 { TDrawThread } 137 138 TDrawThread = class(TListedThread) 139 Engine: TEngine; 140 procedure Execute; override; 141 end; 142 128 143 { TEngine } 129 144 130 145 TEngine = class 131 146 private 147 FActive: Boolean; 132 148 FBitmap: TBitmap; 149 FBitmapLock: TCriticalSection; 133 150 FRedrawPending: Boolean; 134 151 FBitmapLower: TBitmapTColor; 152 FDrawThread: TDrawThread; 153 FSystemThread: TSystemThread; 135 154 IntfImage: TLazIntfImage; 136 155 function GetPlayerCount: Integer; 156 procedure SetActive(const AValue: Boolean); 137 157 procedure SetBitmap(const AValue: TBitmap); 138 158 procedure SetPlayerCount(const AValue: Integer); 139 159 procedure Redraw; 140 160 function IsInsideHouses(Pos: TPoint): Boolean; 161 procedure DoDrawToBitmap; 141 162 public 142 163 Keyboard: TKeyboard; 143 164 World: TWorld; 144 165 Players: TObjectList; // <TPlayer> 166 Lock: TCriticalSection; 145 167 constructor Create; 146 168 destructor Destroy; override; … … 148 170 procedure Tick; 149 171 procedure Draw; 172 procedure NewGame; 150 173 property PlayerCount: Integer read GetPlayerCount write SetPlayerCount; 151 174 property Bitmap: TBitmap read FBitmap write SetBitmap; 152 pro cedure NewGame;175 property Active: Boolean read FActive write SetActive; 153 176 end; 154 177 … … 171 194 function SwapBRComponent(Value: Integer): Integer; inline; 172 195 196 173 197 implementation 174 198 … … 179 203 TFastBitmapPixelComponents(Result).R := TFastBitmapPixelComponents(Value).B; 180 204 TFastBitmapPixelComponents(Result).B := TFastBitmapPixelComponents(Value).R; 205 end; 206 207 { TSystemThread } 208 209 procedure TSystemThread.Execute; 210 begin 211 repeat 212 Engine.Tick; 213 Sleep(50); 214 until Terminated; 215 end; 216 217 { TDrawThread } 218 219 procedure TDrawThread.Execute; 220 begin 221 repeat 222 Engine.Draw; 223 Sleep(50); 224 until Terminated; 181 225 end; 182 226 … … 580 624 function TPlayer.ShowTankProc(Item1, Item2: Byte): Byte; 581 625 begin 582 if Item2 > 0 then Result := Item2 else Result := Item1; 626 if Item2 > 0 then Result := Item2 627 else Result := Item1; 583 628 end; 584 629 … … 596 641 with Engine.World do begin 597 642 Surface.Merge(Surface.CreateIndex(Position.X - TTank(Tanks[Direction]).Image.Count.X div 2, 598 Position.Y - TTank(Tanks[Direction]).Image.Count.Y div 2), TTank(Tanks[Direction]).Image, ShowTankProc); 643 Position.Y - TTank(Tanks[Direction]).Image.Count.Y div 2), 644 TTank(Tanks[Direction]).Image, ShowTankProc); 599 645 end; 600 646 end; … … 761 807 end; 762 808 809 procedure TEngine.SetActive(const AValue: Boolean); 810 begin 811 if FActive = AValue then Exit; 812 FActive := AValue; 813 if AValue then begin 814 FDrawThread := TDrawThread.Create(True); 815 FDrawThread.Engine := Self; 816 FDrawThread.FreeOnTerminate := False; 817 FDrawThread.Name := 'Draw'; 818 FDrawThread.Start; 819 FSystemThread := TSystemThread.Create(True); 820 FSystemThread.Engine := Self; 821 FSystemThread.FreeOnTerminate := False; 822 FSystemThread.Name := 'Engine'; 823 FSystemThread.Start; 824 end else begin 825 FreeAndNil(FDrawThread); 826 FreeAndNil(FSystemThread); 827 end; 828 end; 829 763 830 procedure TEngine.SetBitmap(const AValue: TBitmap); 764 831 begin … … 805 872 end; 806 873 807 procedure TEngine.ResizePlayerFrames; 808 var 809 HorizFrameCount: Integer; 810 VertFrameCount: Integer; 811 I: Integer; 812 begin 813 if Assigned(FBitmapLower) then begin 814 if Players.Count > 1 then begin 815 if Players.Count > 2 then VertFrameCount := 2 816 else VertFrameCount := 1; 817 HorizFrameCount := Round(Players.Count / VertFrameCount); 818 end else begin 819 VertFrameCount := 1; 820 HorizFrameCount := 1; 821 end; 822 FBitmapLower.Count := FBitmapLower.CreateIndex(80 * HorizFrameCount, 60 * VertFrameCount); 823 for I := 0 to Players.Count - 1 do begin 824 TPlayer(Players[I]).ScreenFrame.AsTRect := Rect( 825 (I mod HorizFrameCount) * (FBitmapLower.Count.X div HorizFrameCount), 826 (I div HorizFrameCount) * (FBitmapLower.Count.Y div VertFrameCount), 827 ((I mod HorizFrameCount) + 1) * (FBitmapLower.Width div HorizFrameCount), 828 ((I div HorizFrameCount) + 1) * (FBitmapLower.Height div VertFrameCount)); 829 end; 830 end; 831 Redraw; 832 end; 833 834 constructor TEngine.Create; 835 begin 836 FBitmapLower := TBitmapTColor.Create; 837 IntfImage := TLazIntfImage.Create(1, 1); 838 Players := TObjectList.Create; 839 Keyboard := TKeyboard.Create; 840 World := TWorld.Create; 841 World.Engine := Self; 842 Redraw; 843 end; 844 845 destructor TEngine.Destroy; 846 begin 847 FBitmapLower.Free; 848 IntfImage.Free; 849 Players.Free; 850 Keyboard.Free; 851 World.Free; 852 inherited Destroy; 853 end; 854 855 procedure TEngine.Tick; 856 var 857 I: Integer; 858 begin 859 for I := 0 to Players.Count - 1 do begin 860 TPlayer(Players[I]).Control; 861 TPlayer(Players[I]).Tick; 862 end; 863 end; 864 865 procedure TEngine.Draw; 874 procedure TEngine.DoDrawToBitmap; 866 875 var 867 876 I: Integer; … … 885 894 TargetWidth: Integer; 886 895 begin 896 if Assigned(FBitmap) then 897 try 898 Bitmap.BeginUpdate; 899 RawImage := Bitmap.RawImage; 900 BytePerPixel := RawImage.Description.BitsPerPixel div 8; 901 BytePerRow := RawImage.Description.BytesPerLine; 902 FillChar(RawImage.Data^, Bitmap.Height * BytePerRow, 0); 903 904 if (FBitmap.Width / FBitmapLower.Width) < (FBitmap.Height / FBitmapLower.Height) then 905 Ratio := FBitmap.Width / FBitmapLower.Width 906 else Ratio := FBitmap.Height / FBitmapLower.Height; 907 908 // Preserve aspect ratio 909 TargetWidth := Trunc(FBitmapLower.Width * Ratio); 910 TargetHeight := Trunc(FBitmapLower.Height * Ratio); 911 912 Shift.X := Trunc((Bitmap.Width - TargetWidth) / 2); 913 Shift.Y := Trunc((Bitmap.Height - TargetHeight) / 2); 914 915 XDiv := TargetWidth div FBitmapLower.Width; 916 XMod := TargetWidth mod FBitmapLower.Width; 917 YDiv := TargetHeight div FBitmapLower.Height; 918 YMod := TargetHeight mod FBitmapLower.Height; 919 920 PixelRowPtr := PInteger(RawImage.Data + BytePerRow * Shift.Y); 921 YAcc := FBitmapLower.Height div 2; 922 for Y := 0 to FBitmapLower.Height - 1 do begin 923 SubPixelSizeY := YDiv; 924 Inc(YAcc, YMod); 925 if YAcc >= FBitmapLower.Height then begin 926 Dec(YAcc, FBitmapLower.Height); 927 Inc(SubPixelSizeY); 928 end; 929 930 PixelPtr := PixelRowPtr + Shift.X; 931 XAcc := FBitmapLower.Width div 2; 932 for X := 0 to FBitmapLower.Width - 1 do begin 933 SubPixelSizeX := XDiv; 934 Inc(XAcc, XMod); 935 if XAcc >= FBitmapLower.Width then begin 936 Dec(XAcc, FBitmapLower.Width); 937 Inc(SubPixelSizeX); 938 end; 939 940 Color := SwapBRComponent(FBitmapLower.Pixels[X, Y]); 941 942 // Draw large pixel 943 SubPixelRowPtr := PixelPtr; 944 for PixelY := 0 to SubPixelSizeY - 1 do begin 945 SubPixelPtr := SubPixelRowPtr; 946 for PixelX := 0 to SubPixelSizeX - 1 do begin 947 SubPixelPtr^ := Color; 948 Inc(PByte(SubPixelPtr), BytePerPixel); 949 end; 950 Inc(PByte(SubPixelRowPtr), BytePerRow); 951 end; 952 Inc(PByte(PixelPtr), BytePerPixel * SubPixelSizeX); 953 end; 954 Inc(PByte(PixelRowPtr), BytePerRow * SubPixelSizeY); 955 end; 956 finally 957 FBitmap.EndUpdate; 958 end; 959 end; 960 961 procedure TEngine.ResizePlayerFrames; 962 var 963 HorizFrameCount: Integer; 964 VertFrameCount: Integer; 965 I: Integer; 966 begin 967 if Assigned(FBitmapLower) then begin 968 if Players.Count > 1 then begin 969 if Players.Count > 2 then VertFrameCount := 2 970 else VertFrameCount := 1; 971 HorizFrameCount := Round(Players.Count / VertFrameCount); 972 end else begin 973 VertFrameCount := 1; 974 HorizFrameCount := 1; 975 end; 976 FBitmapLower.Count := FBitmapLower.CreateIndex(80 * HorizFrameCount, 60 * VertFrameCount); 977 for I := 0 to Players.Count - 1 do begin 978 TPlayer(Players[I]).ScreenFrame.AsTRect := Rect( 979 (I mod HorizFrameCount) * (FBitmapLower.Count.X div HorizFrameCount), 980 (I div HorizFrameCount) * (FBitmapLower.Count.Y div VertFrameCount), 981 ((I mod HorizFrameCount) + 1) * (FBitmapLower.Width div HorizFrameCount), 982 ((I div HorizFrameCount) + 1) * (FBitmapLower.Height div VertFrameCount)); 983 end; 984 end; 985 Redraw; 986 end; 987 988 constructor TEngine.Create; 989 begin 990 Lock := TCriticalSection.Create; 991 FBitmapLower := TBitmapTColor.Create; 992 FBitmapLock := TCriticalSection.Create; 993 IntfImage := TLazIntfImage.Create(1, 1); 994 Players := TObjectList.Create; 995 Keyboard := TKeyboard.Create; 996 World := TWorld.Create; 997 World.Engine := Self; 998 Redraw; 999 end; 1000 1001 destructor TEngine.Destroy; 1002 begin 1003 Active := False; 1004 FBitmapLower.Free; 1005 FBitmapLock.Free; 1006 IntfImage.Free; 1007 Players.Free; 1008 Keyboard.Free; 1009 World.Free; 1010 Lock.Free; 1011 inherited Destroy; 1012 end; 1013 1014 procedure TEngine.Tick; 1015 var 1016 I: Integer; 1017 begin 1018 try 1019 Lock.Acquire; 1020 for I := 0 to Players.Count - 1 do begin 1021 TPlayer(Players[I]).Control; 1022 TPlayer(Players[I]).Tick; 1023 end; 1024 finally 1025 Lock.Release; 1026 end; 1027 end; 1028 1029 procedure TEngine.Draw; 1030 var 1031 I: Integer; 1032 begin 887 1033 if FRedrawPending then 888 1034 begin 889 1035 FRedrawPending := False; 890 //FBitmapLower.FillAll(0);891 for I := 0 to Players.Count - 1 do begin892 TPlayer(Players[I]).Paint;893 end;894 895 if Assigned(FBitmap) then896 1036 try 897 Bitmap.BeginUpdate; 898 RawImage := Bitmap.RawImage; 899 BytePerPixel := RawImage.Description.BitsPerPixel div 8; 900 BytePerRow := RawImage.Description.BytesPerLine; 901 //FillChar(RawImage.Data^, Bitmap.Height * BytePerRow, 0); 902 903 if (FBitmap.Width / FBitmapLower.Width) < (FBitmap.Height / FBitmapLower.Height) then 904 Ratio := FBitmap.Width / FBitmapLower.Width 905 else Ratio := FBitmap.Height / FBitmapLower.Height; 906 907 // Preserve aspect ratio 908 TargetWidth := Trunc(FBitmapLower.Width * Ratio); 909 TargetHeight := Trunc(FBitmapLower.Height * Ratio); 910 911 Shift.X := Trunc((Bitmap.Width - TargetWidth) / 2); 912 Shift.Y := Trunc((Bitmap.Height - TargetHeight) / 2); 913 914 XDiv := TargetWidth div FBitmapLower.Width; 915 XMod := TargetWidth mod FBitmapLower.Width; 916 YDiv := TargetHeight div FBitmapLower.Height; 917 YMod := TargetHeight mod FBitmapLower.Height; 918 919 PixelRowPtr := PInteger(RawImage.Data + BytePerRow * Shift.Y); 920 YAcc := FBitmapLower.Height div 2; 921 for Y := 0 to FBitmapLower.Height - 1 do begin 922 SubPixelSizeY := YDiv; 923 Inc(YAcc, YMod); 924 if YAcc >= FBitmapLower.Height then begin 925 Dec(YAcc, FBitmapLower.Height); 926 Inc(SubPixelSizeY); 927 end; 928 929 PixelPtr := PixelRowPtr + Shift.X; 930 XAcc := FBitmapLower.Width div 2; 931 for X := 0 to FBitmapLower.Width - 1 do begin 932 SubPixelSizeX := XDiv; 933 Inc(XAcc, XMod); 934 if XAcc >= FBitmapLower.Width then begin 935 Dec(XAcc, FBitmapLower.Width); 936 Inc(SubPixelSizeX); 937 end; 938 939 Color := SwapBRComponent(FBitmapLower.Pixels[X, Y]); 940 941 // Draw large pixel 942 SubPixelRowPtr := PixelPtr; 943 for PixelY := 0 to SubPixelSizeY - 1 do begin 944 SubPixelPtr := SubPixelRowPtr; 945 for PixelX := 0 to SubPixelSizeX - 1 do begin 946 SubPixelPtr^ := Color; 947 Inc(PByte(SubPixelPtr), BytePerPixel); 948 end; 949 Inc(PByte(SubPixelRowPtr), BytePerRow); 950 end; 951 Inc(PByte(PixelPtr), BytePerPixel * SubPixelSizeX); 952 end; 953 Inc(PByte(PixelRowPtr), BytePerRow * SubPixelSizeY); 1037 Lock.Acquire; 1038 //FBitmapLower.FillAll(0); 1039 for I := 0 to Players.Count - 1 do begin 1040 TPlayer(Players[I]).Paint; 954 1041 end; 955 1042 finally 956 FBitmap.EndUpdate; 957 end; 1043 Lock.Release; 1044 end; 1045 Synchronize(DoDrawToBitmap); 958 1046 end; 959 1047 end;
Note:
See TracChangeset
for help on using the changeset viewer.