我想在python / pygame中创建一个脚本,当你按住一个移动按钮时,它会使角色加速(因此,当我按住左键时,角色会加速到特定的速度,然后速度会均匀当我松开钥匙时,它会慢慢减速直到完全停止。)
此刻,我的代码会识别出角色必须加速,但速度的变化只会在每次按下并释放按键时发生(例如:第一次按键的速度为1,第二次按下将在重置之前,一直到第五或第六次按下最大速度。)
我想编写我的代码,这意味着当按键被按下而不需要多次按下时,角色会加速。
这是我的代码到目前为止的移动部分(周围有几个随机位):
x = (display_width * 0.45)
y = display_height * 0.8
x_change = 0
negx = 0
posx = 0
bun_speed = 0
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
posx = 0
if negx != -5:
negx = negx - 1
x_change = negx
elif negx == -5:
negx = 0
x_change = -5
elif event.key == pygame.K_RIGHT:
negx = 0
if posx != 5:
posx = posx + 1
x_change = posx
elif posx == 5:
posx = 0
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
x_change = 0
elif event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
display.fill(white)
bunny(x,y)
pygame.display.update()
clock.tick(60)
两个变量negx和posx分别根据按下的键减小和增加。按下分配给一个变量的键会将另一个键重置为零,因此当按下相反按钮时接下来调用该变量时,它将从零加速。一旦任一变量达到最大速度,它将在按钮释放时重置,这意味着角色可以再次加速。
如果有任何方法可以使这项工作(以及如果你能够完成代码的话),那么我们将非常感谢您对如何使其发挥作用的指导。
答案 0 :(得分:1)
为加速度定义变量(示例中为accel_x
),将其设置为事件循环中的所需值,并将其添加到每帧的x_change
以加速。要将x_change
限制为最高速度,您必须对其进行标准化并将其乘以max_speed
。
要减速对象,当没有按下任何键时,可以将x_change
乘以低于1的值。
import pygame
pygame.init()
display = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
GRAY = pygame.Color('gray12')
display_width, display_height = display.get_size()
x = display_width * 0.45
y = display_height * 0.8
x_change = 0
accel_x = 0
max_speed = 6
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
elif event.type == pygame.KEYDOWN:
# Set the acceleration value.
if event.key == pygame.K_LEFT:
accel_x = -.2
elif event.key == pygame.K_RIGHT:
accel_x = .2
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
accel_x = 0
x_change += accel_x # Accelerate.
if abs(x_change) >= max_speed: # If max_speed is exceeded.
# Normalize the x_change and multiply it with the max_speed.
x_change = x_change/abs(x_change) * max_speed
# Decelerate if no key is pressed.
if accel_x == 0:
x_change *= 0.92
x += x_change # Move the object.
display.fill(GRAY)
pygame.draw.rect(display, (0, 120, 250), (x, y, 20, 40))
pygame.display.update()
clock.tick(60)
pygame.quit()
答案 1 :(得分:0)
我发现了加速角色的另一种方法。不用改变距离,而要改变时间。我定义了一个在pygame.time.delay()中的变量,延迟是我改变的。这样做会更好,因为从一个地方移到另一个地方时,角色看起来不会出现毛刺。
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
pygame.display.set_caption("ACCELERATE")
def main():
k = True
thita = 40
x = 250
y = 400
while k:
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
thita = 40
if event.key == pygame.K_RIGHT:
thita = 40
if event.type == pygame.QUIT:
k = False
if keys[pygame.K_LEFT]:
x -= 4
pygame.time.delay(thita)
if thita > 12:
thita -= 1
if keys[pygame.K_RIGHT]:
x += 4
pygame.time.delay(thita)
if thita > 11:
thita -= 1
pygame.draw.rect(win, (255, 0, 0), (x, y, 10, 10))
pygame.display.update()
win.fill((0, 0, 0))
main()
您看到提起钥匙后,thita便恢复到其原始值。
答案 2 :(得分:0)
我试图结合srkx的方法进行加速。当我使用右键向右移动时,我会加速到最大速度。当我释放它时,我确实减速停止。但是,当使用向左键向左移动并释放它之后,我继续以固定速度移动,然后过了一会儿突然停止。知道我的代码有什么问题吗?非常感谢你!
原始代码来自http://programarcadegames.com/python_examples/show_file.php?file=platform_jumper.py
import pygame
# Global constants
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# Screen dimensions
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Player(pygame.sprite.Sprite):
""" This class represents the bar at the bottom that the player
controls. """
# -- Methods
def __init__(self):
""" Constructor function """
# Call the parent's constructor
super().__init__()
# Create an image of the block, and fill it with a color.
# This could also be an image loaded from the disk.
width = 40
height = 60
self.image = pygame.Surface([width, height])
self.image.fill(RED)
# Set a referance to the image rect.
self.rect = self.image.get_rect()
# Set speed vector of player
self.xVel = 0
self.yVel = 0
# List of sprites we can bump against
self.level = None
def update(self):
""" Move the player. """
# Gravity
self.calc_grav()
# Move left/right
# See if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# If we are moving right,
# set our right side to the left side of the item we hit
if self.xVel > 0:
self.rect.right = block.rect.left
elif self.xVel < 0:
# Otherwise if we are moving left, do the opposite.
self.rect.left = block.rect.right
# Move up/down
self.rect.y += self.yVel
# Check and see if we hit anything
block_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
for block in block_hit_list:
# Reset our position based on the top/bottom of the object.
if self.yVel > 0:
self.rect.bottom = block.rect.top
elif self.yVel < 0:
self.rect.top = block.rect.bottom
# Stop our vertical movement
self.yVel = 0
def calc_grav(self):
""" Calculate effect of gravity. """
if self.yVel == 0:
self.yVel = 1
else:
self.yVel += .35
# See if we are on the ground.
if self.rect.y >= SCREEN_HEIGHT - self.rect.height and self.yVel >= 0:
self.yVel = 0
self.rect.y = SCREEN_HEIGHT - self.rect.height
def jump(self):
""" Called when user hits 'jump' button. """
# move down a bit and see if there is a platform below us.
# Move down 2 pixels because it doesn't work well if we only move down
# 1 when working with a platform moving down.
self.rect.y += 2
platform_hit_list = pygame.sprite.spritecollide(self, self.level.platform_list, False)
self.rect.y -= 2
# If it is ok to jump, set our speed upwards
if len(platform_hit_list) > 0 or self.rect.bottom >= SCREEN_HEIGHT:
self.yVel = -10
class Platform(pygame.sprite.Sprite):
""" Platform the user can jump on """
def __init__(self, width, height):
""" Platform constructor. Assumes constructed with user passing in
an array of 5 numbers like what's defined at the top of this
code. """
super().__init__()
self.image = pygame.Surface([width, height])
self.image.fill(GREEN)
self.rect = self.image.get_rect()
class Level(object):
""" This is a generic super-class used to define a level.
Create a child class for each level with level-specific
info. """
def __init__(self, player):
""" Constructor. Pass in a handle to player. Needed for when moving platforms
collide with the player. """
self.platform_list = pygame.sprite.Group()
self.enemy_list = pygame.sprite.Group()
self.player = player
# Background image
self.background = None
# Update everythign on this level
def update(self):
""" Update everything in this level."""
self.platform_list.update()
self.enemy_list.update()
def draw(self, screen):
""" Draw everything on this level. """
# Draw the background
screen.fill(BLUE)
# Draw all the sprite lists that we have
self.platform_list.draw(screen)
self.enemy_list.draw(screen)
# Create platforms for the level
class Level_01(Level):
""" Definition for level 1. """
def __init__(self, player):
""" Create level 1. """
# Call the parent constructor
Level.__init__(self, player)
# Array with width, height, x, and y of platform
level = [[210, 70, 500, 500],
[210, 70, 200, 400],
[210, 70, 600, 300],
]
# Go through the array above and add platforms
for platform in level:
block = Platform(platform[0], platform[1])
block.rect.x = platform[2]
block.rect.y = platform[3]
block.player = self.player
self.platform_list.add(block)
def main():
""" Main Program """
pygame.init()
# Set the height and width of the screen
size = [SCREEN_WIDTH, SCREEN_HEIGHT]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Platformer Jumper")
# Create the player
player = Player()
# Create all the levels
level_list = []
level_list.append(Level_01(player))
# Set the current level
current_level_no = 0
current_level = level_list[current_level_no]
active_sprite_list = pygame.sprite.Group()
player.level = current_level
player.rect.x = 340
player.rect.y = SCREEN_HEIGHT - player.rect.height
active_sprite_list.add(player)
accel_x = 0
max_speed = 6
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# -------- Main Program Loop -----------
while not done:
player_running = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
accel_x = -0.5
if event.key == pygame.K_RIGHT:
accel_x = 0.5
if event.key == pygame.K_SPACE:
player.jump()
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
accel_x = 0
player.xVel += accel_x # Accelerate.
if abs(player.xVel) >= max_speed: # If max_speed is exceeded.
# Normalize the x_change and multiply it with the max_speed.
player.xVel = player.xVel / abs(player.xVel) * max_speed
# Decelerate if no key is pressed.
if accel_x == 0:
player.xVel *= 0.5
player.rect.x += player.xVel
# Update the player.
active_sprite_list.update()
# Update items in the level
current_level.update()
# If the player gets near the right side, shift the world left (-x)
if player.rect.right > SCREEN_WIDTH:
player.rect.right = SCREEN_WIDTH
# If the player gets near the left side, shift the world right (+x)
if player.rect.left < 0:
player.rect.left = 0
# ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
current_level.draw(screen)
active_sprite_list.draw(screen)
# ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
# Limit to 60 frames per second
clock.tick(60)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit()
if __name__ == "__main__":
main()
答案 3 :(得分:0)
Kevin,您提到的是关键点,但这是一个非常简单的解决方法,您只需要用一些减速的代码替换检查x_change是正数还是负数的东西,然后在确定了x_change后加减即可。
例如,他的代码是:
if accel_x == 0:
x_change *= 0.92
用以下内容代替:
if accel_x == 0:
if x_change > 0:
x_change -= 0.2
if x_change < 0.2:
x_change = 0
elif x_change < 0:
x_change += 0.2
if x_change > -0.2:
x_change = 0