我目前正在尝试在 python/pygame(来自 java,编码火车视频的 p5: https : //www.youtube.com/watch?v= BZUdGqeOD0w)中复制水波纹效果。

我无法让它工作,屏幕保持空白(黑色:背景色)或者我给了我错误:

 Traceback (most recent call last): File "/Users/vicki/Documents/Atom Test/Water Ripple.py", line 39, in <module> screen.fill((current[i][j],current[i][j],current[i][j]),(i,j,1,1)) TypeError: invalid color argument

我实际上发现这是正常的,因为我们从 0 开始使用一个正数来获得像素的颜色:

current[i][j] = (previous[i-1][j]+previous[i+1][j]+ previous[i][j+1]+ previous[i][j-1])/ 2 - current[i][j]

previous[i-1][j] , previous[i+1][j] , previous[i][j-1] , previous[i][j+1]都等于 0,而current[I][j]是一个正数,所以逻辑上它应该给出一个负的颜色值。 也许这与数组在 Python 与 Java 中的工作方式有关?

如需更多帮助,这里是用于制作他的视频的网站编码训练: https : //web.archive.org/web/20160418004149/http : //freespace.virgin.net/hugo.elias/graphics/x_water.htm

这是我的代码:

import pygame

pygame.init()

width = 200
height = 200

cols = width
rows = height

#dampening = how fast the ripple effect stops.
dampening = 0.999


#Arrays that hold the colors of the screen.
current = [[0]*cols]*rows
previous = [[0]*cols]*rows


screen = pygame.display.set_mode((width,height))
#Sets the initial background to black
screen.fill((0,0,0))

#Mainloop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        if event.type == pygame.MOUSEBUTTONDOWN:
            #if the user clicks the screen, it sets the pixel the user clicked upon white
            mouse_pos = pygame.mouse.get_pos()
            current[mouse_pos[0]][mouse_pos[1]] = 255



    #This part seems to be the problem
    for i in range(1,rows-1):
        for j in range(1,cols-1):
            #This computation is weird: we are substracting positive/zero number from a null number which should normally give us a negative number. A color value (RGB) cannot be a negative number!
            current[i][j] = (previous[i-1][j]+previous[i+1][j]+ previous[i][j+1]+ previous[i][j-1])/ 2 - current[i][j]
            current[i][j] *= dampening
            #This line is where it gives me the error
            screen.fill((current[i][j],current[i][j],current[i][j]),(i,j,1,1))

    #Switching the arrays, have also tried: previous, current = current, previous (doesn't work either)
    temp = previous
    previous = current
    current = temp
    pygame.display.flip()

这是编码训练的代码(在java P5中):(注意:他使用mousedraft而不是mouseTouch(在视频中他使用mousetouch)但这并不重要。)

// Daniel Shiffman
// http://codingtra.in
// http://patreon.com/codingtrain

// 2D Water Ripples
// Video: https://youtu.be/BZUdGqeOD0w
// Algorithm: https://web.archive.org/web/20160418004149/http://freespace.virgin.net/hugo.elias/graphics/x_water.htm

int cols;
int rows;
float[][] current;// = new float[cols][rows];
float[][] previous;// = new float[cols][rows];

float dampening = 0.99;

void setup() {
  size(600, 400);
  cols = width;
  rows = height;
  current = new float[cols][rows];
  previous = new float[cols][rows];
}

void mouseDragged() {
  previous[mouseX][mouseY] = 500;
}

void draw() {
  background(0);

  loadPixels();
  for (int i = 1; i < cols-1; i++) {
    for (int j = 1; j < rows-1; j++) {
      current[i][j] = (
        previous[i-1][j] + 
        previous[i+1][j] +
        previous[i][j-1] + 
        previous[i][j+1]) / 2 -
        current[i][j];
      current[i][j] = current[i][j] * dampening;
      int index = i + j * cols;
      pixels[index] = color(current[i][j]);
    }
  }
  updatePixels();

  float[][] temp = previous;
  previous = current;
  current = temp;
}

#1楼 票数:2 已采纳

首先

current = [[0]*cols]*rows previous = [[0]*cols]*rows

不是二维数组。 它生成一个列表,然后生成一个外部列表,其中每个元素都引用同一个内部列表。

如果你想生成一个列表,其中每个元素都是一个单独的列表,那么你必须:
(内部维度应该是行,例如current[col][row] / current[x][y]

current = [[0]*rows for col in range(cols)]
previous = [[0]*rows for col in range(cols)]

在 pygame 中,颜色通道的值必须是 [0, 255] 范围内的整数值:

val = min(255, max(0, round(current[i][j])))
screen.fill((val, val, val), (i,j,1,1)) 

此外, MOUSEBUTTONDOWN事件仅在按下鼠标按钮时发生一次。 你必须评估鼠标的当前状态是否被pygame.mouse.get_pressed()按下:

while True:
    # [...]
    
    if any(pygame.mouse.get_pressed()):
        mouse_pos = pygame.mouse.get_pos()
        previous[mouse_pos[0]][mouse_pos[1]] = 500

我建议分别使用pygame.Surfacepygame.PixelArray来提高性能。 这是类似loadPixels() / updatePixels()处理

img = pygame.Surface((width, height))
while True:
    # [...]

    pixelArray = pygame.PixelArray(img)
    for i in range(1,cols-1):
        for j in range(1,rows-1):
            current[i][j] = (
                previous[i-1][j] + 
                previous[i+1][j] +
                previous[i][j-1] + 
                previous[i][j+1]) / 2 - current[i][j]
            current[i][j] *= dampening
            val = min(255, max(0, round(current[i][j])))
            pixelArray[i, j] = (val, val, val)
    pixelArray.close()
    screen.blit(img, (0, 0))

可悲的是,一切仍然非常缓慢。 完整示例:

import pygame
    
pygame.init()

width = 300
height = 200

cols = width
rows = height

#dampening = how fast the ripple effect stops.
dampening = 0.999

#Arrays that hold the colors of the screen.
current = [[0]*rows for col in range(cols)]
previous = [[0]*rows for col in range(cols)]

print(current[0][0], current[199][199])

screen = pygame.display.set_mode((width,height))
#Sets the initial background to black
screen.fill((0,0,0))

img = pygame.Surface((width, height))

#Mainloop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()         

    if any(pygame.mouse.get_pressed()):
        mouse_pos = pygame.mouse.get_pos()
        previous[mouse_pos[0]][mouse_pos[1]] = 500

    #This part seems to be the problem
    pixelArray = pygame.PixelArray(img)
    for i in range(1,cols-1):
        for j in range(1,rows-1):
            current[i][j] = (
                previous[i-1][j] + 
                previous[i+1][j] +
                previous[i][j-1] + 
                previous[i][j+1]) / 2 - current[i][j]
            current[i][j] *= dampening
            val = min(255, max(0, round(current[i][j])))
            pixelArray[i, j] = (val, val, val)
    pixelArray.close()

    # Switching the arrays
    previous, current = current, previous

    screen.blit(img, (0, 0))
    pygame.display.flip()

为了获得真正好的性能,您必须使用NumPy 在以下示例中,我使用pygame.time.Clock.tick限制了每秒帧数:

import numpy
import pygame
import scipy
pygame.init()

window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

size = window.get_size()
dampening = 0.999

current = numpy.zeros(size, numpy.float32)
previous = numpy.zeros(size, numpy.float32)
kernel = numpy.array([[0.0, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0]])

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False    
        
    if any(pygame.mouse.get_pressed()):
        mouse_pos = pygame.mouse.get_pos()
        previous[mouse_pos] = 1000

    # either:
    # current = (scipy.ndimage.convolve(previous, kernel) - current) * dampening
    # or:
    current[1:size[0]-1, 1:size[1]-1] = (
        (previous[0:size[0]-2, 0:size[1]-2] + 
         previous[2:size[0], 0:size[1]-2] + 
         previous[0:size[0]-2, 2:size[1]] + 
         previous[2:size[0], 2:size[1]]) / 2 - 
        current[1:size[0]-1, 1:size[1]-1]) * dampening

    array = numpy.transpose(255 - numpy.around(numpy.clip(current, 0, 255)))
    array = numpy.repeat(array.reshape(*size, 1).astype('uint8'), 3, axis = 2)
    image = pygame.image.frombuffer(array.flatten(), size, 'RGB')

    previous, current = current, previous

    window.blit(image, (0, 0))
    pygame.display.flip()

pygame.quit()
exit()    

  ask by Victor translate from so

未解决问题?本站智能推荐:

2回复

Pygame水波纹效果

我已经谷歌搜索它,但没有准备好的脚本 - 而不是对Flash的相同效果。 我已经检查了水效应解释的算法,并测试了Perlin噪声的实现,它可以很好地模拟平面上的波浪末端。 我正在寻找基于鼠标悬停/悬停操作在几个Flash Effects上找到的相同实现。 这是针对一个交互式楼层库,我很乐意
1回复

在pygame上绘制对象

我正在为 covid 模拟重新启动一些代码,因为我无法在当前的代码中使用碰撞功能。 我已经能够绘制基本背景,并绘制一个单元格。 但是,当我尝试在屏幕上的不同位置创建单元格时,由于某种原因它不会出现。 我的代码如下所示: 感谢您提前提供任何帮助
2回复

使用pygame创建滑块

我正在创建一个 covid 模拟器,并使用滑块来允许用户调整数字,例如待在家里的人数。 我已经能够成功创建滑块,但是由于某种原因,当我尝试移动一个时,它们都会移动。 我创建的代码是: 提前感谢您的任何帮助。
1回复

pygame中的随机系统运动

我正在制作一个 Covid 模拟器,需要我的球随机移动。 但是,我希望它们保持在选择的第一个随机方向上移动,并且只有在碰到另一个单元格或碰到墙壁时才改变方向。 我目前的代码如下: 我想知道是否有办法做到这一点,非常感谢您的帮助。 提前致谢。 我尝试将下面的第一个答案复制到我的 pycharm 中,但
1回复

Pygame浮点精度碰撞检测

我正在构建一个物理模拟,并想制作一个 pygame 可视化。 对于位置和速度计算,我使用Vector2 ,效果很好。 使用内置的矩形碰撞检测会很有帮助。 不幸的是,我必须先将矩形的当前位置四舍五入到一个像素。 由于在我的模拟中将 1 像素设置为 1 米,因此我只能确定 1 米内的物理碰撞。 有谁知道
1回复

如何移动和在pygame的指定的时间间隔示出了在一定速度的机器人

我尝试使用pygame的模拟机器人的运动。 机器人获取速度和间隔长度从RL算法。 例如,机器人移动以10 1秒的速度,然后以10 2秒,等的速度。 我尝试了这个方法,但没有奏效。
1回复

如何在基于pygame的模拟中最好地表示/实现运动对象?

我目前正在尝试进行大学的Bee模拟,并且已经开始研究如何做蜜蜂的基础知识。 最初的想法是使用PyGame并在屏幕上向用户展示蜜蜂,但现在我只是首先执行基本功能。 我遇到的功能是蜜蜂将查找未被使用的细胞然后去使用它们的功能。 它在每个新帧上运行,并在每个蜜蜂对象上运行,因此每个蜜蜂都会检
1回复

我如何才能使我的随机移动物体在pygame中以特定角度移动

完整代码 我目前正在用 pygame 在 python 中构建一个蚂蚁模拟器。 蚂蚁从中间开始,然后从那里随机移动。 运动是这样工作的。 每隔几毫秒self.new_line设置为 True。 然后计算新的self.deltax和self.deltay 。 现在,只要self.new_line为 F