Pygame: Timer For Time Alive - python

Hello I am currently making a game in python and I am trying to make a timer which I have never attempted before, hence asking this question. What I really need to know is how to loop this small area where it says #Timer. Any help will be appreciated, thank you.
import pygame, time
import pygame.mixer
from bullet import Bullet
from constants import DIR_LEFT, DIR_RIGHT
# 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('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.jumpSound = pygame.mixer.Sound('sounds/jump.ogg')
self.shootSound = pygame.mixer.Sound('sounds/laser.ogg')
#~ 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.health = 200
self.score = 0
self.alivetime = 0
self.second = 1000
self.direction = DIR_RIGHT
# 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:
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)
elif event.key == pygame.K_a:
#pygame.transform.flip(self.images[self.currentImage], False, False)
self.velX = -5
elif event.key == pygame.K_d:
#pygame.transform.flip(self.images[self.currentImage], True, False)
self.velX = +5
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 pygame.time.get_ticks() >= self.second:
self.alivetime = +1
pygame.time.get_ticks() == 0
# 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)

Run player.update() in mainloop in every loop and Timer will loop too.
By The Way:
if you try to set tick to zero in this
pygame.time.get_ticks() == 0
than you are wrong. You can't change number of ticks.
Use this
# __init__()
self.time_to_change_alivetime = pygame.time.get_ticks() + self.second
# update()
if pygame.time.get_ticks() >= self.time_to_change_alivetime:
self.alivetime += 1
self.time_to_change_alivetime += self.second
or this (without if)
# __init__()
self.start_alivetime = pygame.time.get_ticks()
# update()
self.alivetime = (pygame.time.get_ticks() - self.start_alivetime) / self.second
or more precisely (1 minute = 60 seconds = 60 000 milliseconds)
# __init__()
self.start_alivetime = pygame.time.get_ticks()
# update()
milliseconds = pygame.time.get_ticks() - self.start_alivetime
self.alivetime_minutes = milliseconds / 60000
self.alivetime_seconds = (milliseconds % 60000) / self.second
self.alivetime_milliseconds = milliseconds % self.second

Related

How can I go back and forth between modules in pygame?

I'm trying to make a Home Screen for two games in pygame, I changed the first game's name to module1 in the code Im providing and the Home Screen to Mainscreen
module1 is already done and now I'm just trying to get the Main Menu script to import the maingame when I click on the play button that I already have on the screen display, then when I finish the game (health reaches 0) , if I want to go back to the Main Menu I should just click anywhere on the "game over" screen that should appear when health reaches 0 or press escape.
here is what I tried:
this is the whole game script, the game loop is at the end of the script and sorry for how messy it is:
# Pygame skeleton
import pygame
import math
import random
import sys
import os
pygame.init()
pygame.mixer.init()
vec = pygame.math.Vector2
# Constants
WIDTH = 1306
HEIGHT = 526
FPS_INGAME = 60
FPS_HOMESCREEN = 30
FULL_SCREEN = (0,0)
bullet_img = pygame.image.load('Bullet.png')
jump = False
bullet_timer = 0
score = 0
moving_left = False
moving_right = False
shoot = False
acceleration = 0.7
friction = -0.1
gravity = 9.8
platform_color = (150,59,230)
# Classes and Sprites
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.shoot_cooldown = 0
self.anime = []
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
self.action = 0
animation_types = ["Shoot","Go"]
for animation in animation_types:
temp_list = []
num_of_frames = len(os.listdir(f'MySprite/{animation}'))
for i in range(1,num_of_frames):
img = pygame.image.load(f'MySprite/{animation}/{i}.png')
temp_list.append(img)
self.anime.append(temp_list)
self.direction = 1
self.flip = False
self.image = self.anime[self.action][self.frame_index]
self.rect = self.image.get_rect()
# vectors and sprite constants
self.health = 100
self.pos = vec(WIDTH/2, HEIGHT/2)
self.vel_vec = vec(0,0)
self.acc_vec = vec(0,0)
def jump(self):
self.rect.y += 1
hits = pygame.sprite.spritecollide(player_group.sprite, platform_group,False)
self.rect.y -= -1
if hits:
self.vel_vec.y = -15
def screen_edge(self):
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
def get_damage(self,damage_mag):
self.health -= damage_mag
def update(self):
animation_cooldown = 75
self.image = self.anime[self.action][self.frame_index]
if pygame.time.get_ticks() - self.update_time >= animation_cooldown:
self.update_time = pygame.time.get_ticks()
self.frame_index += 1
if self.frame_index >= len(self.anime[self.action]):
self.frame_index = 0
if self.shoot_cooldown > 0:
self.shoot_cooldown -= 1
def update_action(self,new_action):
if new_action != self.action:
self.action = new_action
self.frame_index = 0
self.update_time = pygame.time.get_ticks()
def move(self,moving_left,moving_right):
self.acc_vec = vec(0,acceleration)
if moving_left:
self.acc_vec.x = -(acceleration)
self.direction = 1
self.flip = False
if moving_right:
self.acc_vec.x = acceleration
self.direction = -1
self.flip = True
self.acc_vec.x += self.vel_vec.x * friction
self.vel_vec += self.acc_vec
self.pos += self.vel_vec + 0.5 * self.acc_vec
self.rect.midbottom = self.pos
hits = pygame.sprite.spritecollide(player_group.sprite, platform_group,False)
if hits:
self.pos.y = hits[0].rect.top
self.vel_vec.y = 0
def draw(self):
screen.blit(pygame.transform.flip(self.image,self.flip,False),self.rect)
class Platform(pygame.sprite.Sprite):
def __init__(self,x,y,w,h):
super().__init__()
self.image = pygame.Surface((w,h))
self.image.fill(platform_color)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
class Hostiles(pygame.sprite.Sprite):
def __init__(self,x_pos,y_pos,speed):
super(Hostiles,self).__init__()
self.images = []
self.images.append(pygame.image.load('MySprite/images/go_1.png'))
self.images.append(pygame.image.load('MySprite/images/go_2.png'))
self.images.append(pygame.image.load('MySprite/images/go_3.png'))
self.images.append(pygame.image.load('MySprite/images/go_4.png'))
self.images.append(pygame.image.load('MySprite/images/go_5.png'))
self.images.append(pygame.image.load('MySprite/images/go_6.png'))
self.images.append(pygame.image.load('MySprite/images/go_7.png'))
self.images.append(pygame.image.load('MySprite/images/go_8.png'))
self.images.append(pygame.image.load('MySprite/images/go_9.png'))
self.images.append(pygame.image.load('MySprite/images/go_10.png'))
self.index = 0
self.image = self.images[self.index]
self.rect = self.image.get_rect(center = (x_pos,y_pos))
self.speed = speed
def update(self):
self.index += 1
if self.index >= len(self.images):
self.index = 0
self.image = self.images[self.index]
self.rect.centerx += self.speed
if self.rect.centerx >= 1350 or self.rect.centerx <= -50:
self.kill()
class Hostiles2(pygame.sprite.Sprite):
def __init__(self,x_pos,y_pos,speed):
super(Hostiles2,self).__init__()
self.images2 = []
self.images2.append(pygame.image.load('MySprite/images2/go_1.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_2.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_3.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_4.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_5.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_6.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_7.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_8.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_9.png'))
self.images2.append(pygame.image.load('MySprite/images2/go_10.png'))
self.index = 0
self.image = self.images2[self.index]
self.rect = self.image.get_rect(center = (x_pos,y_pos))
self.speed = speed
def update(self):
self.index += 1
if self.index >= len(self.images2):
self.index = 0
self.image = self.images2[self.index]
self.rect.centerx += self.speed
if self.rect.centerx >= 1350 or self.rect.centerx <= -50:
self.kill()
class Bullets(pygame.sprite.Sprite):
def __init__(self,x,y,direction):
super().__init__()
self.speed = 10
self.image = bullet_img
self.rect = self.image.get_rect(center = (x,y))
self.direction = direction
def update(self):
self.rect.x -= (self.direction * self.speed)
if self.rect.left >= WIDTH or self.rect.right <= 0:
self.kill()
screen.blit(self.image,self.rect)
# Functions
def make_text(font_type,font_size,text,color,position):
font = pygame.font.Font(font_type, font_size)
title = font.render(text,True,(color))
title_rect = title.get_rect(center = (position))
screen.blit(title,title_rect)
def main_game():
pygame.draw.rect(screen,(255,0,0),(22,20,200,10))
pygame.draw.rect(screen,platform_color,(22,20,2 * player_group.sprite.health,10))
screen.blit(heart,(0,2))
bullet_group.draw(screen)
player.draw()
hostiles_group.draw(screen)
platform_group.draw(screen)
bullet_group.update()
player_group.update()
hostiles_group.update()
player_group.update()
player.screen_edge()
if shoot:
if player.shoot_cooldown == 0:
bullet = Bullets(player.rect.centerx - (0.6 * player.direction * player.rect.size[0]),player.rect.centery,player.direction)
bullet_group.add(bullet)
player.shoot_cooldown = 40
if moving_left or moving_right:
player.update_action(1)
else:
player.update_action(0)
player.move(moving_left,moving_right)
if pygame.sprite.spritecollide(player_group.sprite,hostiles_group,True):
player_group.sprite.get_damage(10)
pygame.sprite.groupcollide(hostiles_group, bullet_group,True,True)
return 2
def game_over():
screen.fill((0,0,0))
text = gamefont.render("GAME OVER",True,(255,255,255))
text_rect = text.get_rect(center = (653,243))
screen.blit(text,text_rect)
scoresurface = gamefont.render(f"Score: {score}",True,(255,255,255))
score_rect = scoresurface.get_rect(center = (653,283))
screen.blit(scoresurface,score_rect)
# Creating window
screen = pygame.display.set_mode((WIDTH,HEIGHT))
pygame.display.set_caption("game name")
clock = pygame.time.Clock()
# Groups and objects
gamefont = pygame.font.Font('Chernobyl.ttf',40)
player = Player()
platform = Platform(0,HEIGHT-96,WIDTH,100)
platform_group = pygame.sprite.GroupSingle()
platform_group.add(platform)
player_group = pygame.sprite.GroupSingle()
player_group.add(player)
hostiles_group = pygame.sprite.Group()
hostile_event = pygame.USEREVENT
pygame.time.set_timer(hostile_event,300)
bullet_group = pygame.sprite.Group()
pygame.mouse.set_visible(True)
sky = pygame.image.load('SkyNight.png')
wallpaper = pygame.image.load('GamePlatform.png')
heart = pygame.image.load('Heart.png')
# Game loop
running = True
while running:
# Events (Inputs)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == hostile_event:
random_xpos = [-40,-20]
random_xpos2 = [1340,1360]
random_hs = [-2,2]
hostile_left = Hostiles2(random.choice(random_xpos),400,random.choice(random_hs))
hostile_right = Hostiles(random.choice(random_xpos2),400,random.choice(random_hs))
hostiles_group.add(hostile_left,hostile_right)
if event.type == pygame.MOUSEBUTTONDOWN and player_group.sprite.health <= 0:
player_group.sprite.health = 100
hostiles_group.empty()
score = 0
import MainMenu
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
moving_left = True
if event.key == pygame.K_RIGHT:
moving_right = True
if event.key == pygame.K_q:
shoot = True
if event.key == pygame.K_ESCAPE:
running = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
moving_left = False
if event.key == pygame.K_RIGHT:
moving_right = False
if event.key == pygame.K_q:
shoot = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player_group.sprite.jump()
if player_group.sprite.health > 0:
score += main_game()
print (score)
else:
game_over()
pygame.display.update()
screen.blit(sky,FULL_SCREEN)
screen.blit(wallpaper,FULL_SCREEN)
programIcon = pygame.image.load('icon.png')
pygame.display.set_icon(programIcon)
clock.tick(FPS_INGAME)
and this is all the main screen / main menu .py file:
import pygame,sys
pygame.init()
screen = pygame.display.set_mode((1306,526))
clock = pygame.time.Clock()
pygame.mouse.set_visible(True)
screen_home = pygame.image.load('HomeScreen.png')
def make_text(font_type,font_size,text,color,position):
font = pygame.font.Font(font_type, font_size)
title = font.render(text,True,(color))
title_rect = title.get_rect(center = (position))
screen.blit(title,title_rect)
while True:
font1 = pygame.font.Font('Starjedi.ttf',60)
game1 = font1.render("Play",True,(255,255,255))
game1_rect = game1.get_rect(center = (640,300))
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if game1_rect.collidepoint(event.pos):
import MainGame.py
screen.blit(screen_home,(0,0))
screen.blit(game1,game1_rect)
make_text('Chernobyl.ttf',70,"Title Here",(255,255,255),(315,80))
pygame.display.update()
clock.tick(45)
when I run the main menu I get the Home Screen I made, then I click on the on my display screen and it imports the game script and the game starts, when my health reaches 0 and I click on the screen to quit the game loop, it takes me back to the main menu which is exactly what I wanted,however, when I press play again to go back to the game it doesn't work it gives me an error:
ModuleNotFoundError: No module named 'MainGame.py'; 'MainGame' is not a package
I know the code is a mess I'm still new at this I'm sorry if my question wasn't clear enough, any help would be appreciated!
Ok, now that I see your code I can see you have a big problem using import:
You use it like this:
import MainGame.py
Assume the file you created is MainGame.py you supposed to import it this way:
import MainGame
Same goes to
import MainMenu.py
And that's might be the problem, though if you still have an issue, so instead of:
in the game, this is part of the main game loop:
Please copy all of the code, in both files, and write the name of each file next to the code.

How to use groupcollide?

So I've been wondering how to use the pygame groupcollide. And I'm utterly stumped right now. As I am using collide_rect and it is fine. But for groupcollide I can't seem to figure out how to call the properties of the item inside of that group. And I can't do collide rect because there's going to be a lot of bullets.
def check_blast_collisions(player,bullet):
hits = pg.sprite.groupcollide(player,bullet,False,True)
for hit in hits:
print (hits)
if hit.vx == 20:
player.vx += 40
elif hit.vx == -20:
player.vx += -40
Here is a snippet of where I'm trying to use groupcollide.
After I made this function, the bullets don't even show up. (The bullets are supposed to be called blasts but I forgot about it in this function.)
import pygame as pg
#settings
CAPTION = "Knockback Arena"
resolution = 1600,900
WIDTH = resolution[0]
HEIGHT = resolution[1]
FPS = 60
player_jump_height = 30
player_max_fall_speed = 30
player_fall_speed_increase = 2
player_lives = 5
shoot_cooldown = 500
#initialize pygame
pg.init()
pg.mixer.init()
pg.font.init
screen = pg.display.set_mode(resolution)
pg.display.set_caption(CAPTION)
clock = pg.time.Clock()
#sprites
class Platform(pg.sprite.Sprite):
def __init__(self,x,y,width,height,r,g,b):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((width,height))
self.image.fill((r,g,b))
self.rect = self.image.get_rect()
self.rect.center = (x,y)
class Player(pg.sprite.Sprite):
def __init__(self,r,g,b,x,y):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((40, 100))
self.image.fill((r,g,b))
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.startx = x
self.starty = y
self.vx = 0
self.vy = 5
self.vy_max = player_max_fall_speed
self.vy_increase = player_fall_speed_increase
self.lives = player_lives
self.last_shot = 0
self.facing_right = False
self.facing_left = False
def update(self):
self.rect.x += self.vx
self.rect.y += self.vy
if self.vy >= self.vy_max:
self.vy = self.vy_max
self.vy_increase = 0
if self.vy < self.vy_max:
self.vy_increase = player_fall_speed_increase
if self.rect.bottom < HEIGHT:
self.vy += self.vy_increase
if self.rect.top >= HEIGHT:
self.rect.x = self.startx
self.rect.y = self.starty
self.lives -= 1
if self.lives <= 0:
self.kill()
if self.rect.right >= WIDTH:
self.rect.right = WIDTH
self.vx = 0
if self.rect.left <= 0:
self.rect.left = 0
self.vx = 0
def jump(self):
if self.rect.bottom >= main_platform.rect.top:
self.vy -= player_jump_height
if self.rect.bottom >= HEIGHT:
self.vy -= player_jump_height
def shoot(self):
if pg.time.get_ticks() - self.last_shot >= shoot_cooldown:
if self.facing_left == True:
return "shoot_left"
elif self.facing_right == True:
return "shoot_right"
else:
return "cd_not_done"
class Blast(pg.sprite.Sprite):
def __init__(self,player,direction):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface((20,10))
self.image.fill((0,255,255))
self.rect = self.image.get_rect()
self.rect.center = (player.rect.center)
self.direction = direction
if self.direction == 0:
self.vx = -20
elif self.direction == 1:
self.vx = 20
def update(self):
self.rect.x += self.vx
if self.rect.right < 0:
self.kill()
if self.rect.left > WIDTH:
self.kill()
#functions
def check_for_collisions(player,platform):
hits = pg.sprite.collide_rect(player,platform)
if hits:
if hits and player.vy > 0:
player.rect.bottom = platform.rect.top
player.vy = 0
def check_blast_collisions(player,bullet):
hits = pg.sprite.groupcollide(player,bullet,False,True)
for hit in hits:
print (hits)
if hit.vx == 20:
player.vx += 40
elif hit.vx == -20:
player.vx += -40
font = pg.font.Font('font/Roboto-Light.ttf', 30)
all_sprites = pg.sprite.Group()
players = pg.sprite.Group()
platforms = pg.sprite.Group()
blasts = pg.sprite.Group()
main_platform = Platform(WIDTH/2,650,1000,100,0,200,0)
player_1 = Player(0,0,255,WIDTH/2 + -100,200)
player_2 = Player(255,0,0,WIDTH/2 + 100,200)
platforms.add(main_platform)
players.add(player_1)
players.add(player_2)
all_sprites.add(player_1)
all_sprites.add(player_2)
all_sprites.add(main_platform)
menu = True
run = True
while run:
#check for closing window
for event in pg.event.get():
if event.type == pg.KEYDOWN:
if event.key == pg.K_w:
player_1.jump()
if event.key == pg.K_a:
player_1.vx = -10
player_1.facing_left = True
player_1.facing_right = False
elif event.key == pg.K_d:
player_1.vx = 10
player_1.facing_right = True
player_1.facing_left = False
if event.key == pg.K_UP:
player_2.jump()
if event.key == pg.K_LEFT:
player_2.vx = -10
player_2.facing_left = True
player_2.facing_right = False
elif event.key == pg.K_RIGHT:
player_2.vx = 10
player_2.facing_right = True
player_2.facing_left = False
if event.key == pg.K_j:
if player_1.shoot() == "shoot_left":
b = Blast(player_1,0)
all_sprites.add(b)
blasts.add(b)
elif player_1.shoot() == "shoot_right":
b = Blast(player_1,1)
all_sprites.add(b)
blasts.add(b)
if event.key == pg.K_KP1:
if player_2.shoot() == "shoot_left":
b = Blast(player_2,0)
all_sprites.add(b)
blasts.add(b)
elif player_2.shoot() == "shoot_right":
b = Blast(player_2,1)
all_sprites.add(b)
blasts.add(b)
elif event.type == pg.KEYUP:
if event.key == pg.K_a:
player_1.vx = 0
if event.key == pg.K_d:
player_1.vx = 0
if event.key == pg.K_LEFT:
player_2.vx = 0
if event.key == pg.K_RIGHT:
player_2.vx = 0
if event.type == pg.QUIT:
pg.quit()
exit()
#update all sprites
all_sprites.update()
check_for_collisions(player_1,main_platform)
check_for_collisions(player_2,main_platform)
check_blast_collisions(players,blasts)
#draw sprites
screen.fill((255,255,255))
all_sprites.draw(screen)
#draw other stuff
p1lives = font.render(str(player_1.lives), False, (0,0,255))
screen.blit(p1lives,(20,50))
p2lives = font.render(str(player_2.lives), False, (255,0,0))
screen.blit(p2lives,(1580,50))
clock.tick(FPS)
pg.display.flip()
Here is the entire code.
Any help is much appreciated. Thanks.
You cannot use pygame.sprite.groupcollide() here, because the bullets collide with the player that shoots the bullets.
You have to use pygame.sprite.spritecollide(), with one player and the bullets of the opponent. Call it once for each player.

Multiple sprite collision detections

Ok, so I have been trying to figure out how to set this up and can't get it working properly. I'm trying to get the functionality similar to the moving logs in the game Frogger if you are familiar with it. So far what I have works with the collision detection for only one pygame.sprite.Group()
import pygame
import os
import random
os.environ['SDL_VIDEO_CENTERED'] = '1'
WIDTH = 480
HEIGHT = 720
FPS = 60
# Moving Object spacing setup first row
INSTANCE_COUNT = 0
BOX_WIDTH = 30
SPACING = 120
# object speed
pos_objspeed = 1
neg_objspeed = -1
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((30, 30))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH / 2
self.rect.bottom = HEIGHT - 96
self.speedx = 0
self.speedy = 0
class MovingObj_Test(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((90, 30))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = (INSTANCE_COUNT * (SPACING+ BOX_WIDTH))
#self.rect.x = random.randrange(WIDTH)
self.rect.bottom = 384
self.speedx = pos_objspeed
def update(self):
self.rect.x += self.speedx
if self.rect.x >= 480:
self.rect.x = -30
self.rect.bottom = 384
self.speedx = pos_objspeed
class MovingObj_TestTwo(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((90, 30))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = (INSTANCE_COUNT * (SPACING+ BOX_WIDTH))
#self.rect.x = random.randrange(WIDTH)
self.rect.bottom = 336
self.speedx = neg_objspeed
def update(self):
self.rect.x += self.speedx
if self.rect.x >= 480:
self.rect.x = -30
self.rect.bottom = 336
self.speedx = neg_objspeed
all_sprites = pygame.sprite.Group()
movingobj_l = pygame.sprite.Group()
movingobj_r = pygame.sprite.Group()
for i in range (3):
INSTANCE_COUNT = i + 1
obj1 = MovingObj_Test()
all_sprites.add(obj1)
movingobj_l.add(obj1)
for i in range (3):
INSTANCE_COUNT = i + 1
obj2 = MovingObj_TestTwo()
all_sprites.add(obj2)
movingobj_r.add(obj2)
player = Player()
all_sprites.add(player)
running = True
onLogLeft = False
onLogRight = False
groundSpd = 48
while running:
clock.tick(FPS)
hitsleft = pygame.sprite.spritecollide(player, movingobj_l, False, pygame.sprite.collide_rect)
for hit in hitsleft:
player.speedx = pos_objspeed
player.speedy = 0
onLogLeft = True
if len(hitsleft) == 0:
onLogLeft = False
player.speedx = 0
player.speedy = 0
hitsright = pygame.sprite.spritecollide(player, movingobj_r, False, pygame.sprite.collide_rect)
for hit in hitsright:
player.speedx = neg_objspeed
player.speedy = 0
onLogRight = True
if len(hitsright) == 0:
onLogRight = False
player.speedx = 0
player.speedy = 0
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.speedx = -groundSpd
if event.key == pygame.K_RIGHT:
player.speedx = groundSpd
if event.key == pygame.K_UP:
player.speedy = -groundSpd
if event.key == pygame.K_DOWN:
player.speedy = groundSpd
if event.type == pygame.KEYUP and onLogLeft == False and onLogRight == False:
if event.key == pygame.K_LEFT:
player.speedx = 0
if event.key == pygame.K_RIGHT:
player.speedx = 0
if event.key == pygame.K_UP:
player.speedy = 0
if event.key == pygame.K_DOWN:
player.speedy = 0
if onLogLeft == False and onLogRight == False and player.rect.bottom <= 384:
running = False
player.rect.x += player.speedx
player.rect.y += player.speedy
if event.type == pygame.QUIT:
running = False
#player.rect.x += player.speedx
#player.rect.y += player.speedy
all_sprites.update()
screen.fill(BLACK)
all_sprites.draw(screen)
pygame.display.flip()
pygame.quit()
quit()
Ok so in my code the
hitsright = pygame.sprite.spritecollide(player, movingobj_r, False, pygame.sprite.collide_rect)
checks the collision and updates the players speed how I'm expecting it to but, the
hitsleft = pygame.sprite.spritecollide(player, movingobj_l, False, pygame.sprite.collide_rect)
is not doing the same.
I'm confused as to why this is if anyone has any ideas. Also how could I fix it to work for both?
The code for left and right behaves different, because if a collision with hitsleft is detected, the player.speedx is set:
for hit in hitsleft:
player.speedx = pos_objspeed
But if there is a collision with hitsleft there it no collision with hitsright and player.speedx is reset immediately:
if len(hitsright) == 0:
onLogRight = False
player.speedx = 0
You have to set player.speedx dependent on both conditions (e.g. in a if - elif - else statement):
while running:
# [...]
hitsleft = pygame.sprite.spritecollide(player, movingobj_l, False, pygame.sprite.collide_rect)
onLogLeft = any(hitsleft)
hitsright = pygame.sprite.spritecollide(player, movingobj_r, False, pygame.sprite.collide_rect)
onLogRight = any(hitsright)
player.speedy = 0
if onLogLeft:
player.speedx = pos_objspeed
elif onLogRight:
player.speedx = neg_objspeed
else:
player.speedx = 0

Pygame velocity and collision trouble

i am currentely making my final project for my exam and i'm making a platform game. Actually i'm made the collisions and it works. But the actual problem is that if i jump on a platform and i keep my player static for 1 second the player disappears which is weird. Could you help me to solve this issue? I have a hint that this issue is related to the velocity (calles vitesse_x and vitesse_y).
import pygame
from pygame.locals import *
pygame.init()
fenetre = pygame.display.set_mode((1024,768))
pygame.display.set_caption("Portal Escape")
class Perso(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50,50))
self.rect = self.image.get_rect(bottomleft=(0,740))
self.image.fill((255, 0, 0))
self.doit_monter = False
self.vitesse_x = 0
self.vitesse_y = 0
def update(self):
self.rect.x += self.vitesse_x
self.rect.y += self.vitesse_y
touche = pygame.key.get_pressed()
if touche[pygame.K_RIGHT] and self.rect.x < 920:
self.vitesse_x += 1
if touche[pygame.K_LEFT] and self.rect.x > 0:
self.vitesse_x -= 1
collision = pygame.sprite.spritecollide(self, blocs, False)
for bloc in collision:
if self.vitesse_y >= 0:
self.rect.bottom = bloc.rect.top
elif self.vitesse_y < 0:
self.rect.top = bloc.rect.bottom
perso = Perso()
class Bloc(pygame.sprite.Sprite): #pour creer un obstacle et éléments du jeu
def __init__(self, x, y, w, h):
super().__init__()
self.image = pygame.Surface((w,h))
self.image.fill((0, 255, 0))
self.rect = self.image.get_rect(topleft=(x, y))
all_sprites = pygame.sprite.Group()
blocs = pygame.sprite.Group()
all_sprites.add(perso)
b1 = Bloc(200,500,250,50)
b2 = Bloc(500,600,200,50)
b3 = Bloc(0,740,1024,30)
blocs.add(b1,b2,b3)
all_sprites.add(b1,b2,b3)
new_y = 0
continuer = True
while continuer:
pygame.time.Clock().tick(60)
for event in pygame.event.get():
if event.type == QUIT:
continuer = False
if event.type == KEYDOWN:
if event.key == pygame.K_SPACE:
perso.doit_monter = True
new_y = perso.rect.y - 100
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT and perso.vitesse_x < 0:
perso.vitesse_x = 0
perso.vitesse_y = 0
if event.key == pygame.K_RIGHT and perso.vitesse_x > 0:
perso.vitesse_x = 0
perso.vitesse_y = 0
if event.key == pygame.K_SPACE and perso.vitesse_y < 0:
perso.vitesse_y = 0
if perso.doit_monter == True:
if perso.rect.y > new_y and perso.rect.y > 0:
perso.vitesse_y -= 5
else:
perso.doit_monter = False
else:
perso.vitesse_y += 1
all_sprites.update()
fenetre.fill((0,0,0))
all_sprites.draw(fenetre)
pygame.display.flip()
pygame.quit()
Ok simple, problem, simple solution. You have to reset the y velocity if you are on the ground.
In Perso.update:
for bloc in collision:
if self.vitesse_y >= 0:
self.vitesse_y = 0 # reset velocity, so it isn't increasing forever
self.rect.bottom = bloc.rect.top
elif self.vitesse_y < 0:
self.rect.top = bloc.rect.bottom
If you don't do that, the velocity will increase, till it is high enough to jump throug the floor in one go without colliding with stopping box

Horizontal collisions when colliding with a block [duplicate]

This question already has answers here:
how to know pygame.Rect's side that collide to other Rect?
(1 answer)
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 successfully got my player sprite to detect where this is a block and stop falling. However, i cant seem to do the same for the its colliding side of with a block. If i do the same thing i did with vspeed and to it to hspeed it messes up the game and the characters zooms off the screen. I was trying to get my sprite to recognize the collision and then not go through the block. Any help would be appreciated. Thanks.
class Player(pygame.sprite.Sprite):
def __init__(self,x,y,width = 65, height = 35):
pygame.sprite.Sprite.__init__(self)
self.x = x
self.y = y
self.hspeed,self.vspeed = 0,0
self.speed = 2
self.Jump = 10
self.images=[]
r0 = pygame.image.load("Images\Player\i1.png")
r1 = pygame.image.load("Images\Player\i2.png")
r2 = pygame.image.load("Images\Player\i3.png")
r3 = pygame.image.load("Images\Player\i4.png")
self.hurt = pygame.image.load("Images\Player\Hurt.png")
self.images.append(r0)
self.images.append(r1)
self.images.append(r2)
self.images.append(r3)
self.rotatedimages = []
rr0 = pygame.transform.flip(r0 ,True, False)
rr1 = pygame.transform.flip(r1 ,True, False)
rr2 = pygame.transform.flip(r2 ,True, False)
rr3 = pygame.transform.flip(r3 ,True, False)
self.rotatedimages.append(rr0)
self.rotatedimages.append(rr1)
self.rotatedimages.append(rr2)
self.rotatedimages.append(rr3)
self.deadimages = [self.hurt]
self.gravity = 0.35
self.index = 0
self.image = self.images[self.index]
self.rect = pygame.Rect(self.x,self.y,width,height)
self.TimeNum=0
self.TimeTarget=10
self.Timer = 0
self.power_up_timer = 0
self.running = False
def update(self):
self.calcgravity()
self.rect.x += self.hspeed
self.rect.y += self.vspeed
def level_3_collisions(self, BlockListDirt2):
PlatformCollision = pygame.sprite.spritecollide(self, BlockListDirt2, False )
for each_block in PlatformCollision:
if self.vspeed > 0:
self.rect.bottom = each_block.rect.top
self.vspeed = 0
if self.vspeed <0:
self.rect.top = each_block.rect.bottom
self.vspeed = 0
def move(self, hspeed, vspeed):
self.hspeed += hspeed
self.vspeed += vspeed
class Level3:
def __init__(self):
self.level3 = [
[1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1],
[1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1],
[1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1],
[1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1],
[1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1],
[1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
]
for y in range(0,len(self.level3)):
for x in range(0,len(self.level3[y])):
if self.level3[y][x] == 1:
BlockListDirt2.add(Block(x*40,y*40))
def update(self):
for block in BlockListDirt2:
block.render2(screen)
def main3():
TrapList.empty()
TrapList.add(trap4)
player.hspeed = 0
player.rect.x,player.rect.y = 50,0
player.Timer = 0
bullet_list_v.empty()
bullet_list_h.empty()
FiringBullet = pygame.USEREVENT + 1
pygame.time.set_timer(FiringBullet, 1500)
GameExit = False
while GameExit==False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player.move(-player.speed,0)
if event.key == pygame.K_RIGHT:
player.move(player.speed,0)
if event.key == pygame.K_UP:
player.move(0,-player.Jump)
JumpSound.play()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.move(player.speed,0)
if event.key == pygame.K_RIGHT:
player.move(-player.speed,0)
if event.key == pygame.K_UP:
player.move(0,0)
if event.type == FiringBullet:
bullet = VerticalBullets(400,200)
bullet2 = VerticalBullets(500,200)
bullet3 = VerticalBullets(625,200)
hbullet = HorizontalBullets(700,400)
bullet_list_v.add(bullet)
bullet_list_v.add(bullet2)
bullet_list_v.add(bullet3)
bullet_list_h.add(hbullet)
screen.fill(BLACK)
level3.update()
for eachbullet in bullet_list_v:
bullet_list_v.draw(screen)
bullet_list_v.update()
for eachbullet in bullet_list_h:
bullet_list_h.draw(screen)
bullet_list_h.update()
if player.rect.x > 600 and player.rect.y < 0:
NextLevel3()
TrapList.draw(screen)
trampoline.render()
playergroup.update()
playergroup.draw(screen)
player.level_3_collisions(BlockListDirt2)
pygame.display.update()
clock.tick(60)

Categories