Machen Sie einen Sprite in die Maus klicken Position Schritt für Schritt

Ich schreibe ein kleines Piratenspiel in Pygame. Wenn du im Empires Total War Seeschlachten spielst, hast du eine Vorstellung davon, was ich erreichen möchte:

Der Sprite des Schiffes ist an der Position (x1|y1) . Der Spieler klickt nun auf Position (x2|y2) auf dem Bildschirm. Der Sprite soll nun (x2|y2) als seine neue Position nehmen – indem man Schritt für Schritt dorthin geht, nicht um dort sofort zu strahlen.

Ich habe herausgefunden, dass es etwas mit der Diagonale des Rechtecks (x1|y1) , (x1|y2) , (x2|y2) , (x2|y1) (x2|y2) , aber ich kann es einfach nicht herausfinden, besonders nicht Wobei die Geschwindigkeit gleich ist, egal welcher Winkel die Diagonale hat und wenn man bedenkt, dass die x und y Werte von entweder (Schiff oder Klick) größer oder kleiner als die jeweils anderen sind.

Dieses kleine Snippet ist mein letzter Versuch, eine funktionierende Funktion zu schreiben:

 def update(self, new_x, new_y, speed, screen, clicked): if clicked: self.xshift = (self.x - new_x) self.yshift = ((self.y - new_y) / (self.x - new_x)) if self.x > (new_x + 10): self.x -= 1 self.y -= self.yshift elif self.x > new_x and self.x < (new_x + 10): self.x -= 1 self.y -= self.yshift elif self.x < (new_x - 10): self.x += 1 self.y += self.yshift elif self.x < new_x and self.x < (new_x - 10): self.x += 1 self.y += self.yshift else: self.x += 0 self.y += 0 screen.set_at((self.x, self.y), (255, 0, 255)) 

Das "Schiff" ist hier nur ein rosa Pixel. Die Reaktion, die es bei meinen Klicks auf den Bildschirm zeigt, ist, sich grob zu meinem Klick zu bewegen, aber um in einer scheinbar zufälligen Entfernung des Punktes zu stoppen, auf den ich geklickt habe.

Die Variablen sind:

new_x , new_y = Position des Mausklicks
speed = konstante Geschwindigkeit abhängig von Schiffstypen
MOUSEBUTTONDOWN = getroffen durch das MOUSEBUTTONDOWN Ereignis, um sicherzustellen, dass die xshift und yshift von Selbst nur definiert sind, wenn der Spieler angeklickt hat und nicht jedes Frame wieder.

Wie kann ich das Schiff reibungslos von seiner aktuellen Position zu dem Punkt bewegen, an dem der Spieler geklickt hat?

One Solution collect form web for “Machen Sie einen Sprite in die Maus klicken Position Schritt für Schritt”

Sagen Sie die aktuelle Position ist pos , und der Punkt, den der Spieler anklickt, ist target_pos , dann nehmen Sie den Vektor zwischen pos und target_pos .

Jetzt weißt du, wie man von pos nach target_pos , aber in konstanter Geschwindigkeit (und nicht die ganze Distanz auf einmal) zu bewegen, musst du den Vektor normalisieren und eine Geschwindigkeitskonstante durch skalare Multiplikation anwenden.

Das ist es.


Komplettes Beispiel: (der entsprechende Code ist in der Ship.update Methode)

 import pygame import math # some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637 def magnitude(v): return math.sqrt(sum(v[i]*v[i] for i in range(len(v)))) def add(u, v): return [ u[i]+v[i] for i in range(len(u)) ] def sub(u, v): return [ u[i]-v[i] for i in range(len(u)) ] def dot(u, v): return sum(u[i]*v[i] for i in range(len(u))) def normalize(v): vmag = magnitude(v) return [ v[i]/vmag for i in range(len(v)) ] class Ship(object): def __init__(self): self.x, self.y = (0, 0) self.set_target((0, 0)) self.speed = 0.7 @property def pos(self): return self.x, self.y # for drawing, we need the position as tuple of ints # so lets create a helper property @property def int_pos(self): return map(int, self.pos) @property def target(self): return self.t_x, self.t_y @property def int_target(self): return map(int, self.target) def set_target(self, pos): self.t_x, self.t_y = pos def update(self): # if we won't move, don't calculate new vectors if self.int_pos == self.int_target: return target_vector = sub(self.target, self.pos) # a threshold to stop moving if the distance is to small. # it prevents a 'flickering' between two points if magnitude(target_vector) < 2: return # apply the ship's speed to the vector move_vector = [c * self.speed for c in normalize(target_vector)] # update position self.x, self.y = add(self.pos, move_vector) def draw(self, s): pygame.draw.circle(s, (255, 0 ,0), self.int_pos, 2) pygame.init() quit = False s = pygame.display.set_mode((300, 300)) c = pygame.time.Clock() ship = Ship() while not quit: quit = pygame.event.get(pygame.QUIT) if pygame.event.get(pygame.MOUSEBUTTONDOWN): ship.set_target(pygame.mouse.get_pos()) pygame.event.poll() ship.update() s.fill((0, 0, 255)) ship.draw(s) pygame.display.flip() c.tick(60) 
  • Wie kann man die Konsolenausgabe in Python unterdrücken?
  • Wie kann ich einen Scrolling-Hintergrund in Python mit Pygame machen?
  • Pygame sprite wall collision
  • Versuchen, einen "soliden" Block in Pygame zu machen, aber es funktioniert nicht
  • Pygame-Anzeige verursacht Segmentierungsfehler 11
  • Pygame Audio-Wiedergabegeschwindigkeit
  • Probleme bei der Installation von Pygame mit Pip installieren
  • PyGame: draw.rect () hat ungültige Parameter
  • Pygame, Töne spielen nicht
  • Running Python-Code in einem String enthalten
  • Pygame - Kollisionserkennung mit zwei CIRCLES
  • Python ist die beste Programmiersprache der Welt.