Why are multiple copies of my player appearing when its moving - python

When I make my character/player jump, a copy image of the player stays on the jumpY and the same is happening for when I shoot a health kit. (long story) My background scroll works but the copy thing is really bothering me. I have no idea why it's happening. This is an image of what happens.
I really don't know how this happened. Here is the code:
import pygame from pygame import mixer
#Imports the pygame module.
pygame.init()
#Initializes Pygame
screen = pygame.display.set_mode((800,600))
#Sets the screen to pygame looks and not normal python looks.
pygame.display.set_caption("Draft")
#Changes the title
icon = pygame.image.load('doctor.png') pygame.display.set_icon(icon)
#Changing the Icon
white = (255,255,255) black = (0,0,0) red = (255,0,0) green = (0,255,0) blue = (0,0,255)
#Setting color variables to make it easier to access later in the code.
#Player player_img = pygame.image.load('Doctor_Running-removebg-preview (1).png') playerx = 20 playery = 390 playerx_change = 0 playery_change = 100
#Making the Player Variables.
#Health Kit HealthImg = pygame.image.load('first-aid-kit.png') HealthX = 20 HealthY = 405 HealthX_Change = -10 HealthY_Change = 0 Health_State = "ready"
#Making the Health_Kit Variables.
#Create a white screen
DISPLAYSURF = pygame.display.set_mode((800,600))
DISPLAYSURF.fill(blue)
pygame.display.set_caption("Game")
#Creating Events
class Background():
def __init__(self):
self.bgimage = pygame.image.load('Ground.png')
self.rectBGimg = self.bgimage.get_rect()
self.bgY1 = 485
self.bgX1 = 0
self.bgY2 = 485
self.bgX2 = self.rectBGimg.width
self.moving_speed = 5
def update(self):
self.bgX1 -= self.moving_speed
self.bgX2 -= self.moving_speed
if self.bgX1 <= -self.rectBGimg.width:
self.bgX1 = self.rectBGimg.width
if self.bgX2 <= -self.rectBGimg.width:
self.bgX2 = self.rectBGimg.width
def render(self):
DISPLAYSURF.blit(self.bgimage, (self.bgX1, self.bgY1))
DISPLAYSURF.blit(self.bgimage, (self.bgX2, self.bgY2))
class Player():
def draw_player():
screen.blit(player_img,(playerx,playery))
class Health():
def fire_Health (x,y):
global Health_State
Health_State = "fire"
screen.blit(HealthImg, ( x + 70, y + 10))
#def states an event. The event will not occur unless you call the event in the main game loop. back_ground = Background()
#Main Game Loop clock = pygame.time.Clock()
SCEEN_UPDATE = pygame.USEREVENT pygame.time.set_timer(SCEEN_UPDATE,150)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playery += playery_change
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
playery -= playery_change
if event.key == pygame.K_SPACE:
if Health_State == "ready":
Health_Fire_Sound = mixer.Sound('laser.wav')
Health_Fire_Sound.play()
Health.fire_Health(HealthX , HealthY)
HealthY = playery + 10
back_ground.update()
back_ground.render()
#Health Kit Movement
if HealthX >= 600:
HealthX = 20
Health_State = "ready"
if Health_State == "fire":
Health.fire_Health(HealthX , HealthY)
HealthX -= HealthX_Change
# draw objects
Player.draw_player()
# update display
pygame.display.update()
clock.tick(60)

The background does not cover the entire display. Therefore you have to clear the entire display in each frame:
running = True
while running:
# [...]
DISPLAYSURF.fill(blue) # <-- clear display
back_ground.update()
back_ground.render()
# [...]

Related

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

pygame "invalid position for blit"

I am trying to make a game but when I run the code the game makes 5 enemies appear on the screen. It says "invalid position for blit". However, I don't know where to put the blit otherwise.
I don't know what to do because I'm still learning. The code was fine before adding the copies. Not sure why that changed anything.
This is the full code:
import pygame
import random
import math
from pygame import mixer
#Imports the pygame, random, math and mixer module.
pygame.init()
#Initializes Pygame
screen = pygame.display.set_mode((800,600))
#Sets the screen to pygame looks and not normal python looks.
pygame.display.set_caption("Draft")
#Changes the title
icon = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/doctor.png')
pygame.display.set_icon(icon)
#Changing the Icon
#Adding Background Music
mixer.music.load('C:/Users/user/Desktop/Python/CodingBee/sb_indreams.mp3')
mixer.music.play(-1)
#Loads the music and plays if until the window is closed
#Colors
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
#Setting color variables to make it easier to access later in the code.
#Player
player_img = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/Doctor_Running-removebg-preview (1).png')
playerx = 20
playery = 390
playerx_change = 0
playery_change = 100
#Making the Player Variables.
#Health Kit
HealthImg = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/first-aid-kit.png')
HealthX = 20
HealthY = 405
HealthX_Change = -10
HealthY_Change = 0
Health_State = "ready"
#Making the Health_Kit Variables.
#Enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
number_of_enemies = 5
#Making a list for all 5 enemies image, x value, y value, x value change, y value change. All variables are a seperate list
for i in range(number_of_enemies):
enemyImg.append(pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/zombie.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyX_change.append(0.45)
enemyY_change.append(40)
#Score
Score_Value = 0
font = pygame.font.Font('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/Mostery.ttf', 25)
#The pygame font extension requires 2 values, the font and the font size.
#.ttf is a font extension
#Making the score variable
ScoreX = 10
ScoreY = 25
#Making a variable for the fonts x and y position
#Heading
headingfont = pygame.font.Font('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/Bouncy-PERSONAL_USE_ONLY.otf', 45)
HeadingX = 230
HeadingY = 10
#Game Over
game_over_font = pygame.font.Font('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/Bouncy-PERSONAL_USE_ONLY.otf', 64)
#Creating Classes
class Background():
def __init__(self):
self.bgimage = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/Ground.png')
self.rectBGimg = self.bgimage.get_rect()
self.bgY1 = 485
self.bgX1 = 0
self.bgY2 = 485
self.bgX2 = self.rectBGimg.width
self.moving_speed = 7
def update(self):
self.bgX1 -= self.moving_speed
self.bgX2 -= self.moving_speed
if self.bgX1 <= -self.rectBGimg.width:
self.bgX1 = self.rectBGimg.width
if self.bgX2 <= -self.rectBGimg.width:
self.bgX2 = self.rectBGimg.width
def render(self):
screen.blit(self.bgimage, (self.bgX1, self.bgY1))
screen.blit(self.bgimage, (self.bgX2, self.bgY2))
class Player():
def draw_player():
screen.blit(player_img,(playerx,playery))
def player_jump():
global playery
playery -= playery_change
class Enemy():
def draw_enemy(enemyx,enemyy,i):
screen.blit(enemyImg[i],(enemyx,enemyy))
def move_enemy():
global enemyX
enemyX[i] += enemyX_change[i]
class Health():
def fire_Health (x,y):
global Health_State
Health_State = "fire"
screen.blit(HealthImg, ( x + 70, y + 10))
class Other():
def isCollision(enemyX, enemyY, HealthX, HealthY):
distance = math.sqrt(math.pow(enemyX - HealthX, 2) + (math.pow(enemyY - HealthY, 2)))
if distance < 27:
return True
else:
return False
def show_heading():
Heading = headingfont.render("Health Run!", True, (255,255,255))
screen.blit(Heading,( HeadingX, HeadingY))
def show_score():
Score = font.render("Score = " + str(Score_Value), True, (255,255,255))
screen.blit(Score,( ScoreX, ScoreY))
def game_over():
Game_Over = headingfont.render("GAME OVER!", True, (255,255,255))
screen.blit(Game_Over,( 200, 400))
Score_Value = 0
#def states an event. The event will not occur unless you call the event in the main game loop.
back_ground = Background()
#Main Game Loop
clock = pygame.time.Clock()
SCEEN_UPDATE = pygame.USEREVENT
pygame.time.set_timer(SCEEN_UPDATE,150)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
Player.player_jump()
if event.key == pygame.K_SPACE:
if Health_State == "ready":
Health_Fire_Sound = mixer.Sound('C:/Users/user/Desktop/Python/Pygame/Space_Invaders/laser.wav')
Health_Fire_Sound.play()
Health.fire_Health(HealthX , HealthY)
HealthY = playery + 10
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
playery += playery_change
screen.fill(blue)
back_ground.update()
back_ground.render()
#Health Kit Movement
if HealthX >= 800:
HealthX = 20
Health_State = "ready"
if Health_State == "fire":
Health.fire_Health(HealthX , HealthY)
HealthX -= HealthX_Change
#Enemy Movement and collision check
for i in range(number_of_enemies):
if enemyX[i] > 20:
for j in range(number_of_enemies):
enemyY = 2000
Other.game_over()
break
Enemy.move_enemy()
collision = Other.isCollision(enemyX[i],enemyY[i],HealthX,HealthY)
if collision:
BulletY = 480
Bullet_State = "ready"
enemyX[i] = random.randint(800,900)
enemyY[i] = 405
HealthX = 20
Health_State = "ready"
Score_Value += 1
# draw objects
Player.draw_player()
Enemy.draw_enemy(enemyX,enemyY, i)
Other.show_heading()
Other.show_score()
# update display
pygame.display.update()
clock.tick(60)
enemyX and enemyY are list of coordinates. You have 2 options:
pass items of the lists to draw_enemy:
class Enemy():
def draw_enemy(enemyx, enemyy, i):
screen.blit(enemyImg[i], (enemyx, enemyy))
Enemy.draw_enemy(enemyX[i], enemyY[i], i)
Get the items from the lists in draw_enemy:
class Enemy():
def draw_enemy(enemyx, enemyy, i):
screen.blit(enemyImg[i], (enemyx[i], enemyy[i]))
Enemy.draw_enemy(enemyX, enemyY, i)
Anyway, I suggest to create an Enemy class with attributes (see Classes). Note that the following code is not complete, it is just an example of how to implement classes and use object instances. I'll leave it up to you as an exercise to incorporate it into your code.
class Enemy():
def __init__(self, image, x, y, changeX, changeY):
self.image = image
self.x = x
self.y = y
self.changeX = changeX
self.changeY = changeY
def move(self):
self.x += self.changeX
self.y += self.changeY
def draw(self):
screen.blit(self.image, (self.x, self.y))
number_of_enemies = 5
enemies = []
enemyImg = pygame.image.load('C:/Users/user/Desktop/Python/CodingBee/zombie.png')
for i in range(number_of_enemies):
x = random.randint(0, 736)
y = random.randint(50, 150)
enemy = Enemy(enemyImg, x, y, 0.45, 0)
enemies.append(enemy)
running = True
while running:
# [...]
for enemy in enemies:
enemy.move()
# [...]
for enemy in enemies:
enemy.draw()
# [...]

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 to code ingame-timer stopper after hitting a given sprite in pygame? Why is my timer running even though I'm still at the main menu?

I have 2 problems. First, I don't know what to code to make the timer stop after hitting the sprite. I would like the timer to remain at the given time that I hit the sprite but the code I created before made the timer go to zero. Second, The timer is already running at the "mainmenu" of my game so when I start the game late, the timer is does not start at zero.
here's the whole code that I did
# initialization of pygame
import pygame
import random
import math
pygame.init()
# creating the display
display = pygame.display.set_mode((500, 500))
# title & icon
spaceship = pygame.image.load("Space Blitz Sprites/spaceship.png")
pygame.display.set_icon(spaceship)
pygame.display.set_caption("SpaceBlitz")
# main menu sprites
spaceblitz = pygame.image.load("Space Blitz Sprites/spaceblitz.png")
play = pygame.image.load("Space Blitz Sprites/play.png")
howtoplay = pygame.image.load("Space Blitz Sprites/howtoplay.png")
about = pygame.image.load("Space Blitz Sprites/about.png")
quit = pygame.image.load("Space Blitz Sprites/quit.png")
# inside main menu
instruction = pygame.image.load("Space Blitz Sprites/instruction.png")
back = pygame.image.load("Space Blitz Sprites/back.png")
aboutdev = pygame.image.load("Space Blitz Sprites/aboutdev.png")
# main menu music
music = pygame.mixer.music.load("Space Blitz Sprites/mountaintrails.mp3")
# PlayerSpriteMovement
playerimg = pygame.image.load("Space Blitz Sprites/spaceship.png")
playerX = 250
playerY = 400
velocity = 3
clock = pygame.time.Clock()
# Bullet
bulletimg = pygame.image.load("Space Blitz Sprites/bullet.png")
bulletX = 0
bulletY = playerY
bulletx_change = 0
bulletY_change = 8
bullet_state = "ready"
# Asteroid
asteroidimg = []
asteroidX = []
asteroidY = []
asteroidX_change = []
asteroidY_change = []
no_of_enemies = 10
score = 0
# Game Over Text
overfont = pygame.font.Font('freesansbold.ttf',32)
def mainmenu():
global menuselect
global spaceblitz
menu = True
pygame.mixer.music.play(50)
pygame.mixer.music.set_volume(0.2)
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
pos = pygame.mouse.get_pos()
if start.collidepoint(pos):
menu = False
menuselect = 1
pygame.mixer.music.stop()
if controls.collidepoint(pos):
menu = False
menuselect = 2
pygame.mixer.music.stop()
if developer.collidepoint(pos):
menu = False
menuselect = 3
pygame.mixer.music.stop()
if exit.collidepoint(pos):
menu = False
menuselect = 4
display.fill((0, 0, 0))
display.blit(spaceblitz, (170,150))
start = display.blit(play, (170,250))
controls = display.blit(howtoplay, (170,300))
developer = display.blit(about, (170,350))
exit = display.blit(quit, (170,400))
pygame.display.flip()
pygame.display.update()
def controls():
global menuselect
global menu
controls = True
while controls:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
pos = pygame.mouse.get_pos()
if balik.collidepoint(pos):
controls = False
menu = True
menuselect = 0
balik = display.blit(back, (0,450))
display.blit(instruction, (0,0))
pygame.display.flip()
pygame.display.update()
display.fill((0, 0, 0))
def developers():
global menuselect
global menu
dev = True
while dev:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
pos = pygame.mouse.get_pos()
if balik.collidepoint(pos):
dev = False
menu = True
menuselect = 0
balik = display.blit(back, (0, 450))
display.blit(aboutdev, (0, 0))
pygame.display.flip()
pygame.display.update()
display.fill((0, 0, 0))
# Asteroid
for r in range(no_of_enemies):
asteroidimg.append(pygame.image.load("Space Blitz Sprites/asteroid.png"))
asteroidX.append(random.randint(0, 468))
asteroidY.append(random.randint(-300, -30))
asteroidX_change.append(0)
asteroidY_change.append(2)
# Sprite image
def player(x, y):
display.blit(playerimg, (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
display.blit(bulletimg, (x + 9, y + -7))
def asteroid(x, y, r):
display.blit(asteroidimg[r], (x, y))
def BulCollision(asteroidX, asteroidY, bulletX, bulletY):
buldistance = math.sqrt((math.pow(bulletX - asteroidX, 2)) + (math.pow(bulletY - asteroidY, 2)))
if buldistance < 27:
return True
else:
return False
def PlayCollision(asteroidX, asteroidY, playerX, playerY):
playdistance = math.sqrt((math.pow(playerX - asteroidX, 2)) + (math.pow(playerY - asteroidY, 2)))
if playdistance < 27:
return True
else:
return False
def gameover_screen():
overtext = overfont.render("GAME OVER",True,(255,255,255))
display.blit(overtext, (150,250))
# mainloop
def gamewindow():
global menuselect
global playerX
global playerY
global velocity
global clock
global bulletX
global bulletY
global bulletY_change
global bullet_state
global asteroidX
global asteroidY
global asteroidY_change
global no_of_enemies
global score
global dev
global menu
running = True
while running:
clock.tick(60)
display.fill((0, 0, 0))
# movement
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
pos = pygame.mouse.get_pos()
if balik.collidepoint(pos):
running = False
menu = True
menuselect = 0
balik = display.blit(back, (0, 450))
# player movement
keys = pygame.key.get_pressed()
if keys[pygame.K_a]:
playerX -= velocity
if keys[pygame.K_d]:
playerX += velocity
if keys[pygame.K_s]:
playerY += velocity
if keys[pygame.K_w]:
playerY -= velocity
if keys[pygame.K_SPACE]:
if bullet_state is "ready":
bulletX = playerX
fire_bullet(bulletX, bulletY)
# Border
if playerX <= 0:
playerX = 0
elif playerX >= 468:
playerX = 468
if playerY <= 0:
playerY = 0
elif playerY >= 468:
playerY = 468
# bullet movement
if bullet_state is "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
if bulletY <= 0:
bulletY = playerY
bullet_state = "ready"
# Bullet Collision
for r in range(no_of_enemies):
asteroidY[r] += asteroidY_change[r]
if asteroidY[r] >= 500:
asteroidY[r] = random.randint(-300, -30)
asteroidX[r] = random.randint(0, 468)
Bulletcollision = BulCollision(asteroidX[r], asteroidY[r], bulletX, bulletY)
if Bulletcollision:
bulletY = playerY
bullet_state = "ready"
asteroidX[r] = random.randint(0, 468)
asteroidY[r] = random.randint(-300, -30)
score += 1
print(score)
asteroid(asteroidX[r], asteroidY[r], r)
# Game over
PlayerCollision = PlayCollision(asteroidX[r], asteroidY[r], playerX, playerY)
if PlayerCollision:
for j in range(no_of_enemies):
asteroidY_change[j] = 0
velocity = 0
gameover_screen()
break
font = pygame.font.Font(None, 54)
font_color = pygame.Color('springgreen')
passed_time = 0
timer_started = True
if timer_started:
passed_time = pygame.time.get_ticks()
text = font.render(str(passed_time / 1000), True, font_color)
display.blit(text, (50, 50))
player(playerX, playerY)
pygame.display.update()
mainmenu()
while True:
if menuselect == 0:
mainmenu()
elif menuselect == 1:
gamewindow()
elif menuselect == 2:
controls()
elif menuselect == 3:
developers()
elif menuselect == 4:
pygame.quit()
Here's the code about the timer.
font = pygame.font.Font(None, 54)
font_color = pygame.Color('springgreen')
passed_time = 0
timer_started = True
if timer_started:
passed_time = pygame.time.get_ticks()
text = font.render(str(passed_time / 1000), True, font_color)
display.blit(text, (50, 50))
player(playerX, playerY)
pygame.display.update()
Here's the code that I tried but it just made the timer go back to zero.
font = pygame.font.Font(None, 54)
font_color = pygame.Color('springgreen')
passed_time = 0
timer_started = True
if timer_started:
passed_time = pygame.time.get_ticks()
if PlayerCollision:
passed_time = False
text = font.render(str(passed_time / 1000), True, font_color)
display.blit(text, (50, 50))
player(playerX, playerY)
pygame.display.update()
pygame.time.get_ticks():
Return the number of milliseconds since pygame.init() was called.
You have to get the time when the game starts (start_time). In the main game loop you have to get the current time (current_time) and to subtract the start time form current time, to get the passed time since the start of the game. Stop computing the passed time when the game is over:
def gamewindow():
# [...]
start_time = pygame.time.get_ticks()
run_timer = True
running = True
while running:
# [...]
for r in range(no_of_enemies):
# [...]
if PlayerCollision:
# stop timer
run_timer = False
# [...]
# [...]
if run_timer:
current_time = pygame.time.get_ticks()
passed_time = current_time - start_time
text = font.render(str(passed_time / 1000), True, font_color)
display.blit(text, (50, 50))
# [...]

How to get car on top of the racetrack

i am working on a top down racing game, and currently i am trying to get the car to go on top of the racetrack. There are 2 cars, one is the computer's car (not finished) and the other is the user controlled car, however when i run the programme the user's car is behind the track, but still moves normally. I have tried a few different things, but the user's car never seems to get on top of the track. So i am mainly asking how to get the user's car on top of the track.
Thank you
import math
import random
from tkinter import *
import pygame
class Buttons:
#window
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.quitButton = Button(frame, text="Race!", fg="red", command=frame.quit)
self.quitButton.pack(side=LEFT)
root = Tk()
b = Buttons(root)
root.mainloop()
pygame.mixer.pre_init(44100,16,2,4096)
pygame.init()
screen = pygame.display.set_mode((1280, 800))
rect = screen.get_rect()
clock = pygame.time.Clock()
#music
pygame.mixer.music.load("Noteblock.mp3")
pygame.mixer.music.set_volume(0.5)
pygame.mixer.music.play(-1)
WHITE = pygame.Color('white')
# Load images globally and reuse them in your program.
# Also use the `.convert()` or `.convert_alpha()` methods after
# loading the images to improve the performance.
VEHICLE1 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE1.fill((130, 180, 20))
#blitting car onto 'rectangle car'
VEHICLE1 = pygame.image.load("YellowLambo.png")
screen.blit(VEHICLE1,(0,0))
pygame.display.update()
VEHICLE2 = pygame.Surface((40, 70), pygame.SRCALPHA)
VEHICLE2.fill((200, 120, 20))
#blitting computer's car
VEHICLE2 = pygame.image.load("RedLambo.png")
screen.blit(VEHICLE2,(0,0))
pygame.display.update()
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track1.png").convert()
screen.blit(BACKGROUND,(0,0))
pygame.display.update()
class Entity(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
class VehicleSprite(Entity):
MAX_FORWARD_SPEED = 10
MAX_REVERSE_SPEED = 2
ACCELERATION = 0.05
TURN_SPEED = 0.000000000001
def __init__(self, image, position):
Entity.__init__(self)
self.src_image = image
self.image = image
self.rect = self.image.get_rect(center=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = self.direction = 0
self.k_left = self.k_right = self.k_down = self.k_up = 0
def update(self, time):
# SIMULATION
self.speed += self.k_up + self.k_down
# To clamp the speed.
self.speed = max(-self.MAX_REVERSE_SPEED,
min(self.speed, self.MAX_FORWARD_SPEED))
# Degrees sprite is facing (direction)
self.direction += (self.k_right + self.k_left)
rad = math.radians(self.direction)
self.velocity.x = -self.speed*math.sin(rad)
self.velocity.y = -self.speed*math.cos(rad)
self.position += self.velocity
self.image = pygame.transform.rotate(self.src_image, self.direction)
self.rect = self.image.get_rect(center=self.position)
class Background(pygame.sprite.Sprite):
def __init__(self, image, location):
pygame.sprite.Sprite.__init__(self)
self.image = image
self.rect = self.image.get_rect(topleft=location)
def game_loop():
bike = VehicleSprite(VEHICLE1, rect.center)
pygame.sprite.LayeredUpdates.move_to_front
ball = VehicleSprite(VEHICLE2, rect.center)
bike_group = pygame.sprite.Group(bike)
ball_group = pygame.sprite.Group(ball)
all_sprites = pygame.sprite.Group(bike_group, ball_group)
background = Background(BACKGROUND, [0, 0])
camera = pygame.math.Vector2(0, 0)
done = False
while not done:
time = clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
# Bike Input (Player 1)
if event.key == pygame.K_d:
bike.k_right = -5
elif event.key == pygame.K_a:
bike.k_left = 5
elif event.key == pygame.K_w:
bike.k_up = 2
elif event.key == pygame.K_s:
bike.k_down = -2
elif event.key == pygame.K_ESCAPE:
done = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d:
bike.k_right = 0
elif event.key == pygame.K_a:
bike.k_left = 0
elif event.key == pygame.K_w:
bike.k_up = 0
elif event.key == pygame.K_s:
bike.k_down = 0
camera -= bike.velocity
#screen.blit(background.image, background.rect)
all_sprites.update(time)
screen.fill(WHITE)
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
pygame.display.flip()
game_loop()
pygame.quit()
The problem lies in the for loop in which you blit the sprite images:
for sprite in all_sprites:
screen.blit(background.image, background.rect.topleft+camera)
screen.blit(sprite.image, sprite.rect.topleft+camera)
Here you blit the background and one of the sprites, then you blit the background again and the next sprite. So the background will be blit above the previous sprites in each iteration of the for loop.
Just blit the background once before the loop and then the sprites:
screen.fill(WHITE)
screen.blit(background.image, background.rect.topleft+camera)
for sprite in all_sprites:
screen.blit(sprite.image, sprite.rect.topleft+camera)
I think you should blit the racetrack before the cars.
BACKGROUND = pygame.Surface((1280, 800))
BACKGROUND.fill((127, 69, 2))
BACKGROUND = pygame.image.load("track1.png").convert()
screen.blit(BACKGROUND,(0,0))
put this before you blit the cars.

Categories

Resources