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.
Related
The following code attempts; unsuccessfully, to move a small graphic together with its mask. The graphic (car.png) moves as intended when the keyboard input indicates forward and backward. However, when the keyboard input indicates a rotation, the car graphic disappears and the place-holder triangle appears. The place-holder triangle subsequently behaves as the car graphic (with its mask) is supposed to behave.
import math
import pygame as pg
from pygame.math import Vector2
class Player(pg.sprite.Sprite):
def __init__(self, pos=(420, 420)):
super(Player, self).__init__()
self.image = pg.Surface((70, 50), pg.SRCALPHA)
pg.draw.polygon(self.image, (50, 120, 180), ((0, 0), (0, 50), (70, 25)))
self.original_image = self.image
self.rect = self.image.get_rect(center=pos)
# Instead we could load a picture of a car
self.image = pg.image.load("car.png").convert_alpha()
self.mask = pg.mask.from_surface(self.image)
self.position = Vector2(pos)
self.direction = Vector2(1, 0) # A unit vector pointing rightward.
self.speed = 2
self.angle_speed = 0
self.angle = 0
def update(self):
if self.angle_speed != 0:
# Rotate the direction vector and then the image.
self.direction.rotate_ip(self.angle_speed)
self.angle += self.angle_speed
self.image = pg.transform.rotate(self.original_image, -self.angle)
self.rect = self.image.get_rect(center=self.rect.center)
# Update the position vector and the rect.
self.position += self.direction * self.speed
self.rect.center = self.position
def main():
pg.init()
screen = pg.display.set_mode((1280, 720))
player = Player((420, 420))
playersprite = pg.sprite.RenderPlain((player))
clock = pg.time.Clock()
done = False
while not done:
clock.tick(60)
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
player.speed += 1
elif event.key == pg.K_DOWN:
player.speed -= 1
elif event.key == pg.K_LEFT:
player.angle_speed = -4
elif event.key == pg.K_RIGHT:
player.angle_speed = 4
elif event.type == pg.KEYUP:
if event.key == pg.K_LEFT:
player.angle_speed = 0
elif event.key == pg.K_RIGHT:
player.angle_speed = 0
playersprite.update()
screen.fill((30, 30, 30))
playersprite.draw(screen)
pg.display.flip()
if __name__ == '__main__':
main()
pg.quit()
See How do I rotate an image around its center using PyGame?. You don't need the triangle at all. original_image needs to be the car:
class Player(pg.sprite.Sprite):
def __init__(self, pos=(420, 420)):
super(Player, self).__init__()
self.original_image = pg.image.load("car.png").convert_alpha()
self.image = self.original_image
self.rect = self.image.get_rect(center=pos)
self.mask = pg.mask.from_surface(self.image)
self.position = Vector2(pos)
self.direction = Vector2(1, 0) # A unit vector pointing rightward.
self.speed = 2
self.angle_speed = 0
self.angle = 0
I am struggling with finding a way to make the sprite jump in pygame. when i basically run the program now the sprite goes straight to the top of the screen and i just want it to do a normal jump. the jump is in a class and is a function. I have used KEYDOWN to check when its pressed to move it downwards.
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/dunes.jpg").convert()
picture = pygame.transform.scale(picture, (1280, 720))
def __init__(self, x, y):
self.xpos = x
self.ypos = y
def draw(self):
# Blit the picture onto the screen surface.
# `self.picture` not just `picture`.
screen.blit(self.picture, (self.xpos, self.ypos))
class Monster:
picture = pygame.image.load("C:/pics/hammerhood.png").convert_alpha()
picture = pygame.transform.scale(picture, (200, 200))
def __init__(self, x, y):
self.xpos = x
self.ypos = y
# If you want to move continuously you need to set these
# attributes to the desired speed and then add them to
# self.xpos and self.ypos in an update method that should
# be called once each frame.
self.speed_x = 0
self.speed_y = 0
def update(self):
# Call this method each frame to update the positions.
self.xpos += self.speed_x
self.ypos += self.speed_y
# Not necessary anymore.
def move_left(self):
self.xpos -= 5 # -= not = -5 (augmented assignment).
def move_right(self):
self.xpos += 5 # += not = +5 (augmented assignment).
def jump(self): #vvvvvvv this is the part i do not know how to fix
# What do you want to do here?
#for x in range(1, 10):
#self.ypos -= 1 # -= not =-
# pygame.display.show() # There's no show method.
#for x in range(1, 10):
#self.ypos += 1
# pygame.display.show()
def draw(self):
screen.blit(self.picture, (self.xpos, self.ypos))
class Enemy: # Use upper camelcase names for classes.
picture = pygame.image.load("C:/pics/dangler_fish.png").convert_alpha()
picture = pygame.transform.scale(picture, (200, 200))
def __init__(self, x, y):
self.xpos = x
self.ypos = y
def teleport(self):
self.xpos = random.randint(1, 1280)
self.ypos= random.randint(1, 720)
def draw(self):
screen.blit(self.picture, (self.xpos, self.ypos))
# Create the instances before the while loop.
ice = Background(0, 0) # I pass 0, 0 so that it fills the whole screen.
hammerhood = Monster(200, 500)
fish = Enemy(0, 0)
while True:
# Handle events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# Check if the `event.type` is KEYDOWN first.
elif event.type == pygame.KEYDOWN:
# Then check which `event.key` was pressed.
if event.key == pygame.K_d:
#hammerhood.move_right()
hammerhood.speed_x = 5
elif event.key == pygame.K_a:
#hammerhood.move_left()
hammerhood.speed_x = -5
elif event.key == pygame.K_w:
hammerhood.jump()
elif event.type == pygame.KEYUP:
# Stop moving when the keys are released.
if event.key == pygame.K_d and hammerhood.speed_x > 0:
hammerhood.speed_x = 0
elif event.key == pygame.K_a and hammerhood.speed_x < 0:
hammerhood.speed_x = 0
# Update the game.
hammerhood.update()
fish.teleport()
if hammerhood.xpos == 1280 or hammerhood.xpos == 0:
hammerhood.speed_x = 0
# Draw everything.
ice.draw() # Blit the background to clear the screen.
hammerhood.draw()
fish.draw()
pygame.display.flip()
clock.tick(60) # Limit the frame rate to 60 FPS.
Just add a GRAVITY constant and add it to the self.speed_y each frame to accelerate the player.
GRAVITY = .9 # Define this in the global scope.
# The Monster's update method.
def update(self):
self.speed_y += GRAVITY # Accelerate downwards.
self.xpos += self.speed_x
self.ypos += self.speed_y
# Stop falling at the bottom of the screen.
if self.ypos >= 520:
self.ypos = 520
self.speed_y = 0
self.on_ground = True
Set the self.speed_y to a negative value when you start to jump:
def jump(self):
if self.on_ground: # This prevents air jumps.
self.on_ground = False
self.speed_y = -25
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)
...
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()
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()