nochmal Modelieren von Kräften
Verfasst: Montag 28. Januar 2019, 17:04
Hallo liebe Forumsmitglieder,
Programm animiert zwei Moverobjekte, auf die Gravitation und Reibung wirken.
Um Reibungskraft zu animieren bin ich so vorgegangen:
Reibung = -1 * C * N * (Einheitsvektor Geschwindigkeit) mit C: Reibungsfaktor
N: Normalkraft ( Wert 1 gesetzt, da nur Animation)
als Code: friction = mover.get_velocity()
friction = friction.normalize() * -1 * C
und dann mit apply_force(friction) den Kräften hinzugefügt
Bekomme jedoch diese Fehlermeldung: friction = friction.normalize() * -1 * C
ValueError: Can't normalize Vector of length Zero
Was auch völlig korrekt ist, da zu Beginn der Animation die Geschwindigkeit (0, 0) ist.
Weil ich nicht weiss, wie man diesen Wert des velocity- Vektors abfangen kann , habe ich einfach
Phantasiewerte für diesen Fall angenommen mit:
if friction[0] == 0.0 or friction[1] == 0.0:
friction[0], friction[1] = .001, .001
Das Programm läuft dann zwar, aber nicht korrekt, denn wenn ich C = 0.0 setze müssten die Moverobjekte unendlich weiter vom Boden abprallen.
Was sie aber nicht tun.
Vielleicht kann mir jemand helfen?
Code:
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,50)
DARKGRAY = (40, 40, 40)
BG_COLOR = YELLOW
# Reibungsfaktor
C = 0.1
class Mover():
def __init__(self, position, 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.mass = m
self.thickness = 2
def get_force(self,force):
self.force = deepcopy(force)
return self.force
def get_velocity(self):
return self.velocity
def apply_force(self,force):
#f = self.get_force(force)
# 2.Newton Gesetz: Beschleunigung = Kraft / Masse
#f /= self.mass
#print(f)
self.acceleration += force/self.mass
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.location.x),
int(self.location.y)), 8*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.location.x = WIDTH
self.velocity.x *= -1 # keine Dämpfung
elif self.location.x < 0:
self.location.x = 0
self.velocity.x *= -1 # keine Dämpfung
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
m1 = Mover((300, 0), 1)
m2 = Mover((500, 0), 5)
movers = [m1, m2]
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.09, 0)
# Gravitation, direkt mit Masse skaliert -> real gravity
#m = mover.mass
gravity = vec(0, 0.5*mover.mass)
# Reibungskraft
friction = mover.get_velocity()
print(friction) # debug
# um unmögliche Berechnung der Normalisierung der Anfangsgeschwindigkeit
# velocity = (0,0) zu umgehen, auf willkürliche Werte festgesetzt
if friction[0] == 0.0 or friction[1] == 0.0:
friction[0], friction[1] = .001, .001
# normalisiere Vektor, skaliere in Gegenrichtung und skaliere mit
# Reibungsfaktor
friction = friction.normalize() * -1 * C
#friction *= -1
#friction = friction.normalize() * C
mover.apply_force(friction)
mover.apply_force(wind)
mover.apply_force(gravity)
mover.update()
mover.display()
mover.check_edges()
pygame.display.set_caption('Movers friction')
pygame.display.flip()
Programm animiert zwei Moverobjekte, auf die Gravitation und Reibung wirken.
Um Reibungskraft zu animieren bin ich so vorgegangen:
Reibung = -1 * C * N * (Einheitsvektor Geschwindigkeit) mit C: Reibungsfaktor
N: Normalkraft ( Wert 1 gesetzt, da nur Animation)
als Code: friction = mover.get_velocity()
friction = friction.normalize() * -1 * C
und dann mit apply_force(friction) den Kräften hinzugefügt
Bekomme jedoch diese Fehlermeldung: friction = friction.normalize() * -1 * C
ValueError: Can't normalize Vector of length Zero
Was auch völlig korrekt ist, da zu Beginn der Animation die Geschwindigkeit (0, 0) ist.
Weil ich nicht weiss, wie man diesen Wert des velocity- Vektors abfangen kann , habe ich einfach
Phantasiewerte für diesen Fall angenommen mit:
if friction[0] == 0.0 or friction[1] == 0.0:
friction[0], friction[1] = .001, .001
Das Programm läuft dann zwar, aber nicht korrekt, denn wenn ich C = 0.0 setze müssten die Moverobjekte unendlich weiter vom Boden abprallen.
Was sie aber nicht tun.
Vielleicht kann mir jemand helfen?
Code:
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,50)
DARKGRAY = (40, 40, 40)
BG_COLOR = YELLOW
# Reibungsfaktor
C = 0.1
class Mover():
def __init__(self, position, 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.mass = m
self.thickness = 2
def get_force(self,force):
self.force = deepcopy(force)
return self.force
def get_velocity(self):
return self.velocity
def apply_force(self,force):
#f = self.get_force(force)
# 2.Newton Gesetz: Beschleunigung = Kraft / Masse
#f /= self.mass
#print(f)
self.acceleration += force/self.mass
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.location.x),
int(self.location.y)), 8*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.location.x = WIDTH
self.velocity.x *= -1 # keine Dämpfung
elif self.location.x < 0:
self.location.x = 0
self.velocity.x *= -1 # keine Dämpfung
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
m1 = Mover((300, 0), 1)
m2 = Mover((500, 0), 5)
movers = [m1, m2]
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.09, 0)
# Gravitation, direkt mit Masse skaliert -> real gravity
#m = mover.mass
gravity = vec(0, 0.5*mover.mass)
# Reibungskraft
friction = mover.get_velocity()
print(friction) # debug
# um unmögliche Berechnung der Normalisierung der Anfangsgeschwindigkeit
# velocity = (0,0) zu umgehen, auf willkürliche Werte festgesetzt
if friction[0] == 0.0 or friction[1] == 0.0:
friction[0], friction[1] = .001, .001
# normalisiere Vektor, skaliere in Gegenrichtung und skaliere mit
# Reibungsfaktor
friction = friction.normalize() * -1 * C
#friction *= -1
#friction = friction.normalize() * C
mover.apply_force(friction)
mover.apply_force(wind)
mover.apply_force(gravity)
mover.update()
mover.display()
mover.check_edges()
pygame.display.set_caption('Movers friction')
pygame.display.flip()