2


ファイルを実行すると、矢印キーを長時間押し続けても、矢印コントロールと左長方形の移動が連続して上下しないのはなぜだろうか。

import pygame

black    = (   0,   0,   0)
white    = ( 255, 255, 255)
green    = (   0, 255,   0)
red      = ( 255,   0,   0)

pygame.init()

size = [700,500]
screen = pygame.display.set_mode(size)

fonto = pygame.font.SysFont("algerian", 100)
font = pygame.font.SysFont("algerian", 12)
text = fonto.render("Game Over", True, (0, 128, 10))

pygame.display.set_caption("Vasanths First Legit Game")

done = False
pygame.mouse.set_visible(0)

clock = pygame.time.Clock()
score = 1

rect_x = 50
rect_y = 50
rect_xp = 10
rect_yp = 10

rect_change_x = 10
rect_change_y = 10
rect_change_xp = 10
rect_change_yp = 3

while done == False:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            done=True 

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_DOWN:
                rect_yp = rect_change_yp+rect_yp
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                rect_yp = 0+rect_yp

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                rect_yp=-3+rect_yp
            if event.key == pygame.K_RIGHT:
                rect_yp=3+rect_yp
            if event.key == pygame.K_UP:
                rect_yp=-3+rect_yp
            if event.key == pygame.K_DOWN:
                rect_yp=3+rect_yp

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT:
                rect_yp=0+rect_yp
            if event.key == pygame.K_RIGHT:
                rect_yp=0+rect_yp
            if event.key == pygame.K_UP:
                rect_yp=0+rect_yp
            if event.key == pygame.K_DOWN:
                rect_yp=0+rect_yp

    pos = pygame.mouse.get_pos()

    x = pos[0] 
    y = pos[1] 

    screen.fill(black)

    pygame.draw.rect(screen,white,[rect_x,rect_y,10,10])
    pygame.draw.rect(screen,green,[x,490,50,10])
    pygame.draw.rect(screen,green,[10,rect_yp,10,50])
    # Move the rectangle starting point
    rect_x += rect_change_x
    rect_y += rect_change_y

    if rect_y == 0:
        rect_change_x=rect_change_x*1
        rect_change_y=rect_change_y*-1
    if rect_y == 490:
       if rect_x < x + 50 :
            scoref = font.render(score, True, (0, 128, 0))
            screen.blit(scoref,
                (20 - scoref.get_width() // 10, 20 - scoref.get_height() // 10))
            rect_change_x=rect_change_x*1
            rect_change_y=rect_change_y*-1

        if rect_x < x:
            rect_change_y = 0
            rect_change_x = 0

            #dont do this , it will go bizzonkes
            score = str(score)
            score = int(score)

    if rect_y == 490:
        if rect_x < x + 50 :
            if rect_change_x !=0:
                if rect_change_y !=0:
                    score=int(score)
                    score = score + 1
                    score=str(score)
    if rect_change_x == 0:
        if rect_change_y == 0:
                    screen.blit(text,
                        (320 - text.get_width() // 2, 240 - text.get_height() // 2))

    if rect_x == 700:
        rect_change_x = rect_change_x*-1
        rect_change_y = rect_change_y*1

    if rect_x == 0:
        rect_change_x = rect_change_x*0
        rect_change_y = rect_change_y*0

    if rect_y == 500:
        rect_change_y = 0
        rect_change_x = 0
        screen.blit(text,
            (320 - text.get_width() // 2, 240 - text.get_height() // 2))
        score=str(score)


    print(score)
    score = str(score)

    scoref = font.render(score, True, (0, 128, 0))
    screen.blit(scoref,
                (20 - scoref.get_width() // 10, 20 - scoref.get_height() // 10))

    clock.tick(30)

    pygame.display.flip()

pygame.quit ()
4

3 に答える 3

4

pygameでは、入力はイベントループで処理されます。イベントキューがあり、システムはキーボードから入力を送信し、呼び出すpygame.event.get()ことでキューの最初のイベントを取得します。イベントには多くの種類があり、最も人気のあるものはKEYUPKEYDOWNです。ほとんどの初心者が犯す間違いは、ボタンが押されると、KEYDOWNイベントが常に送信されると信じていることです。ボタンを押すと離すまで押されるので、これは必要ありません。したがって、ボタンが押されているかどうかを確認するには、特定のフラグが必要です。

これを行う最も一般的な方法は、d = v*t方程式を使用することです。速度は一定なので、方向を導入する必要があります。したがって、方程式は次のようになります。

distance_changed=方向*速度*time_change

次に、イベントループで、方向を変更します。

キーダウンの場合は1-右

-KEYDOWN-LEFTの場合は1

KEYUP-LEFTorRIGHTの場合は0。

今、質問がポップアップするかもしれません、なぜtime_changeを使用するのですか?プログラムがどのマシンで動作するかを予測できないため、ループが繰り返される回数はわかりません。古いマシンを使用すると、ゲームの動作が大幅に遅くなります。そのため、最後の移動からの時間を測定して、別のマシンで変更されないようにします。

ループが終了するのにかかる時間が一定になるように待機するpygame.tick(30)を使用していることがわかりました。古いマシンでこれを実行すると、問題が発生します。ループを高速化することはできません。

提案として、ゲームを関数に分割する必要があります。はるかに読みやすく、さまざまな場所でコードを使用できます。また、イベントループには多くのifが必要です。LEFTがすでに押されている場合、RIGTHキーが押されたかどうかを確認する意味がないため、elifを使用します。

于 2013-03-27T08:49:55.220 に答える
1

これは私が自分のPygameプロジェクトの1つでそれを処理する方法です:

class Inputs:

def __init__(self):
    self.bindings = {"up": pygame.K_UP,
                     "down":  pygame.K_DOWN,
                     "left":  pygame.K_LEFT,
                     "right":   pygame.K_RIGHT,
                     "lp":  pygame.K_a,
                     "mp":  pygame.K_s,
                     "hp":  pygame.K_d,
                     "lk":  pygame.K_z,
                     "mk":  pygame.K_x,
                     "hk":  pygame.K_c,
                     "pause":   pygame.K_RETURN}

    self.inputState = {"up": False,
                   "down": False,
                   "right": False,
                   "left": False,
                   "lp": False,
                   "mp": False,
                   "hp": False,
                   "lk": False,
                   "mk": False,
                   "hk": False,
                   "pause": False}

    self.buffer = InputBuffer()

def lookupBinding(self, keyEntered):
    for binding, keyBound in self.bindings.items():
        if keyEntered == keyBound:
            return binding

    return "not found"

def getInputState(self, events):
    for event in events:

        if event.type == pygame.KEYDOWN:
            binding = self.lookupBinding(event.key)
            if binding != "not found":
                newInput = Input()
                newInput.inputName = binding
                newInput.timeSinceInput = 0
                self.buffer.push(newInput)
                self.inputState[binding] = True

        if event.type == pygame.KEYUP:
            binding = self.lookupBinding(event.key)
            if binding != "not found":
                self.inputState[binding] = False

    return self.inputState

私は2つの辞書を保持しています。1つは方向などのゲーム内の「コマンド」からpygameキーへ、もう1つはコマンドのオン/オフ状態を表すブール値へのコマンドです。KEYDOWNイベントとKEYUPイベントを監視することで、マップされた入力がオンであるかオフであるかを判別できます。

編集:私が言及する必要があるこの方法の利点は、後でキーマッピングを変更すること、またはカスタムキーマッピングを許可することさえ非常に簡単にすることです。ゲームロジックは、ジャンプや移動入力などの基本的な入力のみに依存する必要があり、キーマッピングが変更されても変更する必要はありません。

于 2013-04-03T16:10:04.500 に答える
1

私は使用pygame.key.get_pressed()しますが、あなたも忘れていますpygame.key.set_repeat()。最初の引数は繰り返しを開始するのにかかるミリ秒数であり、2番目の引数はキーが繰り返される間隔です。

これは、次の両方を使用する例です。

x = 400
y = 300

import pygame, sys

bkg = (255, 211, 0)
clr = (0, 0, 0)
squ = (8, 11, 134)

pygame.init()
size = (800, 600)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Bloxy")
pygame.key.set_repeat(1, 1)
font = pygame.font.SysFont("Stencil", 20)
clock = pygame.time.Clock()

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

    keys_pressed = pygame.key.get_pressed()

    if keys_pressed[pygame.K_LEFT]:
        x -= 5
    if keys_pressed[pygame.K_RIGHT]:
        x += 5
    if keys_pressed[pygame.K_UP]:
        y -= 5
    if keys_pressed[pygame.K_DOWN]:
        y += 5

    if x > 800:
        x = 0
    if x < 0:
        x = 800
    if y > 600:
        y = 0
    if y < 0:
        y = 600

    screen.fill(bkg)
    text = font.render('(' + str(x) + ',' + str(y) + ')', True, clr)
    screen.blit(text, [10, 10])
    pygame.draw.rect(screen, squ, [x - 10, y - 10, 20, 20])

    pygame.display.flip()
    clock.tick(60)
于 2014-01-29T12:39:21.887 に答える