2013-10-24 129 views
0

我有要求我做一個分配如下:pygame的:移動旋轉圖像周圍的窗口的邊緣

使用谷歌的高級圖片搜索找到一個球是自由的合理尺寸圖像重用幷包含透明度。修改示例代碼,以便您的球在屏幕底部來回滑動。球從左側向右側移動需要2秒鐘的時間。 改進問題5的動畫,以便球體準確地旋轉,就像它來回滾動一樣。 修改問題6的動畫,使球沿屏幕邊緣逆時針移動

我在最後一部分。試圖修改問題6的動畫做到這一點:(1:24) http://www.youtube.com/watch?v=CEiLc_UFNLI&feature=c4-overview&list=UUpbgjjXBL3hdTKDZ0gZvdWg

我很難過。我似乎無法理解我將如何讓球從一點緩慢移動到另一點。球是一個圖像。這是我迄今爲止的,但它不起作用。

"""Some simple skeleton code for a pygame game/animation 

This skeleton sets up a basic 800x600 window, an event loop, and a 
redraw timer to redraw at 30 frames per second. 
""" 
from __future__ import division 
import math 
import sys 
import pygame 


class MyGame(object): 
    def __init__(self): 
     """Initialize a new game""" 
     pygame.mixer.init() 
     pygame.mixer.pre_init(44100, -16, 2, 2048) 
     pygame.init() 

     # set up a 640 x 480 window 
     self.width = 800 
    self.height = 600 
    self.img = pygame.image.load('ball.png') 
    self.screen = pygame.display.set_mode((self.width, self.height)) 
    self.x = 0 
    self.y = 0 
    self.angle = 0 
    self.rotate_right=True 
    self.first = True 
    #0: Move bottomleft to bottomright 1: Move from bottomright to topright 2:Move from topright to topleft 3:Move from topleft to bottomleft 
    self.mode = 0 
    # use a black background 
    self.bg_color = 0, 0, 0 

    # Setup a timer to refresh the display FPS times per second 
    self.FPS = 30 
    self.REFRESH = pygame.USEREVENT+1 
    pygame.time.set_timer(self.REFRESH, 1000//self.FPS) 


def get_mode(self): 
    rect = self.img.get_rect() 

    if self.first == True: 
     self.first = False 
     return 

    if (self.x, self.y) == (0, self.height - rect.height): 
     #Our starting point, bottom left 
     self.mode = 0 
    elif (self.x, self.y) == (self.width-rect.width, self.height-rect.height): 
     #Bottom right 
     self.mode = 1 
    elif (self.x, self.y) == (self.width-rect.width, 0): 
     #Top Right 
     self.mode = 2 
    elif (self.x, self.y) == (0,0): 
     #Top Left 
     self.mode = 3 

def get_target(self): 
    rect = self.img.get_rect() 

    if self.mode == 0: 
     targetPosition = (0, self.height - rect.height) 

    elif self.mode == 1: 
     targetPosition = (self.width-rect.width, self.height-rect.height) 

    elif self.mode == 2: 
     targetPosition = (self.width-rect.width, 0) 

    elif self.mode == 3: 
     targetPosition = (0,0) 

    return targetPosition 

def get_angle(self): 
    if self.angle == 360: 
     self.rotate_right = False 
    elif self.angle == 0: 
     self.rotate_right = True 

    if self.rotate_right == True: 
     self.angle+=12 
    else: 
     self.angle-=12 

def run(self): 
    """Loop forever processing events""" 
    running = True 
    while running: 
     event = pygame.event.wait() 

     # player is asking to quit 
     if event.type == pygame.QUIT: 
      running = False 

     # time to draw a new frame 
     elif event.type == self.REFRESH: 
      self.draw() 

     else: 
      pass # an event type we don't handle    

def draw(self): 
    """Update the display""" 
    # everything we draw now is to a buffer that is not displayed 
    self.screen.fill(self.bg_color) 

    #Draw img 
    rect = self.img.get_rect() 

    #Note: this can be made dynamic, but right now since this is typically a poor structure, we will use static values. 
    #80 is the padding, so it hits right before. 

    #0,0 : top left 
    #self.width-rect.width, 0 : top right 
    #0, self.height-rect.height : bottom left 
    #self.width-rect.width, self.height-rect.height : bottom right 

    targetPosition =() 

    #img = pygame.transform.rotate(self.img, self.angle) 
    img = self.img 

    self.get_angle() 
    self.get_mode() 

    targetPosition = self.get_target() 

    print targetPosition 
    print self.x, self.y 
    if self.x < targetPosition[0]: 
     self.x+= targetPosition[0]-self.x//self.FPS 

    elif self.x > targetPosition[0]: 
     self.x-= targetPosition[0]+self.x//self.FPS 

    if self.y < targetPosition[1]: 
     print "s" 
     self.y+= targetPosition[1]-self.y//self.FPS 

    elif self.y > targetPosition[1]: 
     self.y-= targetPosition[1]+self.y//self.FPS 


    rect = rect.move(self.x, self.y) 

    self.screen.blit(img, rect) 

    # flip buffers so that everything we have drawn gets displayed 
    pygame.display.flip() 


MyGame().run() 
pygame.quit() 
sys.exit() 
+0

您好! 「它不起作用」是什麼意思?看起來你已經有了移動球的代碼 - 代碼應該做什麼,它目前做了什麼? –

+0

好吧,它應該從左下角開始,慢慢地移動到右下角,然後到右上角然後重複。目前它甚至沒有移動。我還發布了一個youtube鏈接,解釋它必須做的事情。 – user2417731

回答

0

發生了什麼事是你的球開始在(0,0)(0,550)(左下角)目標(左上),發現它是在一個較低的y低於其目標,並及時進行以增加它的位置

targetPosition[1] - (self.y // self.FPS)

這當然是等於550的,所以它立即捕捉到屏幕的底部。

然後在下一個循環中,get_mode()出現,並說'好的,我在(0, 550),所以我會繼續設置模式爲0'。然後get_target()出現,並說'好吧,我在模式0,讓我們回到(0, 550)

然後在下一個循環中再次發生這種情況,下一個和下一個......所以當然你的球不會去任何地方。

你需要做一些事情來解決你的例子:

  • 修正了get_target()您的目標位置。現在他們瞄準的是觸發這些模式的轉換髮生的相同點,所以你的球不會去任何地方。
  • 更仔細地考慮你的速度陳述:現在他們會表現得有些奇怪。正確地做到這一點的一種方法是確定(dx, dy) - 也就是從您到目的地的絕對矢量 - 然後將這個矢量歸一化,使它指向相同的方向,但幅度等於您所需的速度。這種方法適用於你想要的任何目標位置。

闡述一下第二點:

假設我們在(x, y),我們正在試圖讓(target_x, target_y)

dx = target_x - x, dy = target_y - y。這應該是沒有爭議的:我們只是在改變。

那麼我們還記得畢達哥拉斯定理:給出一個直角三角形,邊長爲a, b, c,斜邊爲c,我們記得len(c)**2 == len(a)**2 + len(b)**2。這與矢量是一樣的:矢量(x, y)的長度是邊長爲xy的直角三角形的斜邊。如果你想向自己證明這一點,你可以在一張紙上畫這張照片。

鑑於此,我們可以找到(dx, dy)的長度:它只是L(dx, dy) = sqrt(dx*dx + dy*dy)。這適用於一個奇怪的觀察:如果我們將dxdy乘以標量k,我們還將長度乘以k,因爲sqrt(dx*k*dx*k + dy*k*dy*k) == sqrt(k*k*(dx*dx + dy*dy)) == k*sqrt(dx*dx + dy*dy)

由此可見,我們可以找到平行載體來(dx, dy),但長度爲1的,通過L(dx, dy)除以二者dxdy。預先計算L以避免一些潛在的問題。用你想要的速度乘以這個新的矢量:這是你想要的速度。

+0

這是我卡住的部分 - 數學部分。我不確定如何做矢量的東西。你能詳細說明嗎? – user2417731

+0

@ user2417731更新了答案 – atomicinf

+0

那麼,因爲我仍然無法理解它,所以我完成了它。我現在唯一的問題是,當我嘗試旋轉它時,它開始晃動。 – user2417731