2017-12-10 11 views
1

シンプルなトップダウンシューティングゲームを作成するのにpygameを使用しています。トップダウンの観点から角度計算をたくさん行っています。のは、簡単な矢印と一例としてボールを使用してみましょう、私は、赤い矢印は関係なく、青いボールが動くところの青いボールを指しておきたい:座標グリッドを上下逆にするための対策?

enter image description here

そして、簡単に十分な、私は必要なように見えましたatan2

angle = math.atan2(blue.y - red.y, blue.x - red.x) 

しかし、問題は、このような数学的な座標グリッドのatan2作品です:

enter image description here

どこalpha = math.atan2(blue.y - red.y, blue.x - red.x)

しかし、(少なくともWindows上)pygameのあるものは、グリッド座標は数学的な座標グリッドのように動作しないということです、それはゲーム画面の左上隅から始まる逆さま実際には:

enter image description here

青いボールが数学的にblue.yアップし、より高いですように見えながら、そうred.yよりも大きくする必要があり、これは、逆に、実際にそうではありませんダウンPythonのmath.atan2()が行うグリッドを、座標私が知っていた元の計算:

angle = math.atan2(blue.y - red.y, blue.x - red.x) 

実際に正しい角度の否定が得られます。

今、私が思いついた明白な最初のソリューションだけで符号を反転することで、公正に十分な、それはこれで働いていた:

angle = -math.atan2(blue.y - red.y, blue.x - red.x) 

しかし、私は上のベース、さらに計算を行うために必要ないったん問題が再び開始技術的には逆さまになっている、以前に計算された角度。

「永続的に」この問題を解決するにはどうすればよいですか?私はでそれを解決するために管理し、この特定のケースでは

class Zombie(Entity): 

    def __init__(self, *args, target=None, **kwargs): 
     super().__init__(*args, **kwargs) 
     self.target = target 

    def update(self, dt, app): 
     if self.target: 
      # Face towards target 
      dx = self.target.x - self.x 
      dy = self.target.y - self.y 
      self.angle = math.atan2(dy, dx) 
      # Change velocity towards target 
      speed = self.get_max_speed() 
      vel_x = math.cos(angle) * speed 
      vel_y = math.sin(angle) * speed 
      self.velocity = (vel_x, vel_y) 
     else: 
      self.velocity = (0, 0) 
     # Moves the zombie based on velocity 
     super().update(dt, app) 

:ここ

が、私はこれを必要とする場所の実際の例ですが、私は何もしませんが、それは与えられた目標を次の「ゾンビ」の実体を持っています後で使用するために別々の変数に角度を格納し、self.angleの設定時に別途それを否定:

# Face towards target 
dx = self.target.x - self.x 
dy = self.target.y - self.y 
angle = math.atan2(dy, dx) 
self.angle = -angle 
# Change velocity towards target 
speed = self.get_max_speed() 
vel_x = math.cos(angle) * speed 
vel_y = math.sin(angle) * speed 
self.velocity = (vel_x, vel_y) 

しかし、これはちょうどより多くのバグのために物乞いされ、私は問題をより一般的な解決策を探しています。

+1

pygameには計算のための 'pygame.math.Vector2'があります。 BTW:「数学」モジュールでも角度に問題はありません – furas

+1

私はこの解決策にも問題はありません。あなたはどういう意味ですか?私は通常 'pygame.math.Vector2'も使用します。 [ここには例があります](https://stackoverflow.com/a/47166984/6220679)、私は角度を得るために 'math.atan2'の代わりに' as_polar'メソッドを使います。 – skrx

+1

さて、前に 'Vector2'について聞いたことはありませんでした。リファクタリングしてみてください...ありがとうございました –

答えて

0

マイナス記号に変更する代わりに、あなた自身の角度を計算することができます。私はあなたのボールと矢印の例を使用しました。それは非常に単純な三角法です:

#Import needed programs 
import pygame, sys, time, math 
from pygame.locals import * 

#Initialize pygame 
pygame.init() 
window = pygame.display.set_mode((600, 450)) 
pygame.display.set_caption('PyCloud') 

#Define colours 
aqua = 0,255,255 
white = 255,255,255 

#Defne an arrow sprite class 
arrow = pygame.image.load("arrow.png") 
arrow = pygame.transform.scale(arrow,(50,200)) 

#Define a function to calculate angle 
def calcAngle(triangleA,triangleB): 
    sinAngle = triangleA/triangleB 
    angle = math.asin(sinAngle) 
    return math.degrees(angle)  

#Creat clock lop for stability 
clock = pygame.time.Clock() 

#start main loop 
while True: 
    for event in pygame.event.get(): 
     if event.type == QUIT: 
      pygame.quit() 
      exit() 
     else: 
      pass 

    #Get mouse pos 
    mouse = pygame.mouse.get_pos() 
    x = mouse[0] 
    y = mouse[1] 

    #calculate triangle lengths 
    triangleA = x 
    triangleB = math.hypot(x,(450-y)) 
    angle = calcAngle(triangleA,triangleB) 
    print(angle) 

    #draw screen 
    window.fill(white) 
    pygame.draw.circle(window,aqua,(x,y),10,0) 
    window.blit(arrow,(0,350)) 
    clock.tick(1000) 
    pygame.display.update() 

プログラムがその矢印がangleという変数に入れなければならないこと、正確な角度を格納します。私はあなたがアングルそのものをどうするかを決めることができます。これとあなたがしたことの違いは、数学的なものではなく、パイゲームの軸に基づいて計算することです。

テストする場合の矢印の画像です。下の画像をプログラムと同じフォルダに保存してください: Arrow image used in program

関連する問題