Ich vielen Strategiespielen ist es ja so, dass man nicht nur an den Bildschirmrändern über die Landschaft scrollen kann, sondern (seit Z von den Bitmap Brothers) auch die rechte Maustaste gedrückt halten kann und das Scrolling folgt der Mausbewegung. Ich wollte das ganze mit Andorra umsetzen und das Ergebnis sieht dann so aus:
Delphi-Quellcode:
VScroll: TPoint;
TInputState = (isRightClickScroll);
TInputStates = set of TInputState;
{....}
procedure TEngine.Mousedown(Button: TMouseButton; Shift: TShiftState; X, Y: integer);
var
pt: TPoint;
begin
if Button = mbRight then // Nur bei rechter Maustaste
begin
InputState := InputState + [isRightClickScroll]; // Merken, dass Rechtklick-Scrolling an ist
pt := Point(AParent.ClientOrigin.X+AParent.ClientWidth div 2,AParent.ClientOrigin.Y+AParent.ClientHeight div 2);
SetCursorPos(pt.X, pt.Y); // Cursor auf Mitte zentrieren
end;
end;
procedure TEngine.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer);
begin
if Button = mbRight then
begin
InputState := InputState - [isRightClickScroll]; // Merken, dass Rechtklick-Scrolling aus ist
VScroll := Point(0, 0); // Scrollingversatz zurücksetzen
end;
end;
procedure TEngine.MouseMove(X, Y: integer);
Center, RealPoint: TPoint;
begin
if isRightClickScroll in InputState then
begin
// Mitte ermitteln
Center := Point(AParent.ClientOrigin.X+AParent.ClientWidth div 2,AParent.ClientOrigin.Y+AParent.ClientHeight div 2);
// Tatsächliche Mausposition ermitteln
RealPoint := Point(AParent.ClientOrigin.X+X,AParent.ClientOrigin.Y+Y);
// Anstand in "Vektor" speichern (hier TPoint zweckentfremdet
VScroll.x := VScroll.X + (Center.X - RealPoint.X);
VScroll.y := VScroll.Y + (Center.Y - RealPoint.Y);
end;
procedure TEngine.DoScroll(TimeGap: double);
var
Center: TPoint;
begin
if isRightClickScroll in InputState then
if (VScroll.X <> 0) or (VScroll.Y <> 0) then // Nur ausführen, wenn auch Versatz da ist
begin
// Entsprechend des Versatzes scrollen
SpriteEngine.X := SpriteEngine.X + VScroll.X;
SpriteEngine.Y := SpriteEngine.Y + VScroll.y;
// Es wurde gescrollt, also Vektor zurücksetzen
VScroll.x := 0;
VScroll.Y := 0;
// Cursor wieder auf Mitte festhalten
Center:=Point(AParent.ClientOrigin.X+AParent.ClientWidth div 2,AParent.ClientOrigin.Y+AParent.ClientHeight div 2);
SetCursorPos(Center.X, Center.Y);
Exit;
end;
end;
Neben viel drum herum ist die Hauptaufgabe, die Maus immer wieder auf den Fenstermittelpunkt zu zentrieren und im MouseMove auf Mausbewegungen zu reagieren. Dort wird dann nur der Versatz vom Mittelpunkt aus gespeichert, der Mauszeiger zurückgesetzt und beim nächsten Zeichnen der Landschaft das Scrolling angewandt (und der Vektor für den Versatz wieder auf 0,0 zurückgesetzt)
Edit: Die Verwendung des Sets ist dadurch bedingt, dass ich das aus einem größeren Spielprojekt herausgelöst habe. Hier natürlich auch eine Boolean-Variable reichen