Spielfigur mit der Maus steuern

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Rokur
Beiträge: 167
Registriert: 29.12.2005 09:58
Computerausstattung: Intel Core2 Quad (4x2,4 GHz), 4096 MB RAM, GForce 8800GTX 786 MB
Windows XP 32 Bit, PureBasic 4.40 (x86)

Spielfigur mit der Maus steuern

Beitrag von Rokur »

Hallo,

ich habe mir mal Gedanken gemacht wie man eine Maussteuerung wie sie z.B. in Diablo II, Legend - Hand of God und ähnlichen Spielen verwendet wird umsetzen könnte.

Ein Klick mit der linken Maustaste legt das Ziel fest, die Spielfigur bewegt sich mit einer festgelegten Geschwindigkeit direkt auf das Ziel zu. Wird die Maus mit gedrückter Taste bewegt, läuft die Spielfigur immer dem Cursor nach.

Automatisches Umlaufen von Hindernissen sowie Kollisionsabfragen fehlen zwar noch, aber als Ansatz schonmal ganz brauchbar.

roter Kreis: Spielfigur
gelbes Kreuz: Cursor
grünes Kreuz: Ziel

Verwendete PB-Version: 4.10 Windows

Code: Alles auswählen

InitSprite()
InitMouse()
InitKeyboard()

#width = 800
#height = 600

#fps = 60

frame.l = 0

speed.l = 5 ;Geschwindigkeit in Pixel

posX.l = #width / 2
posY.l = #height / 2
zielX.l = posX
zielY.l = posY
vectorX.l = 0
vectorY.l = 0
vector.f = 0
factor.f = 0

OpenWindow(0, 0, 0, #width, #height, "Maussteuerung", #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
OpenWindowedScreen(WindowID(0), 0, 0, #width, #height, #False, 0, 0)

SetFrameRate(#fps)

Repeat
  event.l = WindowEvent()
  
  ;Frame-Zähler
  frame = frame + 1
  If frame > #fps
    frame = 0
  EndIf
  
  Select event
    Case #PB_Event_CloseWindow
      End
    ;hier kommt der Rest rein
  EndSelect
  
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Escape)
    End
  EndIf
  
  ExamineMouse()
  ;linke Maustaste => neues Ziel auf Cursor-Position setzen
  If MouseButton(#PB_MouseButton_Left)
    zielX = MouseX()
    zielY = MouseY()
  EndIf
  
  If frame%2=0 ;Berechnung nicht bei jedem Frame durchführen
    Gosub SpielerBewegen
  EndIf
  
  ClearScreen(RGB(0,0,0))
  
  Gosub zeichnen
  
  FlipBuffers()
  
  Delay(1) ;CPU freigeben
ForEver

End

SpielerBewegen:
  ;Spieler nicht am Zielort => zum Zielort bewegen
  If posX <> zielX Or posY <> zielY
    ;Vektoren berechnen
    vector = Sqr(Pow(ZielX-posX,2)+Pow(ZielY-PosY,2)) ;Entfernung zum Ziel mit dem Satz des Pythagoras berechnen
    factor = speed / vector
    vectorX = (ZielX-posX)*factor
    vectorY = (ZielY-posY)*factor
    ;nahe genug am Ziel um es mit einem Schritt zu erreichen => letzten Schritt verkürzen, um nicht über das Ziel hinaus zu laufen
    If Abs(posX-zielX)<speed
      posX = ZielX
    Else
      posX = posX + vectorX
    EndIf
    If Abs(posY-ZielY)<speed
      posY = ZielY
    Else
      posY = posY + vectorY
    EndIf
  EndIf
Return

zeichnen:
  StartDrawing(ScreenOutput())
    
    ;Text
    DrawText(1,1,"Laufen: linke Maustaste, Beenden: Esc",RGB(255,255,255), RGB(0,0,0))
    
    
    ;Zielort (um zu sehen wie das Ganze hier funktioniert)
    Line(zielX-5, zielY,   10, 0,  RGB(0,255,0))
    Line(zielX,   zielY-5, 0,  10, RGB(0,255,0))
  
    ;Spieler
    Circle(posX,posY,5,RGB(255,0,0))
    
    ;Cursor (zum Schluss, damit er über allem anderen liegt und somit immer sichtbar ist)
    Line(MouseX()-5, MouseY(),   10, 0,  RGB(255,255,0))
    Line(MouseX(),   MouseY()-5, 0,  10, RGB(255,255,0))
    
  StopDrawing()
Return
Grüße
Rokur
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

du solltest bei "freien Bewegungsrichtungen" allgemein immer mit Floats arbeiten, da sonst die bewegung sehr ruckelt.
Auch wenn die Position immer nur Pixelweise sein kann, ist es besser:
posX,posY,vectorX,vectorY auch Float zu machen, damit die bewegung als ganzes flüssig ist.

EDIT: könnte auch an deiner "verkürzung" liegen, das bei leicht geneigten Wegen der Spieler auf einfach springt.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten