456 lines
14 KiB
Plaintext
Executable File
456 lines
14 KiB
Plaintext
Executable File
unit rennen;
|
||
|
||
interface
|
||
|
||
uses
|
||
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
|
||
StdCtrls, Math, ExtCtrls, ComCtrls, Grids, IniFiles;
|
||
|
||
type
|
||
TAuto = class
|
||
Loc: TPoint;
|
||
LastLoc: TPoint;
|
||
Color: TColor;
|
||
Dir: Double;
|
||
LastDir: Double;
|
||
RndState: boolean;
|
||
Throttle: Double;
|
||
Steer: Double;
|
||
v: Double;
|
||
a: Double;
|
||
|
||
Name: String;
|
||
LapTime: Cardinal;
|
||
LapTimeTot: Cardinal;
|
||
LapTimeAvg: Cardinal;
|
||
FastestLap: Cardinal;
|
||
|
||
Masse: Double;
|
||
FRoll: Double;
|
||
FLuft: Double;
|
||
FAntrieb: Double;
|
||
RLuft: Double;
|
||
FMax: Double;
|
||
|
||
PedalInc: Double;
|
||
PedalDec: Double;
|
||
SteerInc: Double;
|
||
SteerDec: Double;
|
||
RSpeedMax: Double;
|
||
RSpeedCollission: Double;
|
||
|
||
KeyUp: Integer;
|
||
KeyDown: Integer;
|
||
KeyLeft: Integer;
|
||
KeyRight: Integer;
|
||
|
||
Rnd: Integer;
|
||
|
||
Form: array of TPoint;
|
||
StdForm: array of TPoint;
|
||
|
||
PbSpeed: TProgressBar;
|
||
PbThrottle: TProgressBar;
|
||
|
||
constructor Create();
|
||
procedure Draw(Ground: TBitmap; Loc: TPoint; Dir: Double);
|
||
procedure CalcLoc;
|
||
procedure CalcDir;
|
||
procedure Display(i: Integer);
|
||
procedure RndCount;
|
||
procedure Collission;
|
||
end;
|
||
|
||
TForm1 = class(TForm)
|
||
Timer: TTimer;
|
||
SgData: TStringGrid;
|
||
procedure FormCreate(Sender: TObject);
|
||
procedure TimerTimer(Sender: TObject);
|
||
procedure FormKeyUp(Sender: TObject; var Key: Word;
|
||
Shift: TShiftState);
|
||
procedure FormResize(Sender: TObject);
|
||
procedure SgDataDrawCell(Sender: TObject; ACol, ARow: Integer;
|
||
Rect: TRect; State: TGridDrawState);
|
||
procedure FormKeyDown(Sender: TObject; var Key: Word;
|
||
Shift: TShiftState);
|
||
private
|
||
{ Private-Deklarationen}
|
||
public
|
||
{ Public-Deklarationen}
|
||
end;
|
||
|
||
procedure Rotate(car: TAuto; m: TPoint; dir: double);
|
||
function GetCarBgd(Ground: TBitmap; Form: array of TPoint; color: TColor): Integer;
|
||
function ColorToHtml(AColor: TColor): string;
|
||
function HtmlToColor(AHtmlColor: string): TColor;
|
||
|
||
var
|
||
Form1: TForm1;
|
||
Auto: array of TAuto;
|
||
Real: TBitmap;
|
||
Shadow: TBitmap;
|
||
Background: TBitmap;
|
||
StartTime: Cardinal;
|
||
RaceState: Integer;
|
||
Rnds: Integer;
|
||
|
||
implementation
|
||
|
||
{$R *.DFM}
|
||
|
||
constructor TAuto.Create();
|
||
begin
|
||
SetLength(StdForm, 5);
|
||
SetLength(Form, 5);
|
||
|
||
StdForm[0] := Point(-7,-10);
|
||
StdForm[1] := Point(+7,-10);
|
||
StdForm[2] := Point(+7,+15);
|
||
StdForm[3] := Point(0,+20);
|
||
StdForm[4] := Point(-7,+15);
|
||
|
||
PbSpeed := TProgressBar.Create(nil);
|
||
PbSpeed.Smooth := true;
|
||
PbSpeed.Step := 1;
|
||
PbSpeed.Parent := Form1.SgData;
|
||
|
||
PbThrottle := TProgressBar.Create(nil);
|
||
PbThrottle.Smooth := true;
|
||
PbThrottle.Step := 1;
|
||
PbThrottle.parent := Form1.SgData;
|
||
end;
|
||
|
||
procedure TAuto.Collission;
|
||
begin
|
||
//Kollission
|
||
if GetCarBgd(Shadow, Form, clBlack) > 0 then
|
||
begin
|
||
Loc := LastLoc;
|
||
Dir := LastDir;
|
||
Rotate(self, Loc, Dir);
|
||
v := -v * RSpeedCollission;
|
||
end;
|
||
end;
|
||
|
||
procedure TAuto.Draw(Ground: TBitmap; loc: TPoint; dir: Double);
|
||
begin
|
||
Ground.Canvas.Pen.color := color;
|
||
Ground.Canvas.Brush.Color := color;
|
||
Ground.Canvas.Polygon(form);
|
||
end;
|
||
|
||
procedure TAuto.CalcDir;
|
||
begin
|
||
//Lenkdynamik
|
||
Steer := Steer * SteerDec;
|
||
|
||
if Abs(v) < 1 then
|
||
Steer := 0;
|
||
|
||
if v > 0 then
|
||
Dir := Dir + Steer
|
||
else
|
||
dir := dir - steer;
|
||
end;
|
||
|
||
procedure TAuto.CalcLoc;
|
||
var
|
||
FFahr: Double;
|
||
Sinus, Cosinus: Extended;
|
||
begin
|
||
//Fahrzeugdynamik
|
||
Throttle := Throttle * PedalDec;
|
||
|
||
if v > 0 then
|
||
FFahr := FRoll + FLuft
|
||
else
|
||
FFahr := -FRoll - FLuft;
|
||
|
||
FLuft := RLuft * Sqr(v);
|
||
FAntrieb := FMax * Throttle;
|
||
a := (FAntrieb - FFahr) / Masse;
|
||
|
||
v := v + a;
|
||
if v < RSpeedMax then v := RSpeedMax;
|
||
|
||
//Streckenberechnung
|
||
SinCos(degtorad(dir), sinus, cosinus);
|
||
|
||
loc.x := Round(loc.x + v * sinus);
|
||
loc.y := Round(loc.y + v * cosinus);
|
||
end;
|
||
|
||
procedure TAuto.Display(i: Integer);
|
||
begin
|
||
//Anzeige
|
||
Form1.SgData.Cells[0,i + 1] := name;
|
||
Form1.SgData.Cells[1,i + 1] := inttostr(rnd) + ' / ' + inttostr(rnds);
|
||
Form1.SgData.Cells[2,i + 1] := floattostr(LapTime / 1000);
|
||
Form1.SgData.Cells[3,i + 1] := floattostr((LapTimeTot + LapTime) / 1000);
|
||
if Auto[i].rnd <> 0 then
|
||
Form1.SgData.Cells[4,i + 1] := floattostr((LapTimeTot / Rnd) / 1000)
|
||
else
|
||
Form1.SgData.Cells[4,i + 1] := '0';
|
||
|
||
Form1.SgData.Cells[5,i + 1] := floattostr(FastestLap / 1000);
|
||
Form1.SgData.Cells[6,i + 1] := inttostr(loc.x) + ' | ' + inttostr(loc.y);
|
||
Form1.SgData.Cells[7,i + 1] := floattostr(Round(Dir));
|
||
|
||
//Progressbars
|
||
PbSpeed.position := round(Abs(Auto[i].v*3));
|
||
if v > 0 then
|
||
PbSpeed.Perform($0409, 0, clGreen)
|
||
else
|
||
PbSpeed.Perform($0409, 0, clRed);
|
||
|
||
PbThrottle.position := round(Abs(Auto[i].throttle*100));
|
||
if Throttle > 0 then
|
||
PbThrottle.Perform($0409, 0, clGreen)
|
||
else
|
||
PbThrottle.Perform($0409, 0, clRed);
|
||
end;
|
||
|
||
procedure TAuto.RndCount;
|
||
begin
|
||
//Rundenz<6E>hler
|
||
if (Shadow.Canvas.Pixels[LastLoc.x,LastLoc.y] = clBlue) and (Shadow.Canvas.Pixels[Loc.x,Loc.y] = clRed) then
|
||
if RndState = true then
|
||
begin
|
||
if Rnd = 0 then FastestLap := LapTime;
|
||
if LapTime < FastestLap then
|
||
FastestLap := LapTime;
|
||
|
||
if Rnd + 1 = Rnds then
|
||
begin
|
||
RaceState := -1;
|
||
if Application.MessageBox(PChar(Name + ' hat gewonnen! Neues Rennen starten?'), 'Ziel', 4+32) = IDYES then
|
||
begin
|
||
RaceState := 0;
|
||
StartTime := GetTickCount;
|
||
FastestLap := 0;
|
||
Rnd := 0;
|
||
end
|
||
else
|
||
Form1.Close;
|
||
end
|
||
else
|
||
begin
|
||
Inc(Rnd);
|
||
RndState := false;
|
||
LapTimeTot := LapTimeTot + LapTime;
|
||
LapTime := 0;
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
if (Rnd = 0) and (RaceState = 0) then
|
||
begin
|
||
RaceState := 1;
|
||
StartTime := GetTickCount;
|
||
end;
|
||
RndState := true;
|
||
end;
|
||
end;
|
||
|
||
procedure TForm1.FormCreate(Sender: TObject);
|
||
var
|
||
Ini: TIniFile;
|
||
i: Integer;
|
||
begin
|
||
//Autos
|
||
ini:=TIniFile.create(ExtractFilePath(ParamStr(0)) + 'Auto.ini');
|
||
i := 0;
|
||
while ini.SectionExists('Auto' + inttostr(i)) do
|
||
begin
|
||
inc(i)
|
||
end;
|
||
|
||
SetLength(Auto, i);
|
||
|
||
for i := 0 to i - 1 do
|
||
begin
|
||
Auto[i] := TAuto.Create;
|
||
Auto[i].Loc.x := ini.ReadInteger('Auto' + inttostr(i), 'loc_x', 0);
|
||
Auto[i].Loc.y := ini.ReadInteger('Auto' + inttostr(i), 'loc_y', 0);
|
||
Auto[i].Color := htmltocolor(ini.ReadString('Auto' + inttostr(i), 'color', '#FFFFFF'));
|
||
Auto[i].Dir := ini.ReadInteger('Auto' + inttostr(i), 'dir', 90);
|
||
Auto[i].Name := ini.ReadString('Auto' + inttostr(i), 'name', 'Auto ' + inttostr(i + 1));
|
||
Auto[i].KeyUp := ini.ReadInteger('Auto' + inttostr(i), 'key_up', 0);
|
||
Auto[i].KeyDown := ini.ReadInteger('Auto' + inttostr(i), 'key_down', 0);
|
||
Auto[i].KeyLeft := ini.ReadInteger('Auto' + inttostr(i), 'key_left', 0);
|
||
Auto[i].KeyRight := ini.ReadInteger('Auto' + inttostr(i), 'key_right', 0);
|
||
|
||
Auto[i].Masse := ini.ReadFloat('Auto' + inttostr(i), 'Masse', ini.ReadFloat('general', 'Masse', 1000));
|
||
Auto[i].FRoll := ini.ReadFloat('Auto' + inttostr(i), 'FRoll', ini.ReadFloat('general', 'FRoll', 80));
|
||
Auto[i].RLuft := ini.ReadFloat('Auto' + inttostr(i), 'RLuft', ini.ReadFloat('general', 'RLuft', 2.5));
|
||
Auto[i].FMax := ini.ReadFloat('Auto' + inttostr(i), 'FMax', ini.ReadFloat('general', 'FMax', 3000));
|
||
|
||
Auto[i].PedalInc := ini.ReadFloat('Auto' + inttostr(i), 'PedalInc', ini.ReadFloat('general', 'PedalInc', 0.2));
|
||
Auto[i].PedalDec := ini.ReadFloat('Auto' + inttostr(i), 'PedalDec', ini.ReadFloat('general', 'PedalDec', 0.8));
|
||
Auto[i].SteerInc := ini.ReadFloat('Auto' + inttostr(i), 'SteerInc', ini.ReadFloat('general', 'SteerInc', 5));
|
||
Auto[i].SteerDec := ini.ReadFloat('Auto' + inttostr(i), 'SteerDec', ini.ReadFloat('general', 'SteerDec', 0.9));
|
||
Auto[i].RSpeedMax := ini.ReadFloat('Auto' + inttostr(i), 'RSpeedMax', ini.ReadFloat('general', 'RSpeedMax', -10));
|
||
Auto[i].RSpeedCollission := ini.ReadFloat('Auto' + inttostr(i), 'RSpeedCollission', ini.ReadFloat('general', 'RSpeedCollission', 0.4));
|
||
end;
|
||
|
||
Rnds := ini.ReadInteger('general', 'rnds', 10);
|
||
|
||
Doublebuffered := true;
|
||
Background := TBitmap.Create;
|
||
Background.LoadFromFile(Ini.ReadString('general', 'map', ''));
|
||
|
||
Real := TBitmap.Create;
|
||
Real.Width := Background.Width;
|
||
Real.Height := Background.Height;
|
||
|
||
Shadow := TBitmap.Create;
|
||
Shadow.Width := Background.Width;
|
||
Shadow.Height := Background.Height;
|
||
Shadow.LoadFromFile(Ini.ReadString('general', 'shmap', ''));
|
||
|
||
ClientWidth := Background.Width;
|
||
ClientHeight := Background.Height + SgData.RowCount * SgData.DefaultRowHeight;
|
||
|
||
SgData.RowCount := High(Auto) + 2;
|
||
|
||
for i:= 0 to SgData.ColCount - 1 do
|
||
SgData.Cells[i,0] := ini.ReadString('general', 'col' + inttostr(i), '');
|
||
|
||
ini.free;
|
||
end;
|
||
|
||
procedure TForm1.TimerTimer(Sender: TObject);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
Real.Canvas.StretchDraw(Rect(0,0,Background.Width, Background.Height),Background);
|
||
|
||
for i := Low(Auto) to High(Auto) do
|
||
begin
|
||
Auto[i].LastLoc := Auto[i].Loc;
|
||
Auto[i].LastDir := Auto[i].Dir;
|
||
|
||
Auto[i].CalcDir();
|
||
Auto[i].CalcLoc();
|
||
|
||
Rotate(Auto[i], Auto[i].Loc, Auto[i].Dir);
|
||
|
||
Auto[i].Collission;
|
||
|
||
Auto[i].RndCount;
|
||
|
||
//Zeit
|
||
if RaceState = 1 then
|
||
Auto[i].LapTime := GetTickCount - StartTime - Auto[i].LapTimeTot;
|
||
|
||
Auto[i].Display(i);
|
||
Auto[i].Draw(Real, Auto[i].loc, Auto[i].dir);
|
||
end;
|
||
|
||
Canvas.StretchDraw(Rect(0,0,ClientWidth, ClientHeight - SgData.RowCount * (SgData.DefaultRowHeight + SgData.GridLineWidth) + 1), Real);
|
||
end;
|
||
|
||
procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
|
||
Shift: TShiftState);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
if RaceState <> -1 then
|
||
for i := Low(Auto) to High(Auto) do
|
||
begin
|
||
if Key = Auto[i].KeyUp then Auto[i].Throttle := Auto[i].Throttle + Auto[i].PedalInc;
|
||
if Key = Auto[i].KeyDown then Auto[i].Throttle := Auto[i].Throttle - Auto[i].PedalInc;
|
||
if Key = Auto[i].KeyLeft then Auto[i].Steer := Auto[i].Steer + Auto[i].SteerInc;
|
||
if Key = Auto[i].KeyRight then Auto[i].Steer := Auto[i].Steer - Auto[i].SteerInc;
|
||
end;
|
||
|
||
case Key of
|
||
VK_ESCAPE: close;
|
||
|
||
Ord('F'): if BorderStyle = bsSizeable then
|
||
begin
|
||
BorderStyle := bsNone;
|
||
WindowState := wsMaximized;
|
||
end
|
||
else
|
||
begin
|
||
BorderStyle := bsSizeable;
|
||
WindowState := wsNormal;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TForm1.FormResize(Sender: TObject);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
SgData.Width := ClientWidth;
|
||
SgData.DefaultColWidth := SgData.Width div SgData.ColCount;
|
||
|
||
SgData.Height := SgData.RowCount * SgData.DefaultRowHeight;
|
||
|
||
for i := Low(Auto) to High(Auto) do
|
||
begin
|
||
Auto[i].PbSpeed.Boundsrect := SgData.Cellrect(8, i + 1);
|
||
Auto[i].PbThrottle.Boundsrect := SgData.Cellrect(9, i + 1);
|
||
end;
|
||
end;
|
||
|
||
function GetCarBgd(Ground: TBitmap; Form: array of TPoint; Color: TColor): Integer;
|
||
var
|
||
i: Integer;
|
||
begin
|
||
result := 0;
|
||
for i := Low(form) to High(form) do
|
||
if Ground.Canvas.Pixels[form[i].x, form[i].y] = color then
|
||
inc(result);
|
||
end;
|
||
|
||
function ColorToHtml(AColor: TColor): string;
|
||
begin
|
||
Result := IntToHex(ColorToRgb(AColor), 6);
|
||
Result := '#' + Copy(Result, 5, 2) + Copy(Result, 3, 2) + Copy(Result, 1, 2);
|
||
end;
|
||
|
||
function HtmlToColor(AHtmlColor: string): TColor;
|
||
begin
|
||
Delete(AHtmlColor, 1, 1);
|
||
Result := StrToInt('$' + Copy(AHtmlColor, 5, 2) + Copy(AHtmlColor, 3, 2) + Copy(AHtmlColor, 1, 2));
|
||
end;
|
||
|
||
procedure Rotate(car: TAuto; m: TPoint; dir: double);
|
||
var
|
||
i: Integer;
|
||
Sinus, Cosinus: Extended;
|
||
begin
|
||
SinCos(degtorad(dir), sinus, cosinus);
|
||
for i := 0 to High(car.form) do
|
||
begin
|
||
Car.Form[i].x := Round(Car.StdForm[i].x*cosinus + car.StdForm[i].y*sinus + m.x);
|
||
Car.Form[i].y := Round(-Car.StdForm[i].x*sinus + car.StdForm[i].y*cosinus + m.y);
|
||
end;
|
||
end;
|
||
|
||
procedure TForm1.SgDataDrawCell(Sender: TObject; ACol, ARow: Integer;
|
||
Rect: TRect; State: TGridDrawState);
|
||
var
|
||
i: Integer;
|
||
begin
|
||
for i := 0 to High(Auto) do
|
||
if ARow = i + 1 then
|
||
begin
|
||
SgData.Canvas.Brush.Color := Auto[i].Color;
|
||
SgData.Canvas.FillRect(Rect);
|
||
SgData.Canvas.Font.Color := (not ColorToRGB(Auto[i].Color)) and $00FFFFFF;
|
||
end;
|
||
SgData.Canvas.TextOut(Rect.Left + 2, Rect.Top + 1, SgData.Cells[ACol, ARow]);
|
||
end;
|
||
|
||
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
|
||
Shift: TShiftState);
|
||
begin
|
||
SgData.Selection := TGridRect(Rect(-1,-1,-1,-1));
|
||
end;
|
||
|
||
end.
|