I wanna know how to shoot a projectile towards the direction the player is looking. I would also like to know how to shoot that projectile from the middle of the player. I have got my bullet class sort of ready but don't know my next step.
here is my code and replit...
https://replit.com/@TahaSSS/game-1#main.py
import pygame
from sys import exit
from random import randint
import math
from pygame.constants import K_LSHIFT, K_SPACE, MOUSEBUTTONDOWN
pygame.init()
pygame.mouse.set_visible(True)
class Player(pygame.sprite.Sprite):
def __init__(self, x , y):
super().__init__()
self.x = x
self.y = y
self.image = pygame.image.load('graphics/Robot 1/robot1_gun.png').convert_alpha()
self.rect = self.image.get_rect()
self.orig_image = pygame.image.load('graphics/Robot 1/robot1_gun.png').convert_alpha()
self.rotate_vel = 1
self.cross_image = pygame.image.load('graphics/crosshair049.png')
def draw(self, surface):
""" Draw on surface """
# blit yourself at your current position
surface.blit(self.image, self.rect)
dir_vec = pygame.math.Vector2()
dir_vec.from_polar((180, -self.rotate_vel))
cross_pos = dir_vec + self.rect.center
cross_x, cross_y = round(cross_pos.x), round(cross_pos.y)
surface.blit(self.cross_image, self.cross_image.get_rect(center = (cross_x, cross_y)))
def movement(self):
key = pygame.key.get_pressed()
self.rect = self.image.get_rect(center = (self.x, self.y))
dist = 3 # distance moved in 1 frame, try changing it to 5
if key[pygame.K_DOWN] or key[pygame.K_s]: # down key
self.y += dist # move down
elif key[pygame.K_UP] or key[pygame.K_w]: # up key
self.y -= dist # move up
if key[pygame.K_RIGHT] or key[pygame.K_d]: # right key
self.x += dist # move right
elif key[pygame.K_LEFT] or key[pygame.K_a]: # left key
self.x -= dist # move left
def rotate(self, surface):
keys = pygame.key.get_pressed()
if keys[K_LSHIFT]:
self.rotate_vel += 5
self.image = pygame.transform.rotate(self.orig_image, self.rotate_vel)
self.rect = self.image.get_rect(center=self.rect.center)
surface.blit(self.image, self.rect)
if keys[K_SPACE]:
self.rotate_vel += -5
self.image = pygame.transform.rotate(self.orig_image, self.rotate_vel)
self.rect = self.image.get_rect(center=self.rect.center)
surface.blit(self.image, self.rect)
def update(self):
self.movement()
self.draw(screen)
self.rotate(screen)
class Bullet(pygame.sprite.Sprite):
def __init__(self, x , y):
super().__init__()
self.bullet_image = pygame.image.load('graphics/weapons/bullets/default_bullet.png')
self.bullet_rect = self.bullet_image.get_rect(center = (x,y))
self.bullet_speed = 15
#screen
clock = pygame.time.Clock()
FPS = 60
screen = pygame.display.set_mode((800, 400))
#player
player_sprite = Player(600, 300)
player = pygame.sprite.GroupSingle()
player.add(player_sprite)
#bullet
bullet_group = pygame.sprite.Group()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
#screen
screen.fill('grey')
#player sprite funtions
player.update()
clock.tick(FPS)
pygame.display.update()
pygame.sprite.Group.draw()
and pygame.sprite.Group.update()
are methods which are provided by pygame.sprite.Group
.
The former delegates the to the update
method of the contained pygame.sprite.Sprite
s - you have to implement the method. See pygame.sprite.Group.update()
:
Calls the
update()
method on all Sprites in the Group [...]
The later uses the image
and rect
attributes of the contained pygame.sprite.Sprite
s to draw the objects - you have to ensure that the pygame.sprite.Sprite
s have the required attributes. See pygame.sprite.Group.draw()
:
Draws the contained Sprites to the Surface argument. This uses the
Sprite.image
attribute for the source surface, andSprite.rect
. [...]
A Sprite kan be removed from all Groups and thus delted by calling kill
.
Since pygame.Rect
is supposed to represent an area on the screen, a pygame.Rect
object can only store integral data.
The coordinates for Rect objects are all integers. [...]
The fraction part of the coordinates gets lost when the new position of the object is assigned to the Rect object. If this is done every frame, the position error will accumulate over time.
If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the pygame.Rect
object. round
the coordinates and assign it to the location (e.g. .center
) of the rectangle.
Write a Sprite class with an update
method that moves the bullet in a certain direction. Destroy the bullet when it goes out of the display:
class Bullet(pygame.sprite.Sprite):
def __init__(self, pos, angle):
super().__init__()
self.image = pygame.image.load('graphics/weapons/bullets/default_bullet.png')
self.image = pygame.transform.rotate(self.image, angle)
self.rect = self.image.get_rect(center = pos)
self.speed = 15
self.pos = pos
self.dir_vec = pygame.math.Vector2()
self.dir_vec.from_polar((self.speed, -angle))
def update(self, screen):
self.pos += self.dir_vec
self.rect.center = round(self.pos.x), round(self.pos.y)
if not screen.get_rect().colliderect(self.rect):
self.kill()
pygame.key.get_pressed()
returns a list with the state of each key. If a key is held down, the state for the key is True
, otherwise False
. Use pygame.key.get_pressed()
to evaluate the current state of a button and get continuous movement.
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN
event occurs once every time a key is pressed. KEYUP
occurs once every time a key is released. Use the keyboard events for a single action.
Use an keyboard event to generate a new Bullet
object (e.g. TAB). Call bullet_group.update(screen)
and bullet_group.draw(screen)
in the application loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_TAB:
pos = player_sprite.rect.center
dir_vec = pygame.math.Vector2()
new_bullet = Bullet(pos, player_sprite.rotate_vel)
bullet_group.add(new_bullet)
bullet_group.update(screen)
screen.fill('grey')
player.update()
bullet_group.draw(screen)
pygame.display.update()
clock.tick(FPS)