Python 子弹看起来不像是从枪里射出来的
我有一个问题,我的子弹看起来不像是从我的枪里出来的,它们看起来像是从球员身上出来的,你可以在视频中看到,它在其他地方射击,或者是枪,左边也是一样,它向上射出好球,向下射出坏球 ***我想说的是,我怎样才能让我的枪在我的鼠标位置准确旋转*** 我试着把我的枪调到120,但是发生的事情是所有的事情都对右边有效,而不是左边,正如你所看到的,只是小故障Python 子弹看起来不像是从枪里射出来的,python,pygame,Python,Pygame,我有一个问题,我的子弹看起来不像是从我的枪里出来的,它们看起来像是从球员身上出来的,你可以在视频中看到,它在其他地方射击,或者是枪,左边也是一样,它向上射出好球,向下射出坏球 ***我想说的是,我怎样才能让我的枪在我的鼠标位置准确旋转*** 我试着把我的枪调到120,但是发生的事情是所有的事情都对右边有效,而不是左边,正如你所看到的,只是小故障 def draw(self,drawX,drawY): self.rect.topleft = (drawX,drawY
def draw(self,drawX,drawY):
self.rect.topleft = (drawX,drawY)
# the guns hitbox
# rotatiing the gun
dx = self.look_at_pos[0] - self.rect.centerx
dy = self.look_at_pos[1] - self.rect.centery
angle = (190/math.pi) * math.atan2(-dy, dx)
gun_size = self.image.get_size()
pivot = (8, gun_size[1]//2)
blitRotate(window, self.image, self.rect.center, pivot, angle)
if((angle > 90 or angle < -90) and self.gunDirection != "left"):
self.gunDirection = "left"
self.image = pygame.transform.flip(self.image, False, True)
if((angle < 90 and angle > -90) and self.gunDirection != "right"):
self.gunDirection = "right"
self.image = pygame.transform.flip(self.image, False, True)
我想我想说的是,我怎样才能让我的枪在我的鼠标位置准确地旋转而不出任何问题呢
我的完整代码一种方法是计算出枪尖相对于其坐标x,y移动的弧的椭圆。使用此选项可创建一个“” 由0索引时的查找表→360°,其中,对于给定的角度,它给出了一对要添加到“手臂”原点位置的偏移。这个新点加在一起就是枪尖的坐标。例如,假设枪位于30°,我们访问枪查找[30]的
结束,它返回(12,-6)
,这对应于“臂”精灵位置和枪尖之间的差异
检查代码时,角度似乎从大约-120
到120
。显然,我们不能对查找表使用负索引,所以我们只需将所有内容移动120
,因此end\u of_gun\u lookup[0]
用于角度-120
,end\u of_gun\u lookup[1]
用于角度-119
,等等
因此,现在当您开始初始定位子弹时,应该在“手臂”位图中创建它原点
,再加上枪的末端查找[120+圆形(角度)]
但是!我们如何创建查找表
实现这一点的一种方法是在位图旋转时以编程方式“跟随”枪尖。一旦找到枪尖,立即将该位置存储在已知角度的查找表中
为了找到枪的尖端,我修改了“手臂”位图,在枪的末端有一个亮绿色像素块(3x3)。这可能是位图中尚未使用的任何颜色,但我选择了绿色(8255,0)
然后我们创建一个函数,在每次旋转期间,在旋转位图的每个像素中费力地查找绿色像素。这是相当缓慢的,并且不是你想在游戏中做的事情
这就是这个函数。_gun_lookup的end_是最终的查找表。首先,我们用“无值”None
填充每个可能的角度
# Create empty look-up point for green-pixel offsets
SUPA_GREEN = ( 8, 255, 0 )
end_of_gun_lookup = [ None ] * 360
findGreenPixels()
函数可以在找到像素位置时填充此全局列表:
def findGreenPixels( origin, image, rotation_angle ):
global end_of_gun_lookup
result = None
# Bitmap offset
origin_x, origin_y = origin
# find the Super Green pixel at the end of the gun.
# very slow, and inefficient
width = image.get_rect().width
height = image.get_rect().height
for y in range( height ):
for x in range( width ):
pixel_colour = image.get_at( ( x, y ) )
if ( pixel_colour == SUPA_GREEN ):
#print( "GREEN AT %d -> %d,%d" % ( rotation_angle, x, y ) )
result = ( round( origin_x - x ), round( origin_y - y ) )
# results go from -120 -> 120, so offset
# before storing the point.
# Distance is relative to bitmap orgin too
end_of_gun_lookup[ round( rotation_angle ) + 120 ] = ( result )
if ( result != None ):
break
if ( result != None ):
break
return result
它基本上遍历每个像素,寻找绿色。如果找到,将填充查找表。我使用了一个3x3像素块,因为在图像旋转过程中,像素被着色和模糊,一个像素块在保持完全相同的颜色方面有更好的变化
在程序结束时,我们转储查找表:
pygame.quit()
### PRINT THE LOOKUP TABLE
end_of_gun_lookup = fillLookupHoles( end_of_gun_lookup )
print( "end_of_gun_lookup = "+ str( end_of_gun_lookup ) )
在我的测试过程中,无论我移动鼠标有多慢,有时桌子上都有未定义的位置。虽然我只管理过一次完美的桌子。无论如何,我添加了一些代码,使用中点线算法来估计单个缺失值的位置。这把那些洞清理干净了。显然,您不能在表的末尾生成点,这些点保持为None
。也许代码需要处理这些,也许它们永远不会发生
这给了我这样一个结果:
查表结束=[(108160),(109162),(110163),(111163),(111163),(112164),(111166),(113167),(114168),(114170),(115171),(116173),(116174),(118175),(118177),(120178),(121180),(122182),(124183),(125185),(95181),(126188),(129189),(130191),(130193),(133196),(103, 194), (104, 197), (137, 199), (107, 201), (106, 199), (137, 197), (105, 196), (104, 194), (101, 193), (101, 191), (101, 189), (130, 183), (99, 186), (99, 184), (99, 183), (97, 182), (98, 180), (98, 178), (95, 179), (96, 177), (96, 175), (94, 174), (95, 172), (94, 171), (94, 170), (94, 170), (93, 168), (94, 166), (95, 165), (95, 164), (95, 163), (95, 162), (94, 161), (94, 160), (95, 159), (95, 158), (96, 157), (97, 156), (98, 155), (98, 154), (98, 155), (98, 154), (98, 152), (101, 151), (101, 151), (101, 150), (102, 150), (102, 149), (104, 148), (105, 148), (106, 148), (107, 146), (108, 147), (109, 146), (110, 146), (110, 146), (112, 146), (114, 145), (115, 145), (117, 144), (117, 144), (119, 145), (119, 144), (122, 145), (123, 144), (126, 146), (126, 146), (128, 145), (129, 145), (131, 146), (134, 145), (134, 145), (136, 147), (138, 147), (140, 147), (142, 147), (144, 148), (144, 148), (148, 149), (149, 150), (151, 150), (153, 150), (154, 152), (158, 151), (159, 152), (161, 153), (163, 153), (166, 154), (169, 156), (170, 156), (172, 158), (175, 158), (177, 159), (179, 160), (178, 159), (176, 157), (174, 156), (173, 154), (171, 154), (169, 152), (168, 149), (164, 149), (163, 149), (163, 147), (161, 146), (160, 144), (159, 143), (155, 142), (154, 141), (154, 141), (154, 140), (151, 138), (151, 138), (148, 138), (146, 137), (145, 136), (144, 135), (144, 134), (143, 134), (142, 133), (139, 133), (140, 132), (138, 132), (137, 131), (136, 131), (135, 130), (134, 130), (133, 129), (133, 129), (132, 130), (130, 130), (130, 129), (129, 129), (129, 129), (128, 129), (127, 128), (128, 129), (126, 129), (126, 129), (125, 129), (125, 130), (124, 130), (124, 130), (123, 131), (124, 131), (124, 132), (123, 132), (122, 132), (122, 134), (122, 134), (123, 134), (122, 134), (122, 135), (122, 136), (122, 137), (123, 139), (122, 139), (12
def findGreenPixels( origin, image, rotation_angle ):
global end_of_gun_lookup
result = None
# Bitmap offset
origin_x, origin_y = origin
# find the Super Green pixel at the end of the gun.
# very slow, and inefficient
width = image.get_rect().width
height = image.get_rect().height
for y in range( height ):
for x in range( width ):
pixel_colour = image.get_at( ( x, y ) )
if ( pixel_colour == SUPA_GREEN ):
#print( "GREEN AT %d -> %d,%d" % ( rotation_angle, x, y ) )
result = ( round( origin_x - x ), round( origin_y - y ) )
# results go from -120 -> 120, so offset
# before storing the point.
# Distance is relative to bitmap orgin too
end_of_gun_lookup[ round( rotation_angle ) + 120 ] = ( result )
if ( result != None ):
break
if ( result != None ):
break
return result
pygame.quit()
### PRINT THE LOOKUP TABLE
end_of_gun_lookup = fillLookupHoles( end_of_gun_lookup )
print( "end_of_gun_lookup = "+ str( end_of_gun_lookup ) )
def blitRotate(surf, image, pos, originPos, angle):
...
# use lookup table to find the end-of gun at this angle
x_origin, y_origin = origin
x_offset, y_offset = end_of_gun_lookup[ round( angle ) + 120 ]
final_pos = ( x_origin + x_offset, y_origin + y_offset )
# rotate and blit the image
surf.blit( rotated_image, final_pos )
import pygame
import random
import math
# Window size
WINDOW_WIDTH = 400
WINDOW_HEIGHT = 400
WINDOW_SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
DARK_BLUE = ( 3, 5, 54)
# Create empty look-up point for green-pixel offsets
SUPA_GREEN = ( 8, 255, 0 )
end_of_gun_lookup = [ None ] * 360
def midpoint( point_a, point_b ):
""" Use the midpoint-line formula to return the point between
point_a and point_b """
mid_x = round( ( point_a[0] + point_b[0] ) / 2 )
mid_y = round( ( point_a[1] + point_b[1] ) / 2 )
return ( mid_x, mid_y )
def fillLookupHoles( coord_list ):
""" Find any gaps in the lookup table, by finding the mid-point line
pixel between the two points, giving an estimated position """
for i in range( 1, len ( coord_list )-1 ): # we can't fix end-points, ignore first & last
before = coord_list[ i-1 ]
after = coord_list[ i+1 ]
if ( coord_list[ i ] == None and before != None and after != None ):
coord_list[ i ] = midpoint( before, after )
print( "Filled hole at angle %d" % ( i - 120 ) )
return coord_list
def findGreenPixels( origin, image, rotation_angle ):
global end_of_gun_lookup
result = None
# Bitmap offset
origin_x, origin_y = origin
# find the Super Green pixel at the end of the gun.
# very slow, and inefficient
width = image.get_rect().width
height = image.get_rect().height
for y in range( height ):
for x in range( width ):
pixel_colour = image.get_at( ( x, y ) )
if ( pixel_colour == SUPA_GREEN ):
#print( "GREEN AT %d -> %d,%d" % ( rotation_angle, x, y ) )
result = ( round( origin_x - x ), round( origin_y - y ) )
# results go from -120 -> 120, so offset
# before storing the point.
# Distance is relative to bitmap orgin too
end_of_gun_lookup[ round( rotation_angle ) + 120 ] = ( result )
if ( result != None ):
break
if ( result != None ):
break
return result
def blitRotate(surf, image, pos, originPos, angle):
# calcaulate the axis aligned bounding box of the rotated image
w, h = image.get_size()
sin_a, cos_a = math.sin(math.radians(angle)), math.cos(math.radians(angle))
min_x, min_y = min([0, sin_a*h, cos_a*w, sin_a*h + cos_a*w]), max([0, sin_a*w, -cos_a*h, sin_a*w - cos_a*h])
# calculate the translation of the pivot
pivot = pygame.math.Vector2(originPos[0], -originPos[1])
pivot_rotate = pivot.rotate(angle)
pivot_move = pivot_rotate - pivot
# calculate the upper left origin of the rotated image
origin = (pos[0] - originPos[0] + min_x - pivot_move[0], pos[1] - originPos[1] - min_y + pivot_move[1])
# get a rotated image
rotated_image = pygame.transform.rotate(image, angle)
end_of_gun_coord = findGreenPixels( origin, rotated_image, angle )
# rotate and blit the image
surf.blit(rotated_image, origin)
class handgun():
def __init__(self,x,y,height,width,color):
self.x = x
self.y = y
self.height = height
self.width = width
self.color = color
self.rect = pygame.Rect(x,y,height,width)
# LOL THESE IS THE HAND
self.shootsright = pygame.image.load("nug.png")
self.image = self.shootsright
self.rect = self.image.get_rect(center = (self.x, self.y))
self.look_at_pos = (self.x, self.y)
self.isLookingAtPlayer = False
self.look_at_pos = (x,y)
self.hitbox = (self.x + -18, self.y, 46,60)
self.gunDirection = "right"
def draw(self,drawX,drawY):
self.rect.topleft = (drawX,drawY)
# the guns hitbox
# rotatiing the gun
dx = self.look_at_pos[0] - self.rect.centerx
dy = self.look_at_pos[1] - self.rect.centery
angle = (120/math.pi) * math.atan2(-dy, dx)
gun_size = self.image.get_size()
pivot = (8, gun_size[1]//2)
blitRotate(window, self.image, self.rect.center, pivot, angle)
if((angle > 90 or angle < -90) and self.gunDirection != "left"):
self.gunDirection = "left"
self.image = pygame.transform.flip(self.image, False, True)
if((angle < 90 and angle > -90) and self.gunDirection != "right"):
self.gunDirection = "right"
self.image = pygame.transform.flip(self.image, False, True)
def lookAt( self, coordinate ):
self.look_at_pos = coordinate
white = (255,255,255)
handgun1 = handgun(300,300,10,10,white)
### initialisation
pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Track Path of Green")
### Main Loop
clock = pygame.time.Clock()
done = False
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.MOUSEBUTTONUP ):
# On mouse-click
pass
handgun1.direction = "right"
# gun rotation
mousex, mousey = pygame.mouse.get_pos()
if not handgun1.isLookingAtPlayer:
handgun1.lookAt((mousex, mousey))
# Update the window, but not more than 60fps
window.fill( DARK_BLUE )
handgun1.draw( 200, 200 )
pygame.display.flip()
# Clamp FPS
clock.tick_busy_loop(60)
pygame.quit()
### PRINT THE LOOKUP TABLE
end_of_gun_lookup = fillLookupHoles( end_of_gun_lookup )
print( "end_of_gun_lookup = "+ str( end_of_gun_lookup ) )