Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
408 views
in Technique[技术] by (71.8m points)

python - How do you properly implement gravity to a free floating space object and some sort of friction when thrusting in opposite direction

I am trying to program movement that is basically like Asteroids where once UP button is pressed you accelerate to a certain speed and then because in space you don't stop and can only slow down by thrusting in opposite direction. On top of that, I would like gravity to be pulling you towards the bottom of the screen. I have this accomplished for the most part but the issue I have is:

  1. When I turn around and thrust opposite direction, it doesn't slow down first going backwards before starting to move forwards again, it just shoots off in opposite direction at full speed

Any suggestions of how to handle this and make movement smoother in general?

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()


      
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you press UP you don't have to change the speed, but you have to set the acceleration:

self.vel = vec(PLAYER_SPEED, 0).rotate(-self.rot)

self.acc += vec(PLAYER_ACC, 0).rotate(-self.rot)

Add the acceleration to the velocity:

self.vel += self.acc

I recommend limiting the maximum. However, I recommend doing this separately for each direction:

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]))

Apply this to the method 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...