Hello I am currently working on a survival shooter game and I am currently getting frustrated at a few things. One being my player animation not working. I have the code for the player class right here:
import pygame
from zombie import *
# Player
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gravity):
# Player dimensions and position
# Player image and animation
self.images = []
self.images.append(pygame.image.load('images/Sprites/player.png'))
self.images.append(pygame.image.load('images/Sprites/player2.png'))
#~ self.images.append(pygame.image.load('ball1.png'))
#~ self.images.append(pygame.image.load('ball2.png'))
self.maxImage = len(self.images)
self.currentImage = 0
#~ self.rect = pygame.Rect(x, y, 80, 80)
self.rect = self.images[0].get_rect()
self.rect.x = x
self.rect.y = y
self.timeTarget = 10
self.timeNum = 1
self.velX = 0
self.velY = 0
self.health = 100
# Jump and gravity
self.jumping = False
self.on_ground = False
self.origJumpVel = 15
self.jumpVel = self.origJumpVel
self.gravity = 0.5
# Jump inputs
def do_jump(self):
if self.jumping and not self.on_ground:
self.velY = -self.jumpVel
self.jumpVel -= self.gravity
if self.on_ground:
self.jumping = False
self.jumpVel = self.origJumpVel
self.velY = 0
self.on_ground = True
def handle_events(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if not self.jumping:
self.jumping = True
self.on_ground = False
elif event.key == pygame.K_a:
self.velX = -5
elif event.key == pygame.K_d:
self.velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.velX = 0
# PLayer updates
def update(self):
# Animations
if self.timeNum == self.timeTarget:
self.currentImage += 1
if self.currentImage >= self.maxImage:
self.currentImage = 0
self.timeNum = 1
# Health
#if self.rect.x == zombie.rect.x:
#self.health -= 10
# Screen wrap
if self.rect.right > 1280:
self.rect.left = 0
elif self.rect.left < 0:
self.rect.right = 1280
# Player rendering
def render(self, surface):
surface.blit(self.images[self.currentImage], self.rect)
If you want to know about any of my other problems/frustrations just say so. Any help will be greatly appreciated. Thank you.
You have
if self.timeNum == self.timeTarget:
# ...
self.timeNum += 1
but self.timeNum is 1 and self.timeTarget is 10 so it can't be run and it can't change self.timeNum
You probably need
if self.timeNum == self.timeTarget:
# ...
# inside of `if`
self.timeNum = 0
# outside of `if`
self.timeNum += 1
Related
I am trying to make my player jump (from this tutorial https://opensource.com/article/19/12/jumping-python-platformer-game) but it only jumps once when you press key_up or key "w". And when I look at the output produced in the terminal while I am running the game.py file I see that it was printed jump several times in the terminal.
game.py:
import pygame
import sys
import os
'''
Objects
'''
class Platform(pygame.sprite.Sprite):
# x location, y location, img width, img height, img file
def __init__(self,xloc,yloc,imgw,imgh,img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images',img)).convert()
self.image.convert_alpha()
self.rect = self.image.get_rect()
self.rect.y = yloc
self.rect.x = xloc
class Player(pygame.sprite.Sprite):
'''
Spawn a player
'''
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.movex = 0
self.movey = 0
self.frame = 0
self.health = 10
# gravity variables here
self.collide_delta = 0
self.jump_delta = 6
self.score = 1
self.images = []
for i in range(1,9):
img = pygame.image.load(os.path.join('images','spr' + str(i) + '.png')).convert()
img.convert_alpha()
img.set_colorkey(ALPHA)
self.images.append(img)
self.image = self.images[0]
self.rect = self.image.get_rect()
def jump(self,platform_list):
self.jump_delta = 0
def gravity(self):
self.movey += 3.2 # how fast player falls
if self.movey >= 15:
self.movey = 6
if self.rect.bottom > worldy and self.movey >= 0: # <-- uses bottom
self.movey = 0
self.rect.bottom = worldy # <-- uses bottom
def control(self,x,y):
'''
control player movement
'''
self.movex += x
self.movey += y
def update(self):
'''
Update sprite position
'''
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
self.collide_delta = 0 # stop jumping
self.movey = 0
if self.rect.y > p.rect.y:
self.rect.y = p.rect.y+ty
else:
self.rect.y = p.rect.y-ty
if self.collide_delta < 6 and self.jump_delta < 6:
self.jump_delta = 6*2
self.movey -= 33 # how high to jump
self.collide_delta += 6
self.jump_delta += 6
self.rect.x = self.rect.x + self.movex
self.rect.y = self.rect.y + self.movey
# moving left
if self.movex < 0:
self.frame += 1
if self.frame > ani*3:
self.frame = 0
self.image = self.images[self.frame//ani]
# moving right
if self.movex > 0:
self.frame += 1
if self.frame > ani*3:
self.frame = 0
self.image = self.images[(self.frame//ani)+4]
# collisions
enemy_hit_list = pygame.sprite.spritecollide(self, enemy_list, False)
for enemy in enemy_hit_list:
self.health -= 1
print(self.health)
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
self.rect.bottom = p.rect.top
ground_hit_list = pygame.sprite.spritecollide(self, ground_list, False)
for g in ground_hit_list:
self.movey = 0
self.rect.y = worldy-ty-ty
self.collide_delta = 0 # stop jumping
if self.rect.y > g.rect.y:
self.health -= 1
print(self.health)
class Enemy(pygame.sprite.Sprite):
'''
Spawn an enemy
'''
def __init__(self,x,y,img):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(os.path.join('images',img))
#self.image.convert_alpha()
#self.image.set_colorkey(ALPHA)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.counter = 0
def move(self):
'''
enemy movement
'''
distance = 80
speed = 8
if self.counter >= 0 and self.counter <= distance:
self.rect.x += speed
elif self.counter >= distance and self.counter <= distance*2:
self.rect.x -= speed
else:
self.counter = 0
self.counter += 1
class Level():
def bad(lvl,eloc):
if lvl == 1:
enemy = Enemy(eloc[0],eloc[1],'yeti.png') # spawn enemy
enemy_list = pygame.sprite.Group() # create enemy group
enemy_list.add(enemy) # add enemy to group
if lvl == 2:
print("Level " + str(lvl) )
return enemy_list
def loot(lvl,lloc):
print(lvl)
def ground(lvl,gloc,tx,ty):
ground_list = pygame.sprite.Group()
i=0
if lvl == 1:
while i < len(gloc):
ground = Platform(gloc[i],worldy-ty,tx,ty,'ground.png')
ground_list.add(ground)
i=i+1
if lvl == 2:
print("Level " + str(lvl) )
return ground_list
def platform(lvl,tx,ty):
plat_list = pygame.sprite.Group()
ploc = []
i=0
if lvl == 1:
ploc.append((0,worldy-ty-128,3))
ploc.append((300,worldy-ty-256,3))
ploc.append((500,worldy-ty-128,4))
while i < len(ploc):
j=0
while j <= ploc[i][2]:
plat = Platform((ploc[i][0]+(j*tx)),ploc[i][1],tx,ty,'ground.png')
plat_list.add(plat)
j=j+1
print('run' + str(i) + str(ploc[i]))
i=i+1
if lvl == 2:
print("Level " + str(lvl) )
return plat_list
'''
Setup
'''
worldx = 960
worldy = 720
fps = 40 # frame rate
ani = 4 # animation cycles
clock = pygame.time.Clock()
pygame.init()
main = True
BLUE = (25,25,200)
BLACK = (23,23,23 )
WHITE = (254,254,254)
ALPHA = (0,255,0)
world = pygame.display.set_mode([worldx,worldy])
backdrop = pygame.image.load(os.path.join('images','stage.png')).convert()
backdropbox = world.get_rect()
player = Player() # spawn player
player.rect.x = 0
player.rect.y = 0
player_list = pygame.sprite.Group()
player_list.add(player)
steps = 10 # how fast to move
eloc = []
eloc = [200,20]
gloc = []
#gloc = [0,630,64,630,128,630,192,630,256,630,320,630,384,630]
tx = 64 #tile size
ty = 64 #tile size
i=0
while i <= (worldx/tx)+tx:
gloc.append(i*tx)
i=i+1
enemy_list = Level.bad( 1, eloc )
ground_list = Level.ground( 1,gloc,tx,ty )
plat_list = Level.platform( 1,tx,ty )
'''
Main loop
'''
while main == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit()
main = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == ord('a'):
print("LEFT")
player.control(-steps,0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
print("RIGHT")
player.control(steps,0)
if event.key == pygame.K_UP or event.key == ord('w'):
print('jump')
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == ord('a'):
player.control(steps,0)
if event.key == pygame.K_RIGHT or event.key == ord('d'):
player.control(-steps,0)
if event.key == pygame.K_UP or event.key == ord('w'):
player.jump(plat_list)
if event.key == ord('q'):
pygame.quit()
sys.exit()
main = False
world.blit(backdrop, backdropbox)
player.gravity() # check gravity
player.update()
player_list.draw(world)
enemy_list.draw(world)
ground_list.draw(world)
plat_list.draw(world)
for e in enemy_list:
e.move()
pygame.display.flip()
clock.tick(fps)
The original images are from here https://opengameart.org/sites/default/files/opp2_sprites.zip but I have separated in imgur for easy explanation:
content folder images:
For enemy (sprit) is yeti.png:
For background is stage.png: https://imgur.com/YyiEJ0q
and the image of the player: spr.png:
To do a jump, self.collide_delta and self.jump_delta have to be less than 6. See your code:
if self.collide_delta < 6 and self.jump_delta < 6:
self.jump_delta = 6*2
The issue is that self.collide_delta is not set 0, when the player hits a platform:
(in the 2nd case)
plat_hit_list = pygame.sprite.spritecollide(self, plat_list, False)
for p in plat_hit_list:
self.rect.bottom = p.rect.top
self.collide_delta = 0 # <----- this is missing
I am trying to create a retro style 2d shooter game and am currently making a homing missile. I need to randomly select a sprite from a group (pygame.sprite.Group) and find out its x and y coords. I have already made it home in on these coords so I do not need help with that. My code is:
an Enemy class (they are all the same just with different sizes and pictures):
class EnemyShipLevel1(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("C:/Users /Me/PycharmProjects/Game folder/SpaceShip game/Enemy1.png")
self.rect = self.image.get_rect()
self.rect.y = -50
self.rect.centerx = random.randint(15, SCREEN_WIDTH-15)
self.change_y = 0
self.cooldown = 0
self.targetx = 500
self.health = 1
if self.targetx >= self.rect.centerx:
self.change_x = 2
else:
self.change_x = -2
def update(self):
self.rect.x += self.change_x
self.rect.y += self.change_y
if self.rect.centery < 200:
self.rect.centery += 2
self.get_target()
if self.targetx > self.rect.centerx+10:
self.change_x = 3
elif self.targetx < self.rect.centerx-10:
self.change_x = -3
else:
self.change_x = 0
self.cooldown -= 1
if self.rect.left < screen_rect.left:
self.change_x = -self.change_x
if self.rect.right > screen_rect.right:
self.change_x = -self.change_x
if self.cooldown < 0 and (self.rect.centerx-50 < self.targetx < self.rect.centerx+50) and player.trans is False:
self.cooldown = random.randint(15, 25)
laser = NormalLaser(self.rect.centery, self.rect.centerx, False, 0, 8)
all_sprite_list.add(laser)
enemy_laser_list.add(laser)
player_laser_hit_list = pygame.sprite.spritecollide(self, player_laser_list, True)
for laser in player_laser_hit_list:
if self.health < 1:
all_sprite_list.remove(self)
enemy_list.remove(self)
else:
self.health -= 1
def get_target(self):
self.targetx = player.rect.centerx
Targeting Laser class (I know you can't bend lasers):
class TargetingLaser(pygame.sprite.Sprite):
def __init__(self, start_x, start_y, dest_x, dest_y):
super().__init__()
self.floating_point_x = start_x
self.floating_point_y = start_y
self.x_diff = dest_x - start_x
self.y_diff = dest_y - start_y
self.angle = math.atan2(self.y_diff, self.x_diff)
self.velocity = 10
self.change_x = math.cos(self.angle) * self.velocity
self.change_y = math.sin(self.angle) * self.velocity
self.image = pygame.image.load("C:/Users/Minecraft/PycharmProjects/Game folder/SpaceShip game/Laser.png")
self.image = pygame.transform.rotate(self.image, -(math.degrees(self.angle)+90))
self.rect = self.image.get_rect()
self.rect.centerx = start_x
self.rect.centery = start_y
def update(self):
self.floating_point_y += self.change_y
self.floating_point_x += self.change_x
self.rect.y = int(self.floating_point_y)
self.rect.x = int(self.floating_point_x)
if self.rect.top < screen_rect.top:
player_laser_list.remove(self)
enemy_laser_list.remove(self)
all_sprite_list.remove(self)
if self.rect.bottom > screen_rect.bottom:
player_laser_list.remove(self)
all_sprite_list.remove(self)
enemy_laser_list.remove(self)
if self.rect.left < screen_rect.left:
player_laser_list.remove(self)
all_sprite_list.remove(self)
enemy_laser_list.remove(self)
if self.rect.right > screen_rect.right:
player_laser_list.remove(self)
all_sprite_list.remove(self)
enemy_laser_list.remove(self)
Game Loop:
all_sprite_list = pygame.sprite.Group()
enemy_list = pygame.sprite.Group()
player_list = pygame.sprite.GroupSingle()
player_laser_list = pygame.sprite.Group()
enemy_laser_list = pygame.sprite.Group()
live_list = pygame.sprite.Group()
health_bar_list = pygame.sprite.GroupSingle()
screen = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
screen_rect = screen.get_rect()
pygame.display.set_caption('Game')
clock = pygame.time.Clock()
Play = True
player = Player(SCREEN_WIDTH/2, SCREEN_HEIGHT-30)
all_sprite_list.add(player)
player_list.add(player)
for counter in range(2):
enemy = EnemyShipLevel1()
all_sprite_list.add(enemy)
enemy_list.add(enemy)
live1 = LivesIcon(5, 0, 1)
live_list.add(live1)
live1 = LivesIcon(27, 30, 2)
live_list.add(live1)
live1 = LivesIcon(50, 0, 3)
live_list.add(live1)
live1 = LivesIcon(72, 30, 4)
live_list.add(live1)
live1 = LivesIcon(95, 0, 5)
live_list.add(live1)
all_sprite_list.add(live_list)
health_bar = PlayerHealthBar(0, 690)
all_sprite_list.add(health_bar)
health_bar_list.add(health_bar)
ship = EnemyShipLevel3()
all_sprite_list.add(ship)
enemy_list.add(ship)
while Play is True:
# Shooting
if player.shooting is True:
if player.laser_cooldown < 0:
player.laser_cooldown = 5
if player.last_shot == "left":
player.last_shot = "right"
laser = NormalLaser(player.rect.centery-2, player.rect.centerx + 11, True, 0, 8)
all_sprite_list.add(laser)
player_laser_list.add(laser)
else:
player.last_shot = "left"
laser = NormalLaser(player.rect.centery-2, player.rect.centerx - 11, True, 0, 8)
all_sprite_list.add(laser)
player_laser_list.add(laser)
if player.rocket_cooldown < 0:
player.rocket_cooldown = 15
for counter in range(10):
laser = TargetingLaser(player.rect.centerx,player.rect.centery, player.rect.centerx, 0)
all_sprite_list.add(laser)
player_laser_list.add(laser)
# Shooting
# Levels
if len(enemy_list) == 0:
all_sprite_list.remove(enemy_laser_list)
all_sprite_list.remove(player_laser_list)
enemy_laser_list.empty()
player_laser_list.empty()
player.level += 1
for counter in range(player.spawn_enemies1):
enemy = EnemyShipLevel1()
all_sprite_list.add(enemy)
enemy_list.add(enemy)
for counter in range(player.spawn_enemies2):
enemy2 = EnemyShipLevel2()
all_sprite_list.add(enemy2)
enemy_list.add(enemy2)
for counter in range(player.spawn_enemies3):
ship = EnemyShipLevel3()
all_sprite_list.add(ship)
enemy_list.add(ship)
if player.level == 2:
player.spawn_enemies1 = 3
player.spawn_enemies2 = 1
if player.level == 3:
player.spawn_enemies1 = 5
player.spawn_enemies2 = 2
if player.level == 4:
player.spawn_enemies1 = 10
player.spawn_enemies2 = 5
if player.level == 5:
player.spawn_enemies1 = 12
player.spawn_enemies2 = 8
player.spawn_enemies3 = 1
# Levels
# End Game
if player.lives == 0:
Play = False
# End Game
# Keys
for event in pygame.event.get():
if event.type == pygame.QUIT:
Play = False
elif event.type == pygame.KEYDOWN:
if (event.key == pygame.K_a) or (event.key == pygame.K_LEFT):
player.change_x = -5
elif (event.key == pygame.K_d) or (event.key == pygame.K_RIGHT):
player.change_x = 5
if event.key == pygame.K_SPACE:
player.shooting = True
elif event.type == pygame.KEYUP:
player.rotation = 0
player.change_x = 0
player.change_y = 0
if event.key == pygame.K_SPACE:
player.shooting = False
# Keys
all_sprite_list.update()
screen.fill(BLACK)
all_sprite_list.draw(screen)
enemy_laser_list.draw(screen)
player_laser_list.draw(screen)
pygame.display.update()
clock.tick(60)
quit()
Each time you kill all of the spawned enemies then the game spawns in more and adds them to enemy_list().
If you are asking how to randomly choose a sprite then use a random.randint(0, 30) (or the number of sprites) then do a long series of if statements. Example Code.
import random
import pygame
class Enemy:
def __init__()
random_sprite = random.randint(0, 1)
# Then put in two variables which equal to the png (I will use sprite1 and sprite2)
def sprite_render
if random_sprite == 0:
# Just blit sprite1
elif random_sprite == 1:
# Just blit sprite2
(The reason why I just commented the actions for the image stuff is because almost everyone does it in a different way and that is not the main point of this answer.)
You could assign a number attribute to each enemy.
For example, you could start off your enemy function like this:
class EnemyShipLevel1(pygame.sprite.Sprite):
number = None
def __init__(self,number):
super().__init__()
self.number = number
self.image = pygame.image.load("C:/Users /Me/PycharmProjects/Game folder/SpaceShip game/Enemy1.png")
Now when you spawn in the enemies, you would add the number attribute:
for counter in range(2): # change this number to use more than 2 enemies (I use 30 later)
enemy = EnemyShipLevel1(counter)
all_sprite_list.add(enemy)
enemy_list.add(enemy)
All you have to do is randomly choose the sprite:
choice = random.randrange(0,30) # between 0 and the number of enemies spawned
for i in enemy_list:
if i.number == choice:
# make i the target of the laser
target_x = i.rect.x
target_y = i.rect.y
This question already has answers here:
Animated sprite from few images
(4 answers)
How can I load an animated GIF and get all of the individual frames in Pygame?
(3 answers)
How do I make a sprite as a gif in pygame? [duplicate]
(2 answers)
Closed 2 years ago.
I am currently working on a game and I am adding player animation and trying to use pyganim for the animations. I have the images I want to use for left idle, right idle, left running, right running. Here is the code for my Player:
import pygame, time
import pygame.mixer
from bullet import Bullet
from constants import *
# Player
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gravity):
pygame.mixer.init()
# Player dimensions and position
# Player image and animation
self.images = []
self.images.append(pygame.image.load('data/images/Sprites/player.png'))
self.images.append(pygame.image.load('data/images/Sprites/player2.png'))
self.maxImage = len(self.images)
self.currentImage = 0
self.jumpSound = pygame.mixer.Sound('data/sounds/jump.ogg')
self.shootSound = pygame.mixer.Sound('data/sounds/laser.ogg')
self.power = POWER_NONE
#~ self.rect = pygame.Rect(x, y, 80, 80)
self.rect = self.images[0].get_rect()
self.rect.x = x
self.rect.y = y
self.timeTarget = 10
self.timeNum = 0
self.velX = 0
self.velY = 0
self.friction = 1
self.health = 200
self.lives = 3
self.score = 0
self.second = 1000
self.minute = 60000
self.start_alivetime = pygame.time.get_ticks()
self.start_alivetime2 = pygame.time.get_ticks()
self.direction = DIR_RIGHT
# Jump and gravity
self.jumping = False
self.on_ground = False
self.origJumpVel = 17
self.jumpVel = self.origJumpVel
self.gravity = 0.5
# Jump inputs
def do_jump(self):
if self.jumping and not self.on_ground:
self.velY = -self.jumpVel
self.jumpVel -= self.gravity
if self.on_ground:
self.jumping = False
self.jumpVel = self.origJumpVel
self.velY = 0
self.on_ground = True
def handle_events(self, event):
key = pygame.key.get_pressed()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
self.jumpSound.play(0)
if not self.jumping:
self.jumping = True
self.on_ground = False
if event.key == pygame.K_s:
self.shootSound.play(0)
if key[pygame.K_a]:
self.velX = -7
if key[pygame.K_d]:
self.velX = +7
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
self.shootSound.play(0)
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.velX = 0
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
bullet.velX = 0
# PLayer updates
def update(self):
#self.timeNum += 1
# Animations
#if self.direction == DIR_LEFT:
#if self.timeNum == self.timeTarget:
#self.currentImage += 1
#if self.currentImage >= self.maxImage:
#self.currentImage = 0
#self.timeNum = 0
# Timer
if self.health > 0:
self.alivetime = (pygame.time.get_ticks() - self.start_alivetime) / self.second
if self.health <= 0:
self.alivetime = pygame.time.get_ticks() + 0
self.start_alivetime = self.alivetime
# Screen wrap
if self.rect.right > 1280:
self.rect.left = 0
elif self.rect.left < 0:
self.rect.right = 1280
if self.velX < 0 and self.direction != DIR_RIGHT: # Moving right
self.direction = DIR_RIGHT
self.images[self.currentImage] = pygame.transform.flip(self.images[self.currentImage], True, False)
elif self.velX > 0 and self.direction != DIR_LEFT: # Moving left
self.direction = DIR_LEFT
self.images[self.currentImage] = pygame.transform.flip(self.images[self.currentImage], True, False)
# Player rendering
def render(self, surface):
surface.blit(self.images[self.currentImage], self.rect)
Here are the two images for my player animation (Running left):
Hello I am currently making a survival shooter but cannot find any way on how to do my collisions! I am trying to make the player collide with the floors but with no success. Here is an image of the map (I want to collide with moon blocks):
http://i.stack.imgur.com/R2apz.jpg
Here is an image of moon blocks with no Background:
http://i.stack.imgur.com/W9H2m.png
And finally here is my code:
import pygame
import random
gravity = .5
jump_time = 2000
x = 0
y = 0
# Player
class Player(pygame.sprite.Sprite):
def __init__(self, x, y, gravity):
# Player dimensions and position
self.gravity = gravity
# Player image and animation
self.images = []
self.images.append(pygame.image.load('images/player.png'))
self.images.append(pygame.image.load('images/player2.png'))
#~ self.images.append(pygame.image.load('ball1.png'))
#~ self.images.append(pygame.image.load('ball2.png'))
self.maxImage = len(self.images)
self.currentImage = 0
#~ self.rect = pygame.Rect(x, y, 80, 80)
self.rect = self.images[0].get_rect()
self.rect.x = x
self.rect.y = y
self.timeTarget = 10
self.timeNum = 1
self.velX = 0
self.velY = 0
# Jump and gravity
self.vSpeed = 3
self.jumpForce = 15
self.maxVspeed = 3
self.isJumping = False
# Jump inputs
def handle_events(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
if not self.isJumping:
self.isJumping = True
elif event.key == pygame.K_a:
self.velX = -5
elif event.key == pygame.K_d:
self.velX = +5
elif event.type == pygame.KEYUP:
if event.key in (pygame.K_a, pygame.K_d):
self.velX = 0
# PLayer updates
def update(self, ground):
keys = pygame.key.get_pressed()
# Jumping
self.vSpeed += gravity
if self.vSpeed > self.maxVspeed:
self.vSpeed = self.maxVspeed
self.rect.y += self.vSpeed
if self.rect.y >= ground.y:
self.vSpeed = 0
self.rect.y = ground.y
self.isJumping = False
if keys[pygame.K_SPACE]:
if not self.isJumping:
self.isJumping = True
if self.isJumping:
if pygame.time.get_ticks() < jump_time:
self.isJumping == True
else:
self.isJumping = False
self.vSpeed -= self.jumpForce
#print "isJumping:", self.isJumping
# Animations
if self.timeNum == self.timeTarget:
self.currentImage += 1
if self.currentImage >= self.maxImage:
self.currentImage = 0
self.timeNum = 0
self.rect.centerx += self.velX
self.rect.centery += self.velY
# Screen wrap
if self.rect.right > 1280:
self.rect.left = 0
elif self.rect.left < 0:
self.rect.right = 1280
# Player rendering
def render(self, surface):
surface.blit(self.images[self.currentImage], self.rect)
#----------------------------------------------------------------------
class Zombie():
def __init__(self, x, y):
self.image = pygame.image.load('images/zombie.png')
#~ self.image = pygame.image.load('ball2.png')
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.direction_left = True
def update(self, surface_rect):
if self.direction_left:
self.rect.x -= 1
if self.rect.left <= surface_rect.left:
self.direction_left = not self.direction_left
else:
self.rect.x += 1
if self.rect.right >= surface_rect.right:
self.direction_left = not self.direction_left
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Background():
def __init__(self):
self.image = pygame.image.load('images/arena2.jpg')
#~ self.image = pygame.image.load('background.jpg')
self.rect = self.image.get_rect()
def render(self, surface):
surface.blit(self.image, self.rect)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
# A few variables
self.gravity = .50
self.ground = pygame.Rect(0, 640, 1280, 80)
# Screen
size = (1280, 720)
self.screen = pygame.display.set_mode(size)
pygame.display.set_caption('Moon Survival!')
# Moon / Background
self.moon = Background()
# Zombies
self.zombies = []
for i in range(10):
self.zombies.append( Zombie(random.randint(0,1280), random.randint(0,720)) )
# Player
self.player = Player(25, 320, self.gravity)
# Font for text
self.font = pygame.font.SysFont(None, 72)
# Pause - center on screen
self.pause_text = self.font.render("PAUSE", -1, (255,0,0))
self.pause_rect = self.pause_text.get_rect(center = self.screen.get_rect().center)
def run(self):
clock = pygame.time.Clock()
# "state machine"
RUNNING = True
PAUSED = False
GAME_OVER = False
# Game loop
while RUNNING:
# (all) Events
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
elif event.key == pygame.K_p:
PAUSED = not PAUSED
# Player/Zomies events
if not PAUSED and not GAME_OVER:
self.player.handle_events(event)
# (all) Movements / Updates
if not PAUSED and not GAME_OVER:
self.player.update(self.ground)
for z in self.zombies:
z.update(self.screen.get_rect())
# (all) Display updating
self.moon.render(self.screen)
for z in self.zombies:
z.render(self.screen)
self.player.render(self.screen)
if PAUSED:
self.screen.blit(self.pause_text, self.pause_rect)
pygame.display.update()
# FTP
clock.tick(100)
# --- the end ---
pygame.quit()
#---------------------------------------------------------------------
Game().run()
Any help will be greatly appreciated, thank you.
I made a very similar game for PyWeek #17 called "Miner".
Here's a screenshot: http://media.pyweek.org/dl/17/powrtoch/miner_ss.png (you can see the similarity!)
You can find the relevant code on GitHub here: https://github.com/marcusmoller/pyweek17-miner/blob/master/miner/engine.py#L202-L220:
def checkCollision(self, sprite, xVel, yVel):
for x in range(len(level.levelStructure)):
for y in range(len(level.levelStructure[x])):
block = level.levelStructure[x][y]
if block is not None:
if pygame.sprite.collide_rect(sprite, block):
if xVel < 0:
sprite.rect.x = block.rect.x + block.rect.w
if xVel > 0:
sprite.rect.x = block.rect.x - sprite.rect.w
if yVel < 0:
sprite.rect.y = block.rect.y + block.rect.h
if yVel > 0 and not sprite.onGround:
sprite.onGround = True
sprite.rect.y = block.rect.y - sprite.rect.h
You could do something like this using collide_rect:
# See if the Sprite block collides with anything in the Ground block_list
for block in groundBlocks:
if(collide_rect(player, block)):
# do not fall
else:
# fall
where all Block you can walk on are in the groundBlocks list.
I have two sprites, a cat and a mouse, and I'm trying to make the cat chase the mouse. The cat should move towards the mouse and try to "catch" it no matter where the mouse is. If the mouse is above the cat, the cat will move up to try to "catch" it. The program runs and I can move the mouse with my arrow keys, but the cat won't move. Here is my code:
from pygame import *
size_x = 800
size_y = 600
class Object:
def disp(self, screen):
screen.blit(self.sprite, self.rect)
class Cat(Object):
def __init__(self):
self.sprite = image.load("cat.bmp")
self.rect = self.sprite.get_rect()
self.rect.centerx = size_x / 2
self.rect.centery = size_y / 2
self.move_x = 0
self.move_y = 0
def cycle(self):
# self.rect.centerx = 500 - abs(self.count)
# self.count += 2
# if self.count > 400:
# self.count = -400
self.rect.centerx += self.move_x
if self.rect.centerx < 0:
self.rect.centerx = 800
# self.rect.centery = 500 - abs(self.count)
# self.count += 2
# if self.count > 400:
# self.count = -400
self.rect.centery += self.move_y
if self.rect.centery < 0:
self.rect.centery = 800
def chase(self, mouse):
#These should move the cat towards the mouse.
#If the cat is to the left of the mouse, this should move the cat right.
if self.rect.centerx < mouse.rect.centerx:
self.move_x += 3
#If the cat is to the right of the mouse, this should move the cat left.
elif self.rect.centerx > mouse.rect.centerx:
self.move_x -= 3
#If the cat is above the mouse, this should move the cat down.
if self.rect.centery < mouse.rect.centery:
self.move_y += 3
#If the cat is below the mouse, this should move the cat up.
elif self.rect.centery > mouse.rect.centery:
self.move_y -= 3
class Mouse(Object):
def __init__(self):
self.sprite = image.load("mouse.bmp")
self.rect = self.sprite.get_rect()
self.rect.centerx = 100
self.rect.centery = 100
self.count = 0
self.move_x = 0
self.move_y = 0
def checkwith(self, otherrect):
if self.rect.colliderect(otherrect):
exit()
def cycle(self):
# self.rect.centerx = 500 - abs(self.count)
# self.count += 2
# if self.count > 400:
# self.count = -400
self.rect.centerx += self.move_x
if self.rect.centerx < 0:
self.rect.centerx = 800
# self.rect.centery = 500 - abs(self.count)
# self.count += 2
# if self.count > 400:
# self.count = -400
self.rect.centery += self.move_y
if self.rect.centery < 0:
self.rect.centery = 800
def right(self):
self.move_x += 10
def left(self):
self.move_x -= 10
def up(self):
self.move_y -= 10
def down(self):
self.move_y += 10
def stop_x(self):
self.move_x = 0
def stop_y(self):
self.move_y = 0
init()
screen = display.set_mode((size_x, size_y))
c = Cat()
m = Mouse()
clock = time.Clock()
while True:
for e in event.get():
if e.type == QUIT:
quit()
if e.type == KEYDOWN:
if e.key == K_RIGHT:
m.right()
elif e.key == K_LEFT:
m.left()
elif e.key == K_UP:
m.up()
elif e.key == K_DOWN:
m.down()
if e.type == KEYUP:
if e.key == K_RIGHT or e.key == K_LEFT:
m.stop_x()
if e.key == K_UP or e.key == K_DOWN:
m.stop_y()
c.chase(m)
m.cycle()
screen.fill((255,255,255))
m.disp(screen)
c.disp(screen)
display.flip()
clock.tick(60)
Your Cat class doesn't update its rect, like you do for the Mouse in Mouse.cycle().
Just copy-paste the cycle() method to the Cat class, and add c.cycle() to your main loop.
Shouldn't you have
self.rect.centerx += self.move_x
somewhere in the Cat class? (same for y of course)