我有一项任务要求我执行以下操作:
使用Google的高级图片搜索功能,可以找到合理大小的球形图像,该图像可以自由重复使用并且包含透明度。修改示例代码,以便您的球在屏幕底部来回滑动。球从左侧向右侧需要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)
正在发生的事情是你的球从(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)
的长度是边长为x
和y
的直角三角形的斜边。如果你想自己证明这一点,你可以在一张纸上画出来。
鉴于此,我们可以找到(dx, dy)
的长度:它只是L(dx, dy) = sqrt(dx*dx + dy*dy)
。这有助于一个奇怪的观察:如果我们将dx
和dy
乘以标量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)
和dx
除以dy
,我们可以找到与L(dx, dy)
平行且长度为1的向量。预先计算L
以避免一些潜在问题。将这个新矢量乘以你想要的速度:这是你想要的速度。