web-dev-qa-db-ja.com

2点間の角度を知る方法は?

私はpygameで小さなゲームを作っており、その中心を中心に回転する銃を作りました。私の問題は、銃を敵の方向にそれ自体で回転させたいことですが、銃と敵の間の角度を見つけることができず、銃をそれに向けて回転させることができませんでした。 atan2を使用する必要があることがわかりましたが、機能するコードが見つからなかったため、誰かが私を助けてくれることを願っています。

これが私のコードです:

import pygame
from pygame.locals import*
pygame.init()
height=650
width=650
screen=pygame.display.set_mode((height,width))
clock=pygame.time.Clock()
gun=pygame.image.load("m2.png").convert_alpha() 
gun=pygame.transform.smoothscale(gun,(200,200)).convert_alpha()
angle=0
angle_change=0
RED=(255,0,0)
x=525
y=155
while True :
    screen.fill((150,150,150))
    for event in pygame.event.get():
        if event.type==QUIT:
            pygame.quit()
            quit()
        if event.type==KEYDOWN:
            if event.key==K_a:
                angle_change=+1
            if event.key==K_d:
                angle_change=-1
        Elif event.type==KEYUP:
            angle_change=0
    angle+=angle_change
    if angle>360:
        angle=0
    if angle<0:
        angle=360
    pygame.draw.rect(screen,RED,(x,y,64,64))
    position = (height/2,width/2)
    gun_rotate=pygame.transform.rotate(gun,angle) 
    rotate_rect = gun_rotate.get_rect()
    rotate_rect.center = position
    screen.blit(gun_rotate, rotate_rect)
    pygame.display.update()
    clock.tick(60) 

そして、ここにそれを明確にしようとしている写真があります:

enter image description here

どうすれば問題を解決できますか?

2点間の角度のタンジェントは、デルタy /デルタxとして定義されます。つまり、(y2-y1)/(x2-x1)です。これは、math.atan2(dy, dx)が2点間の角度を与えることを意味します仮定座標を定義するベース軸を知っていること。

ラジアンで角度を計算するために、銃は軸の(0、0)点と見なされます。その角度を取得したら、残りの計算にその角度を使用できます。

角度はラジアンであるため、コード内では180度ではなくmath.piを使用する必要があることに注意してください。また、360度を超えるテスト(2 * math.pi)も必要ありません。負(<0)のテストは、それを0に強制すると正しくないため、ターゲットはx軸の正方向に強制されます。

したがって、銃とターゲットの間の角度を計算するためのコードは

myradians = math.atan2(targetY-gunY, targetX-gunX)

ラジアンを度に変換したい場合

mydegrees = math.degrees(myradians)

度からラジアンに変換するには

myradians = math.radians(mydegrees)

Python ATAN2

Python ATAN2関数は、Python数学関数の1つであり、X軸から指定された点(y、x)までの角度(ラジアン)を返すために使用されます。

math.atan2()

定義正接(y、x)を半径で返します。

構文
math.atan2(y、x)

パラメータ
y、x =数値


返品は:

>>> import math  
>>> math.atan2(88,34)  
1.202100424136847  
>>>
15
sabbahillel

1人のコメンターがすでに言ったように、この3つのポイントから導き出せる3つのポイント間または2つの交差するベクトル間の角度のみがあります。銃とターゲット(ベクトル1)とX軸(ベクトル2)が持つ角度が必要だと思います。これは、その角度を計算する方法を説明するページへのリンクです。 http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

Pythonの例:

import math

def angle(vector1, vector2):
    length1 = math.sqrt(vector1[0] * vector1[0] + vector1[1] * vector1[1])
    length2 = math.sqrt(vector2[0] * vector2[0] + vector2[1] * vector2[1])
    return math.acos((vector1[0] * vector2[0] + vector1[1] * vector2[1])/ (length1 * length2))

vector1 = [targetX - gunX, targetY - gunY] # Vector of aiming of the gun at the target
vector2 = [1,0] #vector of X-axis
print(angle(vector1, vector2))
1
Alex

特にshapely linestringオブジェクト。オブジェクト(2点)が(min long, min lat, max long, max lat)

from math import atan2,degrees
line = #Your-LineString-Object
lineList = list(line.coords)

def AngleBtw2Points(pointA, pointB):
  changeInX = pointB[0] - pointA[0]
  changeInY = pointB[1] - pointA[1]
  return degrees(atan2(changeInY,changeInX)) #remove degrees if you want your answer in radians

AngleBtw2Points(lineList[0],lineList[1]) 
1
Chidi

Pygameの Vector2 クラスのas_polarメソッドを使用するだけで、ベクターの 極座標 (半径と極角(度単位))を返すことができます。

したがって、2番目のポイントベクトルから最初のポイントベクトルを減算し、結果のベクトルのas_polarメソッドを呼び出すだけです。

import pygame as pg
from pygame.math import Vector2


pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')

point = Vector2(320, 240)
mouse_pos = Vector2(0, 0)
radius, angle = (mouse_pos - point).as_polar()

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True
        Elif event.type == pg.MOUSEMOTION:
            mouse_pos = event.pos
            radius, angle = (mouse_pos - point).as_polar()

    screen.fill(BG_COLOR)
    pg.draw.line(screen, (0, 100, 255), point, mouse_pos)
    pg.display.set_caption(f'radius: {radius:.2f} angle: {angle:.2f}')
    pg.display.flip()
    clock.tick(60)
0
skrx