Why am i getting invalid syntax when adding a def? - python
import pygame
import math
#initialise pygame
pygame.init()
#game window
WINDOW_WIDTH = 1200
WINDOW_HEIGHT = 750
#create game window
win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('Castle Defender')
clock = pygame.time.Clock()
FPS = 60
#load images
background_img = pygame.image.load('Animations/BG.png').convert_alpha()
background = pygame.transform.scale(background_img,(1200,750))
castle_img = pygame.image.load('Animations/Castle.png').convert_alpha()
bullet_img = pygame.image.load('Animations/SmallBullet.png').convert_alpha()
b_w = bullet_img.get_width()
b_h = bullet_img.get_height()
bullet_img = pygame.transform.scale(bullet_img, (int(b_w * 0.075), int(b_h * 0.075)))
WHITE =(255,255,255)
#Castle class
class Castle():
def __init__(self, image, x, y, scale):
self.health = 1000
self.max_health = self.health
width = image.get_width()
height = image.get_height()
self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale)))
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def shoot(self):
pos = pygame.mouse.get_pos()
x_dist = pos[0] - self.rect.midleft[0]
y_dist = -(pos[1] - self.rect.midleft[1])
self.angle = math.degrees(math.atan2(y_dist, x_dist))
#mouseclick
if pygame.mouse.get_pressed()[0] and self.fired == False:
self.fired = True
bullet = Bullet(bullet_img, self.rect.right[0], self.rect.right[1], self.angle)
bullet_group.add(bullet)
#reset mouseclick
if pygame.mouse.get_pressed()[0] == False:
self.fired = False
#Method
def draw(self):
self.image = self.image
win.blit(self.image, self.rect)
class Bullet(pygame.sprite.Sprite):
def __init__(self, image, x, y, angle):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.angle = math.radians(angle)
self.speed = 10
self.dx = math.cos(self.angle) * self.speed
self.dy = -(math.sin(self.angle) * self.speed)
def update(self):
#check if bullet has gone off the screen
if self.rect.right < 0 or self.rect.left > SCREEN_WIDTH or self.rect.bottom < 0 or self.rect.top > SCREEN_HEIGHT:
self.kill()
#move bullet
self.rect.x += self.dx
self.rect.y += self.dy
castle = Castle(castle_img, WINDOW_WIDTH - 1350, WINDOW_HEIGHT - 400, 0.7)
bullet_group = pygame.sprite.Group()
run = True
while run:
clock.tick(FPS)
win.blit(background, (0, 0))
castle.draw()
castle.shoot()
#bullet drawing
bullet_group.update()
bullet_group.draw(win)
print(len(bullet_group))
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#update display window
pygame.display.update()
pygame.quit()
I am trying to see the line from my base and my mouse. However I get an error of the following
bullet = Bullet(bullet_img, self.rect.right[0], self.rect.right[1], self.angle)
(My end goal is for bullets to come out of the castle and i am relatively new to coding and this will be my first project) . Also i keep getting an error when trying to submit this saying it is mostly code so the parenthisis was me rambling on
The issue the code is trying to use self.rect.right as if it was a python list. But self.rect.right is an integer.
self.rect.right[0]
self.rect.right[1]
Probably this should be self.rect.right and self.rect.top (since it deals with the y-dimension).
Then you also need to correct references to SCREEN_WIDTH and SCREEN_HEIGHT. It looks like these should be WINDOW_ etc.
After these changes are made, your program does not exit with an error when the mouse is clicked.
Related
Bullet movement not working as expected when player sprite is moving
My game is a top down shooter. When the player is stationary and is shooting in any direction, the bullet goes in the same direction as the mouse. However, when I move diagonally whilst shooting the bullet is no longer in the direction of the mouse position. So basically it works when the player is stationary, but not when I'm moving. Edit: I will keep trying to fix this but here is a video to better understand the issue https://imgur.com/a/8QRr1PO Here is the code: import pygame from sys import exit import math pygame.init() # window and text WIDTH = 1280 HEIGHT = 720 FPS = 60 screen = pygame.display.set_mode((WIDTH,HEIGHT)) pygame.display.set_caption('Shooting problem demo') game_font = pygame.font.Font('freesansbold.ttf', 50) clock = pygame.time.Clock() # loads imgs background = pygame.image.load("background/gamemap.png").convert() plain_bg = pygame.image.load("background/plain_bg.png").convert() bullet_img = pygame.image.load("bullets/bluebullet.png").convert_alpha() class Player(pygame.sprite.Sprite): def __init__(self, pos): super().__init__() self.image = pygame.image.load("handgun/move/survivor-move_handgun_0.png").convert_alpha() self.image = pygame.transform.rotozoom(self.image, 0, 0.35) self.base_player_image = self.image self.pos = pos self.base_player_rect = self.base_player_image.get_rect(center = pos) self.rect = self.base_player_rect.copy() self.player_speed = 10 # was 4 self.shoot = False self.shoot_cooldown = 0 def player_turning(self): self.mouse_coords = pygame.mouse.get_pos() self.x_change_mouse_player = (self.mouse_coords[0] - (WIDTH // 2)) self.y_change_mouse_player = (self.mouse_coords[1] - (HEIGHT // 2)) self.angle = int(math.degrees(math.atan2(self.y_change_mouse_player, self.x_change_mouse_player))) self.angle = (self.angle) % 360 self.image = pygame.transform.rotate(self.base_player_image, -self.angle) self.rect = self.image.get_rect(center=self.base_player_rect.center) def player_input(self): self.velocity_x = 0 self.velocity_y = 0 keys = pygame.key.get_pressed() if keys[pygame.K_w]: self.velocity_y = -self.player_speed if keys[pygame.K_s]: self.velocity_y = self.player_speed if keys[pygame.K_d]: self.velocity_x = self.player_speed if keys[pygame.K_a]: self.velocity_x = -self.player_speed if self.velocity_x != 0 and self.velocity_y != 0: # moving diagonally self.velocity_x /= math.sqrt(2) self.velocity_y /= math.sqrt(2) if keys[pygame.K_SPACE]: self.shoot = True self.is_shooting() else: self.shoot = False if event.type == pygame.KEYUP: if event.key == pygame.K_SPACE: self.shoot = False def move(self): self.base_player_rect.centerx += self.velocity_x self.base_player_rect.centery += self.velocity_y self.rect.center = self.base_player_rect.center def is_shooting(self): if self.shoot_cooldown == 0 and self.shoot: self.bullet = Bullet(self.base_player_rect.centerx, self.base_player_rect.centery, self.angle) self.shoot_cooldown = 20 bullet_group.add(self.bullet) all_sprites_group.add(self.bullet) def update(self): self.player_turning() self.player_input() self.move() if self.shoot_cooldown > 0: self.shoot_cooldown -= 1 class Bullet(pygame.sprite.Sprite): def __init__(self, x, y, angle): super().__init__() self.image = bullet_img self.image = pygame.transform.rotozoom(self.image, 0, 0.1) self.image.set_colorkey((0,0,0)) self.rect = self.image.get_rect() self.rect.center = (x, y) self.x = x self.y = y self.speed = 10 self.angle = angle self.x_vel = math.cos(self.angle * (2*math.pi/360)) * self.speed self.y_vel = math.sin(self.angle * (2*math.pi/360)) * self.speed self.bullet_lifetime = 750 self.spawn_time = pygame.time.get_ticks() def bullet_movement(self): self.x += self.x_vel self.y += self.y_vel self.rect.x = int(self.x) self.rect.y = int(self.y) if pygame.time.get_ticks() - self.spawn_time > self.bullet_lifetime: self.kill() def update(self): self.bullet_movement() class Camera(pygame.sprite.Group): def __init__(self): super().__init__() self.offset = pygame.math.Vector2() self.floor_rect = background.get_rect(topleft = (0,0)) def custom_draw(self): self.offset.x = player.rect.centerx - (WIDTH // 2) self.offset.y = player.rect.centery - (HEIGHT // 2) #draw the floor floor_offset_pos = self.floor_rect.topleft - self.offset screen.blit(background, floor_offset_pos) for sprite in all_sprites_group: offset_pos = sprite.rect.topleft - self.offset screen.blit(sprite.image, offset_pos) # Groups all_sprites_group = pygame.sprite.Group() player = Player((900,900)) all_sprites_group.add(player) bullet_group = pygame.sprite.Group() camera = Camera() while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() screen.blit(plain_bg, (0,0)) camera.custom_draw() all_sprites_group.update() pygame.display.update() clock.tick(FPS)
Actually, there is no problem at all. It is just an optical illusion. The projectile does not move relative to the player, but relative to the camera. The player is always in the center of the screen, because the player doesn't move, but the camera does. When the camera moves, all objects move with the camera. For example, if you shoot a bullet to the right and move the player up, it will look like the bullet is moving diagonally to the right and down. To the right because it changes position, to the right and down because the player moves upwards. To illustrate this, I reduced the speed of the player (self.player_speed = 2) and the speed of the bullet (self.speed = 4) and drew the scene on a checkered background: if event.type == pygame.KEYUP: only makes sens in the event loop, but not in player_input. Shooting only one bullet at once just needs another condition (and not self.shoot): if keys[pygame.K_SPACE] and not self.shoot: self.shoot = True self.is_shooting() else: self.shoot = False
How do i make my sprite shoot from the middle of the rectangle?
import pygame import math #initialise pygame pygame.init() #game window WINDOW_WIDTH = 1200 WINDOW_HEIGHT = 750 #create game window win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption('Castle Defender') clock = pygame.time.Clock() FPS = 60 #load images background_img = pygame.image.load('Animations/BG.png').convert_alpha() background = pygame.transform.scale(background_img,(1200,750)) castle_img = pygame.image.load('Animations/Castle.png').convert_alpha() bullet_img = pygame.image.load('Animations/SmallBullet.png').convert_alpha() b_w = bullet_img.get_width() b_h = bullet_img.get_height() bullet_img = pygame.transform.scale(bullet_img, (15,15)) WHITE =(255,255,255) #Castle class class Castle(): def __init__(self, image, x, y, scale): self.health = 1000 self.max_health = self.health self.fired = False width = image.get_width() height = image.get_height() self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale))) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def shoot(self): pos = pygame.mouse.get_pos() x_dist = pos[0] - self.rect.midright[0] y_dist = -(pos[1] - self.rect.midtop[1]) self.angle = math.degrees(math.atan2(y_dist, x_dist)) #mouseclick if pygame.mouse.get_pressed()[0] and self.fired == False: self.fired = True bullet = Bullet(bullet_img, self.rect.right, self.rect.top, self.angle) bullet_group.add(bullet) #reset mouseclick if pygame.mouse.get_pressed()[0] == False: self.fired = False #Method def draw(self): self.image = self.image win.blit(self.image, self.rect) class Bullet(pygame.sprite.Sprite): def __init__(self, image, x, y, angle): pygame.sprite.Sprite.__init__(self) self.image = image self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.angle = math.radians(angle) #angle to radians self.speed = 10 # Speed !!! self.dx = math.cos(self.angle) * self.speed #caculate speed of x self.dy = -(math.sin(self.angle) * self.speed) # caculate speed of y def update(self): #check if bullet has gone off the screen if self.rect.right < 0 or self.rect.left > WINDOW_WIDTH or self.rect.bottom < 0 or self.rect.top > WINDOW_HEIGHT: self.kill() #move bullet self.rect.x += self.dx self.rect.y += self.dy castle = Castle(castle_img, WINDOW_WIDTH - 1350, WINDOW_HEIGHT - 400, 0.7) bullet_group = pygame.sprite.Group() run = True while run: clock.tick(FPS) win.blit(background, (0, 0)) castle.draw() castle.shoot() #bullet drawing bullet_group.update() bullet_group.draw(win) print(len(bullet_group)) #event handler for event in pygame.event.get(): if event.type == pygame.QUIT: run = False #update display window pygame.display.update() pygame.quit() import pygame import math #initialise pygame pygame.init() #game window WINDOW_WIDTH = 1200 WINDOW_HEIGHT = 750 #create game window win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption('Castle Defender') clock = pygame.time.Clock() FPS = 60 #load images background_img = pygame.image.load('Animations/BG.png').convert_alpha() background = pygame.transform.scale(background_img,(1200,750)) castle_img = pygame.image.load('Animations/Castle.png').convert_alpha() bullet_img = pygame.image.load('Animations/SmallBullet.png').convert_alpha() b_w = bullet_img.get_width() b_h = bullet_img.get_height() bullet_img = pygame.transform.scale(bullet_img, (15,15)) WHITE =(255,255,255) #Castle class class Castle(): def __init__(self, image, x, y, scale): self.health = 1000 self.max_health = self.health width = image.get_width() height = image.get_height() self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale))) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def shoot(self): pos = pygame.mouse.get_pos() x_dist = pos[0] - self.rect.midleft[0] y_dist = -(pos[1] - self.rect.midleft[1]) self.angle = math.degrees(math.atan2(y_dist, x_dist)) #mouseclick if pygame.mouse.get_pressed()[0] and self.fired == False: self.fired = True bullet = Bullet(bullet_img, self.rect.right[0], self.rect.right[1], self.angle) bullet_group.add(bullet) #reset mouseclick if pygame.mouse.get_pressed()[0] == False: self.fired = False #Method def draw(self): self.image = self.image win.blit(self.image, self.rect) class Bullet(pygame.sprite.Sprite): def __init__(self, image, x, y, angle): pygame.sprite.Sprite.__init__(self) self.image = image self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.angle = math.radians(angle) self.speed = 10 self.dx = math.cos(self.angle) * self.speed self.dy = -(math.sin(self.angle) * self.speed) def update(self): #check if bullet has gone off the screen if self.rect.right < 0 or self.rect.left > SCREEN_WIDTH or self.rect.bottom < 0 or self.rect.top > SCREEN_HEIGHT: self.kill() #move bullet self.rect.x += self.dx self.rect.y += self.dy castle = Castle(castle_img, WINDOW_WIDTH - 1350, WINDOW_HEIGHT - 400, 0.7) bullet_group = pygame.sprite.Group() run = True while run: clock.tick(FPS) win.blit(background, (0, 0)) castle.draw() castle.shoot() #bullet drawing bullet_group.update() bullet_group.draw(win) print(len(bullet_group)) #event handler for event in pygame.event.get(): if event.type == pygame.QUIT: run = False #update display window pygame.display.update() pygame.quit() import pygame import math #initialise pygame pygame.init() #game window WINDOW_WIDTH = 1200 WINDOW_HEIGHT = 750 #create game window win = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption('Castle Defender') clock = pygame.time.Clock() FPS = 60 #load images background_img = pygame.image.load('Animations/BG.png').convert_alpha() background = pygame.transform.scale(background_img,(1200,750)) castle_img = pygame.image.load('Animations/Castle.png').convert_alpha() bullet_img = pygame.image.load('Animations/SmallBullet.png').convert_alpha() b_w = bullet_img.get_width() b_h = bullet_img.get_height() bullet_img = pygame.transform.scale(bullet_img, (int(b_w * 0.075), int(b_h * 0.075))) WHITE =(255,255,255) #Castle class class Castle(): def __init__(self, image, x, y, scale): self.health = 1000 self.max_health = self.health width = image.get_width() height = image.get_height() self.image = pygame.transform.scale(image, (int(width * scale), int(height * scale))) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y def shoot(self): pos = pygame.mouse.get_pos() x_dist = pos[0] - self.rect.midleft[0] y_dist = -(pos[1] - self.rect.midleft[1]) self.angle = math.degrees(math.atan2(y_dist, x_dist)) #mouseclick if pygame.mouse.get_pressed()[0] and self.fired == False: self.fired = True bullet = Bullet(bullet_img, self.rect.right[0], self.rect.right[1], self.angle) bullet_group.add(bullet) #reset mouseclick if pygame.mouse.get_pressed()[0] == False: self.fired = False #Method def draw(self): self.image = self.image win.blit(self.image, self.rect) class Bullet(pygame.sprite.Sprite): def __init__(self, image, x, y, angle): pygame.sprite.Sprite.__init__(self) self.image = image self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y self.angle = math.radians(angle) self.speed = 10 self.dx = math.cos(self.angle) * self.speed self.dy = -(math.sin(self.angle) * self.speed) def update(self): #check if bullet has gone off the screen if self.rect.right < 0 or self.rect.left > SCREEN_WIDTH or self.rect.bottom < 0 or self.rect.top > SCREEN_HEIGHT: self.kill() #move bullet self.rect.x += self.dx self.rect.y += self.dy castle = Castle(castle_img, WINDOW_WIDTH - 1350, WINDOW_HEIGHT - 400, 0.7) bullet_group = pygame.sprite.Group() run = True while run: clock.tick(FPS) win.blit(background, (0, 0)) castle.draw() castle.shoot() #bullet drawing bullet_group.update() bullet_group.draw(win) print(len(bullet_group)) #event handler for event in pygame.event.get(): if event.type == pygame.QUIT: run = False #update display window pygame.display.update() pygame.quit() So my code works without producing an error but when i shoot my bullet it comes out of the topright of the rectangle for my castle whereas i want it to be near the middle as for my image it is just shooting from the middle of nowhere as my image is not a square.
The starting position of the bullet should be the center of the rectangle: bullet = Bullet(bullet_img, self.rect.right, self.rect.top, self.angle) bullet = Bullet(bullet_img, self.rect.centerx, self.rect.centery, self.angle) Set the center position of the bullet rectangle instead of the top left position: class Bullet(pygame.sprite.Sprite): def __init__(self, image, x, y, angle): pygame.sprite.Sprite.__init__(self) self.image = image self.rect = self.image.get_rect() self.rect.centerx = x # <--- self.rect.centery = y # <---
add() argument after * must be an iterable, not int [duplicate]
Hello I am new to pygame and I am trying to write a shmup game. However I am always having this error: TypeError: add() argument after * must be an iterable, not int self.add(*group) This is the traceback of the error: File "C:/Users/Pygame/game.py", line 195, in player.shoot() File "C:/Users/Pygame/game.py", line 78, in shoot bullet = Bullets(self.rect.center,self.angle) File "C:/Users/Pygame/game.py", line 124, in init super(Bullets,self).init(pos,angle) This is the code I have written so far, it works well however when the user wants to shoot the error is being raised. import os import pygame import random import math WIDTH = 480 HEIGHT = 600 FPS = 60 #colors: WHITE = (255,255,255) BLACK = (0,0,0) GREEN = (0,250,0) RED = (255,0,0) BLUE = (0,0,255) YELLOW = (255,255,0) #setup assets game_folder = os.path.dirname("C:/Users/PygameP/") img_folder = os.path.join(game_folder,"img") #intialise pygame pygame.init() pygame.mixer.init() screen = pygame.display.set_mode((WIDTH,HEIGHT)) clock = pygame.time.Clock() class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((50,40)) self.image.fill(GREEN) self.rect = self.image.get_rect() self.rect.centerx = WIDTH/2 self.rect.bottom = HEIGHT-10 #controls the speed self.angle = 0 self.orig_image = self.image #self.rect = self.image.get_rect(center=pos) def update(self): keystate = pygame.key.get_pressed() if keystate[pygame.K_LEFT]: self.angle -= 5 self.rotate() if keystate[pygame.K_RIGHT]: self.angle += 5 self.rotate() def rotate(self): self.image = pygame.transform.rotozoom(self.orig_image, self.angle, 1) self.rect = self.image.get_rect(center=self.rect.center) def shoot(self): bullet = Bullets(self.rect.center,self.angle) all_sprites.add(bullet) bullets.add(bullet) class Mob(pygame.sprite.Sprite): def __init__(self): super(Mob,self).__init__() self.image = pygame.Surface((30,40)) self.image = meteor_img self.image = pygame.transform.scale(meteor_img,(50,38)) self.image.set_colorkey(BLACK) self.rect = self.image.get_rect() self.radius = int(self.rect.width/2) self.rect.x = random.randrange(0,WIDTH - self.rect.width) self.rect.y = random.randrange(-100,-40) self.speedy = random.randrange(1,8) #updating the position of the sprite def update(self): self.rect.y += self.speedy if self.rect.top > HEIGHT + 10: self.rect.x = random.randrange(0,WIDTH - self.rect.width) self.rect.y = random.randrange(-100,-40) self.speedy = random.randrange(1,8) class Bullets(pygame.sprite.Sprite): def __init__(self,pos,angle): super(Bullets,self).__init__(pos,angle) # Rotate the image. self.image = pygame.Surface((10,20)) self.image = bullet_img self.image = pygame.transform.scale(bullet_img,(50,38)) self.image = pygame.transform.rotate(bullet_img, angle) self.rect = self.image.get_rect() speed = 5 self.velocity_x = math.cos(math.radians(-angle))*speed self.velocity_y = math.sin(math.radians(-angle))*speed #store the actual position self.pos = list(pos) def update(self): self.pos[0] += self.velocity_x self.pos[1] += self.velocity_y self.rect.center = self.pos if self.rect.bottom <0: self.kill() #load all game graphics background = pygame.image.load(os.path.join(img_folder,"background.png")).convert() background_rect = background.get_rect() player_img = pygame.image.load(os.path.join(img_folder,"arrow.png")).convert() bullet_img = pygame.image.load(os.path.join(img_folder,"bullet.png")).convert() meteor_img = pygame.image.load(os.path.join(img_folder,"m.png")).convert() #creating a group to store sprites to make it easier to deal with them #every sprite we make goes to this group all_sprites = pygame.sprite.Group() mobs = pygame.sprite.Group() bullets = pygame.sprite.Group() player = Player() all_sprites.add(player) for i in range(8): m = Mob() all_sprites.add(m) mobs.add(m) running = True while running: clock.tick(FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: player.shoot() #Update all_sprites.update() #checking if a bullet hits a mob hits = pygame.sprite.groupcollide(mobs,bullets,True,True) for hit in hits: m = Mob() all_sprites.add(m) mobs.add(m) hits = pygame.sprite.spritecollide(player,mobs, False,pygame.sprite.collide_circle) #drawing the new sprites here screen.fill(BLACK) #show the background image screen.blit(background,background_rect) all_sprites.draw(screen) pygame.display.flip() pygame.quit() Any comments?
You're passing the pos and the angle to the __init__ method of pygame.sprite.Sprite here, super(Bullets,self).__init__(pos,angle) but you can only pass sprite groups to which this sprite instance will be added. So just remove those arguments: super(Bullets,self).__init__()
How do I make my player(ship) rotate when I press the right or left keys?
I am trying to make an asteroid game and was wondering how to rotate the player clock wise or counter clock wise when the right or left keys have been pressed, and then when the up key is pressed the player should move forward. class Player(pygame.sprite.Sprite): def __init__(self): pygame.sprite.Sprite.__init__(self) self.image = pygame.transform.scale(player_img, (50, 38)) self.image.set_colorkey(BLACK) self.rect = self.image.get_rect() self.radius = 20 # pygame.draw.circle(self.image, RED, self.rect.center, self.radius) self.rect.centerx = WIDTH / 2 self.rect.bottom = HEIGHT - 10 self.speedx = 0 self.speedy = 0 self.shield = 100 self.shoot_delay = 250 self.last_shot = pygame.time.get_ticks() self.lives = 3 def update(self): self.speedx = 0 keystate = pygame.key.get_pressed() if keystate[pygame.K_LEFT]: self.speedx = -8 if keystate[pygame.K_RIGHT]: self.speedx = 8 if keystate[pygame.K_DOWN]: self.speedy = 8 if keystate[pygame.K_UP]: self.speedy = -8 if keystate[pygame.K_SPACE]: self.shoot() self.rect.x += self.speedx self.rect.y += self.speedy if self.rect.right > WIDTH: self.rect.right = WIDTH if self.rect.left < 0: self.rect.left = 0 def shoot(self): now = pygame.time.get_ticks() if now - self.last_shot > self.shoot_delay: self.last_shot = now bullet = Bullet(self.rect.centerx, self.rect.top) all_sprites.add(bullet) bullets.add(bullet) def hide(self): # hide player temporarily self.hidden = True self.hide_timer = pygame.time.get_ticks() self.rect.center = (WIDTH / 2, HEIGHT + 200)````
You can find below a working example (just rename the loaded image), I've kept only the essential code for movement and rotation. import sys import math import pygame class Player(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.player_img = pygame.image.load("yourimage.png").convert() self.image = self.player_img self.rect = self.image.get_rect() self.rect.move_ip(x, y) self.current_direction = 0 #0 degree == up self.speed = 10 def update(self): self.speedx = 0 keystate = pygame.key.get_pressed() prev_center = self.rect.center if keystate[pygame.K_LEFT]: self.current_direction += 10 if keystate[pygame.K_RIGHT]: self.current_direction -= 10 if keystate[pygame.K_DOWN]: self.rect.x += self.speed * math.sin(math.radians(self.current_direction)) self.rect.y += self.speed * math.cos(math.radians(self.current_direction)) if keystate[pygame.K_UP]: self.rect.x -= self.speed * math.sin(math.radians(self.current_direction)) self.rect.y -= self.speed * math.cos(math.radians(self.current_direction)) if keystate[pygame.K_LEFT] or keystate[pygame.K_RIGHT]: self.image = pygame.transform.rotate(self.player_img, self.current_direction) self.rect = self.image.get_rect() self.rect.center = prev_center pygame.init() screen = pygame.display.set_mode((500, 500)) player = Player(200, 200) clock = pygame.time.Clock() while True: screen.fill((0, 0, 0), player.rect) for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() player.update() screen.blit(player.image, player.rect) pygame.display.update() clock.tick(50) Since you want rotation, you do not need to assing speed directly to x and y but you need to calculate it according to the direction the player is facing. The basic idea is to use transform.rotate. Keep track of the rotation angle (I called it current_direction), add / subcract a fixed amount (the rotation speed, if you wish) to this angle when LEFT or RIGTH keys are pressed, and then rotate the original image. Since rotation scales the image, I also keep track of the center of the rect, save the new rect from the iamge and and reassing the previous center to the rect.center after rotation, so that the image remains centered on rotation. When UP or DOWN keys are pressed, you need to decompose the velocity on x and y axes using trigonometry and move the rect attribute coordinates.
Bullet not colliding with enemy Pygame (Python 3)
I want to make a mega man similar game where you jump around and shooting stuff. But I've noticed there's something wrong with the collision, I have a video below: https://youtu.be/p2VCtbBkefo I'm planning to make this project open source, so anybody can customize it. Please don't steal this code, but you may use chunks of it to help you with something. because I haven't put it on GitHub publicly yet. main.py: import pygame as pg from player import * from settings import * from levels import * from block import * from enemy import * class Game: def __init__(self): pg.init() pg.mixer.init() self.screen = pg.display.set_mode((width, height)) pg.display.set_caption("wait until realesed.") self.clock = pg.time.Clock() self.enemiesList = [] self.running = True self.shootRight = True def loadLevel(self, level, enemies, group, group2, group3): for y in range(0, len(level)): for x in range(0, len(level[y])): if (level[y][x] == 1): blockList.append(Block(x*32, y*32)) group.add(Block(x*32, y*32)) group2.add(Block(x*32, y*32)) for amount in range(0, enemies): group2.add(FlyingEnemy(self)) group3.add(FlyingEnemy(self)) self.enemies.add(FlyingEnemy(self)) self.enemiesList.append(FlyingEnemy(self)) def new(self): self.platforms = pg.sprite.Group() self.all_sprites = pg.sprite.Group() self.enemies = pg.sprite.Group() self.bullets = pg.sprite.Group() self.player = Player() self.loadLevel(level1["platform"], level1["enemies"], self.platforms, self.all_sprites, self.enemies) self.all_sprites.add(self.player) self.run() def shoot(self): if self.shootRight: self.bullet = Bullet(self.player.rect.centerx, self.player.rect.centery) self.bullet.speed = 10 self.all_sprites.add(self.bullet) self.bullets.add(self.bullet) print(self.bullet) elif self.shootRight == False: self.bullet = Bullet(self.player.rect.centerx, self.player.rect.centery) self.bullet.speed = -10 self.all_sprites.add(self.bullet) self.bullets.add(self.bullet) print(self.bullet) def run(self): self.playing = True while self.playing: self.clock.tick(FPS) self.events() self.update() self.draw() def update(self): self.all_sprites.update() self.enemy_hits = pg.sprite.spritecollide(self.player, self.enemies, False) #print(enemy_hits) if self.enemy_hits: pass #print("hit") self.bullet_hits = pg.sprite.groupcollide(self.enemies, self.bullets, True, True) if self.bullet_hits: print(self.bullet_hits) pygame.quit() hits = pg.sprite.spritecollide(self.player, self.platforms, False) if hits: self.player.pos.y = hits[0].rect.top + 1 self.player.vel.y = 0 def events(self): for event in pg.event.get(): if event.type == pg.QUIT: if self.playing: self.playing = False self.running = false if event.type == pg.KEYDOWN: if event.key == pg.K_UP: self.player.jump() if event.key == pg.K_SPACE: self.shoot() if event.key == pg.K_RIGHT: self.shootRight = True if event.key == pg.K_LEFT: self.shootRight = False def draw(self): self.screen.fill((255, 255, 255)) self.all_sprites.draw(self.screen) 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() """width = 800 height = 600 FPS = 60 pg.init() pg.mixer.init() screen = pg.display.set_mode((width, height)) pg.display.set_caption("doom room") clock = pg.time.Clock() running = True while running: for event in pg.event.get(): clock.tick(FPS) if event.type == pg.QUIT: running = false screen.fill((255, 255, 255)) pg.display.flip() pg.quit()""" import pygame class Bullet(pygame.sprite.Sprite): def __init__(self, x, y): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface((20, 10)) self.image.fill((240, 43, 12)) self.rect = self.image.get_rect() self.rect.bottom = y self.rect.centerx = x self.speed = -10 def update(self): self.rect.x += self.speed if self.rect.bottom < 0: self.kill() player.py import pygame as pg from settings import * from laser import * vec = pg.math.Vector2 class Player(pg.sprite.Sprite): def __init__(self): pg.sprite.Sprite.__init__(self) self.image = pg.Surface((40, 40)) self.image.fill((80, 123, 255)) self.rect = self.image.get_rect() self.rect.center = (width / 2, height / 2) self.pos = vec(width / 2, height / 2) self.vel = vec(0, 0) self.acc = vec(0, 0) #self.vx = 0 #self.vy = 0 def jump(self): self.vel.y = -15 def update(self): self.acc = vec(0, player_gravity) keys = pg.key.get_pressed() if keys[pg.K_LEFT]: self.acc.x = -player_acc if keys[pg.K_RIGHT]: self.acc.x = player_acc self.acc.x += self.vel.x * player_friction self.vel += self.acc self.pos += self.vel + 0.5 * self.acc if self.pos.x > width: self.pos.x = 0 if self.pos.x < 0: self.pos.x = width if self.pos.y <= 0: self.pos.y += 15 self.rect.midbottom = self.pos enemy.py import pygame as pg from random import * from settings import * class FlyingEnemy(pg.sprite.Sprite): def __init__(self, game): pg.sprite.Sprite.__init__(self) self.game = game self.image = pg.Surface((45, 45)) self.image.fill((20, 203, 50)) self.rect = self.image.get_rect() self.rect.centerx = choice([-100, width + 100]) self.vx = randrange(4, 7) if self.rect.centerx > width: self.vx *= -1 self.rect.y = height / 4 self.rect.x = 0 self.vy = 0 self.dy = 0.5 def update(self): if self.rect.x > width: self.rect.x = 0 if self.rect.x < 0: self.rect.x = width self.rect.x += self.vx self.vy += self.dy if self.vy > 3 or self.vy < -3: self.dy *= -1 center = self.rect.center if self.dy < 0: pass #print("bobbed up") else: pass #print("bobbed down") settings.py import pygame blockList = [] player_acc = 1.0 player_friction = -0.12 player_gravity = 0.5 bullets = pygame.sprite.Group() true = True false = False width = 800 height = 600 FPS = 60 levels.py level1 = { "platform": [ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1], [1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0], [0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0], [0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0], [0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0], [0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], ], "enemies": 5 } block.py import pygame as pg class Block(pg.sprite.Sprite): def __init__(self, x, y): pg.sprite.Sprite.__init__(self) self.image = pg.Surface((32, 32)) self.image.fill((0, 0, 0)) self.rect = self.image.get_rect() self.rect.x = x self.rect.y = y Thanks all help is appreciated.
This part of the loadLevel method causes the problem: for amount in range(0, enemies): group2.add(FlyingEnemy(self)) group3.add(FlyingEnemy(self)) self.enemies.add(FlyingEnemy(self)) self.enemiesList.append(FlyingEnemy(self)) You're adding 4 different FlyingEnemy objects to these groups and the list (btw, the list is useless), so the sprites in the self.all_sprites group and in the self.enemies group are not the same. Since you're only updating the all_sprites and not the enemies, the sprites in the enemies group, which are used for the collision detection, stay at the left screen edge all the time and are also invisible, because you don't draw this group. To solve the problem, create one instance and add this instance to the two groups: for amount in range(0, enemies): enemy = FlyingEnemy(self) self.enemies.add(enemy) self.all_sprites.add(enemy) I found the bug by printing the rect of one enemy sprite in the self.enemies group. Then I checked the update method of this sprite, but it looked correct, so I went to the instantiation part in loadLevel and noticed the mistake.