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
247 views
in Technique[技术] by (71.8m points)

python - calculating direction of the player to shoot pygame

This is my player class

class Player:
    def  __init__(self, image):
        self.rotation_angle = 0

    def rotate(self, keys, left, right):
        if keys[right]:
            self.rotation_angle -= 0.5
        if keys[left]:
            self.rotation_angle += 0.5
        self.rotated_player = pygame.transform.rotate(self.player, (self.rotation_angle))

Now based onself.rotation_angle, i need to shoot the bullet. So i did the following.

class Bullet:
    def __init__(self):
        self.pos = [player1.pos[0], player1.pos[1]]
        self.direction = math.radians(player1.rotation_angle)
        self.bullet = pygame.Surface((5, 20))
        self.rotated_bullet = pygame.transform.rotate(self.bullet, (self.direction))
        self.bullet.fill((100, 200, 120))
        self.time = 0

    def shoot(self):
        self.pos[0] += math.cos(self.direction) * self.time
        self.pos[1] += math.sin(self.direction) * self.time
        self.time += 0.5

But this dosent work and the resulting bullet just moves in some random direction. I tried not converting the angle to radians and changing the self.direction value for y-axis to negative but it just isn't working. How would i accurately calculate the direction for bullet? Thanks for any help.

Question&Answers:os

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

1 Reply

0 votes
by (71.8m points)

The unit of the angle for the mathematical operations math.sin and math.cos is radian, but the unit of the angel for pygame.transform.rotate() is degrees. Furthermore you have to create a pygame.Surface with the flag SRCALPHA and to fill the surface with the bullet color, before it is rotated:

class Bullet:
    def __init__(self):
        self.pos = [player1.pos[0], player1.pos[1]]
        self.direction = math.radians(player1.rotation_angle)
        self.bullet = pygame.Surface((10, 5), pygame.SRCALPHA)
        self.bullet.fill((100, 200, 120))
        self.rotated_bullet = pygame.transform.rotate(self.bullet, player1.rotation_angle)
        self.time = 0

In pygame the y axis points form the top to the bottom. That is the opposite direction than in a usual Cartesian coordinate system. Because of that the y coordinate of the direction has to be inverted:

class Bullet:
    # [...]

    def shoot(self):
        self.pos[0] += math.cos(self.direction) * self.time
        self.pos[1] -= math.sin(self.direction) * self.time
        self.time += 0.5

See the example:

import pygame
import math

pygame.init()
WIDTH, HEIGHT = 500, 500
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

class Player():
    def  __init__(self):
        self.rotation_angle = 0
        self.player = pygame.Surface((20, 20), pygame.SRCALPHA)
        self.player.fill((0, 255, 0))
        self.rotated_player = self.player
        self.pos = (WIDTH//2, HEIGHT//2)
        
    def rotate(self, keys, left, right):
        if keys[right]:
            self.rotation_angle -= 0.5
        if keys[left]:
            self.rotation_angle += 0.5
        self.rotated_player = pygame.transform.rotate(self.player, (self.rotation_angle))

class Bullet:
    def __init__(self):
        self.pos = [player1.pos[0], player1.pos[1]]
        self.direction = math.radians(player1.rotation_angle)
        self.bullet = pygame.Surface((10, 5), pygame.SRCALPHA)
        self.bullet.fill((100, 200, 120))
        self.rotated_bullet = pygame.transform.rotate(self.bullet, player1.rotation_angle)
        self.time = 0

    def shoot(self):
        self.pos[0] += math.cos(self.direction) * self.time
        self.pos[1] -= math.sin(self.direction) * self.time
        self.time += 0.5

player1 = Player()

bullets = []
pos = (250, 250)
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            bullets.append(Bullet())

    keys = pygame.key.get_pressed()
    player1.rotate(keys, pygame.K_LEFT, pygame.K_RIGHT)       

    for bullet in bullets[:]:
        bullet.shoot()
        if not window.get_rect().collidepoint(bullet.pos):
            bullets.remove(bullet)

    window.fill(0)
    window.blit(player1.rotated_player, player1.rotated_player.get_rect(center=player1.pos))
    for bullet in bullets:
        window.blit(bullet.rotated_bullet, bullet.rotated_bullet.get_rect(center=bullet.pos))
    pygame.display.flip()

See also Why aren't any bullets appearing on screen? - pygame
Shooting a bullet in pygame in the direction of mouse

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

1.4m articles

1.4m replys

5 comments

56.9k users

...