2017-02-11 69 views
1

我的问题与下面问题的答案有关。如何将旋转限制在pygame中设定的度数?

rotating a rectangle.

如何限制旋转到以红色标示在这张照片上的面积?我尝试了各种方法,但没有成功。代码始终保持在其他区域的防御者。 我修改了下面的代码。

import pygame, math, base64 
pygame.init() 
screen = pygame.display.set_mode((200, 200)) 

surf = pygame.image.load("D:\\PYTHON\\SoftwareDG\\Games\\Platform_Suvivor\\assets\\rg.png").convert_alpha() 

def rot_center(image, angle): 
    orig_rect = image.get_rect() 
    rot_image = pygame.transform.rotate(image, angle) 
    rot_rect = orig_rect.copy() 
    rot_rect.center = rot_image.get_rect().center 
    rot_image = rot_image.subsurface(rot_rect).copy() 
    return rot_image 

current_angle = 0 

while True: 
    if pygame.event.get(pygame.QUIT): break 
    pygame.event.get() 

    mouseX, mouseY = pygame.mouse.get_pos() 
    rect = surf.get_rect(center=(92, 92)) 
    target_angle = math.degrees(math.atan2(mouseY - rect.centery, mouseX - rect.centerx)) 
    if target_angle < -120: 
     target_angle = -120 
    if target_angle > 120: 
     target_angle = 120 
    print target_angle 
    if current_angle > target_angle: 
     current_angle -= 0.03 
    if current_angle < target_angle: 
     current_angle += 0.03 

    screen.fill((40, 140, 40)) 
    screen.blit(rot_center(surf, -current_angle), rect) 
    pygame.display.update() 

pointer should stay in red area

+0

备注:使用'pygame.time.Clock'来限制帧率,否则Pygame渲染尽可能多的帧。在main while循环创建一个时钟实例'clock = pygame.time.Clock()'之前,并在循环结束时调用'clock.tick(enter_desired_framerate_here)'。 – skrx

+0

在上面的代码中使用时钟的相关性是什么?它会减慢代码的速度,但小增量值无论如何都会这样做。 – emorphus

+0

如果你不使用时钟,Pygame会占用更多的处理能力,而动画运行速度会比较慢,而CPU占用率则更低。 – skrx

回答

1

您正在寻找这样的钳位功能?

def clamp(value, min_, max_): 
    """Clamp value to a range between min_ and max_.""" 
    return max(min_, min(value, max_)) 

在你的情况,你还必须检查current_angle大于或小于0

if current_angle <= 0: 
    current_angle = clamp(current_angle, -180, -120) 
elif current_angle > 0: 
    current_angle = clamp(current_angle, 120, 180) 

更新:这是与载体的例子。我使用矢量来确定精灵需要旋转的方向。请注意,右侧现在为0度,左侧为180度,从0度到360度。

这里有一些有趣的链接,帮助我学习如何做到这一点: http://docs.godotengine.org/en/stable/tutorials/matrices_and_transforms.html http://www.wildbunny.co.uk/blog/vector-maths-a-primer-for-games-programmers/

import math 
import pygame 


pygame.init() 
screen = pygame.display.set_mode((300, 300)) 
font = pygame.font.Font(None, 24) 
GRAY = pygame.Color('gray90') 


def clamp(value, min_value, max_value): 
    """Clamp value to a range between min_value and max_value.""" 
    return max(min_value, min(value, max_value)) 


def main(): 
    current_angle = 0 
    clock = pygame.time.Clock() 
    surf = pygame.Surface((80, 50), pygame.SRCALPHA) 
    pygame.draw.polygon(surf, (40, 100, 200), ((0, 0), (80, 25), (0, 50))) 
    orig_surf = surf 
    rect = surf.get_rect(center=(150, 150)) 
    orig_direction = pygame.math.Vector2(0, 1) 

    playing = True 

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

     # Here I figure out if the target is closer in clock- 
     # or counterclockwise direction. `orientation` is positive 
     # if the target is closer in clockwise and negative 
     # if it's in counterclockwise direction. 
     vec_to_target = pygame.math.Vector2(pygame.mouse.get_pos()) - rect.center 
     direction = orig_direction.rotate(current_angle) 
     orientation = vec_to_target.dot(direction) 
     # I use orientation > 3 and < -3 instead of 0 to 
     # avoid jittering when the target angle is reached. 
     if orientation > 3: 
      current_angle += 3 
     elif orientation < -3: 
      current_angle -= 3 

     # You can use this modulo operation to keep the angle between 
     # 0° and 360°, but this is not needed because of the clamp. 
     # current_angle %= 360 
     # Clamp the value to the desired range. 
     current_angle = clamp(current_angle, 120, 240) 

     surf = pygame.transform.rotate(orig_surf, -current_angle) 
     rect = surf.get_rect(center=rect.center) 

     # Draw 
     screen.fill((40, 40, 40)) 
     screen.blit(surf, rect) 
     txt = font.render('angle {:.1f}'.format(current_angle), True, GRAY) 
     screen.blit(txt, (10, 10)) 
     txt = font.render('orientation {:.1f}'.format(orientation), True, GRAY) 
     screen.blit(txt, (10, 25)) 

     pygame.display.update() 
     clock.tick(30) 


if __name__ == '__main__': 
    main() 
    pygame.quit() 
+0

上述解决方案不能完全工作。如果当前角度以+值开始,则指针停留在加号部分,如果是 - 则指针停留在负部分。 – emorphus

+0

啊,是的,有一个问题,因为你根据target_angle增加current_angle。我实际上用一个简单的程序测试了代码,该程序只是立即将图像旋转到target_angle。您可以添加更多的if以检查current_angle是需要增加还是减少,或者使用向量来确定图像是否必须顺时针或逆时针旋转(这是通过计算点积来完成的)。稍后我会更新我的帖子,告诉你如何。 – skrx

+0

谢谢。这使得它更清晰。我正在等待你更新。到目前为止,答案并不完整,所以我不能接受。 – emorphus

0

我设法只是添加一行到枪的旋转限制在一个有限的区域旋转前检查。代码远非完美。当从+象限穿越到 - 象限时,反之亦然,枪向相反的方向旋转到另一侧。在增加角度之前进行更多检查将纠正旋转方向,但现在问题已经以基本方式解决了。代码如下。

import pygame, math, base64 
pygame.init() 
screen = pygame.display.set_mode((200, 200)) 

surf = pygame.image.load("put your image here").convert_alpha() 

def rot_center(image, angle): 
    orig_rect = image.get_rect() 
    rot_image = pygame.transform.rotate(image, angle) 
    rot_rect = orig_rect.copy() 
    rot_rect.center = rot_image.get_rect().center 
    rot_image = rot_image.subsurface(rot_rect).copy() 
    return rot_image 

current_angle = -180 

clock = pygame.time.Clock() 
while True: 
    if pygame.event.get(pygame.QUIT): break 
    pygame.event.get() 

    mouseX, mouseY = pygame.mouse.get_pos() 
    rect = surf.get_rect(center=(92, 92)) 
    target_angle = math.degrees(math.atan2(mouseY - rect.centery, mouseX - rect.centerx)) 

    # the new line is just below 
    if 180 > target_angle > 120 or - 120 > target_angle > -179: 
     print "ok", target_angle 
     if current_angle > target_angle: 
      current_angle -= 2 
     if current_angle < target_angle: 
      current_angle += 2 

    screen.fill((40, 140, 40)) 
    screen.blit(rot_center(surf, -current_angle), rect) 
    pygame.display.update() 
    clock.tick(60)