如何制作子弹击中目标并显示目标被击中或错过?

时间:2016-06-24 19:02:50

标签: python

所以对于这个项目,我必须让子弹击中目标。     使用度数射击子弹击中目标。     我使子弹能够射击以及随机创建的目标。     然而,每当我射击子弹时,它只是要求进入另一个学位     射击子弹。我不知道为了让子弹识别我失踪了什么     代码结尾附近的for循环和if语句。它似乎只是忽略了它。该     子弹也刚射过目标。我需要做到这一点     基本上与子弹,度数和目标创造一个直角。我想     我做到了,但显然缺少了一些东西。     另外,choice = simple.dialog也没有效果,而idk为什么。     谢谢你的帮助!

from tkinter import*
import time
import math
import random

master = Tk()
cw= 1000
ch=650
w = Canvas(master, width=cw, height=ch, bg="skyblue")
w.pack()

w.create_line(10, 635, 80, 610, fill="black", width= 15)
w.create_oval(30, 630, 60, 650, fill="brown")

target_x= 900

target_y= random.randrange(40, 610)
choice = simpledialog.askstring

w.create_oval(900, target_y, 900 -40, target_y -40, fill="pink")

while(True):
    if choice == "n":
        break;


    w.create_oval(900, target_y, 900 -40, target_y -40, fill="pink")     

    dMove= w.create_oval(81, 600, 80+10, 600+10, fill= "red")


    degree = simpledialog.askstring("Enter degree", "What is your guess",      
        initialvalue="Enter a degree")

    degree= 90 - int(degree)


    for i in range(90):
        w.move(dMove, math.sin(math.radians(degree))*10, \
            -math.cos(math.radians(degree))*10)
        time.sleep(0.06)
        w.update()

    b = 820
    a  =  target_y    


    c = b / math.cos(math.radians(degree))

    c1 = math.sqrt(math.pow(b, 2) + math.pow(target_y+10, 2)) 
    c2 = math.sqrt(math.pow(b, 2) + math.pow(target_y-10, 2))
    w.update()


    if c < c2 and c > c1:
         print("You got it")
         break
    else:
         print("enter degree")

1 个答案:

答案 0 :(得分:0)

代码不断要求新的degrees因为它总是认为你错过了目标。我不知道你当前计算你是否打击是如何工作的,所以我真的不知道如何直接修复它。但我已经提出了两种新的方法来使事物按预期发挥作用。

有两种不同的碰撞检测方法可以在这里工作。第一种是计算你是否直接从角度命中,因为在你选择拍摄角度后没有任何动态变化。根据目标的位置,您可以计算到达目标死点的角度,并计算至少部分子弹仍会击中目标的角度的最大偏移量。如果用户输入perfect_angle - max_offsetperfect_angle + max_offset之间的角度,则会受到影响。

from tkinter import*
import time
import math
import random

master = Tk()
cw= 1000
ch=650
w = Canvas(master, width=cw, height=ch, bg="skyblue")
w.pack()

w.create_line(10, 635, 80, 610, fill="black", width= 15)
w.create_oval(30, 630, 60, 650, fill="brown")

target_x= 900
target_y= random.randrange(40, 605)
target_radius = 20

bullet_x = 91
bullet_y = 605
bullet_radius = 10

rel_x = target_x - bullet_x
rel_y = target_y - bullet_y

perfect_angle = math.atan2(rel_y, rel_x)
distance = math.sqrt(rel_x**2 + rel_y**2)
max_angle_offset = math.asin((bullet_radius + target_radius)/ distance)

target = w.create_oval(target_x-target_radius, target_y-target_radius,
                       target_x+target_radius, target_y+target_radius,
                       fill="pink")

#print(math.degrees(perfect_angle), math.degrees(max_angle_offset))

while True:
    bullet = w.create_oval(bullet_x-bullet_radius, bullet_y-bullet_radius,
                           bullet_x+bullet_radius, bullet_y+bullet_radius,
                           fill= "red")

    degree = simpledialog.askstring("Enter degree", "What is your guess",      
        initialvalue="Enter a degree")

    rad = math.radians(-float(degree))


    for i in range(int(distance / 10) + 1):
        w.move(bullet, math.cos(rad)*10, math.sin(rad)*10)
        time.sleep(0.06)
        w.update()

    #print(math.degrees(rad), math.degrees(perfect_angle - rad))

    if perfect_angle - max_angle_offset <= rad <= perfect_angle + max_angle_offset:
         print("You got it")
         break
    else:
         print("enter degree")

问题的另一个方法是在你移动子弹时进行碰撞检测,而不是预先进行。如果您以后想要将游戏更改为具有移动目标,或者如果您将子弹的动态更改为不易提前计算(例如添加拖动),则这对您来说会更好。我只是从Canvas中提取子弹的坐标(平均边界以获得中心),并对目标进行距离检查。如果在任何给定的帧上我们比半径的总和更接近,我们就会命中! (我实际上是在检查距离的平方以避免昂贵的平方根,但它的工作原理相同。)

from tkinter import*
import time
import math
import random

master = Tk()
cw= 1000
ch=650
w = Canvas(master, width=cw, height=ch, bg="skyblue")
w.pack()

w.create_line(10, 635, 80, 610, fill="black", width= 15)
w.create_oval(30, 630, 60, 650, fill="brown")

target_x= 900
target_y= random.randrange(40, 605)
target_radius = 20

bullet_x = 91
bullet_y = 605
bullet_radius = 10

rel_x = target_x - bullet_x
rel_y = target_y - bullet_y
distance = math.sqrt(rel_x**2 + rel_y**2)

hit_distance = bullet_radius + target_radius

target = w.create_oval(target_x-target_radius, target_y-target_radius,
                       target_x+target_radius, target_y+target_radius,
                       fill="pink")

hit = False

while True:
    bullet = w.create_oval(bullet_x-bullet_radius, bullet_y-bullet_radius,
                           bullet_x+bullet_radius, bullet_y+bullet_radius,
                           fill= "red")

    degree = simpledialog.askstring("Enter degree", "What is your guess",      
        initialvalue="Enter a degree")

    rad = math.radians(-float(degree))


    for i in range(int(distance / 10) + 1):
        w.move(bullet, math.cos(rad)*10, math.sin(rad)*10)
        x0, y0, x1, y1 = w.coords(bullet)
        x = (x1 + x0) // 2
        y = (y1 + y0) // 2
        if (target_x-x)**2 + (target_y-y)**2 < hit_distance**2:
            hit = True
        time.sleep(0.06)
        w.update()

    if hit:
         print("You got it")
         break
    else:
        #print(x, y, target_x, target_y,
        #      (target_x-x)**2 + (target_y-y)**2, hit_distance**2)
        print("enter degree")

请注意,我还清理了代码中的许多其他内容,因为无法分辨出您使用的某些常量来自哪些(以及哪些常量可能不正确)。

一个特别重要的变化是,target_x / _y变量和新的bullet_x / _y变量始终引用 center 有问题的对象,这使数学更容易。您的旧代码通过不同方向的半径来抵消这两个形状!

您也以非常奇怪的方式使用degrees角度。我现在只将它转换为弧度一次并让它保持正常的数学意义(角度沿着正x轴从零开始,并且当朝向正y轴旋转时增加)。这意味着子弹所采取的角度通常是负面的,但这并不会给我们带来麻烦,因为我们不打算显示它们(除了我已经注释掉的调试print调用)。