你如何正确地对一个自由浮动的 space 物体施加重力,并在向相反方向推进时产生某种摩擦力
How do you properly implement gravity to a free floating space object and some sort of friction when thrusting in opposite direction
我正在尝试编写基本上类似于小行星的运动程序,一旦按下向上按钮,您就会加速到某个速度,然后因为在 space 中您不会停下来,只能通过推入来减速相反的方向。最重要的是,我希望重力将您拉向屏幕底部。我已经完成了大部分工作,但我遇到的问题是:
- 当我转身反方向冲刺时,它并没有先向后减速再开始向前运动,而是全速向相反方向射出
关于如何处理此问题并使移动总体上更流畅的任何建议?
import pygame as pg
import os
vec = pg.math.Vector2
TITLE = "GRAVITAR"
WIDTH = 800
HEIGHT = 600
FPS = 60
GREY = (211, 211, 211)
# Player properties
ROCKET_SHIP = 'Images/Rocket_Ship.png' # <a href='https://pngtree.com/so/spaceship-clipart'>spaceship
# clipart png from pngtree.com</a>
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.00
PLAYER_GRAV = 0.1
PLAYER_ROT_SPEED = 200
PLAYER_SPEED = 5
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = game.rocket_ship
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.vel = vec(0, 0)
self.pos = vec(x, y)
self.rot = 0
def get_keys(self):
self.rot_speed = 0
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.rot_speed = PLAYER_ROT_SPEED
if keys[pg.K_RIGHT]:
self.rot_speed = -PLAYER_ROT_SPEED
if keys[pg.K_UP]:
self.vel = vec(PLAYER_SPEED, 0).rotate(-self.rot)
if keys[pg.K_SPACE]:
self.shoot()
self.acc += self.vel * PLAYER_FRICTION
self.vel += self.acc
if self.vel[1] >= 2:
self.vel[1] = 2
self.pos += self.vel + 0.5 * self.acc
def shoot(self):
pass
def update(self):
self.get_keys()
self.rot = (self.rot + self.rot_speed * self.game.dt) % 360
self.image = pg.transform.rotate(self.game.rocket_ship, self.rot - 90)
self.rect = self.image.get_rect()
self.rect.center = self.pos
self.pos += self.vel * self.game.dt
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
if self.pos.y > HEIGHT:
self.pos.y = 0
if self.pos.y < 0:
self.pos.y = HEIGHT
class Game:
def __init__(self):
# Initialize pygame and create window
pg.init()
pg.mixer.init()
pg.key.set_repeat(10, 50)
os.environ['SDL_VIDEO_WINDOW_POS'] = '568, 101'
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.running = True
self.load_data()
def load_data(self):
self.rocket_ship = pg.image.load(ROCKET_SHIP).convert_alpha()
self.rocket_ship = pg.transform.scale(self.rocket_ship, (32, 32))
def new(self):
# Start a new game
self.all_sprites = pg.sprite.Group()
self.player = Player(self, WIDTH / 2, HEIGHT / 4)
self.all_sprites.add(self.player)
self.run()
def run(self):
# Game loop
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000.0
self.events()
self.update()
self.draw()
def update(self):
# Game loop update
self.all_sprites.update()
def events(self):
# Game loop events
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
def draw(self):
# Game loop draw
pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
self.screen.fill(GREY)
self.all_sprites.draw(self.screen)
# After drawing everything, flip display
pg.display.flip()
def show_start_screen(self):
pass
def show_go_screen(self):
pass
g = Game()
g.show_start_screen()
while g.running:
g.new()
g.show_go_screen()
pg.quit()
当你按UP时你不用改变速度,但是你要设置加速度:
self.vel = vec(PLAYER_SPEED, 0).rotate(-self.rot)
self.acc += vec(PLAYER_ACC, 0).rotate(-self.rot)
将加速度加到速度上:
self.vel += self.acc
我建议限制最大值。但是,我建议对每个方向分别执行此操作:
max_vel = 2
self.vel[0] = max(-max_vel, min(max_vel, self.vel[0]))
self.vel[1] = max(-max_vel, min(max_vel, self.vel[1]))
将此应用于方法 get_keys
:
class Player(pg.sprite.Sprite):
# [...]
def get_keys(self):
self.rot_speed = 0
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.rot_speed = PLAYER_ROT_SPEED
if keys[pg.K_RIGHT]:
self.rot_speed = -PLAYER_ROT_SPEED
if keys[pg.K_UP]:
self.acc += vec(PLAYER_ACC, 0).rotate(-self.rot)
if keys[pg.K_SPACE]:
self.shoot()
self.vel += self.acc + self.vel * PLAYER_FRICTION
max_vel = 2
self.vel[0] = max(-max_vel, min(max_vel, self.vel[0]))
self.vel[1] = max(-max_vel, min(max_vel, self.vel[1]))
self.pos += self.vel
我正在尝试编写基本上类似于小行星的运动程序,一旦按下向上按钮,您就会加速到某个速度,然后因为在 space 中您不会停下来,只能通过推入来减速相反的方向。最重要的是,我希望重力将您拉向屏幕底部。我已经完成了大部分工作,但我遇到的问题是:
- 当我转身反方向冲刺时,它并没有先向后减速再开始向前运动,而是全速向相反方向射出
关于如何处理此问题并使移动总体上更流畅的任何建议?
import pygame as pg
import os
vec = pg.math.Vector2
TITLE = "GRAVITAR"
WIDTH = 800
HEIGHT = 600
FPS = 60
GREY = (211, 211, 211)
# Player properties
ROCKET_SHIP = 'Images/Rocket_Ship.png' # <a href='https://pngtree.com/so/spaceship-clipart'>spaceship
# clipart png from pngtree.com</a>
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.00
PLAYER_GRAV = 0.1
PLAYER_ROT_SPEED = 200
PLAYER_SPEED = 5
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = game.rocket_ship
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.vel = vec(0, 0)
self.pos = vec(x, y)
self.rot = 0
def get_keys(self):
self.rot_speed = 0
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.rot_speed = PLAYER_ROT_SPEED
if keys[pg.K_RIGHT]:
self.rot_speed = -PLAYER_ROT_SPEED
if keys[pg.K_UP]:
self.vel = vec(PLAYER_SPEED, 0).rotate(-self.rot)
if keys[pg.K_SPACE]:
self.shoot()
self.acc += self.vel * PLAYER_FRICTION
self.vel += self.acc
if self.vel[1] >= 2:
self.vel[1] = 2
self.pos += self.vel + 0.5 * self.acc
def shoot(self):
pass
def update(self):
self.get_keys()
self.rot = (self.rot + self.rot_speed * self.game.dt) % 360
self.image = pg.transform.rotate(self.game.rocket_ship, self.rot - 90)
self.rect = self.image.get_rect()
self.rect.center = self.pos
self.pos += self.vel * self.game.dt
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
if self.pos.y > HEIGHT:
self.pos.y = 0
if self.pos.y < 0:
self.pos.y = HEIGHT
class Game:
def __init__(self):
# Initialize pygame and create window
pg.init()
pg.mixer.init()
pg.key.set_repeat(10, 50)
os.environ['SDL_VIDEO_WINDOW_POS'] = '568, 101'
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.running = True
self.load_data()
def load_data(self):
self.rocket_ship = pg.image.load(ROCKET_SHIP).convert_alpha()
self.rocket_ship = pg.transform.scale(self.rocket_ship, (32, 32))
def new(self):
# Start a new game
self.all_sprites = pg.sprite.Group()
self.player = Player(self, WIDTH / 2, HEIGHT / 4)
self.all_sprites.add(self.player)
self.run()
def run(self):
# Game loop
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000.0
self.events()
self.update()
self.draw()
def update(self):
# Game loop update
self.all_sprites.update()
def events(self):
# Game loop events
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
def draw(self):
# Game loop draw
pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
self.screen.fill(GREY)
self.all_sprites.draw(self.screen)
# After drawing everything, flip display
pg.display.flip()
def show_start_screen(self):
pass
def show_go_screen(self):
pass
g = Game()
g.show_start_screen()
while g.running:
g.new()
g.show_go_screen()
pg.quit()
当你按UP时你不用改变速度,但是你要设置加速度:
self.vel = vec(PLAYER_SPEED, 0).rotate(-self.rot)
self.acc += vec(PLAYER_ACC, 0).rotate(-self.rot)
将加速度加到速度上:
self.vel += self.acc
我建议限制最大值。但是,我建议对每个方向分别执行此操作:
max_vel = 2
self.vel[0] = max(-max_vel, min(max_vel, self.vel[0]))
self.vel[1] = max(-max_vel, min(max_vel, self.vel[1]))
将此应用于方法 get_keys
:
class Player(pg.sprite.Sprite):
# [...]
def get_keys(self):
self.rot_speed = 0
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.rot_speed = PLAYER_ROT_SPEED
if keys[pg.K_RIGHT]:
self.rot_speed = -PLAYER_ROT_SPEED
if keys[pg.K_UP]:
self.acc += vec(PLAYER_ACC, 0).rotate(-self.rot)
if keys[pg.K_SPACE]:
self.shoot()
self.vel += self.acc + self.vel * PLAYER_FRICTION
max_vel = 2
self.vel[0] = max(-max_vel, min(max_vel, self.vel[0]))
self.vel[1] = max(-max_vel, min(max_vel, self.vel[1]))
self.pos += self.vel