I'm creating a tennis game, similar to pong but will be much more similar to real tennis (i.e. ability to control the direction and type of your shot). I think I've got the collision detection with the ball and the player figured out, but when the player collides with the ball it moves a few pixels then stops. I need it to keep going like in pong. Not sure if the problem is with the collision detection or just with something else in the code.
import pygame
pygame.init()
# Define some colors
BLACK = (0, 0, 0)
OUT = (193, 58, 34)
COURT = (69, 150, 81)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
SKIN = (232, 214, 162)
ballspeed = 2
# Create the screen
windowsize = (700, 500)
screen = pygame.display.set_mode(windowsize)
pygame.display.set_caption('Tennis')
# Player Sprites
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("Robert_tennis.png")
self.rect = self.image.get_rect()
self.rect.center = (360, 480)
self.speedx = 0
self.speedy = 0
def update(self):
self.speedx = 0
self.speedy = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_LEFT]:
self.speedx = -4
if keystate[pygame.K_RIGHT]:
self.speedx = 4
self.rect.x += self.speedx
if self.rect.right > 700:
self.rect.right = 700
if self.rect.right < 0:
self.rect.left = 0
if keystate[pygame.K_UP]:
self.speedy = -5
if keystate[pygame.K_DOWN]:
self.speedy = 3
self.rect.y += self.speedy
if self.rect.y < 235:
self.rect.y = 235
if self.rect.y < 0:
self.rect.y = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("tennisball.png")
self.rect = self.image.get_rect()
self.rect.center = (360, 325)
def update(self):
if tennisball.rect.colliderect(robert):
self.rect.y -= 2
#Add myself
all_sprites = pygame.sprite.Group()
robert = Player()
tennisball = Ball()
all_sprites.add(robert)
all_sprites.add(tennisball)
carryOn = True
clock = pygame.time.Clock()
while carryOn:
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carryOn = False
all_sprites.update()
# Fill the screen with a sky color
screen.fill(OUT)
# Draw the court
pygame.draw.rect(screen, COURT, [175, 0, 350, 500])
pygame.draw.line(screen, WHITE, (170,500), (170,0), 10)
pygame.draw.line(screen, WHITE, (520,500), (520,0), 10)
pygame.draw.line(screen, WHITE, (170,130), (520,130), 10)
pygame.draw.line(screen, WHITE, (170,370), (520,370), 10)
pygame.draw.line(screen, WHITE, (340,130), (340,370), 10)
pygame.draw.line(screen, BLACK, (170,250), (520,250), 10)
# Update
all_sprites.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
When you do
def update(self):
if tennisball.rect.colliderect(robert):
self.rect.y -= 2
then the ball moves only once. In that "moment" when the player hits the ball and the condition is fulfilled. After the ball has moved, the condition is not fulfilled any more and the ball stops.
When the racket hits the ball then you've to change the speed of the ball rather than its position.
Add attributes which store the speed of the ball (.speedx, .speedy). Initialize the attributes by 0. Continuously change the position of the ball by it speed in the method .update(). When the racket hits the ball then change the speed:
e.g.
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("tennisball.png")
self.rect = self.image.get_rect()
self.rect.center = (360, 325)
self.speedx = 0
self.speedy = 0
def update(self):
if tennisball.rect.colliderect(robert):
self.speedy = -2
self.rect = self.rect.move(self.speedx, self.speedy)
Note, if there is a player at the other side of the court, which hits the ball, then the speed is changed again. The speed can also have an sideward component for a diagonal movement.
Related
This question already has an answer here:
Sometimes the ball doesn't bounce off the paddle in pong game
(1 answer)
Closed 1 year ago.
I am currently trying to create a pong game but for some reason, the ball would not bounce off of the rectangles and I am not sure where I have made a mistake even though I followed a video about rectangle collision online. Please let me know where I made a mistake and how I can improve my code. Thanks!
import pygame, sys, random, time
from pygame.time import Clock
pygame.init()
#colours
black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)
# Display
screen_width = 1000
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("2-player Pong")
# Rectangles
class Rectangle():
def __init__(self, screen, x):
self.screen = screen
self.screen_rect= screen.get_rect()
self.x = x
self.y = 250
self.width = 30
self.height = 100
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.colour = black
self.velocity = 5
def draw_rectangle(self):
pygame.draw.rect(self.screen, self.colour, self.rect)
rect1 = Rectangle(screen, 50)
rect2 = Rectangle(screen, 920)
class Ball():
def __init__(self, colour):
self.screen = screen
self.colour = colour
self.width = 20
self.height = 20
self.x = screen_width//2 - 25
self.y = screen_height//2 - 25
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.possible_velocities_x = [-4, 4]
self.possible_velocities_y = [-2, 2]
self.velocity = [random.choice(self.possible_velocities_x), random.choice(self.possible_velocities_y)]
def draw_ball(self):
pygame.draw.rect(self.screen, self.colour, self.rect)
def move_ball(self):
global rect1, rect2
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
# Collision with Screen
if self.rect.top <= 10 or self.rect.bottom >= screen_height - 10:
self.velocity[1] *= -1
# Collision with Rectangles
if self.rect.colliderect(rect1) or self.rect.colliderect(rect2):
if self.rect.left - rect1.rect.right == 0:
self.possible_velocities_x *= -1
if self.rect.right - rect2.rect.left == 0:
self.possible_velocities_x *= -1
clock = pygame.time.Clock()
ball = Ball(white)
pong = True
while pong:
pygame.time.delay(10)
clock.tick(100)
# Watch for keyboard and mouse events.
for event in pygame.event.get():
if event.type == pygame.QUIT:
pong = False
keys = pygame.key.get_pressed()
if keys[pygame.K_UP] and rect2.rect.y >= 0:
rect2.rect.y -= rect2.velocity
if keys[pygame.K_DOWN] and rect2.rect.y <= 600 - rect2.rect.height:
rect2.rect.y += rect2.velocity
if keys[pygame.K_w] and rect1.rect.y >= 0:
rect1.rect.y -= rect1.velocity
if keys[pygame.K_s] and rect1.rect.y <= 600 - rect1.rect.height:
rect1.rect.y += rect1.velocity
screen.fill(green)
rect1.draw_rectangle()
rect2.draw_rectangle()
ball.draw_ball()
ball.move_ball()
# pygame.draw.rect(screen, black, (rect_x2, rect_y2, rect_width2, rect_height2))
pygame.display.update() # Make the most recently drawn screen visible.
pygame.quit()
You must change self.velocity[0] when the ball touches the paddle. Since the movement of the ball is more than 1 pixel per frame, the ball does not exactly touch the paddle. This mans the condition self.rect.left - rect1.rect.right == 0 and self.rect.right - rect2.rect.left == 0 will not be fulfilled. If the movement in x direction is negative, the new movement needs to be positive (abs(self.velocity[0])). If the movement in x direction is positive, the new movement needs to be negative (-abs(self.velocity[0])):
class Ball():
# [...]
def move_ball(self):
self.rect.x += self.velocity[0]
self.rect.y += self.velocity[1]
# Collision with Screen
if self.rect.top <= 10 or self.rect.bottom >= screen_height - 10:
self.velocity[1] *= -1
# Collision with Rectangles
if self.rect.colliderect(rect1) or self.rect.colliderect(rect2):
if self.velocity[0] < 0:
self.velocity[0] = abs(self.velocity[0])
else:
self.velocity[0] = -abs(self.velocity[0])
See also Sometimes the ball doesn't bounce off the paddle in pong game
This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
I'm making a platform game and I've got collisions working, however with the platforms there seems to be an extra cube area on the left side which the player can walk on. I can't seem to figure out how to remove it. Below is some of the code I believe is the cause of it however I'm not sure exactly.
. I've trimmed down the image for the platforms etc but the problem persists.
background_image = pygame.image.load("JungleBackground.png")
done = False
clock = pygame.time.Clock()
black = ( 0, 0, 0)
white = ( 255, 255, 255)
x = 300
y = 88
class Character(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((100,100))
self.image.set_colorkey(black)
self.rect = self.image.get_rect(center=(50, 300))
self.rect.x = 50
self.rect.y = 300
self.pos = vec(50, 300)
self.vel = vec(0,0)
self.acc = vec(0,0)
self.image.blit(pygame.image.load("TheoHillsS.png"),(0,0))
def characterJump(self):
self.rect.y += 1
hits = pygame.sprite.spritecollide(self, platforms, False)
self.rect.y -= 1
if hits:
self.vel.y = -13
def update(self):
self.acc = vec(0, 0.5)
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
self.acc.x = -PLAYER_ACC
if keys[pygame.K_d]:
self.acc.x = PLAYER_ACC
# apply friction
self.vel.x *= PLAYER_FRICTION
self.vel += self.acc
self.pos += self.vel
self.rect.midbottom = self.pos
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((100, 88))
self.image.fill(black)
self.image = pygame.image.load("Platform1.png")
self.rect = self.image.get_rect(topleft=(x, y))
all_sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()
character = Character()
all_sprites.add(character)
p1 = Platform(-80, 350, WIDTH - 400, HEIGHT - 10)
p2 = Platform(175, 220, WIDTH - 400, HEIGHT - 10)
p3 = Platform(500, 350, WIDTH - 400, HEIGHT - 10)
all_sprites.add(p1, p2, p3)
platforms.add(p1, p2, p3)
# Main Game
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
character.characterJump()
all_sprites.update()
hits = pygame.sprite.spritecollide(character, platforms, False)
for platform in hits:
if character.vel.y > 0:
character.rect.bottom = platform.rect.top
character.vel.y = 0
elif character.vel.y < 0:
character.rect.top = platform.rect.bottom
character.vel.y = 3
character.pos.y = character.rect.bottom
screen.blit(background_image,[0,0])
all_sprites.draw(screen)
pygame.display.flip()
game_intro()
game_loop()
pygame.quit()
quit()
The collision is tested against the bounding rectangle of the image, not the area drawn on the image. Make sure the platforms and player fill almost the entire area of the pygame.Surface.
Instead of drawing the player on a transparent Surface that is much larger than the player, use the Surface created by pygame.image.load directly:
class Character(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("TheoHillsS.png")
self.rect = self.image.get_rect(topleft = (50, 300))
self.pos = vec(50, 300)
self.vel = vec(0,0)
self.acc = vec(0,0)
# [...]
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.
I'm quite new to pygame and came across a bug that i just can't fix on my own. I'm trying to program a Flappy Bird game. The Problem is that the collision detection works, but it also messes with my sprites. If i manage to get past the first obstacle while playing, then the gap resets itself randomly. But the gap should always be the same, just on another position. If i remove the collision detection, it works perfectly fine. Any ideas?
import pygame
import random
randomy = random.randint(-150, 150)
class Bird(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((25,25))
self.image.fill((255,255,255))
self.rect = self.image.get_rect()
self.rect.center = (100, 200)
self.velocity = 0.05
self.acceleration =0.4
def update(self):
self.rect.y += self.velocity
self.velocity += self.acceleration
if self.rect.bottom > 590:
self.velocity = 0
self.acceleration = 0
class Pipe1(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((85, 500))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.center = (500, randomy)
self.randomyupdate = random.randint(-150, 150)
def update(self):
self.rect.x -= 2
if self.rect.x < -90:
self.randomyupdate = random.randint(-150, 150)
self.rect.center = (450, self.randomyupdate)
class Pipe2(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((85, 500))
self.image.fill((255, 255, 255))
self.rect = self.image.get_rect()
self.rect.center = (500, (randomy +640))
def update(self):
self.rect.x -= 2
self.randomyupdate = Pipe1.randomyupdate
if self.rect.x < -90:
self.rect.center = (450, (self.randomyupdate + 640))
pygame.init()
pygame.mouse.set_visible(1)
pygame.key.set_repeat(1, 30)
pygame.display.set_caption('Crappy Bird')
clock = pygame.time.Clock()
Bird_sprite = pygame.sprite.Group()
Pipe_sprite = pygame.sprite.Group()
Bird = Bird()
Pipe1 = Pipe1()
Pipe2 = Pipe2 ()
Bird_sprite.add(Bird)
Pipe_sprite.add(Pipe1)
Pipe_sprite.add(Pipe2)
def main():
running = True
while running:
clock.tick(60)
screen = pygame.display.set_mode((400,600))
screen.fill((0,0,0))
Bird_sprite.update()
Pipe_sprite.update()
Bird_sprite.draw(screen)
Pipe_sprite.draw(screen)
The line im talking about:
collide = pygame.sprite.spritecollideany(Bird, Pipe_sprite)
if collide:
running = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.event.post(pygame.event.Event(pygame.QUIT))
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
Bird.rect.y -= 85
Bird.velocity = 0.05
Bird.acceleration = 0.4
Bird.rect.y += Bird.velocity
Bird.velocity += Bird.acceleration
pygame.display.flip()
if __name__ == '__main__':
main()
This has nothing to do with the collision detection, it has to do with the order of the sprites in the sprite group which can vary because sprite groups use dictionaries internally which are unordered (in Python versions < 3.6). So if the Pipe1 sprite comes first in the group, the game will work correctly, but if the Pipe2 sprite comes first, then its update method is also called first and the previous randomyupdate of Pipe1 is used to set the new centery coordinate of the sprite.
To fix this you could either turn the sprite group into an ordered group, e.g.
Pipe_sprite = pygame.sprite.OrderedUpdates()
or update the rect of Pipe2 each frame,
def update(self):
self.rect.x -= 2
self.rect.centery = Pipe1.randomyupdate + 640
if self.rect.x < -90:
self.rect.center = (450, Pipe1.randomyupdate + 640)
Also, remove the global randomy variable and always use the randomyupdate attribute of Pipe1.
So I've been doing quite a lot of research on this question, and I still haven't been able to implement other people's solutions to solve mine. I'm trying to make the Mob2 class move towards the Player class. Any suggestions to my code, or even how to improve my code would be greatly appreciated :) BTW, the code I've written below has been made in Atom, if you have any questions I'll be around to answer them. Thank you all so much!!
# Pygame template - skeleton for a new pygame project
import pygame
import random
import math
from os import path
working_dir = path.dirname(__file__)
from pygame.locals import *
WIDTH = 1000
HEIGHT = 700
FPS = 60
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
# initialize pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Virus Invaders")
clock = pygame.time.Clock()
font_name = pygame.font.match_font('arial')
health = 4
def draw_text(surf, text, size, x, y):
font = pygame.font.Font(font_name, size)
text_surface = font.render(text, True, WHITE)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
def newmob():
m = Mob()
all_sprites.add(m)
mobs.add(m)
def newmob2():
n = Mob2()
all_sprites.add(n)
mobs2.add(n)
def draw_health_bar(surf, x, y, health):
if health==4:
healthImage = healthSheet.get_image(0, 102, 176, 23)
screen.blit(healthImage, [50, 50])
if health==3:
healthImage = healthSheet.get_image(0, 128, 176, 23)
screen.blit(healthImage, [50, 50])
if health==2:
healthImage = healthSheet.get_image(0, 155, 176, 23)
screen.blit(healthImage, [50, 50])
if health==1:
healthImage = healthSheet.get_image(0, 182, 176, 23)
screen.blit(healthImage, [50, 50])
if health==0:
healthImage = healthSheet.get_image(0, 209, 176, 23)
screen.blit(healthImage, [50, 50])
class Player(pygame.sprite.Sprite):
def __init__(self, health):
pygame.sprite.Sprite.__init__(self)
self.image = dudeSpriteSheet.get_image(60, 0, 60, 60)
self.rect = self.image.get_rect()
self.radius = 25
#pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.centerx = 100
self.rect.centery = 400.5
self.speedx = 0
self.speedy = 0
self.health = health
def update(self):
self.speedx = 0
self.speedy = 0
keystate = pygame.key.get_pressed()
if keystate[pygame.K_s]:
self.speedy = 4
if keystate[pygame.K_w]:
self.speedy = -4
if keystate[pygame.K_d]:
self.speedx = 4
if keystate[pygame.K_a]:
self.speedx = -4
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.right > WIDTH-80:
self.rect.right = WIDTH-80
if self.rect.left < 90:
self.rect.left = 90
if self.rect.bottom > HEIGHT-87:
self.rect.bottom = HEIGHT-87
if self.rect.top < 187:
self.rect.top = 187
def shoot(self, X, Y, direction):
if direction == 1:
self.image = dudeSpriteSheet.get_image(60, 0, 60, 60)
elif direction == 2:
self.image = dudeSpriteSheet.get_image(0, 0, 60, 60)
elif direction == 3:
self.image = dudeSpriteSheet.get_image(120, 0, 60, 60)
elif direction == 4:
self.image = dudeSpriteSheet.get_image(180, 0, 60, 60)
X = X+self.speedx
Y = Y+self.speedy
bullet = Bullet(self.rect.centerx, self.rect.centery, X, Y)
all_sprites.add(bullet)
bullets.add(bullet)
class Mob(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = virus_img
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width * 0.85 / 2)
#pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = WIDTH - 200
self.rect.y = 400.5
self.speedx = random.randrange(-4, 4)
self.speedy = random.randrange(-4, 4)
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
if self.rect.bottom >= HEIGHT - 87:
self.speedy = -self.speedy
if self.rect.top <= 193:
self.speedy = -self.speedy
if self.rect.left <= 94:
self.speedx = -self.speedx
if self.rect.right >= WIDTH - 96:
self.speedx = -self.speedx
class Mob2(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = virus2_img
self.image.set_colorkey(WHITE)
self.rect = self.image.get_rect()
self.radius = int(self.rect.width * 0.85 / 2)
pygame.draw.circle(self.image, RED, self.rect.center, self.radius)
self.rect.x = WIDTH - 200
self.rect.y = 300
self.rot = 0
self.speed = 3
def update(self, Player):
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y, X, Y):
pygame.sprite.Sprite.__init__(self)
self.image = bullet_img
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.radius = 25
self.rect.bottom = y
self.rect.centerx = x
self.speedy = Y
self.speedx = X
def update(self):
self.rect.x += self.speedx
self.rect.y += self.speedy
# Kill if it moves off the top of the screen
if self.rect.bottom < 0 or self.rect.top > 700 or self.rect.right <
0 or self.rect.left > 1000:
self.kill()
class Spritesheet:
#Utility class for loading and parsing spritesheets
def __init__(self, filename):
self.spritesheet = pygame.image.load(filename).convert()
def get_image(self, x, y, width, height):
#Grab an image out of a larger spritesheet
image = pygame.Surface((width, height))
image.blit(self.spritesheet, (0, 0), (x, y, width, height))
image.set_colorkey(BLACK)
return image
# Load all game graphics
background = pygame.image.load(path.join(working_dir,
'GameScreen.png')).convert()
background_rect = background.get_rect()
player_img = pygame.image.load(path.join(working_dir,'dude.png')).convert()
virus_img =
pygame.image.load(path.join(working_dir,'badguy1.png')).convert()
bullet_img =
pygame.image.load(path.join(working_dir,'bullet.png')).convert()
dudeSpriteSheet = Spritesheet(path.join(working_dir,
'DudeSpriteSheet2.png'))
healthSheet = Spritesheet(path.join(working_dir, 'health.png'))
virus2_img =
pygame.image.load(path.join(working_dir,'badguy2(2).png')).convert()
all_sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
mobs2 = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player(health)
all_sprites.add(player)
for i in range(8):
newmob()
newmob2()
score = 0
# Game loop
running = True
while running:
# keep loop running at the right speed
clock.tick(FPS)
# Process input (events)
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
player.shoot(10, 0, 1)
elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
player.shoot(0, -10, 2)
elif event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
player.shoot(0, 10, 3)
elif event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
player.shoot(-10, 0, 4)
# Update
all_sprites.update()
#Check to see if bullet hits a mob
hits = pygame.sprite.groupcollide(mobs, bullets, True,
pygame.sprite.collide_circle)
for hit in hits:
score += 1
newmob()
# Check to see if a virus hits a player
hits = pygame.sprite.spritecollide(player, mobs, True,
pygame.sprite.collide_circle)
for hit in hits:
health -= 1
newmob()
if health <= 0:
running = False
# Draw / render
screen.fill(BLACK)
screen.blit(background, background_rect)
all_sprites.draw(screen)
draw_text(screen, str(score), 18, WIDTH / 2, 10)
draw_health_bar(screen, 5, 5, health)
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.quit()
First compare Mob.rect.x with Player.rect.x to see if it should move left or right, then do the same with rect.y to see if it should move up or down. The its simply getting Mob to move in that direction.