2017-06-22 62 views
2

我一直在研究并试图弄清楚这一点。我正在尝试创建一个父/子附加系统,以便父母移动时,附加到它的孩子移动/旋转/缩放相同。我遇到的主要问题是轮换。sge-pygame旋转父母和孩子的小精灵

这是我目前使用的儿童代码:

def _rotate(self, origin, point, angle): 
    ox, oy = origin 
    px, py = point 

    qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy) 
    qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy) 

    return qx, qy 

的_rotate代码旋转的2D点周围的原点,我发现,当搜寻的答案,我的问题的角度。我使用的点是每个盒子/精灵的中心。

在旋转父对象时,我使用sge-pygame image_rotation,然后继续进行子对象定位。之后,我需要根据新位置和旋转儿童的新角度来计算儿童的旋转角度。会发生什么

图片:

初始
enter image description here

旋转的10deg
enter image description here

母公司是大矩形框是孩子。

我遇到的第二个问题是弄清楚孩子的旋转角度是如何保持与父母内联的。我通过stackflow发现math.atan2的使用应该用于这个,但我似乎无法弄清楚如何使用它。

任何帮助,这将不胜感激。

谢谢

+1

我不能发布一个答案,但现在这里有一些提示:1.旋转孩子,移动它的支点,以其父的支点,当你做了父应用的精确转动。 2。然后使用父母方向矢量(如果没有方向矢量,可以从cos(角度),sin(角度))创建一个方向矢量,然后使用'direction * offset'移动孩子,其中* offset *是距离从父母的枢轴点到您想要孩子所在的位置。 –

+1

@ted好吧,我已经想出了使用第一部分。这是方向矢量和移动我似乎有问题的孩子。在等待答案的同时,我会继续尝试解决它。谢谢 – ecool

回答

1

您开始时将父母和孩子的数量相同(在本例中假设父母应该被控制,而孩子则不应该)。然后,您只需将孩子移动到父级的轴心点(在本例中为中心点),并在父级所面向的方向上添加一个额外的偏移量(偏移量当然是可选的)。

from math import cos, sin, radians 
import pygame 
pygame.init() 

SIZE = WIDTH, HEIGHT = 720, 480 
BACKGROUND_COLOR = pygame.Color('black') 
FPS = 60 

screen = pygame.display.set_mode(SIZE) 
clock = pygame.time.Clock() 


def update_child_rotation(parent, child, degrees, offset): 
    # Rotate the parent and child with the same angle. 
    parent.rotate(degrees) 
    child.rotate(degrees) 

    # Calculate the direction the parent is pointing. If you remember the unit circle then you'll 
    # know that cos(angle) represent the x value and sin(angle) the y value. At angle = 0 the direction 
    # is to the right (which is what your sprite should be pointing, otherwise you'll have to add an angle 
    # offset), and it rotates counterclockwise. The minus in '-sin' is because pygame uses positive y as downwards. 
    angle_in_radians = radians(parent.angle) 
    direction = pygame.math.Vector2(cos(angle_in_radians), -sin(angle_in_radians)) 

    # Update the child's position to the parent's position but with an added offset in the direction the parent 
    # is pointing. 
    child.position = parent.position + direction * offset 


class Entity(pygame.sprite.Sprite): 

    def __init__(self, position, size): 
     super().__init__() 

     self.original_image = pygame.Surface(size) 
     self.original_image.fill((255, 0, 0)) 
     self.original_image.set_colorkey(BACKGROUND_COLOR) 

     self.image = self.original_image 
     self.rect = self.image.get_rect(center=position) 

     self.angle = 0 
     self.position = pygame.math.Vector2(position) 
     self.velocity = pygame.math.Vector2(0, 0) 

    def rotate(self, degrees): 
     self.angle = (self.angle + degrees) % 360 
     self.image = pygame.transform.rotate(self.original_image, self.angle) 
     self.rect = self.image.get_rect(center=self.position) 

    def update(self, dt): 
     self.position += self.velocity 
     self.rect.center = self.position 


def main(): 
    parent = Entity(position=(200, 200), size=(128, 32)) 
    child = Entity(position=(356, 200), size=(32, 32)) 
    all_sprites = pygame.sprite.Group(parent, child) 

    running = True 
    while running: 

     dt = clock.tick(FPS)/1000 

     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       running = False 
      elif event.type == pygame.KEYDOWN: 
       if event.key == pygame.K_q: 
        update_child_rotation(parent, child, 10, 156) 
       elif event.key == pygame.K_e: 
        update_child_rotation(parent, child, -10, 156) 
      elif event.type == pygame.KEYUP: 
       if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT: 
        parent.velocity.x = 0 
       elif event.key == pygame.K_DOWN or event.key == pygame.K_UP: 
        parent.velocity.y = 0 

     all_sprites.update(dt) 

     screen.fill(BACKGROUND_COLOR) 
     all_sprites.draw(screen) 
     pygame.display.update() 


if __name__ == '__main__': 
    main() 
1

您可以通过枢轴和实例(我在下面的例子中使用pygame.math.Vector2 S)期间所需的偏移量给孩子。如果父母移动,更新其所有孩子(我将它们存储在一个列表中),并将父母的速度传给他们,以便他们更新他们的位置。

旋转的工作原理类似,只需要将角度传递给孩子,然后旋转它们的偏移矢量和图像,并将新矩形的中心设置为旧中心加偏移。

import sys 
import pygame as pg 
from pygame.math import Vector2 


class Player(pg.sprite.Sprite): 

    def __init__(self, pos, *groups): 
     super().__init__(groups) 
     self.image = pg.Surface((90, 40), pg.SRCALPHA) 
     self.image.fill(pg.Color('steelblue2')) 
     self.orig_image = self.image 
     self.rect = self.image.get_rect(center=pos) 
     self.vel = Vector2(0, 0) 
     self.pos = Vector2(pos) 
     self.angle = 0 
     # A list that holds all children instances. 
     self.children = [Child(self.pos, Vector2(90, 30), *groups)] 

    def update(self): 
     self.pos += self.vel 
     self.rect.center = self.pos 
     for child in self.children: 
      child.move(self.vel) 

    def rotate(self, angle): 
     self.angle += angle 
     # Rotate the image and generate a new rect to keep it centered. 
     self.image = pg.transform.rotate(self.orig_image, self.angle) 
     self.rect = self.image.get_rect(center=self.rect.center) 
     # Rotate the children. 
     for child in self.children: 
      child.rotate(angle) 


class Child(pg.sprite.Sprite): 

    def __init__(self, pos, offset, *groups): 
     super().__init__(groups) 
     self.image = pg.Surface((50, 30), pg.SRCALPHA) 
     self.image.fill(pg.Color('mediumaquamarine')) 
     self.orig_image = self.image 
     self.rect = self.image.get_rect(center=pos) 
     self.pos = Vector2(pos) # Parent center. 
     # Offset from parent center. 
     self.offset = Vector2(offset) 
     self.angle = 0 

    def move(self, vel): 
     self.pos += vel 
     self.rect.center = self.pos + self.offset 

    def rotate(self, angle): 
     # Rotate the offset vector (negative angle otherwise it would 
     # rotate in the wrong direction). 
     self.offset.rotate_ip(-angle) 
     self.angle += angle 
     # Rotate the image. 
     self.image = pg.transform.rotate(self.orig_image, self.angle) 
     # Add the new offset to the center. 
     self.rect = self.image.get_rect(center=self.rect.center + self.offset) 


def main(): 
    screen = pg.display.set_mode((640, 480)) 
    clock = pg.time.Clock() 
    sprite_group = pg.sprite.Group() 
    player = Player((100, 250), sprite_group) 

    done = False 

    while not done: 
     for event in pg.event.get(): 
      if event.type == pg.QUIT: 
       done = True 
      elif event.type == pg.KEYDOWN: 
       if event.key == pg.K_d: 
        player.vel.x = 5 
       elif event.key == pg.K_r: 
        player.rotate(15) 
       elif event.key == pg.K_c: 
        player.children.append(Child(
         player.pos, Vector2(-90, -30), sprite_group)) 
      elif event.type == pg.KEYUP: 
       if event.key == pg.K_d: 
        player.vel.x = 0 

     sprite_group.update() 
     screen.fill((30, 30, 30)) 
     sprite_group.draw(screen) 

     pg.display.flip() 
     clock.tick(30) 


if __name__ == '__main__': 
    pg.init() 
    main() 
    pg.quit() 
    sys.exit() 

按'd'移动到右边,'r'旋转'c'添加更多的孩子。

+0

我对SGE不熟悉。它允许你使用pygame sprites,sprite组和向量吗?如果没有,您可以根据您的要求调整代码。 – skrx