Hallo liebe Forummitglieder,
ich versuche z.Z. gerade Programmbeispiele aus dem Buch Nature of Code von D. Shiffman auf Pygame und Python zu übertragen. (Kapitel 2)
Moverobjekte fallen durch Gravitation zu Boden und werden dabei durch Windkraft abgetrieben, sie prellen vom Boden ab und kommen dann zur Ruhe.
Shiffman verwendet Vektoren (PVector) für location ,velocity, usw., sowie für Kräfte, also habe ich pygame's Vector2 verwendet.
Die Methode apply_force in meinem Programm arbeitet auf einer Kopie des Kraftvektors, daher benötigte ich eine Hilfsmethode get_force, die eine
Kopie des Vektors zurückgibt.
Frage: kann ich das so machen, da ich in der Doku zu Vector2 keine copy-Methode gefunden habe
Noch eine Frage: Das Programm funktioniert , allerdings sollte es nicht ganz so funktionieren. Da keine Dämpfung auf die Objekte implementiert ist, sollten sie
unendlich lange weiter prellen, was sie aber nicht tun., denn sie kommen zur Ruhe. Was läuft hier grundsätzlich falsch.
Für Hilfe und Tipps wäre ich dankbar.
import pygame
import math
from random import randint, uniform
from copy import deepcopy
vec = pygame.math.Vector2
WIDTH = 1000
HEIGHT = 800
FPS = 60
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
DARKGRAY = (40, 40, 40)
BG_COLOR = YELLOW
class Mover():
def __init__(self, position, size, m):
self.location = vec(0, 0)
self.location.x, self.location.y = position
self.velocity = vec(0,0)
self.acceleration = vec(0,0)
self.colour = BLUE
self.size = size
self.mass = m
self.thickness = 2
def get_force(self,force):
self.force = deepcopy(force)
return self.force
def apply_force(self,force):
f = self.get_force(force)
# 2.Newton Gesetz: Beschleunigung = Kraft / Masse
f /= self.mass
self.acceleration += f
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.location.x),
int(self.location.y)), int(self.size)* int(self.mass), int(self.thickness))
def update(self):
self.velocity += self.acceleration
self.location += self.velocity
self.acceleration * 0.0 # resette nach jedem update
def check_edges(self):
#das passiert, wenn Ball Fenstergrenzen erreicht
if self.location.x > WIDTH-self.size:
self.location.x = WIDTH-self.size
self.velocity.x *= -0.8 # Dämpfung
elif self.location.x < self.size:
self.velocity.x *= -1
self.location.x = self.size
if self.location.y > HEIGHT:
self.velocity.y *= -1 # keine Dämpfung
self.location.y = HEIGHT
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(BG_COLOR)
clock = pygame.time.Clock()
# erzeuge zwei Moverobjekte
num_mover = 2
movers = []
for i in range(num_mover):
size = uniform(10, 30)
position = (uniform(size, WIDTH - size), size)
mass = uniform(1, 5)
mover = Mover(position,size, mass)
movers.append(mover)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(BG_COLOR)
for mover in movers:
# Windkraft
wind = vec(0.001, 0)
# Gravitation, direkt mit Masse skaliert -> real gravity
m = mover.mass
gravity = vec(0, 0.004*m)
mover.apply_force(wind)
mover.apply_force(gravity)
mover.update()
mover.display()
mover.check_edges()
pygame.display.set_caption('Two Movers real gravity and wind')
pygame.display.flip()
Modellieren von Kräften ( Wind Gravitation)
schau dir mal ganz genau deine Methode update() an.
get_force() ist überflüssig
und apply_force() kannst du so schreiben
get_force() ist überflüssig
und apply_force() kannst du so schreiben
Code: Alles auswählen
def apply_force(self, force):
# 2.Newton Gesetz: Beschleunigung = Kraft / Masse
force /= self.mass
self.acceleration += force
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Danke Thomas L,
genau hier liegt laut Shiffman das Problem, er argumentiert so:
wir haben 2 Moveerobjekte m1 und m2 und wir haben eine Windkraft wind = vec2(1.0,0), und Masse mass = 10
m1 erhält die Windkraft : m1 equals wind force: (1,0)
Divided by mass of 10: (0.1,0)
m2 erhält ebenfalls die Windkraft: Frage: welchen Wert hat diese ? wind = vec2(0.1, 0) also den selben Wert wie m1.
But we don’t want m2 to receive
a force divided by the mass of object m1 . We want it to receive that force in its original
state—(1,0).
Also brauchen wir eine Kopie des Vektors: In processing:
void applyForce(PVector force) {
PVector f = force.get();
f.div(mass);
acceleration.add(f);
}
When you pass
an object (in this case a PVector ) into a function, you are passing a reference to that object.
It’s not a copy! So if a function makes a change to that object (which, in this case, it does by
dividing by mass) then that object is permanently changed!
In Englisch alles zitiert nach Shiffman Nature of Code S.72
Ehrlich gesagt, weiss ich wirklich nicht genau, ob das auf Python ebenso zutrifft.
genau hier liegt laut Shiffman das Problem, er argumentiert so:
wir haben 2 Moveerobjekte m1 und m2 und wir haben eine Windkraft wind = vec2(1.0,0), und Masse mass = 10
m1 erhält die Windkraft : m1 equals wind force: (1,0)
Divided by mass of 10: (0.1,0)
m2 erhält ebenfalls die Windkraft: Frage: welchen Wert hat diese ? wind = vec2(0.1, 0) also den selben Wert wie m1.
But we don’t want m2 to receive
a force divided by the mass of object m1 . We want it to receive that force in its original
state—(1,0).
Also brauchen wir eine Kopie des Vektors: In processing:
void applyForce(PVector force) {
PVector f = force.get();
f.div(mass);
acceleration.add(f);
}
When you pass
an object (in this case a PVector ) into a function, you are passing a reference to that object.
It’s not a copy! So if a function makes a change to that object (which, in this case, it does by
dividing by mass) then that object is permanently changed!
In Englisch alles zitiert nach Shiffman Nature of Code S.72
Ehrlich gesagt, weiss ich wirklich nicht genau, ob das auf Python ebenso zutrifft.
per
mover.apply_force(wind)
mover.apply_force(gravity)
werden doch auf jedem mover object völlig unabhängig von einander die Kräfte angewendet.
Diese Wind-Force und Gravitation werden doch gar nicht modifiziert.
Die von dir zitierte Problematik hast du gar nicht.
und, hast du das fehlende Zeichen in update() entdeckt?
mover.apply_force(wind)
mover.apply_force(gravity)
werden doch auf jedem mover object völlig unabhängig von einander die Kräfte angewendet.
Diese Wind-Force und Gravitation werden doch gar nicht modifiziert.
Die von dir zitierte Problematik hast du gar nicht.
und, hast du das fehlende Zeichen in update() entdeckt?
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Thomas L
Hallo,
zu update() : da gehört ein Gleichheitszeichen hin: -> *=
damit ist meine zweite Ausgangsfrage bezüglich der fehlenden Dämpfung erledigt,
Danke!
Was allerdings deine Antwort auf die Verwendung einer Kopie des Vektors betrifft, so bin
ich noch nicht überzeugt. Der Einwand bei Shiffman erscheint mir logisch, allerdings bin ich
Anfänger, was python und pygame betrifft. Die von dir behauptete Unabhängigkeit bezüglich der Windkraft
möchtest du mir genauer erklären, weil ich das nicht verstehe.
Wenn ich 2 Objekte habe, dann geschieht doch
m1.apply_force(wind);
m2.apply_force(wind);
und in apply_force wird mit f /= mass der übergebene Windkraftvektor geändert
Hallo,
zu update() : da gehört ein Gleichheitszeichen hin: -> *=
damit ist meine zweite Ausgangsfrage bezüglich der fehlenden Dämpfung erledigt,
Danke!
Was allerdings deine Antwort auf die Verwendung einer Kopie des Vektors betrifft, so bin
ich noch nicht überzeugt. Der Einwand bei Shiffman erscheint mir logisch, allerdings bin ich
Anfänger, was python und pygame betrifft. Die von dir behauptete Unabhängigkeit bezüglich der Windkraft
möchtest du mir genauer erklären, weil ich das nicht verstehe.
Wenn ich 2 Objekte habe, dann geschieht doch
m1.apply_force(wind);
m2.apply_force(wind);
und in apply_force wird mit f /= mass der übergebene Windkraftvektor geändert
bzgl. apply_force() hast du Recht, force wird geändert
das können wir so umgehen
Code: Alles auswählen
def apply_force(self, force):
# 2.Newton Gesetz: Beschleunigung = Kraft / Masse
self.acceleration += force / self.mass
Code: Alles auswählen
for mover in movers:
wind = vec(0.001, 0)
gravity = vec(0, 0.004 * mover.mass)
mover.apply_force(wind)
mover.apply_force(gravity)
Wenn wind ausserhalb der Schleife definiert wäre, würde deine Problematik greifen.
gravity muss ja innerhalb der Schleife berechnet werden.
Aber mit der geänderten apply_force() gibt es diese Problematik gar nicht mehr.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Danke ThomasL für deine schnellen Antworten,
mein Problem ist, dass ich processing code auf python/pygame übertragen will und deswegen klebe ich doch sehr an
dem processing code.
Dort wird ebenfalls im Hauptprogramm eine Schleife verwendet.
Das Problem scheint mir in apply_force zu liegen. In deiner Version arbeitest du nicht mit einer Kopie, wenn ich das recht verstehe.
Daher würden die Einwände von Shiffmann greifen und für einen frame würde Objekt 2 den Wert von Objekt 1 haben.
Allerdings sind meine Kenntnisse in python ebenso wie processing gering und ich kann nicht nachvollziehen, welche Werte
die einzelnen Kräfte haben. Also verlasse mich lieber auf deine Darstellung.
mein Problem ist, dass ich processing code auf python/pygame übertragen will und deswegen klebe ich doch sehr an
dem processing code.
Dort wird ebenfalls im Hauptprogramm eine Schleife verwendet.
Das Problem scheint mir in apply_force zu liegen. In deiner Version arbeitest du nicht mit einer Kopie, wenn ich das recht verstehe.
Daher würden die Einwände von Shiffmann greifen und für einen frame würde Objekt 2 den Wert von Objekt 1 haben.
Allerdings sind meine Kenntnisse in python ebenso wie processing gering und ich kann nicht nachvollziehen, welche Werte
die einzelnen Kräfte haben. Also verlasse mich lieber auf deine Darstellung.
Hallo Hell,
ich habe gerade noch mal schnell ins Buch geschaut https://natureofcode.com/book/chapter-2-forces/
und aus dem Ende von Kapitel 2.4 zitierst du die von ihm geschilderte Problematik, die man, wie Daniel selber schreibt, halt auf 2 Wegen lösen kann.
Der eine Weg ist der mit einer Kopie des Vektors, da nachfolgend die Vektormethode vector.div(skalar) verwendet wird und diese verändert halt den Vektor.
Der andere Weg, den ich in obigen Code verwende, ist die in Python umgesetzte Version der statische Methode Pvector.div(vector, skalar), die man ja dann in Aufgabe 2.2 verwenden soll.
Dadurch wird der als Parameter übergebene, konstante, Windvektor nicht verändert und könnte außerhalb der Schleife einmalig definiert werden.
Ich habe im übrigen vor einem Jahr genau das gleiche gemacht wie du und das ganze Buch und alle entsprechenden Youtube Folgen in Python codiert.
Bin darüber zu Neuronalen Netzen und Maschine Learning gekommen. Einfach genial.
Wenn du also im weiteren Verlauf Fragen hast, helfe ich gerne.
ich habe gerade noch mal schnell ins Buch geschaut https://natureofcode.com/book/chapter-2-forces/
und aus dem Ende von Kapitel 2.4 zitierst du die von ihm geschilderte Problematik, die man, wie Daniel selber schreibt, halt auf 2 Wegen lösen kann.
Der eine Weg ist der mit einer Kopie des Vektors, da nachfolgend die Vektormethode vector.div(skalar) verwendet wird und diese verändert halt den Vektor.
Der andere Weg, den ich in obigen Code verwende, ist die in Python umgesetzte Version der statische Methode Pvector.div(vector, skalar), die man ja dann in Aufgabe 2.2 verwenden soll.
Dadurch wird der als Parameter übergebene, konstante, Windvektor nicht verändert und könnte außerhalb der Schleife einmalig definiert werden.
Ich habe im übrigen vor einem Jahr genau das gleiche gemacht wie du und das ganze Buch und alle entsprechenden Youtube Folgen in Python codiert.
Bin darüber zu Neuronalen Netzen und Maschine Learning gekommen. Einfach genial.
Wenn du also im weiteren Verlauf Fragen hast, helfe ich gerne.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png