【问题标题】:Drawing a square wave in pygame在pygame中绘制方波
【发布时间】:2014-07-22 20:06:27
【问题描述】:

这段 Python 代码在 pygame 窗口中演示了一个正弦波。

我也想以同样的方式绘制方波,尽管我不知道这段代码可能是什么,也不知道如何绘制方波/如何在 python 中构造方波。

有人知道我该怎么做吗?是否可以使用相同的导入,或者我需要新的?

代码:

    import sys, pygame, math
    from pygame.locals import *

    # set up a bunch of constants
    WHITE      = (255, 255, 255)
    DARKRED    = (128,   0,   0)
    RED        = (255,   0,   0)
    BLACK      = (  0,   0,   0)

    BGCOLOR = WHITE

    WINDOWWIDTH = 640 # width of the program's window, in pixels
    WINDOWHEIGHT = 480 # height in pixels
    WIN_CENTERX = int(WINDOWWIDTH / 2) # the midpoint for the width of the window
    WIN_CENTERY = int(WINDOWHEIGHT / 2) # the midpoint for the height of the window

    FPS = 160 # frames per second to run at

    AMPLITUDE = 80 # how many pixels tall the waves with rise/fall.

    # standard pygame setup code
    pygame.init()
    FPSCLOCK = pygame.time.Clock()
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
    pygame.display.set_caption('Trig Waves')
    fontObj = pygame.font.Font('freesansbold.ttf', 16)

    # variables that track visibility modes
    showSine = True

    pause = False

    xPos = 0
    step = 0 # the current input f
    posRecord = {'sin': []} # keeps track of the ball positions for drawing the waves

    # making text Surface and Rect objects for various labels
    sinLabelSurf         = fontObj.render('sine', True, RED, BGCOLOR)

    sinLabelRect         = sinLabelSurf.get_rect()


    instructionsSurf = fontObj.render('Press Q to toggle wave. P to pause.', True, BLACK, BGCOLOR)
    instructionsRect = instructionsSurf.get_rect()
    instructionsRect.left = 10
    instructionsRect.bottom = WINDOWHEIGHT - 10

    # main application loop
    while True:
        # event handling loop for quit events
        for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
                pygame.quit()
                sys.exit()

            # check for key presses that toggle pausing and wave visibility
            if event.type == KEYUP:
                if event.key == K_q:
                    showSine = not showSine
                elif event.key == K_p:
                    pause = not pause

        # fill the screen to draw from a blank state
        DISPLAYSURF.fill(BGCOLOR)

        # draw instructions
        DISPLAYSURF.blit(instructionsSurf, instructionsRect)



        # sine wave
        yPos = -1 * math.sin(step) * AMPLITUDE
        posRecord['sin'].append((int(xPos), int(yPos) + WIN_CENTERY))
        if showSine:
            # draw the sine ball and label
            pygame.draw.circle(DISPLAYSURF, RED, (int(xPos), int(yPos) + WIN_CENTERY), 10)
            sinLabelRect.center = (int(xPos), int(yPos) + WIN_CENTERY + 20)
            DISPLAYSURF.blit(sinLabelSurf, sinLabelRect)

        # draw the waves from the previously recorded ball positions
        if showSine:
            for x, y in posRecord['sin']:
                pygame.draw.circle(DISPLAYSURF, DARKRED, (x, y), 4)


        # draw the border
        pygame.draw.rect(DISPLAYSURF, BLACK, (0, 0, WINDOWWIDTH, WINDOWHEIGHT), 1)

        pygame.display.update()
        FPSCLOCK.tick(FPS)

        if not pause:
            xPos += 0.5
            if xPos > WINDOWWIDTH:
                xPos = 0
                posRecord = {'sin': []}
                step = 0
            else:
                step += 0.008
                step %= 2 * math.pi

Python 2.6 版、Pygame 1.9.2 版

【问题讨论】:

  • 有人使用基本的sin()计算位置并绘制暗红色圆圈(一个接一个)而不清除屏幕。你需要一些条件来改变浅红色球的方向 - 水平和垂直移动它。
  • 如果你使用yPos = 0 代替yPos = -1 * math.sin(step) * AMPLITUDE 那么你会得到水平线。那么你将不得不不时更改yPos

标签: python pygame draw trigonometry


【解决方案1】:

我做了一些修改以添加方波。

查看带有### HERE 的地点。

import sys, pygame, math
from pygame.locals import *

# set up a bunch of constants
WHITE      = (255, 255, 255)
DARKRED    = (128,   0,   0)
RED        = (255,   0,   0)
BLACK      = (  0,   0,   0)
GREEN      = (  0, 255,   0) ### HERE
BLUE       = (  0,   0, 255) ### HERE

BGCOLOR = WHITE

WINDOWWIDTH = 640 # width of the program's window, in pixels
WINDOWHEIGHT = 480 # height in pixels
WIN_CENTERX = int(WINDOWWIDTH / 2) # the midpoint for the width of the window
WIN_CENTERY = int(WINDOWHEIGHT / 2) # the midpoint for the height of the window

FPS = 160 # frames per second to run at

AMPLITUDE = 80 # how many pixels tall the waves with rise/fall.

# standard pygame setup code
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('Trig Waves')
fontObj = pygame.font.Font('freesansbold.ttf', 16)

# variables that track visibility modes
showSine = True
showSquare = True ### HERE

pause = False

xPos = 0
step = 0 # the current input f

### HERE 
posRecord = {'sin': [], 'square': []} # keeps track of the ball positions for drawing the waves

# making text Surface and Rect objects for various labels

### HERE 
squareLabelSurf = fontObj.render('square', True, BLUE, BGCOLOR)
squareLabelRect = squareLabelSurf.get_rect()

sinLabelSurf = fontObj.render('sine', True, RED, BGCOLOR)
sinLabelRect = sinLabelSurf.get_rect()


instructionsSurf = fontObj.render('Press Q to toggle wave. P to pause.', True, BLACK, BGCOLOR)
instructionsRect = instructionsSurf.get_rect()
instructionsRect.left = 10
instructionsRect.bottom = WINDOWHEIGHT - 10

### HERE
yPosSquare = AMPLITUDE # starting position

# main application loop
while True:
    # event handling loop for quit events
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
            pygame.quit()
            sys.exit()

        # check for key presses that toggle pausing and wave visibility
        if event.type == KEYUP:
            if event.key == K_q:
                showSine = not showSine
            elif event.key == K_p:
                pause = not pause

    # fill the screen to draw from a blank state
    DISPLAYSURF.fill(BGCOLOR)

    # draw instructions
    DISPLAYSURF.blit(instructionsSurf, instructionsRect)

    # sine wave
    yPos = -1 * math.sin(step) * AMPLITUDE
    posRecord['sin'].append((int(xPos), int(yPos) + WIN_CENTERY))
    if showSine:
        # draw the sine ball and label
        pygame.draw.circle(DISPLAYSURF, RED, (int(xPos), int(yPos) + WIN_CENTERY), 10)
        sinLabelRect.center = (int(xPos), int(yPos) + WIN_CENTERY + 20)
        DISPLAYSURF.blit(sinLabelSurf, sinLabelRect)

    # draw the waves from the previously recorded ball positions
    if showSine:
        for x, y in posRecord['sin']:
            pygame.draw.circle(DISPLAYSURF, DARKRED, (x, y), 4)

    ### HERE - drawing horizontal lines
    # square 
    posRecord['square'].append((int(xPos), int(yPosSquare) + WIN_CENTERY))
    if showSquare:
        # draw the sine ball and label
        pygame.draw.circle(DISPLAYSURF, GREEN, (int(xPos), int(yPosSquare) + WIN_CENTERY), 10)
        squareLabelRect.center = (int(xPos), int(yPosSquare) + WIN_CENTERY + 20)
        DISPLAYSURF.blit(squareLabelSurf, squareLabelRect)

    # draw the waves from the previously recorded ball positions
    if showSquare:
        for x, y in posRecord['square']:
            pygame.draw.circle(DISPLAYSURF, BLUE, (x, y), 4)

    # draw the border
    pygame.draw.rect(DISPLAYSURF, BLACK, (0, 0, WINDOWWIDTH, WINDOWHEIGHT), 1)

    pygame.display.update()
    FPSCLOCK.tick(FPS)

    if not pause:
        xPos += 0.5

        if xPos > WINDOWWIDTH:
            #sine ### HERE
            xPos = 0
            posRecord['sin'] = []
            step = 0

            # square ### HERE
            yPosSquare = AMPLITUDE
            posRecord['square'] = []
        else:
            #sine ### HERE
            step += 0.008
            #step %= 2 * math.pi

            # square ### HERE
            # jump top and bottom every 100 pixels
            if xPos % 100 == 0:
                yPosSquare *= -1
                # add vertical line
                for x in range(-AMPLITUDE, AMPLITUDE):
                    posRecord['square'].append((int(xPos), int(x) + WIN_CENTERY))

【讨论】:

  • 我添加了新代码 - 现在您可以在红球下方看到标签 square。我在变量名中使用square
  • 我在再次开始绘制波浪时发现了一个错误 - 答案中有新代码。
  • 非常感谢您的帮助,有什么方法可以让球移动得更快吗?另外,我怎样才能让波浪在屏幕上开始已经完成,让球沿着这条预先绘制的线移动?
  • 脚本使用变量FPS(每秒帧数)在更快和更慢的计算机上保持恒定速度。您可以更改它以获得更快的移动。或者您可以一次绘制更多“点”(在一个循环中)——但这需要对代码进行更多更改。
  • 我试图改变这一点,但似乎如果 FPS 更高,它会达到一个限制,它不会更快。 “循环中的更多点”方法如何工作?
猜你喜欢
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多