Hier noch ein anderer Weg für das Main-Menü meines Spiels. Ist ein Vollbild-Menü mit einer rotierende Münze als Cursor und Text für "Spiel", "Optionen", etc.
Über MouseMove fange ich erstmal die Koordinaten der Maus ab und ordne sie dem gewählten Menüpunkt zu:
Delphi-Quellcode:
procedure TfrmMain.DXDraw1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
MouseCursor.X := X;
MouseCursor.Y := Y;
if assigned(spCoin) AND (Gamestate=gsMenu) then
begin
if (Y>250) AND (Y<=300) then
begin
spCoin.Y:=250;
iMenuselect:=1;
end
else if (Y>350) AND (Y<=400) then
begin
spCoin.Y:=350;
iMenuSelect:=2;
end
else if (Y>450) AND (Y<=500) then
begin
spCoin.Y:=450;
iMenuSelect:=3;
end
else if (Y>550) AND (Y<=600) then
begin
spCoin.Y:=550;
iMenuSelect:=4;
end
else if (Y>650) AND (Y<=700) then
begin
spCoin.Y:=650;
iMenuSelect:=5;
end;
end;
end;
Wenn die Maustaste gedrückt wird, "fade" ich die Hintergrundmusik aus, zerstöre den Münzen-Cursor und setze eine Variable, damit die "Menu.pas" weiß, was jetzt passieren soll:
Delphi-Quellcode:
procedure TfrmMain.DXDraw1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if (Assigned(spCoin)) AND (GameState=gsMenu) then
begin
if Button=mbleft then
begin
bFadeBGSound:=true;
frmMain.DXWL1.Items.Find('menuok').Play(false);
spCoin.Dead;
DXSpriteENgine1.Dead;
end;
end;
if Button=mbleft then
bMBLEFT:=true
else
bMBLEFT:=false;
end;
In der Menu.pas passiert dann folgendes:
Delphi-Quellcode:
procedure doMenu;
begin
frmMain.DXIL2.Items[0].draw(frmMain.DXDraw1.Surface, 0, 0, 0);
frmMain.DXIL2.Items.Find('menu1').Draw(frmMain.DXDraw1.Surface, 350, 250, 0);
frmMain.DXIL2.Items.Find('menu2').Draw(frmMain.DXDraw1.Surface, 400, 350, 0);
frmMain.DXIL2.Items.Find('menu3').Draw(frmMain.DXDraw1.Surface, 450, 450, 0);
frmMain.DXIL2.Items.Find('menu4').Draw(frmMain.DXDraw1.Surface, 500, 550, 0);
frmMain.DXIL2.Items.Find('menu5').Draw(frmMain.DXDraw1.Surface, 350, 650, 0);
with frmMain.DXDraw1.Surface.Canvas do
begin
Brush.Style := bsClear;
Font.Color := clwhite;
Font.Size := 12;
Textout(0,0,inttostr(frmMain.DXWL1.Items.Find('introbeat').Volume));
Textout(0,20,inttostr(iMenuSelect));
end;
if bFadeBGSound=true then
begin
if frmMain.DXWL1.Items.Find('introbeat').Volume>-2000 then
frmMain.DXWL1.Items.Find('introbeat').Volume:=frmMain.DXWL1.Items.Find('introbeat').Volume-20
else
begin
frmMain.DXWL1.Items.Find('introbeat').Stop;
if iMenuSelect=1 then
GameState:=gsGameInit
else if iMenuSelect=4 then
GameState:=gsCreditsInit
else if iMenuSelect=5 then
begin
frmMain.DXTimer1.Enabled:=false;
frmMain.Close;
end;
end;
end;
Dann wird die entsprechende "GameState"-Variable gesetzt, die wiederum im Timer-Event verarbeitet wird:
Delphi-Quellcode:
procedure TfrmMain.DXTimer1Timer(Sender: TObject; LagCount: Integer);
begin
try
DXDraw1.Surface.Fill( clwhite );
ProcessGamestate;
if bShowCardSprite=false then
CardSprite.Visible:=false;
DXSpriteENgine1.Dead;
DXSpriteEngine1.Move(2);
DXSpriteEngine1.Draw;
bmbleft:=false;
except
dxtimer1.Enabled:=false;
messagedlg('An error has occurred',mterror,[mbok],0);
end;
dxdraw1.Flip;
end;
Und das passiert in "ProcessGamestate":
Delphi-Quellcode:
procedure TfrmMain.ProcessGamestate;
begin
case GameState of
gsInit : doInit;
gsStart : doStart;
gsIntro1 : doIntro1;
gsMenuInit : doMenuInit;
gsMenu : doMenu;
gsGameInit : doGameInit;
gsGame : doGame;
gsCreditsInit : doCreditsInit;
gsCredits : doCredits;
end;
end;
Wie gesagt, das ist supernervig umzusetzen, da ich mein Spiel im Vollbildmodus laufen lassen will und mich daher um jeden Mist selbst kümmern muß - man darf ja nicht vergessen, dass neben der reinen Anzeige des Menüs auch noch weitere Aktionen wie Musik abspielen, Cursor animieren, etc. weiter laufen sollen (bzw. müssen).
Gruß Kay