numpy 我的parabolar可以单独使用,但在Pygame中是错误的

pn9klfpd  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(80)

所以我创建了这个parabola类,它可以用3个参数(a,b和c)或3个属于抛物线的点来示例化。punti()函数返回nm定义的范围内属于抛物线的所有点。下面是代码(大部分是意大利语,对不起):

class Parabola:
    def __init__(self, tipo=0, *params):
        '''
        Il tipo è 0 per costruire la parabola con a, b, c; 1 per costruire la parabola con
        tre punti per la quale passa
        '''
        if tipo == 0:
            self.__a = params[0]
            self.__b = params[1]
            self.__c = params[2]
            self.__delta = self.__b ** 2 - (4 * self.__a * self.__c)
        elif tipo == 1:
            matrix_a = np.array([
                [params[0][0]**2, params[0][0], 1],
                [params[1][0]**2, params[1][0], 1],
                [params[2][0]**2, params[2][0], 1]
            ])
            matrix_b = np.array([params[0][1], params[1][1], params[2][1]])
            matrix_c = np.linalg.solve(matrix_a, matrix_b)

            self.__a = round(matrix_c[0], 2)
            self.__b = round(matrix_c[1], 2)
            self.__c = round(matrix_c[2], 2)
            self.__delta = self.__b ** 2 - (4 * self.__a * self.__c)
        def trovaY(self, x):
            y = self.__a * x ** 2 + self.__b * x + self.__c
            return y

        def punti(self, n, m, step=1):
            output = []
            for x in range(int(min(n, m)), int(max(n, m)) + 1, step):
                output.append((x, self.trovaY(x)))
            return output

字符串
现在我的小游戏是关于用弓射击目标,我必须使用抛物线的轨迹,它通过3点:

  • 玩家中心
  • 一个光标为x,玩家为y的点
  • 中间的一个点与光标的y

轨迹用一条黑线表示,但它显然不起作用,我不明白为什么。这是游戏的代码(不要介意弓的旋转,我仍然要让它正常工作):

import os
import sys
import pygame
from random import randint

sys.path.insert(
    1, __file__.replace("pygame-prototype\\" + os.path.basename(__file__), "coniche\\")
)
import parabola

# Initialization
pygame.init()

WIDTH, HEIGHT = 1024, 576
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# Function to rotate without losing quality

def rot_from_zero(surface, angle):
    rotated_surface = pygame.transform.rotozoom(surface, angle, 1)
    rotated_rect = rotated_surface.get_rect()
   return rotated_surface, rotated_rect

# Function to map a range of values to another

def map_range(value, leftMin, leftMax, rightMin, rightMax):
    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin

    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)

    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)

# Player class

class Player:
    def __init__(self, x, y, width=64, height=64):
        self.rect = pygame.Rect(x, y, width, height)
        self.dirx = 0
        self.diry = 0

    def draw(self):
        rectangle = pygame.draw.rect(screen, (255, 0, 0), self.rect)

# Target class

class Target:
    def __init__(self, x, y, acceleration=0.25):
        self.x, self.y = x, y
        self.image = pygame.image.load(
            __file__.replace(os.path.basename(__file__), "target.png")
        )
        self.speed = 0
        self.acceleration = acceleration

    def draw(self):
        screen.blit(self.image, (self.x, self.y))

    def update(self):
        self.speed -= self.acceleration
        self.x += int(self.speed)
        if self.speed < -1:
            self.speed = 0

player = Player(64, HEIGHT - 128)

# Targets init
targets = []
targets_spawn_time = 3000
previous_ticks = pygame.time.get_ticks()

# Ground animation init
ground_frames = []
for i in os.listdir(__file__.replace(os.path.basename(__file__), "ground_frames")):
    ground_frames.append(
        pygame.image.load(
            __file__.replace(os.path.basename(__file__), "ground_frames\\" + i)
        )
    )  # Load all ground frames
ground_frame_counter = 0  # Keep track of the current ground frame
frame_counter = 0

# Bow
bow = pygame.image.load(__file__.replace(os.path.basename(__file__), "bow.png"))
angle = 0

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

    # Spawning the targets
    current_ticks = pygame.time.get_ticks()
    if current_ticks - previous_ticks >= targets_spawn_time:
        targets.append(Target(WIDTH, randint(0, HEIGHT - 110)))
        previous_ticks = current_ticks

    screen.fill((101, 203, 214))
    player.draw()

    for i, e in list(enumerate(targets))[::-1]:
        e.draw()
        e.update()
        if e.x <= -e.image.get_rect().width:
            del targets[i]

    # Calculating the angle of the bow
    mouse_pos = pygame.Vector2(pygame.mouse.get_pos())
    angle = map_range(mouse_pos.x, 0, WIDTH, 90, 0)

    # Rotate the bow
    rotated_bow, rotated_bow_rect = rot_from_zero(bow, angle)
    rotated_bow_rect.center = player.rect.center
    screen.blit(rotated_bow, rotated_bow_rect)

    # Animate the ground
    if frame_counter % 24 == 0:
        ground_frame_counter += 1

    if ground_frame_counter >= len(ground_frames):
        ground_frame_counter = 0

    for i in range(round(WIDTH / ground_frames[ground_frame_counter].get_rect().width)):
        screen.blit(
            ground_frames[ground_frame_counter],
            (
                ground_frames[ground_frame_counter].get_rect().width * i,
                HEIGHT - ground_frames[ground_frame_counter].get_rect().height,
            ),
        )

    # Calculating the trajectory
    mouse_pos.x = (
        mouse_pos.x if mouse_pos.x != rotated_bow_rect.centerx else mouse_pos.x + 1
    )
    # print(mouse_pos, rotated_bow_rect.center)
    v_x = rotated_bow_rect.centerx + ((mouse_pos.x - rotated_bow_rect.centerx) / 2)
    trajectory_parabola = parabola.Parabola(
        1,
        rotated_bow_rect.center,
        (mouse_pos.x, rotated_bow_rect.centery),
        (v_x, mouse_pos.y),
    )
    trajectory = [(i[0], int(i[1])) for i in trajectory_parabola.punti(0, WIDTH)]

    pygame.draw.lines(screen, (0, 0, 0), False, trajectory)
    pygame.draw.ellipse(
        screen, (128, 128, 128), pygame.Rect(v_x - 15, mouse_pos.y - 15, 30, 30)
    )
    pygame.draw.ellipse(
        screen,
        (128, 128, 128),
        pygame.Rect(mouse_pos.x - 15, rotated_bow_rect.centery - 15, 30, 30),
    )

    pygame.display.update()

    if frame_counter == 120:
        for i in trajectory:
            print(i)

    frame_counter += 1


你可以运行这一切,并了解它的问题,帮助?

kzipqqlq

kzipqqlq1#

将a、B和c的值四舍五入到小数点后2位。这对于此应用程序来说太不准确了:
第一个月
self.__b = round(matrix_c[1], 2)
self.__c = round(matrix_c[2], 2)

self.__a = matrix_c[0]
self.__b = matrix_c[1]
self.__c = matrix_c[2]

字符串


的数据
最小示例:

import pygame
import numpy as np

class Parabola:
    def __init__(self, parabloe_type, *params):
        if parabloe_type == 0:
            self.__a = params[0]
            self.__b = params[1]
            self.__c = params[2]

        elif parabloe_type == 1:
            matrix_a = np.array([
                [params[0][0]**2, params[0][0], 1],
                [params[1][0]**2, params[1][0], 1],
                [params[2][0]**2, params[2][0], 1]
            ])
            matrix_b = np.array([params[0][1], params[1][1], params[2][1]])
            matrix_c = np.linalg.solve(matrix_a, matrix_b)
            self.__a = matrix_c[0]
            self.__b = matrix_c[1]
            self.__c = matrix_c[2]

    def claculateY(self, x):
        return self.__a * x ** 2 + self.__b * x + self.__c

    def pointsOnCurve(self, n, m, step=1):
        return [(x, self.claculateY(x)) for x in range(int(min(n, m)), int(max(n, m)) + 1, step)]

pygame.init()
window = pygame.display.set_mode((800, 600))
window_rect = window.get_rect()
pos0 = 100, window_rect.height - 100

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

    mx, my = pygame.mouse.get_pos()
    if abs(mx - pos0[0]) < 2:
        mx = mx-2 if mx < pos0[0] else mx + 2
    pts = [pos0, (mx, pos0[1]), ((mx + pos0[0]) // 2, my)]
    trajectory_parabola = Parabola(1, *pts)
    trajectory = [(pt[0], round(pt[1])) for pt in trajectory_parabola.pointsOnCurve(0, window_rect.width)]

    window.fill(0)
    pygame.draw.lines(window, (255, 255, 0), False, trajectory)
    for pt in pts:
        pygame.draw.circle(window, (255, 0, 0), pt, 10)
    pygame.display.flip()

pygame.quit()
exit()

gmol1639

gmol16392#

与上面的答案类似.
然而,不同意其他的解决方案:这并不重要,你传递坐标到你的抛物线结构的顺序。任何顺序都可以。点是点。
这里是你原来的抛物线函数的图片“下垂”,因为舍入误差:

p1 = (0,   10)  # left
p2 = (100, 10)  # right
p3 = (50, 100)  # apex
p = Parabola(1, p3, p2, p1)

traj = p.punti(0, 100)
xs, ys = zip(*traj)

plt.scatter(xs, ys)
plt.plot([0, 100], [10, 10], color='r')
plt.show()

字符串


的数据

相关问题