当向相反方向推进时,如何正确地对自由漂浮的太空物体施加重力和某种摩擦 [英] How do you properly implement gravity to a free floating space object and some sort of friction when thrusting in opposite direction

查看:16
本文介绍了当向相反方向推进时,如何正确地对自由漂浮的太空物体施加重力和某种摩擦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


      

解决方案

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

这篇关于当向相反方向推进时,如何正确地对自由漂浮的太空物体施加重力和某种摩擦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆