我想知道如何使用箭头键制作一辆可以移动和旋转的汽车。我正在尝试制作一个汽车物理游戏,玩家可以在其中控制汽车并四处行驶和停车,但是我在如何开始实施控制方面遇到了麻烦。我怎样才能让我的车用箭头键沿着它旋转的方向移动?
例如,如果我按下后退箭头键,汽车应该倒车,如果汽车在倒车的同时也在转弯,它应该按照汽车转弯的方式移动。
这是我现在的代码。现在真的没有任何事情发生。
import pygame
pygame.init()
window = pygame.display.set_mode((800,800))
pygame.display.set_caption("car game")
class car:
def __init__(self,x,y,height,width,color):
self.x = x
self.y = y
self.height = height
self.width = width
self.color = color
self.carimage = pygame.image.load("1.png")
self.rect = pygame.Rect(x,y,height,width)
def draw(self):
self.rect.topleft = (self.x,self.y)
window.blit(self.carimage,self.rect)
white = (255,255,2555)
car1 = car(300,300,20,20,white)
def ReDrawWindow():
car1.draw()
# main loop
runninggame = True
while runninggame:
for event in pygame.event.get():
if event.type == pygame.QUIT:
runninggame = False
ReDrawWindow()
pygame.display.update()
pygame.quit()
Run Code Online (Sandbox Code Playgroud)
这是改进后的代码:
import pygame, math
pygame.init()
window = pygame.display.set_mode((600,600))
pygame.display.set_caption("car game")
img = pygame.image.load("1.png")
class Car:
def __init__(self, x, y, height, width, color):
self.x = x - width / 2
self.y = y - height / 2
self.height = height
self.width = width
self.color = color
self.rect = pygame.Rect(x, y, height, width)
self.surface = pygame.Surface((height, width)) # 1
self.surface.blit(img, (0, 0))
self.angle = 0
self.speed = 0 # 2
def draw(self): # 3
self.rect.topleft = (int(self.x), int(self.y))
rotated = pygame.transform.rotate(self.surface, self.angle)
surface_rect = self.surface.get_rect(topleft = self.rect.topleft)
new_rect = rotated.get_rect(center = surface_rect.center)
window.blit(rotated, new_rect.topleft)
white = (255, 255, 255)
car1 = Car(300, 300, 73, 73, white) # 4
clock = pygame.time.Clock()
runninggame = True
while runninggame:
for event in pygame.event.get():
if event.type == pygame.QUIT:
runninggame = False
pressed = pygame.key.get_pressed()
car1.speed *= 0.9 # 5
if pressed[pygame.K_UP]: car1.speed += 0.5 # 6
if pressed[pygame.K_DOWN]: car1.speed -= 0.5 # 6
if pressed[pygame.K_LEFT]: car1.angle += car1.speed / 2 # 7
if pressed[pygame.K_RIGHT]: car1.angle -= car1.speed / 2 # 7
car1.x -= car1.speed * math.sin(math.radians(car1.angle)) # 8
car1.y -= car1.speed * math.cos(math.radians(-car1.angle)) # 8
window.fill((0, 0, 0)) # 9
car1.draw()
pygame.display.flip()
clock.tick(60) # 10
pygame.quit()
Run Code Online (Sandbox Code Playgroud)
需要注意的一些事项:
clock.tick是用来防止它走得太快,它的意思是“最高每秒60帧的”。我希望你明白一切。
我想为这个问题添加一个基于 PyGame Sprite 的答案。将此类事情实现为精灵可以更轻松地使用 PyGame 碰撞函数。例如,可以制作任意数量的 CarSprite,但它们的碰撞会在一次调用中与玩家的 CarSrpite 进行检查groupcollide()。
该实现使用PyGame.math.Vector2()速度和位置。这允许利用 Vector2 的极坐标函数建立相当简单的转弯和速度模型。最初,这给出了奇怪且令人困惑的结果......直到我意识到Vector2.from_polar()所需的角度(以度为单位)。(与几乎所有其他采用角度的编程语言函数不同,不是弧度。)
最初创建精灵时,代码将生成许多预先旋转的图像。这可以以大约每度 1 度 (360) 的速度实现最平滑的转动,但如果内存使用是一个问题,它也可能会少得多。
\n无论如何,代码是相当不言自明的。它需要一个car_128.png图像和一个背景纹理图像road_texture.png。有任何问题请评论。
import pygame\nimport math\n\n# Window size\nWINDOW_WIDTH = 600\nWINDOW_HEIGHT = 600\nWINDOW_SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE\n\n\nclass CarSprite( pygame.sprite.Sprite ):\n """ Car Sprite with basic acceleration, turning, braking and reverse """\n\n def __init__( self, car_image, x, y, rotations=360 ):\n """ A car Sprite which pre-rotates up to <rotations> lots of\n angled versions of the image. Depending on the sprite\'s\n heading-direction, the correctly angled image is chosen.\n The base car-image should be pointing North/Up. """\n pygame.sprite.Sprite.__init__(self)\n # Pre-make all the rotated versions\n # This assumes the start-image is pointing up-screen\n # Operation must be done in degrees (not radians)\n self.rot_img = []\n self.min_angle = ( 360 / rotations ) \n for i in range( rotations ):\n # This rotation has to match the angle in radians later\n # So offet the angle (0 degrees = "north") by 90\xc2\xb0 to be angled 0-radians (so 0 rad is "east")\n rotated_image = pygame.transform.rotozoom( car_image, 360-90-( i*self.min_angle ), 1 )\n self.rot_img.append( rotated_image )\n self.min_angle = math.radians( self.min_angle ) # don\'t need degrees anymore\n # define the image used\n self.image = self.rot_img[0]\n self.rect = self.image.get_rect()\n self.rect.center = ( x, y )\n # movement\n self.reversing = False\n self.heading = 0 # pointing right (in radians)\n self.speed = 0 \n self.velocity = pygame.math.Vector2( 0, 0 )\n self.position = pygame.math.Vector2( x, y )\n\n def turn( self, angle_degrees ):\n """ Adjust the angle the car is heading, if this means using a \n different car-image, select that here too """\n ### TODO: car shouldn\'t be able to turn while not moving\n self.heading += math.radians( angle_degrees ) \n # Decide which is the correct image to display\n image_index = int( self.heading / self.min_angle ) % len( self.rot_img )\n # Only update the image if it\'s changed\n if ( self.image != self.rot_img[ image_index ] ):\n x,y = self.rect.center\n self.image = self.rot_img[ image_index ]\n self.rect = self.image.get_rect()\n self.rect.center = (x,y)\n\n def accelerate( self, amount ):\n """ Increase the speed either forward or reverse """\n if ( not self.reversing ):\n self.speed += amount\n else: \n self.speed -= amount\n\n def brake( self ):\n """ Slow the car by half """\n self.speed /= 2\n if ( abs( self.speed ) < 0.1 ):\n self.speed = 0\n\n def reverse( self ):\n """ Change forward/reverse, reset any speed to 0 """\n self.speed = 0\n self.reversing = not self.reversing\n\n def update( self ):\n """ Sprite update function, calcualtes any new position """\n self.velocity.from_polar( ( self.speed, math.degrees( self.heading ) ) )\n self.position += self.velocity\n self.rect.center = ( round(self.position[0]), round(self.position[1] ) )\n\n\n### initialisation\npygame.init()\npygame.mixer.init()\nwindow = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )\npygame.display.set_caption("Car Steering")\n\n\n### Bitmaps\nroad_image = road_image = pygame.image.load( \'road_texture.png\' )\nbackground = pygame.transform.smoothscale( road_image, ( WINDOW_WIDTH, WINDOW_HEIGHT ) )\ncar_image = pygame.image.load( \'car_128.png\' ).convert_alpha()\n\n\n### Sprites\nblack_car = CarSprite( car_image, WINDOW_WIDTH//2, WINDOW_HEIGHT//2 )\ncar_sprites = pygame.sprite.Group() #Single()\ncar_sprites.add( black_car )\n\n\n### Main Loop\nclock = pygame.time.Clock()\ndone = False\nwhile not done:\n\n # Handle user-input\n for event in pygame.event.get():\n if ( event.type == pygame.QUIT ):\n done = True\n elif ( event.type == pygame.VIDEORESIZE ):\n WINDOW_WIDTH = event.w\n WINDOW_HEIGHT = event.h\n window = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )\n background = pygame.transform.smoothscale( road_image, ( WINDOW_WIDTH, WINDOW_HEIGHT ) )\n elif ( event.type == pygame.MOUSEBUTTONUP ):\n # On mouse-click\n pass\n elif ( event.type == pygame.KEYUP ):\n if ( event.key == pygame.K_h ): \n print( \'meep-meep\' )\n elif ( event.key == pygame.K_r ): \n print( \'resersing\' )\n black_car.reverse()\n elif ( event.key == pygame.K_UP ): \n print( \'accelerate\' )\n black_car.accelerate( 0.5 )\n elif ( event.key == pygame.K_DOWN ): \n print( \'brake\' )\n black_car.brake( )\n\n # Continuous Movement keys\n keys = pygame.key.get_pressed()\n if ( keys[pygame.K_LEFT] ):\n black_car.turn( -1.8 ) # degrees\n if ( keys[pygame.K_RIGHT] ):\n black_car.turn( 1.8 )\n\n # Update the car(s)\n car_sprites.update()\n\n # Update the window\n window.blit( background, ( 0, 0 ) ) # backgorund\n car_sprites.draw( window )\n pygame.display.flip()\n\n # Clamp FPS\n clock.tick_busy_loop(60)\n\npygame.quit()\nRun Code Online (Sandbox Code Playgroud)\n
car_128.png(来源:https://openclipart.org)
| 归档时间: |
|
| 查看次数: |
723 次 |
| 最近记录: |