detecting invalid collision in python pygame [duplicate] - python

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 1 year ago.
import pygame
pygame.init()
pygame.display.set_caption('...SHON...PONG...')
icon=pygame.image.load('icon.png')
pygame.display.set_icon(icon)
FPS=50
fpsClock=pygame.time.Clock()
screenh=500
screenw=300
screen=pygame.display.set_mode((screenh,screenw))
black =((0,0,0))
paddle1=pygame.image.load('paddle1.png')
paddle1_rect=paddle1.get_rect()
paddle1_y=100
paddle1_x=10
paddle2=pygame.image.load('paddle2.png')
paddle2_rect=paddle1.get_rect()
paddle2_y=100
paddle2_x=471
ball=pygame.image.load('player.png')
ball_rect=ball.get_rect()
ball_x=240
ball_y=130
ball_y_speed=2
ball_x_speed=2
speed=15
paddle1_rect.x=paddle1_x
paddle1_rect.y=paddle1_y
paddle2_rect.x=paddle2_x
paddle2_rect.y=paddle2_y
ball_rect.x=ball_x
ball_rect.y=ball_y
def ball_movement():
global ball_x, ball_y, ball_x_speed, ball_y_speed
ball_x -=ball_x_speed
ball_y +=ball_y_speed
def ball_collide_screen():
global ball_x, ball_y, ball_x_speed, ball_y_speed
if ball_y + screenw >= 600:
ball_y_speed = -2
if ball_y + screenw <= 300:
ball_y_speed = -2
def ball_collide_paddles():
global ball_rect, paddle1_rect, paddle2_rect
if paddle1_rect.right - ball_rect.left <= 0:
print('ho')
running=True
while running:
screen.fill((0,0,0))
screen.blit(paddle1, (paddle1_x,paddle1_y))
screen.blit(paddle2, (paddle2_x,paddle2_y))
screen.blit(ball, (ball_x, ball_y))
ball_collide_screen()
ball_movement()
ball_collide_paddles()
pygame.display.update()
fpsClock.tick(FPS)
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_w:
paddle1_y-= speed
if event.key==pygame.K_z:
paddle1_y+=speed
if event.key==pygame.K_UP:
paddle2_y-=speed
if event.key==pygame.K_DOWN:
paddle2_y+=speed
*i am getting problems with the pygame colliderect function. i put a print function whenever the ball collides with paddle and it continues print collide as long as the program is running.....i read somewhere that the rect position has to be matching with the balls initial position and i have tried doing that but all in vain .....i have been doing pygame for a while and i have encountered this problem trying to make this pong game *

You must update the location of the pygame.Rect objects, after moving the objects and before the collision detection:
def ball_movement():
global ball_x, ball_y, ball_x_speed, ball_y_speed
ball_x -=ball_x_speed
ball_y +=ball_y_speed
ball_rect.x=ball_x
ball_rect.y=ball_y
running=True
while running:
# [...]
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_w:
paddle1_y-= speed
if event.key==pygame.K_z:
paddle1_y+=speed
if event.key==pygame.K_UP:
paddle2_y-=speed
if event.key==pygame.K_DOWN:
paddle2_y+=speed
paddle1_rect.x=paddle1_x
paddle1_rect.y=paddle1_y
paddle2_rect.x=paddle2_x
paddle2_rect.y=paddle2_y
Note, you don't need the variables ball_x, ball_y, paddle1_x, paddle1_y, paddle2_x and paddle2_y at all.
Use ball_rect.x, ball_rect.y, paddle1_rect.x, paddle1_rect.y, paddle2_rect.x and paddle2_rect.y instead.
import pygame
pygame.init()
pygame.display.set_caption('...SHON...PONG...')
#icon = pygame.image.load('icon.png')
#pygame.display.set_icon(icon)
FPS = 50
fpsClock = pygame.time.Clock()
screenh = 500
screenw = 300
screen = pygame.display.set_mode((screenh,screenw))
black = ((0,0,0))
#paddle1 = pygame.image.load('paddle1.png')
paddle1 = pygame.Surface((5, 50))
paddle1.fill((255, 255, 255))
paddle1_rect = paddle1.get_rect(topleft = (10, 100))
#paddle2 = pygame.image.load('paddle2.png')
paddle2 = pygame.Surface((5, 50))
paddle2.fill((255, 255, 255))
paddle2_rect = paddle1.get_rect(topleft = (471, 100))
#ball = pygame.image.load('player.png')
ball = pygame.Surface((5, 5))
ball.fill((255, 255, 255))
ball_rect = ball.get_rect(topleft = (240, 130))
ball_x_speed = 2
ball_y_speed = 2
speed = 15
def ball_movement():
ball_rect.x += ball_x_speed
ball_rect.y += ball_y_speed
def ball_collide_screen():
global ball_x_speed, ball_y_speed
if ball_rect.left <= 0:
ball_x_speed = 2
if ball_rect.right >= screen.get_width():
ball_x_speed = -2
if ball_rect.top <= 0:
ball_y_speed = 2
if ball_rect.bottom >= screen.get_height():
ball_y_speed = -2
def ball_collide_paddles():
if paddle1_rect.right - ball_rect.left <= 0:
print('ho')
running=True
while running:
screen.fill((0,0,0))
screen.blit(paddle1, paddle1_rect)
screen.blit(paddle2, paddle2_rect)
screen.blit(ball, ball_rect)
pygame.display.update()
fpsClock.tick(FPS)
ball_collide_screen()
ball_movement()
ball_collide_paddles()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running=False
pygame.quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
paddle1_rect.y -= speed
if event.key == pygame.K_s:
paddle1_rect.y += speed
if event.key == pygame.K_UP:
paddle2_rect.y -= speed
if event.key == pygame.K_DOWN:
paddle2_rect.y += speed

Related

How to make accurate collisions in pygame? [duplicate]

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
Closed 20 days ago.
I am making a platformer and am trying to make a player be able to stay on top of a platform. When I check if they are colliding, I check if the bottom of the player meets the top of the platform. It doesn't give an output, can someone please help?
The buggy part is the collisions where playerRect.colliderect(platform): and the bit below that as well. Help would be much appreciated.
import pygame
pygame.init()
screen = pygame.display.set_mode((1400, 900))
clock = pygame.time.Clock()
playerX = 700
playerY = 870
jumping = False
goingRight = False
goingLeft = False
jumpSpeed = 1
jumpHeight = 18
yVelocity = jumpHeight
gravity = 1
speed = 6
white = (255, 255, 255)
black = (0, 0, 0)
running = True
while running:
screen.fill(black)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
jumping = True
if keys[pygame.K_LEFT]:
goingLeft = True
if keys[pygame.K_RIGHT]:
goingRight = True
platform = pygame.draw.rect(screen, white, (100, 840, 100, 30))
playerRect = pygame.draw.rect(screen, white, (playerX, playerY, 30, 30))
if jumping:
playerY -= yVelocity
yVelocity -= gravity
if yVelocity < -jumpHeight:
jumping = False
yVelocity = jumpHeight
if goingLeft:
playerX -= speed
if goingRight:
playerX += speed
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
goingLeft = False
if event.key == pygame.K_RIGHT:
goingRight = False
if playerRect.colliderect(platform):
if playerRect.bottom - platform.top == 0:
playerRect.bottom = platform.y
pygame.display.update()
clock.tick(60)
`
Most likely this part is the problem.
if playerRect.bottom - platform.top == 0:
You should check if bottom of the player is higher than the top of the platform since chance of them being exact is not high since your yVelocity is different than 1.

How to add game restart in this pgame code? [duplicate]

This question already has answers here:
how restarting game on pygame works
(1 answer)
Pygame restart function
(2 answers)
In game loop, how do I restart game properly using nested class or loop?
(1 answer)
Reset and restart pygame program doesn't work
(1 answer)
Closed 3 months ago.
I followed a tutorial guide on how to make this game but they never said how to put in a restart. I'm not quite sure how to do it, would anyone here know off the top of their head? Here's the code.
import pygame
import math
import random
from pygame import mixer
# Start the Program
pygame.init()
# Create the Screen
screen = pygame.display.set_mode((800, 600))
running = True
# Background
background = pygame.image.load('background.png')
# Background Sound
mixer.music.load('theme.mp3')
mixer.music.play(-1)
# Title and Icon
pygame.display.set_caption("Boot Craft")
icon = pygame.image.load('Starcraft.png')
pygame.display.set_icon(icon)
# Player
player_image = pygame.image.load('BC.png')
playerX = 370
playerY = 480
playerX_change = 0
playerY_change = 0
# Enemy
enemy_image = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemy_image.append(pygame.image.load('Zergling.png'))
enemyX.append(random.randint(0, 768))
enemyY.append(random.randint(50, 150))
enemyX_change.append(0.2)
enemyY_change.append(40)
# Bullet
# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bullet_image = pygame.image.load('Bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = .5
bullet_state = "ready"
# Score
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
def show_score(x,y):
score = font.render('Score: ' + str(score_value), True, (255,255,255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render('GAME OVER', True, (255, 255, 255))
continue_text = over_font.render('CONTINUE? Y/N', True, (255, 255, 255))
screen.blit(over_text, (200, 250))
screen.blit(continue_text, (160, 350))
def player(x, y):
screen.blit(player_image, (x, y))
def enemy(x, y, i):
screen.blit(enemy_image[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bullet_image, (x + 8, y + 10))
def isCollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Game Loop - Runs Game
while running:
# RGB Color Values 0-255
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_y:
running = True
# Check Key pressed.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT or event.key == pygame.K_a:
playerX_change = -0.2
if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
playerX_change = 0.2
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
# Get the current X coordinate of the spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
# Check Key released.
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT or event.key == pygame.K_a or event.key == pygame.K_d:
playerX_change = 0
playerX += playerX_change
# Adds Boundary
if playerX <= 0:
playerX = 0
elif playerX >= 721:
playerX = 721
# Enemy Movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 0:
enemyX_change[i] = 0.2
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 768:
enemyX_change[i] = -0.2
enemyY[i] += enemyY_change[i]
# Collision
collision = isCollision(enemyX[i],enemyY[i],bulletX,bulletY)
if collision:
explosion_sound = mixer.Sound('explode.wav')
explosion_sound.play()
bulletY = 480
bullet_state = "ready"
score_value += 1
enemyX[i] = random.randint(0, 768)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(textX, textY)
pygame.display.update()
I'm not sure what to try, as what I googled used different ways of running the game. New to this, so genuinely confused.

How to use time and make a timer in Pygame? [duplicate]

This question already has answers here:
Countdown timer in Pygame
(8 answers)
Spawning multiple instances of the same object concurrently in python
(1 answer)
Closed 5 months ago.
I am new to pygame programming and I am making a game with the help of tutorials. I finished the tutorial and want to add a new feature to my game.
Game Overview
I have created a space invader game where there are enemies moving on the x-axis and slowly coming down. In bottom there is a space ship which can move on the x axis and can shoot bullets to destroy or kill the enemies. The enemies respawn after being killed and if an enemy reaches the bottom, it is game over
Code
# importing modules
import pygame
import random
import math
from pygame import mixer
# initialize pygame
pygame.init()
# creating a window
screen = pygame.display.set_mode((800, 600))
# Background Music
mixer.music.load('background.wav')
mixer.music.play(-1)
# Background
bg_img = pygame.image.load("background3.png")
bg = pygame.transform.scale(bg_img, (800, 600))
# Title and Icon
pygame.display.set_caption("Space Shooters")
icon = pygame.image.load('spaceship.png')
pygame.display.set_icon(icon)
# Player
player = pygame.image.load('spaceship2.png')
playerX = 370
playerY = 500
playerX_change = 0
# Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6
for i in range(num_of_enemies):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(6, 730))
enemyY.append(random.randint(45, 150))
enemyX_change.append(0.3)
enemyY_change.append(40)
# Bullet
# Ready - The bullet can't be seen
# Fire - The bullet has been shot
bulletImg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 1.5
bullet_state = "Ready"
# Score
score_value = 0
font = pygame.font.Font('freesansbold.ttf', 32)
textX = 10
textY = 10
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
# Function for displaying text
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
# Defining and drawing spaceship
def spaceship(x, y):
screen.blit(player, (x, y))
# Defining and drawing enemy
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "Fire"
screen.blit(bulletImg, (x + 16, y + 10))
def Iscollision(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# making the game window run endlessly and game loop
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Keystroke check (right, left)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.3
if event.key == pygame.K_RIGHT:
playerX_change = 0.3
if event.key == pygame.K_SPACE:
# Checking whether bullet is there on screen, if not making it ready, if yes disabling spacebar
if bullet_state == "Ready":
# Get the current X cordinate of spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# Changing X coordinates to move spaceship
playerX += playerX_change
if playerX <= 6:
playerX = 6
elif playerX >= 730:
playerX = 730
screen.fill(0)
screen.blit(bg, (0, 0))
# Enemy Movement
for i in range(num_of_enemies):
# Game Over
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies):
enemyX[i] += enemyX_change[i]
if enemyX[i] <= 6:
enemyX_change[i] = 0.3
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 730:
enemyX_change[i] = -0.3
enemyY[i] += enemyY_change[i]
# Collision
collision = Iscollision(enemyX[i], enemyY[i], bulletX, bulletY)
# if collision and if collision is true are both the same
if collision:
collision_sound = mixer.Sound('explosion.wav')
collision_sound.play()
bulletY = 480
bullet_state = "Ready"
score_value += 1
enemyX[i] = random.randint(6, 730)
enemyY[i] = random.randint(45, 150)
enemy(enemyX[i], enemyY[i], i)
# Deleting each frame of enemy moving so that it runs smoothly
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "Ready"
if bullet_state == "Fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
spaceship(playerX, playerY)
show_score(textX, textY)
# updating display
pygame.display.update()
New Feature
I want to add a feature that when a laser ( I have a picture) hits the spaceship, shot by the enemies, the spaceship can't move for 10 seconds. I have already tryed other stack overflow questions but they don't match my needs.
If you only have one cooldown to manage, a simple and clean way to do it is by using a custom event :
# Custom event
COOLDOWN_END = pg.USEREVENT
When you detect a collision you simply start a timer :
# Custom event
pg.time.set_timer(COOLDOWN_END, 1000, 1)
The first parameter is the event you are going to send to your event handler, the 2nd is the time in ms (so 1 sec here) and last one is the number of iteration. Here you just want to send the event once, so put 1.
The last step is to do catch this event in your handler and do what you want with it :
for evt in pg.event.get():
if evt.type == pg.QUIT:
exit()
if evt.type == COOLDOWN_END:
print(evt)
# Your logic goes here
Let's put everything together :
(Here, I simply used this technique to have a COOLDOWN_END event 1 sec after I clicked)
# General imports
import pygame as pg
import sys
# Init
pg.init()
# Vars
screen = pg.display.set_mode((500, 500))
pg.display.set_caption("name")
# Clock
FPS = 60
clock = pg.time.Clock()
# Custom event
COOLDOWN_END = pg.USEREVENT
# Main functions
def update():
pass
def draw():
# Clear screen
screen.fill((0,0,0))
def handle_evt():
for evt in pg.event.get():
if evt.type == pg.QUIT:
exit()
if evt.type == pg.KEYDOWN:
if evt.key == pg.K_ESCAPE:
exit()
if evt.type == pg.MOUSEBUTTONDOWN:
if evt.button == 1:
on_click()
if evt.type == COOLDOWN_END:
print(evt)
def on_click():
pg.time.set_timer(COOLDOWN_END, 1000, 1)
def exit():
pg.quit()
sys.exit()
# Main loop
if __name__ == '__main__':
while True:
handle_evt()
update()
draw()
clock.tick(FPS)
pg.display.flip()
You may use custom event with from pygame.locals import USEREVENT.
An alternative is to keep track of time of when you got hit using pygame.time.get_ticks() + some stun cooldown system, and applying only to the portion of the code involved with player movement.
stun_duration = 10000 # milliseconds
damaged_timestamp = -stun_duration # allows to get stunned starting from pygame.init() call
running = True
while running:
for event in pygame.event.get():
# preceding code
# check if beyond stun cooldown
if pygame.time.get_ticks() - damaged_timestamp > stun_duration:
damaged_timestamp = pygame.time.get_ticks()
# Keystroke check (right, left)
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -0.3
if event.key == pygame.K_RIGHT:
playerX_change = 0.3
if event.key == pygame.K_SPACE:
# Checking whether bullet is there on screen, if not making it ready, if yes disabling spacebar
if bullet_state == "Ready":
# Get the current X cordinate of spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
bullet_sound = mixer.Sound('laser.wav')
bullet_sound.play()
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# Changing X coordinates to move spaceship
playerX += playerX_change
if playerX <= 6:
playerX = 6
elif playerX >= 730:
playerX = 730
# proceeding code

Replaying the main loop with a few changes pygame

I have been trying to make a Fangame for Undertale with pygame but i am stuck. This is my first project. I want to replay the main loop with a few changes, for example i want the knife movement to be different, but i dont know how to do it. I have tried with attack2 to replay everything but it doesnt work, for example the player can't move and the knife is also not moving. I also tried defining the main loop but then i can't change anything. Please comment if you can help me. This is the code i have:
import math
import pygame
from pygame import mixer
pygame.init()
screen = pygame.display.set_mode((1000, 800))
# FPS
FPS = 60
clock = pygame.time.Clock()
# Title and icon
pygame.display.set_caption("CharaFight")
icon = pygame.image.load('Chara.png')
pygame.display.set_icon(icon)
# images
fight_button = pygame.image.load('Fight.png')
fight_button2 = pygame.image.load('Fight2.png')
hp_bar1 = pygame.image.load('hp_bar.png')
hp_bar2 = pygame.image.load('hp_bar2.png')
# music and sounds
background_muziek = mixer.music
damage_sound = mixer.Sound('Undertale Sound Effect - Taking Damage.wav')
background_muziek.load('Prepare for Battle!.wav')
background_muziek.set_volume(0.4)
background_muziek.play(-1)
# backgrounds
background = pygame.image.load("Background1.png")
background2 = pygame.image.load("Background2.png")
# Player
playerImg = pygame.image.load("Soul.png")
PlayerX = 450
PlayerY = 550
PlayerX_change = 0
PlayerY_change = 0
HP = 0
# Enemy
enemyImg = pygame.image.load("Chara2.png")
charaImg = pygame.image.load("Chara3.png")
EnemyX = 390
EnemyY = 50
EnemyX_change = 0
EnemyY_change = 0
# Knife
knifeImg = pygame.image.load("knife.png")
KnifeX = 350
KnifeY = 580
KnifeX_change = 5
KnifeY_change = 0
Knife_state = "ready"
# Game over text
over_font = pygame.font.Font('8-BIT WONDER.TTF', 64)
det_font = pygame.font.Font('8-BIT WONDER.TTF', 30)
emy_font = pygame.font.Font('Determination_text.ttf', 45)
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
det_text = det_font.render(" Stay Determined ", True, (255, 255, 255))
screen.blit(over_text, (230, 250))
screen.blit(det_text, (280, 400))
def enemy_text():
chara_text = emy_font.render(" * Give me your SOUL! ", True, (255, 255, 255))
screen.blit(chara_text, (150, 500))
def fade(width, height):
fade1 = pygame.Surface((width, height))
fade1.fill((0, 0, 0))
for alpha in range(0, 150):
fade1.set_alpha(alpha)
screen.blit(fade1, (0, 0))
pygame.display.update()
pygame.time.delay(5)
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y):
screen.blit(enemyImg, (x, y))
def fire_knife(x, y):
global Knife_state
Knife_state = "fire"
screen.blit(knifeImg, (x, y))
def isCollision(PlayerX, PlayerY, KnifeX, KnifeY):
distance = math.sqrt(math.pow(PlayerX - KnifeX, 2) + (math.pow(PlayerY - 37 - KnifeY, 2)))
if distance < 27:
return True
else:
return False
# Here is my attempt to replay the main loop
def attack2():
screen.fill((0, 0, 0))
player(PlayerX, PlayerY)
enemy(EnemyX, EnemyY)
fire_knife(KnifeY, KnifeX)
screen.blit(background, (100, 300))
pygame.display.flip()
# main loop
running = True
while running:
screen.fill((0, 0, 0))
screen.blit(background, (100, 300))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Movement
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
PlayerX_change = -2.5
if event.key == pygame.K_RIGHT:
PlayerX_change = 2.5
if event.key == pygame.K_UP:
PlayerY_change = -2.5
if event.key == pygame.K_DOWN:
PlayerY_change = 2.5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
PlayerX_change = 0
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
PlayerY_change = 0
# Boundaries for player
PlayerY += PlayerY_change
if PlayerY >= 700:
PlayerY = 700
elif PlayerY <= 520:
PlayerY = 520
PlayerX += PlayerX_change
if PlayerX <= 370:
PlayerX = 370
elif PlayerX >= 570:
PlayerX = 570
# Knife movement
if KnifeX >= 550:
KnifeX = 340
KnifeY += 20
Knife_state = "ready"
if KnifeY >= 680:
KnifeY = 480
Knife_state = "ready"
if Knife_state == "fire":
fire_knife(KnifeX, KnifeY)
KnifeX += KnifeX_change
# collision and game over screen
collision = isCollision(PlayerX, PlayerY, KnifeX, KnifeY)
if collision:
Knife_state = "ready"
damage_sound.set_volume(1.5)
damage_sound.play()
HP += 1
if HP > 100:
fade(1000, 800)
screen.fill((0, 0, 0))
game_over_text()
background_muziek.stop()
game_over_sound = mixer.music
game_over_sound.load('Undertale Game Over Theme.wav')
game_over_sound.play(-1)
pygame.display.flip()
pygame.time.wait(5000)
while True:
if pygame.key.get_pressed():
running = True
pygame.quit()
# Fight screen
if pygame.time.get_ticks() > 21700:
fade(1000, 800)
screen.fill((0, 0, 0))
enemy_text()
screen.blit(background2, (140, 250))
screen.blit(charaImg, (390, 50))
screen.blit(fight_button, (330, 630))
screen.blit(hp_bar1, (440, 350))
pygame.display.flip()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
screen.blit(fight_button2, (330, 630))
screen.blit(hp_bar2, (440, 350))
damage_sound.set_volume(10)
damage_sound.play()
pygame.display.flip()
pygame.time.wait(5000)
attack2()------------------> here i try to replay the main loop but i cant move and the knife is also not moving.
if pygame.key.get_pressed():
running = True
clock.tick(FPS)
player(PlayerX, PlayerY)
enemy(EnemyX, EnemyY)
fire_knife(KnifeX, KnifeY)
pygame.display.update()
You can use a class like this to animate stuff:
import pygame
from os import listdir, path
def load_animations(folder_path: str) -> tuple:
animation = listdir(folder_path)
animation = tuple(pygame.image.load(path.join(folder_path, frame)).convert_alpha() for frame in animation)
return animation
class Animation:
def __init__(self, FPS: int, animation_folder: str, speed: float, pos: tuple):
self.animation = load_animations(animation_folder)
self.speed = speed
self.FPS = FPS
self.current_frame = 0
self.image = None
self.rect = None
self.pos = pos
def get_frame(self) -> pygame.Surface:
self.current_frame += self.speed * 10 / self.FPS
if self.current_frame >= len(self.animation):
return
return self.animation[int(self.current_frame)]
def play(self, screen: pygame.Surface):
self.image = self.get_frame()
if not self.image:
return
self.rect = self.image.get_rect(center=self.pos)
screen.blit(self.image, self.rect)
And to use this you would do something like:
animation = Animation(60, "path to the folder", 1, (100, 100))
# Put this inside the main loop.
animation.play(# Put the display surface in here)
And you should make a draw function for your whole game and put this code inside of the draw function (This function should handle all the graphics of your game).

How do I use Images in pygame for collision detection [duplicate]

This question already has answers here:
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Why is my collision test always returning 'true' and why is the position of the rectangle of the image always wrong (0, 0)?
(1 answer)
How do I detect collision in pygame?
(5 answers)
Closed 2 years ago.
import pygame
import os
pygame.init()
# Images
bgImg = pygame.image.load("Images/background.png")
playerImgRight = (pygame.image.load("Images/playerRight.png"))
playerImgLeft = pygame.image.load("Images/playerLeft.png")
playerImgBack = pygame.image.load("Images/playerBack.png")
chestClosed = pygame.transform.scale(pygame.image.load("Images/chestsClosed.png"), (30, 40))
chestOpened = pygame.transform.scale(pygame.image.load("Images/chestOpen.png"), (30, 40))
currentPlayerImg = playerImgBack
screen = pygame.display.set_mode((800, 800))
pygame.display.set_caption("Richmonia")
pygame.display.set_icon(currentPlayerImg)
clock = pygame.time.Clock()
playerX = 380
playerY = 380
playerXSpeed = 0
playerYSpeed = 0
Chest Class
I want but the collision detection in the chest update function
class Chest:
def __init__(self, x, y, openImage, closeImage, playerX, playerY):
self.x = x
self.y = y
self.openImage = openImage
self.closeImage = closeImage
self.currentImage = self.closeImage
self.playerX = playerX
self.playerY = playerY
def update(self):
print("Placeholder")
def show(self):
screen.blit(self.currentImage, (self.x, self.y))
chestOne = Chest(100, 100, chestOpened, chestClosed, playerX, playerY)
running = True
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
currentPlayerImg = playerImgBack
playerYSpeed = -5
if event.key == pygame.K_DOWN:
currentPlayerImg = playerImgBack
playerYSpeed = 5
if event.key == pygame.K_LEFT:
currentPlayerImg = playerImgLeft
playerXSpeed = -5
if event.key == pygame.K_RIGHT:
currentPlayerImg = playerImgRight
playerXSpeed = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playerYSpeed = 0
if event.key == pygame.K_DOWN:
playerYSpeed = 0
if event.key == pygame.K_LEFT:
playerXSpeed = 0
if event.key == pygame.K_RIGHT:
playerXSpeed = 0
if playerY <= 0:
playerY = 0
if playerY >= 740:
playerY = 740
if playerX <= 0:
playerX = 0
if playerX >= 760:
playerX = 760
playerX += playerXSpeed
playerY += playerYSpeed
screen.blit(bgImg, (0, 0))
chestOne.show()
chestOne.update()
screen.blit(currentPlayerImg, (playerX, playerY))
pygame.display.update()
pygame.quit()
quit()
I know there is a way with sprites but I want to know if there is a way to do it with just the images.
Also bonus question how to I get the fps.
Use a pygame.Rect object and colliderect() to find a collision between a rectangle and an object.
pygame.Surface.get_rect.get_rect() returns a rectangle with the size of the Surface object, that always starts at (0, 0) since a Surface object has no position. The position of the rectangle can be specified by a keyword argument:
running = True
while running:
# [...]
player_rect = currentPlayerImg.get_rect(topleft = (playerX, playerY))
chestOne_rect = chestOne.currentImage.get_rect(topleft = (self.x, self.y))
if player_rect .colliderect(chestOne_rect):
print("hit")
# [...]
The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
So in your case the frames per second are 60:
while running:
clock.tick(60)
pygame.time.Clock.tick returns the number of milliseconds passed since the previous call. If you call it in the application loop, then this is the number of milliseconds passed since the last frame.
while run:
ms_since_last_frame = clock.tick(60)

Categories

Resources