Я изменил код, чтобы он точно соответствовал примеру, и, по крайней мере, он больше не взрывается мгновенно.
Основная проблема, казалось, заключалась в циклах с дельтами. Корректировка кода для весеннего обновления и их комментарии приводят к приятным колебаниям, которые не прекращались, но и не взрывались.
Внешний l oop кажется важным, чтобы немного облегчить все .
Я бы подумал, что это из-за добавленной высоты, поскольку изменение высоты изменяет силу пружины.
import pygame, random
import math as m
from pygame import *
pygame.init()
WINDOW_SIZE = (854, 480)
screen = pygame.display.set_mode(WINDOW_SIZE,0,32) # initiate the window
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
class surface_water_particle():
def __init__(self, x,y):
self.x_pos = x
self.y_pos = y
self.target_y = y
self.velocity = 0
self.k = 0.02
self.d = 0.02
self.time = 1
def update(self):
x = self.y_pos - self.target_y #this was overly complicated for some reason
a = -self.k * x - self.d * self.velocity #here was a wrong sign for the dampening
self.y_pos += self.velocity
self.velocity += a
class water():
def __init__(self, x_start, x_end, y_start, y_end, segment_length):
self.springs = []
self.x_start = x_start
self.y_start = y_start
self.x_end = x_end
self.y_end = y_end - 10
for i in range(abs(x_end - x_start) // segment_length):
self.springs.append(surface_water_particle(i * segment_length + x_start, y_end))
def update(self, spread):
for i in range(len(self.springs)):
self.springs[i].update()
leftDeltas = [0] * len(self.springs)
rightDeltas = [0] * len(self.springs)
# adding this outer loop gave the real success
for j in range(0,8):
for i in range(0, len(self.springs) ):
if i > 0:
leftDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i - 1].y_pos)
self.springs[i - 1].velocity += leftDeltas[i]
if i < len(self.springs) - 1:
rightDeltas[i] = spread * (self.springs[i].y_pos - self.springs[i + 1].y_pos)
self.springs[i + 1].velocity += rightDeltas[i]
# here you used velocity instead of height before
for i in range(0, len(self.springs) ):
if i > 0:
self.springs[i - 1].y_pos += leftDeltas[i]
if i < len(self.springs) - 1:
self.springs[i + 1].y_pos += rightDeltas[i]
def splash(self, index, speed):
if index > 0 and index < len(self.springs) :
self.springs[index].velocity = speed
def draw(self):
water_surface = pygame.Surface((abs(self.x_start - self.x_end), abs(self.y_start - self.y_end))).convert_alpha()
water_surface.fill((0,0,0,0))
water_surface.set_colorkey((0,0,0,0))
polygon_points = []
polygon_points.append((self.x_start, self.y_start))
for spring in range(len(self.springs)):
polygon_points.append((water_test.springs[spring].x_pos, water_test.springs[spring].y_pos))
polygon_points.append((water_test.springs[len(self.springs) - 1].x_pos, self.y_start))
#pygame.draw.polygon(water_surface, (0,0,255), polygon_points)
for spring in range(0,len(self.springs) - 1):
pygame.draw.line(screen, (0,0,255), (water_test.springs[spring].x_pos, water_test.springs[spring].y_pos), (water_test.springs[spring + 1].x_pos, water_test.springs[spring + 1].y_pos), 2)
#water_surface.set_alpha(100)
return water_surface
def update_fps():
fps_text = font.render(str(int(clock.get_fps())), 1, pygame.Color("coral"))
screen.blit(fps_text, (0,0))
water_test = water(0,800,200,80, 20)
while True:
screen.fill((255,255,255))
water_test.update(0.5)
screen.blit(water_test.draw(), (0,0))
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == MOUSEBUTTONDOWN:
water_test.splash(10,0.1)
pygame.display.update()
clock.tick(60)
Как правило, вам нужно, чтобы ускорение происходило в противоположное направление перепада высот (хочет восстановить исходное положение). Скорость должна уменьшиться и в конечном итоге вернуться к 0.
С исходным кодом, который у вас был, даже без циклов, выполняющих распространение, скорость увеличивалась, а не уменьшалась.
Скорость, вероятно, увеличится. никогда не достигает 0, поэтому вам, вероятно, также следует добавить порог, где вы просто установите его на 0, чтобы избежать мерцания.
Для отладки всегда печатайте свои значения и посмотрите, имеют ли они смысл. В этом случае вы могли бы заметить, что скорость увеличивается даже для одного шага обновления пружины.
Изменить: этот ответ устраняет проблему, но не настраивает параметры, чтобы она выглядела хорошо. См. Ответ Джеффа Х. , чтобы узнать о хорошем выборе параметров.