Es muss eine spezielle Linie verwendet werden, die dem Finger des Benutzers folgt, die auch andere Verhaltensweisen hat

8

Zuerst ist das kein Duplikat von anderen "glatten" Fragen, weil ich auch Teile meiner Zeile nach Belieben löschen kann und daher brauche ich eine spezielle Möglichkeit, meine Zeile zu speichern.

Ich muss eine Linie dem Finger des Benutzers folgen lassen. Allerdings muss ich auch das Ende dieser Zeile nach Belieben löschen können.

Grundsätzlich muss das Verhalten dieser Linie wie die blaue Linie aussehen, die der Maus des Benutzers in diesem Spiel folgt:

Ссылка

Dafür habe ich einen Code in meiner onTouch-Methode, der jedes Mal, wenn sich der Finger des Benutzers bewegt, einen Punkt zu einem Array hinzufügt.

%Vor%

Dann zeichnet das Spiel in der onDraw () Methode jeden Punkt auf der Linie:

%Vor%

Der Grund, aus dem ich Punkte gezogen habe, um eine Zeile zu erstellen, anstatt Android zu verwenden     Die Klasse Path () ist, weil ich Teile der Linie nach Belieben löschen wollte (durch Entfernen von Punkten aus dem Array "linePoints").

Das Problem ist, wenn ich meinen Finger zu schnell bewege, dann breiten sich die Punkte aus und es hört auf, wie eine Linie auszusehen.

Wie kann ich sicherstellen, dass die Linie glatt bleibt, aber auch so gespeichert ist, dass ich Teile davon löschen kann?

BEARBEITEN: Jemand fragte nach mehr Einzelheiten darüber, wie die Zeile detailliert werden soll, also werde ich zur Verfügung stellen.

Ich möchte mit dem Löschen der Zeile beginnen, wenn der Benutzer die Zeile länger als "X" Sekunden gezeichnet hat. Die Art, wie ich die Zeile löschen möchte, ist:

Das Ende der Zeile beginnt zu verschwinden, bis (während der Benutzer es noch zeichnet), bis die Zeile vollständig gelöscht ist oder der Benutzer den Finger vom Bildschirm genommen hat.

BEARBEITEN 2: Ich muss auch wissen, ob die Linie sich selbst durchschnitten hat oder eine Art geschlossene Form erzeugt hat (weshalb ich das Punktspeichersystem gewählt habe) dachte ich, wenn 2 Punkte im Array die gleichen Koordinaten hätten würde wissen, ob die Linie sich selbst durchschnitten hat). Ich habe derzeit keine Ahnung, wie ich das umsetzen soll (weil die Punkte nicht kontinuierlich sind), aber ich werde weitere Änderungen vornehmen, wenn ich etwas herausgefunden habe.

EDIT 3: Ich habe eine Lösung gefunden, um zu bestimmen, ob die Linie sich selbst schneidet (selbst wenn die Punkte sporadisch verteilt sind)! Allerdings habe ich das Problem, eine glatte Linie ohne Lücken zu erzeugen, immer noch nicht gelöst.

Lösung:

Jedes Mal, wenn das Spiel dem Array einen neuen Punkt hinzufügt, vergleicht es es mit dem vorherigen Punkt, den es dem Array hinzugefügt hat, und modelliert ein Liniensegment "A". Es vergleicht dann das Liniensegment "A" mit allen vorherigen Liniensegmenten, die aus 2 Punkten in dem Array gemacht sind, und bestimmt, ob sich die verglichenen Segmente kreuzen. Wenn sie es tun, dann weiß ich, dass es eine Kreuzung in der Linie gibt.

EDIT 4: Dies ist der vollständige aktuelle Code, den ich gerade benutze.

In diesem Code gebe ich (versuche) ausführliche Kommentare und eine Zusammenfassung an der Spitze, die meine Ziele und das, was ich bisher gemacht habe, erklärt.

Um dieses große Stück Code vorzuschreiben, besteht mein derzeitiges Problem darin, die Zeile in einem gleichmäßigen Tempo (z. B. 10 Millimeter pro Sekunde) löschen zu können, wenn der Benutzer seine Zeile länger als eine bestimmte Zeit gezeichnet hat / p> %Vor%

EDIT 5:

Ich habe den Code von stKent / Titan implementiert und mein Code stürzt ab, weil der Index außerhalb des zulässigen Bereichs liegt.

Ich werde versuchen, das Problem zu finden und es zu beheben, aber bis ich tue, werde ich meinen Code hier posten, wenn jemand anderes eine Hand nehmen will, um es zu reparieren.

%Vor%

Es gibt noch etwas anderes, das sehr wichtig ist, das ich beachten muss. Ich glaube, es ist meine Schuld, dass ich das bis zum Edit 4 nicht notiert habe, aber während ich möchte, dass die Zeile am Ende gelöscht wird, möchte ich auch, dass sie gleichmäßig gelöscht wird. Ich denke, der aktuelle Code von stkent und Titan löscht die Punkte in der Linie in einem gleichmäßigen Tempo, aber das bedeutet nicht, dass die Linie selbst in einem gleichmäßigen Tempo gelöscht wird (Weil die Punkte ungleichmäßig verteilt sind).

Vielen Dank an alle, die mich durch die zahlreichen Änderungen unterstützt haben. Bis jetzt hoffe ich, dass eine Lösung gefunden werden kann, die es auch erlaubt, die Zeile in einem gleichmäßigen Tempo zu löschen.

    
Roymunson 03.01.2016, 14:16
quelle

2 Antworten

2

Basierend auf Ihrem neuesten Code, hier ist, was ich zuerst versuchen würde. Ich mache die folgenden Annahmen in dieser Antwort:

  • Sie werden nur eine Linie / einen Pfad zu einer bestimmten Zeit zeichnen (wenn nicht, müssen Sie das unten beschriebene Verfahren für jeden Pfad ausführen, indem Sie über eine Sammlung von Pfaden iterieren)

Erstellen Sie einen Wrapper um die Klasse Point , der einen Zeitstempel hinzufügt:

%Vor%

Aktualisieren Sie dann Ihren Punktspeicher auf Folgendes:

%Vor%

(Als Folge davon müssen Sie eine Reihe von Änderungen am Code vornehmen. Insbesondere können Sie mit der List Methode add neue Punkte an das Ende dieser Liste anhängen und nicht Verfolgen der arrayIndex explizit.)

Ersetzen Sie in Ihrer Methode onTouchEvent diesen Codeblock:

%Vor%

mit etwas, das so aussieht:

%Vor%

Nehmen Sie eine ähnliche Anpassung überall dort vor, wo Sie dem Array linePoints Werte hinzufügen. Beachten Sie auch, dass wir das Path nicht mehr inkrementell während dieser Schleife erstellen. Das liegt daran, dass wir vor der Erstellung von Path eine Bereinigung durchführen (d. H. Um abgelaufene Punkte zu entfernen). Um dies zu tun, löschen Sie linePath jedes Mal, wenn Sie das Zeichnen vorbereiten (Sie können diese Methode möglicherweise an einen anderen Ort verschieben, wenn die Leistung schlecht ist; ich würde nur vorschlagen, dass dies in onDraw geschieht, um den vorgeschlagenen Lebenszyklus zu verdeutlichen). Ihre onDraw -Methode würde dann etwa so aussehen:

%Vor%

wobei validPoints ein anderes Feld vom Typ List<TimeStampedPoint> s ist. [Im Allgemeinen ist das Aufrufen von invalidate aus onDraw wahrscheinlich nicht die beste Idee, aber das liegt außerhalb des Bereichs dieser Frage.]

Zwei neue Methoden wurden hier eingeführt:

%Vor%

und

%Vor%

Hoffentlich gibt das Ihnen genug von einem Rahmen, um anzufangen. Wenn Sie bemerken, dass das verschwindene Ende der Zeile ruckelt, habe ich Ideen, die helfen können, aber es ist ein Haufen mehr Tippen - also lassen Sie uns nicht vorzeitig optimieren:)

    
stkent 07.01.2016, 15:17
quelle
3

Ich empfehle, eine ArrayList anstelle eines statischen Arrays zu verwenden, da Sie nicht immer 10000 Punkte speichern müssen. Ich schlage auch vor, eine Unterklasse von Point zu erstellen und einen Zeitpunkt bei der Instanziierung speichern zu lassen. Überlegen Sie:

%Vor%

removeOldPoints() entfernt alle Punkte von linePoints , deren Zeitdifferenz größer als der in TimedPoint definierte Schwellenwert ist. Dies setzt voraus, dass Sie removeOldPoints() regelmäßig aufrufen können. Tipp Hinweis, Aufruf in onDraw() wäre toll.

Wenn removeOldPoints() in onDraw aufgerufen wird, bevor die Linie gezeichnet wird, können Sie garantieren, dass jeder Punkt, der in linePoints enthalten ist, gezeichnet werden soll. An diesem Punkt ist es so einfach wie über die Liste zu iterieren und die Punkte als Linie zu zeichnen, und der "Schwanz" verschwindet beim Zeichnen.

Sie könnten auch linePoints an TimedPoint übergeben und eine Timer bei Konstruktion und schedule() jede TimedPoint festlegen, um sich zu einem bestimmten Zeitpunkt in der Zukunft selbst zu entfernen. Dies setzt nicht voraus, dass Sie removeOldPoints() regelmäßig aufrufen können. Überlegen Sie:

%Vor%

Es gibt ein paar Dinge, die Sie auch mit diesem Ansatz optimieren könnten. Zum Beispiel beginnen Punkte zu "sterben", sobald sie "geboren" sind. Wir können das nur ändern, wenn es zur Liste hinzugefügt wird, wenn das geeigneter ist.

Außerdem gibt es wahrscheinlich auch Raum für Optimierung, da ich denke, dass dadurch pro Punkt ein neuer Thread erzeugt werden kann. Dies sollte tatsächlich die Leistung verbessern (wenn removeOldPoints() der Engpass war), bis Ihre CPU durch Kontextwechsel verkrüppelt ist. Wenn Sie sich pedantisch fühlen oder Leistung zu einem Problem wird; Sie könnten einen Threadpool und eine Warteschlange verwenden.

Hier ist die Dokumentation für ArrayList , um Ihnen zu helfen sich an die neue Klasse gewöhnen.

Glückliche Codierung:)

BEARBEITEN Es scheint, dass Sie immer noch Probleme haben. Probieren Sie es aus und lassen Sie mich wissen, was es für Sie tut.

%Vor%     
MeetTitan 07.01.2016 03:45
quelle

Tags und Links