stuck at sprite movement - python

lately I've been working on a little project of mine.
I have a background in which I spawn alot of cars.
I want to have those cars move along a path i define myself. I've gotten to the point where one of my cars moves to the (0,0) position when i call my move method, also, I'm not sure how to have a smooth animation along the path, I don't want the car to suddenly appear at the last waypoint define instantly.
Here is my code:
import assets
import pygame
##this class spawns
class bus(pygame.sprite.Sprite):
def __init__(self):
super(bus,self).__init__()
self.image = pygame.Surface((assets.bus_width,assets.bus_height))
self.rect = self.image.get_rect()
def set_position(self,x,y):
self.rect.x = x
self.rect.y = y
def set_image(self, filename = None):
if filename != None:
self.image = pygame.image.load(filename).convert()
self.rect = self.image.get_rect()
def rotate(self,angle):
self.image = pygame.transform.rotate(self.image,angle)
self.rect = self.image.get_rect()
class car(pygame.sprite.Sprite):
def __init__(self):
super(car,self).__init__()
self.image = pygame.Surface((assets.car_width,assets.car_height))
self.rect = self.image.get_rect()
self.speed = 2
def set_position(self,x,y):
self.rect.x = x
self.rect.y = y
def get_x_position(self):
return self.rect.x
def get_y_position(self):
return self.rect.y
def set_image(self, filename = None):
if filename != None:
self.image = pygame.image.load(filename).convert()
self.rect = self.image.get_rect()
def rotate(self,angle):
self.image = pygame.transform.rotate(self.image,angle)
self.rect = self.image.get_rect()
#not sure what to do here
def move_position(self,x,y):
self.rect.x +=
self.rect.y +=
self.rect = self.image.get_rect()
class WayPoint:
def __init__(self, x, y):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
class WayPointsList:
def __init__(self):
self.wayPoints = []
def add_wayPoint(self, x, y):
self.wayPoints.append(WayPoint(x,y))
def __len__(self):
return len(self.wayPoints)
def get_wayPoint(self, i):
return [self.wayPoints[i].getX(), self.wayPoints[i].getY()]
if __name__ == '__main__':
pygame.init()
window_size = window_width, window_height = assets.screen_width, assets.screen_height
window = pygame.display.set_mode(window_size, pygame.RESIZABLE)
pygame.display.set_caption(assets.caption)
window.fill(assets.white)
clock = pygame.time.Clock()
car_group = pygame.sprite.Group()
#mainloop
running = True
while running:
#loading background
bkg = pygame.image.load(assets.background)
#event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
car110 = car()
car110.set_image(assets.furore)
car110.rotate(180)
car110.set_position(0,273)
car_group.add(car110)
elif event.key == pygame.K_2:
car109 = car()
car109.set_image(assets.hachura)
car109.rotate(180)
car109.set_position(0,306)
car_group.add(car109)
#i want to move this car along some waypoints I've defined in my head
#like so:
#lane = WayPointsList()
#lane.add_wayPoint(50, 250)
#lane.add_wayPoint(250, 350)
#after this i want to move my image along these waypoints I've defined
elif event.key == pygame.K_3:
car108=car()
car108.set_image(assets.jefferson)
car108.rotate(180)
car108.set_position(0,343)
car_group.add(car108)
elif event.key == pygame.K_4:
car107=car()
car107.set_image(assets.michelli)
car107.rotate(270)
car107.set_position(410,550)
car_group.add(car107)
elif event.key == pygame.K_5:
car106=car()
car106.set_image(assets.traceAM)
car106.rotate(270)
car106.set_position(460,550)
car_group.add(car106)
elif event.key == pygame.K_6:
car105=car()
car105.set_image(assets.traceAM)
car105.set_position(750,300)
car_group.add(car105)
elif event.key == pygame.K_7:
car104=car()
car104.set_image(assets.rumbler)
car104.set_position(750,265)
car_group.add(car104)
elif event.key == pygame.K_8:
car103=car()
car103.set_image(assets.rumbler)
car103.rotate(90)
car103.set_position(294,0)
car_group.add(car103)
elif event.key == pygame.K_9:
car102=car()
car102.set_image(assets.rumbler)
car102.rotate(90)
car102.set_position(337,0)
car_group.add(car102)
elif event.key == pygame.K_0:
car101=car()
car101.set_image(assets.rumbler)
car101.rotate(90)
car101.set_position(380,0)
car_group.add(car101)
elif event.key == pygame.K_b:
car201=bus()
car201.set_image(assets.bus)
car201.set_position(700,229)
car_group.add(car201)
elif event.key ==pygame.K_x:
car_group.remove(car101,car102,car103,car104,car105,car106,car107,car108,car109,car110,car201)
car_group.update()
window.fill(assets.white)
window.blit(bkg,(0,0))
car_group.draw(window)
clock.tick(assets.FPS)
pygame.display.update()
pygame.quit()
If anyone could give me some pointers or tell me what I can do to fix it, I would really appreciate it!

In move_position don't use
self.rect = self.image.get_rect()
because image doesn't keep position and it has always (x,y) == (0,0)
In class create update() and run move_position() inside update() and car_group.update() will execute it in every loop.
I save angle in self.angle so I can use it to move in correct direction
radians_angle = math.radians(self.angle)
self.rect.x -= self.speed * math.cos(radians_angle)
self.rect.y -= self.speed * math.sin(radians_angle)
Example works without images so everyone can run it.
import pygame
import math
WHITE = (0,0,0)
##this class spawns
class bus(pygame.sprite.Sprite):
def __init__(self):
super(bus,self).__init__()
self.image = pygame.Surface((800, 600)).convert_alpha()
self.rect = self.image.get_rect()
self.angle = 0 # <-- default direction
def set_position(self,x,y):
self.rect.x = x
self.rect.y = y
def set_image(self, filename = None):
if filename != None:
self.image = pygame.Surface((20, 20)).convert_alpha()
self.image.fill((255,0,0))
self.rect = self.image.get_rect()
def rotate(self,angle):
self.angle = angle # <-- keep it to move it in correct direction
self.image = pygame.transform.rotate(self.image,angle).convert_alpha() # need alpha to correctly rotate
self.rect = self.image.get_rect()
class car(pygame.sprite.Sprite):
def __init__(self):
super(car,self).__init__()
self.image = pygame.Surface((20,20)).convert_alpha()
self.image.fill((255,0,0))
self.rect = self.image.get_rect()
self.speed = 2
self.angle = 0 # <-- default direction
def set_position(self,x,y):
self.rect.x = x
self.rect.y = y
def get_x_position(self):
return self.rect.x
def get_y_position(self):
return self.rect.y
def set_image(self, filename = None):
if filename != None:
self.image = pygame.Surface((20, 20)).convert_alpha() # need alpha to correctly rotate
self.image.fill((0,255,0))
self.rect = self.image.get_rect()
def rotate(self,angle):
self.angle = angle # <-- keep it to move it in correct direction
self.image = pygame.transform.rotate(self.image, angle).convert_alpha() # need alpha to correctly rotate
self.rect = self.image.get_rect()
#not sure what to do here
def move_position(self,x,y):
# use angle to calculate direction
radius_angle = math.radians(self.angle)
self.rect.x -= self.speed * math.cos(radius_angle)
self.rect.y -= self.speed * math.sin(radius_angle)
#print('move', self.angle, self.rect.x, self.rect.y)
#self.rect = self.image.get_rect() # <-- DON'T DO THIS
def update(self):
self.move_position(0,0)
class WayPoint:
def __init__(self, x, y):
self.x = x
self.y = y
def getX(self):
return self.x
def getY(self):
return self.y
class WayPointsList:
def __init__(self):
self.wayPoints = []
def add_wayPoint(self, x, y):
self.wayPoints.append(WayPoint(x,y))
def __len__(self):
return len(self.wayPoints)
def get_wayPoint(self, i):
return [self.wayPoints[i].getX(), self.wayPoints[i].getY()]
if __name__ == '__main__':
pygame.init()
window_size = window_width, window_height = 800, 600
window = pygame.display.set_mode(window_size, pygame.RESIZABLE)
window.fill(WHITE)
clock = pygame.time.Clock()
car_group = pygame.sprite.Group()
#mainloop
running = True
while running:
#loading background
bkg = pygame.Surface((800,600)).convert()
bkg.fill((0,0,255))
#event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
car110 = car()
#car110.set_image(assets.furore)
car110.rotate(180-45)
car110.set_position(0,273)
car_group.add(car110)
elif event.key == pygame.K_2:
car109 = car()
#car109.set_image(assets.hachura)
car109.rotate(180)
car109.set_position(0,306)
car_group.add(car109)
#i want to move this car along some waypoints I've defined in my head
#like so:
#lane = WayPointsList()
#lane.add_wayPoint(50, 250)
#lane.add_wayPoint(250, 350)
#after this i want to move my image along these waypoints I've defined
elif event.key == pygame.K_3:
car108=car()
#car108.set_image(assets.jefferson)
car108.rotate(180)
car108.set_position(0,343)
car_group.add(car108)
elif event.key == pygame.K_4:
car107=car()
#car107.set_image(assets.michelli)
car107.rotate(270)
car107.set_position(410,550)
car_group.add(car107)
elif event.key == pygame.K_5:
car106=car()
#car106.set_image(assets.traceAM)
car106.rotate(270)
car106.set_position(460,550)
car_group.add(car106)
elif event.key == pygame.K_6:
car105=car()
#car105.set_image(assets.traceAM)
car105.set_position(750,300)
car_group.add(car105)
elif event.key == pygame.K_7:
car104=car()
#car104.set_image(assets.rumbler)
car104.set_position(750,265)
car_group.add(car104)
elif event.key == pygame.K_8:
car103=car()
#car103.set_image(assets.rumbler)
car103.rotate(90)
car103.set_position(294,0)
car_group.add(car103)
elif event.key == pygame.K_9:
car102=car()
#car102.set_image(assets.rumbler)
car102.rotate(90)
car102.set_position(337,0)
car_group.add(car102)
elif event.key == pygame.K_0:
car101=car()
#car101.set_image(assets.rumbler)
car101.rotate(90)
car101.set_position(380,0)
car_group.add(car101)
elif event.key == pygame.K_b:
car201=bus()
#car201.set_image(assets.bus)
car201.set_position(700,229)
car_group.add(car201)
elif event.key ==pygame.K_x:
car_group.remove(car101,car102,car103,car104,car105,car106,car107,car108,car109,car110,car201)
car_group.update()
window.fill(WHITE)
window.blit(bkg,(0,0))
car_group.draw(window)
clock.tick(25)
pygame.display.update()
pygame.quit()

Related

How to adjust the direction of movement of bullet sprites?

In my program, when the keys are pressed, the image of the ship is flipped. I decided to bind the direction of the bullets to the flags of the ship's position. But I ran into the problem that all bullets take the direction of the ship when they are already fired. I need to keep the coordinate of the sprite when it is drawn.
import sys
import pygame
from settings import Settings
from rocket import Rocket
from bullet import Bullet
class Cosmos:
"""Главный класс игры Cosmos"""
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)
pygame.display.set_caption('Cosmos')
self.fon_image = pygame.image.load('image/Fon.png')
self.fon = self.fon_image.get_rect()
self.settings = Settings()
self.rocket = Rocket(self.screen, self.settings)
self.bullets = pygame.sprite.Group()
def key_event(self):
"""Обрабатывает нажатие клавиш"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
sys.exit()
elif event.key == pygame.K_d:
self.rocket.move_RIGHT = True
elif event.key == pygame.K_a:
self.rocket.move_LEFT = True
elif event.key == pygame.K_w:
self.rocket.move_UP = True
elif event.key == pygame.K_s:
self.rocket.move_DOWN = True
elif event.key == pygame.K_SPACE:
self.fire_bullet()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
self.rocket.move_RIGHT = False
elif event.key == pygame.K_a:
self.rocket.move_LEFT = False
elif event.key == pygame.K_w:
self.rocket.move_UP = False
elif event.key == pygame.K_s:
self.rocket.move_DOWN = False
def fire_bullet(self):
"""Создание нового снаряда и включение его в группу"""
new_bullet = Bullet(self.screen, self.settings, self.rocket)
self.bullets.add(new_bullet)
def run_game(self):
"""Обновляет события игры"""
while True:
self.screen.blit(self.fon_image, self.fon)
self.key_event()
self.rocket.update_rocket()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self.bullets.update(bullet)
self.rocket.draw_rocket()
pygame.display.flip()
game = Cosmos()
game.run_game()
from pygame.sprite import Sprite
class Bullet(Sprite):
"""Класс для управления снарядами, выпущенными кораблем"""
def __init__(self, screen, settings, rocket):
super().__init__()
self.screen = screen
self.settings = settings
self.rocket = rocket
self.color = self.settings.bullets_color
self.rect = pygame.Rect(0, 0, self.settings.bullets_width, self.settings.bullets_height)
self.rect.midtop = rocket.rect.midtop
self.y = float(self.rect.y)
self.x = float(self.rect.x)
def update(self, bullet):
"""Перемещение снаряда"""
if self.rocket.image == self.rocket.image_right:
bullet.x += 2
if self.rocket.image == self.rocket.image_left:
bullet.x -= 2
if self.rocket.image == self.rocket.image_up:
bullet.y -= 2
if self.rocket.image == self.rocket.image_down:
bullet.y += 2
self.rect.x = self.x
self.rect.y = self.y
def draw_bullet(self):
"""Рисует снаряд"""
pygame.draw.rect(self.screen, self.color, self.rect)
import pygame
class Rocket:
"""Класс для управления кораблём"""
def __init__(self, screen, settings):
self.screen = screen
self.screen_rect = screen.get_rect()
self.settings = settings
self.image = pygame.image.load('image/pixil-frame-0.png')
self.rect = self.image.get_rect()
self.rect.center = self.screen_rect.center
self.x = float(self.rect.x)
self.y = float(self.rect.y)
self.move_RIGHT = False
self.move_LEFT = False
self.move_UP = False
self.move_DOWN = False
self.image_right = pygame.transform.rotate(self.image, -90)
self.image_left = pygame.transform.rotate(self.image, 90)
self.image_up = pygame.transform.rotate(self.image, 0)
self.image_down = pygame.transform.rotate(self.image, 180)
def update_rocket(self):
"""Флаги управления кораблём"""
if self.move_RIGHT and self.rect.right < self.screen_rect.right:
self.image = self.image_right
self.x += self.settings.rocket_speed
if self.move_LEFT and self.rect.left > self.screen_rect.left:
self.image = self.image_left
self.x -= self.settings.rocket_speed
if self.move_UP and self.rect.top > self.screen_rect.top:
self.image = self.image_up
self.y -= self.settings.rocket_speed
if self.move_DOWN and self.rect.bottom < self.screen_rect.bottom:
self.image = self.image_down
self.y += self.settings.rocket_speed
self.rect.x = self.x
self.rect.y = self.y
def draw_rocket(self):
"""Обновляет позицию корабля"""
self.screen.blit(self.image, self.rect)
The problem here is that in Bullet.update, you use the current image of the rocket to determine in which direction the bullet is going. This means that any change of this image results in a change of direction. Instead of doing this, you should save the current direction upon creating a new Bullet instance and then use this saved direction to determine the direction of the rocket.
A possible implementation:
class Bullet(Sprite):
"""Класс для управления снарядами, выпущенными кораблем"""
def __init__(self, screen, settings, rocket):
super().__init__()
self.screen = screen
self.settings = settings
self.rocket = rocket
self.color = self.settings.bullets_color
self.rect = pygame.Rect(0, 0, self.settings.bullets_width, self.settings.bullets_height)
self.rect.midtop = rocket.rect.midtop
self.y = float(self.rect.y)
self.x = float(self.rect.x)
if self.rocket.image == self.rocket.image_right:
self.direction = "right"
elif self.rocket.image == self.rocket.image_left:
self.direction = "left"
elif self.rocket.image == self.rocket.image_up:
self.direction = "up"
elif self.rocket.image == self.rocket.image_down:
self.direction = "down"
def update(self, bullet):
"""Перемещение снаряда"""
if self.direction == "right":
bullet.x += 2
if self.direction == "left":
bullet.x -= 2
if self.direction == "up":
bullet.y -= 2
if self.direction == "down":
bullet.y += 2
self.rect.x = self.x
self.rect.y = self.y
def draw_bullet(self):
"""Рисует снаряд"""
pygame.draw.rect(self.screen, self.color, self.rect)

I am having trouble coding my collision check function for my fps game. How can I write my collision function?

I am stuck on how to write my collision function in my player class. Also should I put my collision check function in my player class or should it be in my bullet class? I honestly don't know. I mean common sense says my bullet should have the collision check function in it, just because I want the top of my bullet checking if it hits a falling cement block sprite, but I don't know.... I would appreciate an answer on how to code my collision function. This would really help me out. My collision function is right below my shoot function in my player class.
My code:
import pygame
pygame.init()
#screen settings
WIDTH = 1000
HEIGHT = 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("AutoPilot")
screen.fill((255, 255, 255))
#fps
FPS = 120
clock = pygame.time.Clock()
#load images
bg = pygame.image.load('background/street.png').convert_alpha() # background
bullets = pygame.image.load('car/bullet.png').convert_alpha()
debris_img = pygame.image.load('debris/cement.png')
#define game variables
shoot = False
#player class
class Player(pygame.sprite.Sprite):
def __init__(self, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.bullet = pygame.image.load('car/bullet.png').convert_alpha()
self.bullet_list = []
self.speed = speed
#self.x = x
#self.y = y
self.moving = True
self.frame = 0
self.flip = False
self.direction = 0
#load car
self.images = []
img = pygame.image.load('car/car.png').convert_alpha()
img = pygame.transform.scale(img, (int(img.get_width()) * scale, (int(img.get_height()) * scale)))
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
self.update_time = pygame.time.get_ticks()
self.movingLeft = False
self.movingRight = False
self.rect.x = 465
self.rect.y = 325
#draw car to screen
def draw(self):
screen.blit(self.image, (self.rect.centerx, self.rect.centery))
#move car
def move(self):
#reset the movement variables
dx = 0
dy = 0
#moving variables
if self.movingLeft and self.rect.x > 33:
dx -= self.speed
self.flip = True
self.direction = -1
if self.movingRight and self.rect.x < 900:
dx += self.speed
self.flip = False
self.direction = 1
#update rectangle position
self.rect.x += dx
self.rect.y += dy
#shoot
def shoot(self):
bullet = Bullet(self.rect.centerx + 18, self.rect.y + 30, self.direction)
bullet_group.add(bullet)
#def collision(self):
#write code here
#bullet class
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, direction):
pygame.sprite.Sprite.__init__(self)
self.speed = 5
self.image = bullets
self.rect = self.image.get_rect()
self.rect.center = (x,y)
self.direction = direction
def update(self):
self.rect.centery -= self.speed
#check if bullet has gone off screen
if self.rect.top < 1:
self.kill()
#debris class
class Debris(pygame.sprite.Sprite):
def __init__(self, x, y, scale, speed):
pygame.sprite.Sprite.__init__(self)
self.scale = scale
self.x = x
self.y = y
self.speed = speed
self.vy = 0
self.on_ground = True
self.move = True
self.health = 4
self.max_health = self.health
self.alive = True
#load debris
self.image = debris_img
self.rect = self.image.get_rect()
self.rect.center = (x,y)
######################CAR/DEBRIS##########################
player = Player(1,5)
debris = Debris(300,15,1,5)
##########################################################
#groups
bullet_group = pygame.sprite.Group()
debris_group = pygame.sprite.Group()
debris_group.add(debris)
#game runs here
run = True
while run:
#draw street
screen.blit(bg, [0, 0])
#update groups
bullet_group.update()
bullet_group.draw(screen)
debris_group.update()
debris_group.draw(screen)
#draw car
player.draw()
player.move()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#check if key is down
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
run = False
if event.key == pygame.K_a:
player.movingLeft = True
if event.key == pygame.K_d:
player.movingRight = True
if event.key == pygame.K_SPACE:
player.shoot()
shoot = True
#check if key is up
if event.type == pygame.KEYUP:
if event.key == pygame.K_a:
player.movingLeft = False
if event.key == pygame.K_d:
player.movingRight = False
#update the display
pygame.display.update()
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
I suggest reading How do I detect collision in pygame?. Use pygame.sprite.spritecollide() for the collision detection. Set the dokill argument True. So the bullets gat automatically destroyed.
The following code is base on one of your previous questions: Check collision of bullet sprite hitting cement block sprite
class Car(pygame.sprite.Sprite):
# [...]
def collision(self, debris_group):
for debris in debris_group:
if pygame.sprite.spritecollide(debris, bullet_group, True):
debris.health -= 1
if debris.health <= 0:
debris.kill()

pygame making the sprite go upwards and downwards

I am trying to make the sprite move up and down by using the arrow keys but it schemes to only be moving slightly upwards and slightly downwards: there is a speed for the x and y axis and also a position. There are also two functions which are draw and update (which gets the new xpos and the new ypos). here is my code
import pygame
import random
import sys
pygame.init()
screen = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock() # A clock to limit the frame rate.
pygame.display.set_caption("this game")
class Background:
picture = pygame.image.load("C:/images/cliff.jpg").convert()
picture = pygame.transform.scale(picture, (1280, 720))
def __init__(self, x, y):
self.xpos = x
self.ypos = y
def draw(self):
screen.blit(self.picture, (self.xpos, self.ypos))
class player_first:
picture = pygame.image.load("C:/aliens/ezgif.com-crop.gif")
picture = pygame.transform.scale(picture, (200, 200))
def __init__(self, x, y):
self.xpos = x
self.ypos = y
self.speed_x = 0
self.speed_y = 0
self.rect = self.picture.get_rect()
def update(self):
self.xpos =+ self.speed_x
self.ypos =+ self.speed_y
def draw(self): #left right
#screen.blit(pygame.transform.flip(self.picture, True, False), self.rect)
screen.blit(self.picture, (self.xpos, self.ypos))
class Bullet_player_1(pygame.sprite.Sprite):
picture = pygame.image.load("C:/aliens/giphy.gif").convert_alpha()
picture = pygame.transform.scale(picture, (100, 100))
def __init__(self):
self.xpos = 360
self.ypos = 360
self.speed_x = 0
super().__init__()
self.rect = self.picture.get_rect()
def update(self):
self.xpos += self.speed_x
def draw(self):
screen.blit(self.picture, (self.xpos, self.ypos))
#self.screen.blit(pygame.transform.flip(self.picture, False, True), self.rect)
def is_collided_with(self, sprite):
return self.rect.colliderect(sprite.rect)
player_one_bullet_list = pygame.sprite.Group()
player_one = player_first(0, 0)
cliff = Background(0, 0)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
player_one.speed_y = -5
print("up")
elif event.key == pygame.K_s:
player_one.speed_y = 5
print("down")
elif event.key == pygame.K_SPACE:
bullet_player_one = Bullet_player_1
bullet_player_one.ypos = player_one.ypos
bullet_player_one.xpos = player_one.xpos
bullet_player_one.speed_x = 14
player_one_bullet_list.add(bullet_player_one)
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d and player_one.speed_x > 0:
player_one.speed_x = 0
elif event.key == pygame.K_a and player_one.speed_x < 0:
player_one.speed_x = 0
player_one.update()
cliff.draw()
player_one.draw()
player_one_bullet_list.update()
for bullet_player_one in player_one_bullet_list:
bullet_player_one.draw()
pygame.display.flip()
clock.tick(60)
You've written self.xpos =+ self.speed_x (which is interpret as self.xpos = +self.speed_x) instead of self.xpos += self.speed_x. So you're not adding the speed to the position, you're overwriting it.

How do I make an enemy follow the player in Pygame?

So, I'm a beginner to Python and Pygame and would like some help. I'm trying to make a game similar to Asteroids and I've made most of this program by looking around at other examples on the internet. However, I'm stuck on this problem: how do I get an enemy sprite to follow the player sprite? I've googled how to do so and tried implementing the same thing on my code but the sprite just stays in one place and doesn't follow the player. I've used the vector stuff to create the player sprite and I still barely understand how that works. I'm sort of on a tight schedule so I don't have time to thoroughly understand this stuff but I intend to later. Sorry if I haven't explained my code properly but I'm still trying to understand how Pygame works and most of this code is basically just copied.
import random, math, pygame, time, sys
from pygame.locals import *
from pygame.math import Vector2
######Setting up Variables
class settings:
fps = 30
windowwidth = 590
windowheight = 332
class ship:
HEALTH = 3
SPEED = 4
SIZE = 25
class colours:
black = (0, 0, 0)
white = (255, 255, 255)
###########################
######################################################################################
class Player(pygame.sprite.Sprite):
def __init__(self,image_file , pos=(0,0)):
super(Player, self).__init__()
self.image = pygame.image.load(image_file)
self.image = pygame.transform.scale(self.image, (25,25))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.position = Vector2(pos)
self.direction = Vector2(1, 0)
self.speed = 0
self.angle_speed = 0
self.angle = 0
def update(self):
if self.angle_speed != 0:
self.direction.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
self.image = pygame.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
self.position += self.direction * self.speed
self.rect.center = self.position
class Enemy(pygame.sprite.Sprite):
def __init__(self, image_file, pos=(0,0)):
super(Enemy, self).__init__()
self.image = pygame.image.load(image_file)
self.image = pygame.transform.scale(self.image, (25, 25))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
self.speed = 1
def move_towards_player(self, Player):
dx, dy = self.rect.x - Player.rect.x, self.rect.y - Player.rect.y
dist = math.hypot(dx, dy)
dx, dy = dx/dist, dy/dist
self.rect.x += dx * self.speed
self.rect.y += dy * self.speed
class Background(pygame.sprite.Sprite):
def __init__(self, image_file, location):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(image_file)
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = location
def main():
pygame.init()
screen = pygame.display.set_mode((settings.windowwidth, settings.windowheight))
pygame.display.set_caption('Final Game')
background = Background('space.jpg',[0,0])
global player, enemy
player = Player('SpaceShip.png',[200,100])
playersprite = pygame.sprite.RenderPlain((player))
enemy = Enemy('Enemy Hexagon.png',[300,150])
enemysprite = pygame.sprite.RenderPlain((enemy))
fpsClock = pygame.time.Clock()
intro = True
while intro == True:
myFont = pygame.font.SysFont('freesansbold.ttf', 75)
otherFont = pygame.font.SysFont('freesansbold.ttf', 30)
SurfaceFont = myFont.render("Space Destroyer", True, (colours.white))
SurfaceFont2 = otherFont.render("Press Space to Start", True, (colours.white))
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_SPACE:
intro= False
screen.blit(SurfaceFont,(50,50))
screen.blit(SurfaceFont2,(125,125))
pygame.display.flip()
screen.blit(background.image, background.rect)
while intro == False:
fpsClock.tick(settings.fps)
for event in pygame.event.get():
enemy.rect.x
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_UP:
player.speed += 4
if event.key == K_LEFT:
player.angle_speed = -4
if event.key == K_RIGHT:
player.angle_speed = 4
if player.position.y < 0:
player.position = (player.position.x ,332)
elif player.position.y > settings.windowheight:
player.position = (player.position.x, 0)
elif player.position.x < 0:
player.position = (590, player.position.y)
elif player.position.x > settings.windowwidth:
player.position = (0, player.position.y)
elif event.type == KEYUP:
if event.key == K_LEFT:
player.angle_speed = 0
if event.key == K_RIGHT:
player.angle_speed = 0
if event.key == K_UP:
player.speed = 0
screen.fill(colours.white)
screen.blit(background.image, background.rect)
enemysprite.draw(screen)
enemysprite.update()
playersprite.draw(screen)
playersprite.update()
pygame.display.update()
playersprite.update()
pygame.display.flip()
if __name__ == '__main__': main()
You never called move_towards_player. Try adding this:
...
enemysprite.draw(screen)
enemysprite.update()
playersprite.draw(screen)
playersprite.update()
enemy.move_towards_player(player)
...

Determining a collision of an arching projectile with another sprite in Pygame

In pygame I have a projectile being shot from one character sprite to another which I would like to determine whether there is a collision or not. That is a collision between a shot projectile and another character I will call TRUMP. I have found an equation in a tutorial that is the best example of an arching trajectory that I can accomplish. If that equation could be helped it would be awesome.
def fireshell(self, elapsedTime):
fire = True
FPS = 60 # frames per second setting
fpsClock = pg.time.Clock()
print("fire", self.pos.x, self.pos.y)
fireX = int(self.pos.x)
fireY = int(self.pos.y)
print("fireX", fireX, "fireY", fireY, "elapsed time", elapsedTime)
power = elapsedTime*.0005
x = int(self.pos.x)
y = int(self.pos.y) - 100
while fire:
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
quit()
pg.draw.circle(self.screen, RED, (x, y), 5)
x -= int(-(elapsedTime*6))
y += int((((x - fireX)*0.015)**2) - ((elapsedTime*2)/(12 - elapsedTime )))
print("X:", x,"Y:", y)
if y > HEIGHT or x > WIDTH:
fire = False
pg.display.update()
self.clock.tick(20)
My character sprite who I would like to check for collisions with the projectile is here:
class TRUMP(pg.sprite.Sprite):
def __init__(self, spritesheet, all_sprites, mudballGroup, jetsGroup):
pg.sprite.Sprite.__init__(self)
self.spritesheet = spritesheet
self.all_sprites = all_sprites
self.mudballGroup = mudballGroup
self.jetsGroup = jetsGroup
self.current_frame2 = 0
self.last_update2 = 0
self.load_images()
self.image = self.TRUMP_fingers_l
self.rect = self.image.get_rect()
self.rect.center = (WIDTH *3/4), (589)
self.rect.centerx = (WIDTH *3/4)
self.rect.centery = 589
self.rect.centerx = (WIDTH*5/6)
self.rect.centery = 589
self.pos = vec((WIDTH/2), (HEIGHT/2))
self.vel = vec(0, 0)
self.acc = vec(0, 0)
self.dir = 0
To get a ballistic trajectory, you can just add a GRAVITY constant to the y-value of the velocity vector each frame.
For the collision detection you can use pygame.sprite.spritecollide again (you already know how that works).
Here's a complete example:
import sys
import pygame as pg
GRAVITY = 3
class Player(pg.sprite.Sprite):
def __init__(self, pos, color):
super().__init__()
self.image = pg.Surface((50, 30))
self.image.fill(color)
self.rect = self.image.get_rect(center=pos)
self.pos = pg.math.Vector2(pos)
self.vel = pg.math.Vector2()
def update(self):
self.pos += self.vel
self.rect.center = self.pos
class Projectile(pg.sprite.Sprite):
def __init__(self, pos, color, target):
super().__init__()
self.image = pg.Surface((7, 5))
self.image.fill(color)
self.rect = self.image.get_rect(center=pos)
self.pos = pg.math.Vector2(pos)
direction = target - self.pos # Vector to the target.
# Normalize, then scale direction to adjust the speed.
self.vel = direction.normalize() * 33
def update(self):
self.pos += self.vel
self.vel.y += GRAVITY
self.rect.center = self.pos
if self.rect.y > 580:
self.kill()
class Game:
def __init__(self):
self.fps = 30
self.screen = pg.display.set_mode((800, 600))
pg.display.set_caption('Ballistic trajectory')
self.clock = pg.time.Clock()
self.bg_color = pg.Color(90, 120, 100)
self.green = pg.Color('aquamarine2')
self.blue = pg.Color(30, 90, 150)
self.font = pg.font.Font(None, 30)
self.player = Player((100, 300), self.green)
self.player2 = Player((400, 300), self.blue)
self.all_sprites = pg.sprite.Group(self.player, self.player2)
self.projectiles = pg.sprite.Group()
self.collisions = 0
self.done = False
def run(self):
while not self.done:
self.handle_events()
self.run_logic()
self.draw()
self.clock.tick(self.fps)
def handle_events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
if event.type == pg.MOUSEBUTTONDOWN:
if event.button == 1:
proj = Projectile(
self.player.rect.center, pg.Color('sienna2'), event.pos)
self.projectiles.add(proj)
self.all_sprites.add(proj)
if event.type == pg.KEYDOWN:
if event.key == pg.K_a:
self.player.vel.x = -3
if event.key == pg.K_d:
self.player.vel.x = 3
if event.key == pg.K_w:
self.player.vel.y = -3
if event.key == pg.K_s:
self.player.vel.y = 3
if event.type == pg.KEYUP:
if event.key == pg.K_a and self.player.vel.x == -3:
self.player.vel.x = 0
if event.key == pg.K_d and self.player.vel.x == 3:
self.player.vel.x = 0
if event.key == pg.K_w and self.player.vel.y == -3:
self.player.vel.y = 0
if event.key == pg.K_s and self.player.vel.y == 3:
self.player.vel.y = 0
def run_logic(self):
self.all_sprites.update()
hits = pg.sprite.spritecollide(self.player2, self.projectiles, True)
for collided_sprite in hits:
self.collisions += 1
def draw(self):
self.screen.fill(self.bg_color)
self.all_sprites.draw(self.screen)
txt = self.font.render('Collisions {}'.format(self.collisions), True, self.green)
self.screen.blit(txt, (20, 20))
pg.display.flip()
if __name__ == '__main__':
pg.init()
game = Game()
game.run()
pg.quit()
sys.exit()

Categories

Resources