2

私はPythonの初心者で、サークルゲームを作ろうとしています。これまでのところ、クリックするとランダムな色と半径でマウスに円が描かれます。

次に、円が画面からランダムな方向に飛んでいきたいと思います。どうすればこれを行うことができますか?これは、これまでの私のコードの主要なチャンクです。

check1 = None
check2 = None

while True:

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

        if event.type == MOUSEBUTTONDOWN:
            last_mouse_pos = pygame.mouse.get_pos()



    if last_mouse_pos:

        global check

        color1 = random.randint(0,255)
        color2 = random.randint(0,255)
        color3 = random.randint(0,255)
        color = (color1,color2,color3)

        radius = random.randint (5,40)
        posx,posy = last_mouse_pos

        if posx != check1 and posy != check2:
            global check1, check2
            screen.lock()
            pygame.draw.circle(screen, color, (posx,posy), radius)
            screen.unlock()
            check1,check2 = posx,posy


    pygame.display.update()

繰り返しますが、円が画面からランダムな方向に飛んでいきたいと思います。私はいくつかの試みをしましたが、まだ成功していません。また、私を助けてくれたjdiに感謝します

4

2 に答える 2

7

(クリックして)円を作成するときに、2つの乱数を生成します。これらは、2次元ユークリッド 速度ベクトルの(x、y)コンポーネントになります。

ここに画像の説明を入力してください

# interval -1.0 to 1.0, adjust as necessary
vx, vy = ( (random.random()*2) -1, (random.random()*2) - 1 )

次に、ボールが作成された後、ゲームループの各反復で、速度ベクトルによってボールの位置をインクリメントします。

ここに画像の説明を入力してください

posx, posy = posx + vx, posy + vy

全体的な速度は変動する可能性があることに注意してください。常に1秒あたり1.0の速度にしたい場合は、ベクトルを正規化します。

ベクトルを正規化するには、ベクトルをその大きさで除算します。

ここに画像の説明を入力してください

だからあなたの場合:

ここに画像の説明を入力してください

それゆえ:

ここに画像の説明を入力してください

したがって、Pythonでは、 :を使用してインポートmathした後import math

mag = math.sqrt(vx*vx + vy*vy)
v_norm = vx/mag, vy/mag
# use v_norm instead of your (vx, vy) tuple

次に、これにいくつかの変数を掛けて、speed信頼できる速度を得ることができます。


複数のオブジェクトが動き回って画面外になる可能性がある場合は、戻ってくる可能性がなく、プログラムとは関係のない画面外のオブジェクトを削除すると便利です。そうしないと、さらに作成しながらこれらすべてのオフスクリーンオブジェクトを追跡し続けると、本質的にメモリリークが発生し、十分な時間/アクションが与えられるとメモリが不足します。


あなたが今していることは非常に単純ですが、まだ行っていないことを前提とすると、いくつかの基本的なベクトル数学を学ぶことはすぐに報われるでしょう。最終的には、特定の変換を行うために、いくつかの行列数学に踏み込む必要があるかもしれません。あなたがそれに慣れていないなら、それは最初に見えるほど難しくはありません。あなたはおそらくそれを勉強しないことで逃げることができます、しかしあなたがもっと野心的なことをしようとし始めればあなたは後であなた自身の努力を節約するでしょう。

于 2012-08-11T03:35:25.407 に答える
5

現在、次のことを行っています(コードを大幅に簡素化しています)...

while True:
    if the mouse was clicked:
        draw a circle on the screen where the mouse was clicked

少し簡単にして、徐々に積み上げていきましょう。

ユーザーがクリックせずに円から始めます

簡単にするために、画面の左上近くに円を作成しましょう。そうすれば、常に円があると想定できます(ロジックの一部が簡単になります)

circle_x, circle_y = 10,10
while True:
    draw the circle at circle_x, circle_y

    pygame.display.update()

円をアニメーション化する

「ランダムな方向」について詳しく説明する前に、簡単にして一方向に進みましょう(たとえば、常に右下に移動します)。

circle_x, circle_y = 0,0
while True:
    # Update
    circle_x += 0.1
    circle_y += 0.1

    # Draw
    draw the circle at circle_x, circle_y
    update the display

これで、ループを通過するたびに、円の中心が少し移動し、新しい位置に描画します。円の移動が速すぎる場合に備えて、circle_xとyに追加する値(私のコードでは0.1)を減らす必要がある場合があることに注意してください。

ただし、画面が円でいっぱいになっていることに気付くでしょう。「動いている」1つの円ではなく、何度も円を描いているだけです。これを修正するために、各描画の前に画面を「クリア」します...

screen = ....
BLACK = (0,0,0) # Defines the "black" color
circle_x, circle_y = 0,0
while True:
    # Update
    circle_x += 0.1
    circle_y += 0.1

    # Draw
    screen.fill(BLACK)
    draw the circle at circle_x, circle_y
    update the display

円を描く直前に全体を黒く塗って画面を「クリア」していることに注意してください。

これで、コードに戻したい残りの作業を開始できます。

複数のサークルを追跡する

これは、2つの円変数ではなく、円のリストを使用して行うことができます

circles = [...list of circle positions...]
while True:
    # Update
    for circle in circles:
        ... Update the circle position...


    # Draw
    screen.fill(BLACK)
    for circle in circles:
        draw the circle at circle position # This will occur once for each circle
    update the display

注意すべき点の1つは、タプル内の円の位置を追跡している場合、それらの値を変更できないことです。オブジェクト指向プログラミングに精通している場合は、Circleクラスを作成し、それを使用してサークルに関連するデータを追跡できます。それ以外の場合は、すべてのループで、各円の更新された座標のリストを作成できます。

ユーザーがクリックしたときに円を追加する

circles = []
while True:
    # event handling
    for event in pygame.event.get():
        if event.type == MOUSEBUTTONDOWN:
            pos = pygame.mouse.get_pos()
            circles.append( pos ) # Add a new circle to the list

    # Update all the circles
    # ....

    # Draw
    clear the screen
    for circle_position in circles:
        draw the circle at circle_position # This will occur once for each circle
    update the display

円をランダムな方向に動かします

これは数学の良い助けが作用するところです。基本的に、ループごとに円のx座標とy座標を更新する方法を決定する方法が必要になります。軸(X、y)ごとに-1から1の間のどこかに移動したいと言うことは完全に可能ですが、必ずしも正しいとは限りません。XとYの両方がゼロになる可能性があります。その場合、円はまったく移動しません。次のサークルは1と1である可能性があり、他のサークルよりも速く進みます。

あなたの数学のバックグラウンドが何であるかわからないので、プログラムに「方向」(「ベクトル」と呼ばれることもあります)を格納する方法の背後にある数学を理解するために、少し学ぶ必要があるかもしれません。Preetの答えを試して、それが役立つかどうかを確認できます。幾何学と三角法のバックグラウンドがあると、真の理解が容易になります(ただし、優れたリソースが見つかった場合は、それがなくても理解できる可能性があります)。

他のいくつかの考え

あなたが覚えておきたい他のいくつかのこと:

  1. 現在、「フレームレートに依存」で再生しているコード。つまり、円が画面上を移動する速度は、コンピューターの実行速度に完全に依存します。遅いコンピューターは円がカタツムリのように動くのを見るでしょうが、速いコンピューターは円が画面から飛び出す前にかろうじて見るでしょう!これを修正する方法はいくつかありますが、自分で調べることができます(「フレームレート依存」またはお気に入りの検索エンジンで他の用語を検索してください)。

  2. 現在、screen.lock()とscreen.unlock()があります。これらは必要ありません。画面の表面をロック/ロック解除する必要があるのは、表面で必要な場合(一部の表面では必要ない場合)、およびピクセルデータに手動でアクセスする場合のみです。画面に円を描く、pygameでサーフェスを自動的にロック/ロック解除するなどの操作を行います。つまり、今すぐロック/ロック解除に対処する必要はありません。

于 2012-08-12T18:25:17.017 に答える