Problem with character animations using pygame with functions - python

I would like to ask your help for solving this problem of mine. I need to develop a game using only functions (NO CLASSES) in pygame.
I already manage to run the game but the animations or sprites do not update as they should. The image always stays the same when it should be changing while moving.
What am I doing wrong?
Here's the code:
import pygame
WIDTH = 800
HEIGHT= 600
pygame.display.set_caption("Nico's worst adventure")
window = pygame.display.set_mode((WIDTH, HEIGHT))
#Color #R #G #B
White = (255, 255, 255)
Black = (0, 0, 0)
Red = (255, 0, 0)
Blue = (0, 0, 255)
#Position
x = 50
y = 425
imageWidth = 64
vel = 5 #Velocity of movement
isJumping = False
jumpCount = 10
left = False
right = False
walkCount = 0
#Image port
walkRight = [pygame.image.load('Nico right(1).png'), pygame.image.load('Nico right(2).png'), pygame.image.load('Nico right(3).png'), pygame.image.load('Nico right(4).png')]
walkLeft = [pygame.image.load('Nico left(1).png'), pygame.image.load('Nico left(2).png'), pygame.image.load('Nico left(3).png'), pygame.image.load('Nico left(4).png')]
still = pygame.image.load('Nico still.png')
backgorund = pygame.image.load('Fondo.png')
def drawCharacter():
global walkCount
window.blit(backgorund, (0,0))
if walkCount + 1 >= 12:
walkCount = 0
if left:
window.blit(walkLeft[walkCount//3], (x, y))
walkCount += 1
elif right:
window.blit(walkRight[walkCount//3], (x, y))
walkCount += 1
else:
window.blit(still, (x, y))
pygame.display.update()
def draw():
global imageWidth
global WIDTH
global x
global y
global vel
global jumpCount
global isJumping
clock = pygame.time.Clock()
play = True
#Main loop
while play:
clock.tick(27)
pygame.init()
for event in pygame.event.get():
if event.type == pygame.QUIT:
play = False
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and x > vel:
x -= vel
left = True
right = False
elif key[pygame.K_RIGHT] and x < WIDTH - imageWidth - vel:
x += vel
right = True
left = False
else:
right = False
left = False
walkCount = 0
if not(isJumping):
if key[pygame.K_SPACE]:
isJumping = True
right = False
left = False
walkCount = 0
else:
if jumpCount >= -10:
neg = 1
if jumpCount < 0:
neg = -1
y -= (jumpCount ** 2) * 0.5 * neg
jumpCount -= 1
else:
isJumping = False
jumpCount = 10
drawCharacter()
pygame.display.flip()
pygame.quit()
draw()
I have already checked it and compared it to other codes but I just can't find what's the real problem.

The simple fix has already been mentioned, but I'd rather suggest getting rid of the global variables altogether and just moving them into the function with the main loop to make them local.
Also, the drawCharacter function shouldn't be responsible to update the walkCount as well as blitting the images. I'd just remove it and update the walkCount in the if key[pygame.K_LEFT]... clauses and then use it to assign the current player image to a variable (player_image) which you can blit later in the drawing section. That allows you to get rid of the left and right variables, too.
The drawCharacter function would then only consist of these two lines,
window.blit(background, (0, 0))
window.blit(player_image, (x, y))
so you could simply call them in the main loop as well instead of calling them in the function (to which you would have to pass these arguments).
By the way, call the convert or convert_alpha methods when you load the images to improve the performance.
Here's the updated code:
import pygame
pygame.init()
WIDTH = 800
HEIGHT= 600
pygame.display.set_caption("Nico's worst adventure")
window = pygame.display.set_mode((WIDTH, HEIGHT))
White = (255, 255, 255)
Black = (0, 0, 0)
Red = (255, 0, 0)
Blue = (0, 0, 255)
# Images (I assume you're using pictures with a transparent background
# so I call the `convert_alpha` method).
walkRight = [
pygame.image.load('Nico right(1).png').convert_alpha(),
pygame.image.load('Nico right(2).png').convert_alpha(),
pygame.image.load('Nico right(3).png').convert_alpha(),
pygame.image.load('Nico right(4).png').convert_alpha(),
]
walkLeft = [
pygame.image.load('Nico left(1).png').convert_alpha(),
pygame.image.load('Nico left(2).png').convert_alpha(),
pygame.image.load('Nico left(3).png').convert_alpha(),
pygame.image.load('Nico left(4).png').convert_alpha(),
]
still = pygame.image.load('Nico still.png').convert_alpha()
background = pygame.image.load('Fondo.png').convert()
def game():
clock = pygame.time.Clock()
# Player related variables.
x = 50
y = 425
imageWidth = 64
vel = 5
isJumping = False
jumpCount = 10
walkCount = 0
player_image = still # Assign the current image to a variable.
play = True
while play:
clock.tick(27)
for event in pygame.event.get():
if event.type == pygame.QUIT:
play = False
key = pygame.key.get_pressed()
if key[pygame.K_LEFT] and x > vel:
x -= vel
# Update the walkCount and image here.
walkCount += 1
player_image = walkRight[walkCount//3]
elif key[pygame.K_RIGHT] and x < WIDTH - imageWidth - vel:
x += vel
walkCount += 1
player_image = walkLeft[walkCount//3]
else:
player_image = still
walkCount = 0
if walkCount + 1 >= 12:
walkCount = 0
if not isJumping:
if key[pygame.K_SPACE]:
isJumping = True
walkCount = 0
else:
if jumpCount >= -10:
neg = 1
if jumpCount < 0:
neg = -1
y -= (jumpCount ** 2) * 0.5 * neg
jumpCount -= 1
else:
isJumping = False
jumpCount = 10
window.blit(background, (0, 0))
window.blit(player_image, (x, y)) # Just blit the current image.
pygame.display.flip() # Only one `flip()` or `update()` call per frame.
game()
pygame.quit()

It's because left and right in the draw function are local variables, not global.
A simple fix is to add
global left
global right
at the beginning of draw.
I need to develop a game using only functions (NO CLASSES) in pygame
That's a strange requirement given that pygame itself is full of classes and you use some of them already.

Related

how to replace picture and check for collision with new image and and a moving image in pygame [duplicate]

This question already has answers here:
Animated sprite from few images
(4 answers)
how to make image/images disappear in pygame?
(1 answer)
Closed 2 years ago.
I'm making a pygame game where a player is moving around on a screen and can buy items from a shop(bombs). I'm able to drop the bombs, now I need to replace the bomb image with an explosion image after 3 secs and check for collision with the enemy. I'm attaching my whole code along with some screenshots for reference. Any help is appreciated, thank you
import pygame
import random
pygame.font.init()
width = 900
height = 600
screen = pygame.display.set_mode([width, height])
walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'),
pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
char = pygame.image.load('standing.png')
bomb_pic = pygame.transform.scale(pygame.image.load('bomb.png'), (20,20))
bomb_explosion = pygame.transform.scale(pygame.image.load('explosion1.png'), (40,40))
# char_rect = char.get_rect()
enemy_Left = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'),
pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'),
pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png')]
x = 50
y = 50
width = 40
height = 60
vel = 5
isJump = False
jumpCount = 10
left = False
right = False
down = False
up = False
walkCount = 0
enemy_vel = 2
enemy_list = []
shop = pygame.transform.scale(pygame.image.load("shop.png"), (60, 60))
clock = pygame.time.Clock()
FPS = 60
font = pygame.font.Font('freesansbold.ttf', 32)
items_font = pygame.font.Font('freesansbold.ttf', 16)
bombs =[]
bag = {'bomb': 0}
print(bag["bomb"])
class Button():
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def draw(self, win, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.SysFont('comicsans', 20)
text = font.render(self.text, 1, (0, 0, 0))
win.blit(text, (
self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))
def shop_run():
shop_bomb = Button((0, 200, 0), 820, 150, 60, 20, text="Bomb_b")
bright_green = (0, 255, 0)
green = (0, 200, 0)
shop_bomb.draw(screen)
def redrawGameWindow():
global walkCount
global font
global bag
global items_font
global enemy_list
screen.fill([166, 166, 166])
for five_enemies in range(6):
random_enemy_location_y = random.randrange(100, 400)
random_enemy_location_x = random.randrange(800, 840)
enemy_list.append([random_enemy_location_x, random_enemy_location_y])
for enemies in range(6):
screen.blit(enemy_Left[enemies], enemy_list[enemies])
enemy_list[enemies][0] -= 0.3
pygame.draw.rect(screen, (0, 0, 0), (800, 0, 100, 600))
if x + char.get_width() < 60 and y + char.get_height() < 60:
shop_run()
screen.blit(shop, (0, 0))
screen.blit(font.render("Menu", True, (255,255,255)),(805, 10))
screen.blit(items_font.render("Bombs: "+ str(bag["bomb"]), True, (255, 255, 255)), (805, 550))
# screen.blit(bomb_explosion, (450, 300))
if walkCount + 1 >= 27:
walkCount = 0
if left:
screen.blit(walkLeft[walkCount // 3], (x, y))
walkCount += 1
elif right:
screen.blit(walkRight[walkCount // 3], (x, y))
walkCount += 1
elif down:
screen.blit(char, (x, y))
walkcount = 0
elif up:
screen.blit(char, (x, y))
walkcount = 0
else:
screen.blit(char, (x, y))
walkCount = 0
for pos in bombs:
screen.blit(bomb_pic, pos)
pygame.display.update()
def main():
run = True
# shopper()
pygame.display.set_caption("bomb-mania")
global x
global y
global width
global height
global vel
global isJump
global jumpCount
global left
global right
global down
global up
global walkCount
global bomb_pic
global font
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if x + char.get_width() < 60 and y + char.get_height() < 60:
buy = pygame.key.get_pressed()
if buy[pygame.K_b]:
bag["bomb"] += 1
print(bag["bomb"])
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and bag["bomb"] >= 1:
bombs.append(((x + (char.get_width()/2)),( y + (char.get_height() - 20))))
bag["bomb"] -= 1
redrawGameWindow()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel - 15:
x -= vel
left = True
right = False
down = False
up = False
elif keys[pygame.K_RIGHT] and x < 800 - vel - width:
x += vel
left = False
right = True
down = False
up = False
elif keys[pygame.K_DOWN] and y < 600 - height:
y += vel
left = False
right = False
down = True
up = False
elif keys[pygame.K_UP] and y > vel - 15:
y -= vel
left = False
right = False
down = False
up = True
else:
left = False
right = False
down = False
up = False
walkCount = 0
clock.tick(FPS)
pygame.display.flip()
main()
enemies are moving towards the left
able to drop bombs
able to buy bombs from the shop
I'm adding a code below please help me troubleshoot and debug this
import pygame
import random
pygame.font.init()
width = 900
height = 600
screen = pygame.display.set_mode([width, height])
walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'),
pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
char = pygame.image.load('standing.png')
bomb_pic = pygame.transform.scale(pygame.image.load('bomb.png'), (20,20))
bomb_explosion = pygame.transform.scale(pygame.image.load('explosion1.png'), (40,40))
# char_rect = char.get_rect()
enemy_Left = [pygame.image.load('L1E.png'), pygame.image.load('L2E.png'), pygame.image.load('L3E.png'),
pygame.image.load('L4E.png'), pygame.image.load('L5E.png'), pygame.image.load('L6E.png'),
pygame.image.load('L7E.png'), pygame.image.load('L8E.png'), pygame.image.load('L9E.png')]
x = 50
y = 50
width = 40
height = 60
vel = 5
isJump = False
jumpCount = 10
left = False
right = False
down = False
up = False
walkCount = 0
enemy_vel = 2
enemy_list = []
shop = pygame.transform.scale(pygame.image.load("shop.png"), (60, 60))
clock = pygame.time.Clock()
FPS = 60
font = pygame.font.Font('freesansbold.ttf', 32)
items_font = pygame.font.Font('freesansbold.ttf', 16)
bombs =[]
bag = {'bomb': 0}
bomb_timer = {"bomb0":0}
bomb_placed = False
bombCount = 1
bombs_dict = {"bomb0": False}
bombTimers = []
explosion_dict = {"explosion0": False}
print(bag["bomb"])
class Button():
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.x = x
self.y = y
self.width = width
self.height = height
self.text = text
def draw(self, win, outline=None):
# Call this method to draw the button on the screen
if outline:
pygame.draw.rect(win, outline, (self.x - 2, self.y - 2, self.width + 4, self.height + 4), 0)
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height), 0)
if self.text != '':
font = pygame.font.SysFont('comicsans', 20)
text = font.render(self.text, 1, (0, 0, 0))
win.blit(text, (
self.x + (self.width / 2 - text.get_width() / 2), self.y + (self.height / 2 - text.get_height() / 2)))
def shop_run():
shop_bomb = Button((0, 200, 0), 820, 150, 60, 20, text="Bomb_b")
bright_green = (0, 255, 0)
green = (0, 200, 0)
shop_bomb.draw(screen)
def redrawGameWindow():
global walkCount
global font
global bag
global items_font
global enemy_list
global bomb_timer
global bomb_placed
global explosion_dict
screen.fill([166, 166, 166])
for five_enemies in range(6):
random_enemy_location_y = random.randrange(100, 400)
random_enemy_location_x = random.randrange(800, 840)
enemy_list.append([random_enemy_location_x, random_enemy_location_y])
for enemies in range(6):
screen.blit(enemy_Left[enemies], enemy_list[enemies])
enemy_list[enemies][0] -= 0.3
pygame.draw.rect(screen, (0, 0, 0), (800, 0, 100, 600))
if x + char.get_width() < 60 and y + char.get_height() < 60:
shop_run()
screen.blit(shop, (0, 0))
screen.blit(font.render("Menu", True, (255,255,255)),(805, 10))
screen.blit(items_font.render("Bombs: "+ str(bag["bomb"]), True, (255, 255, 255)), (805, 550))
# screen.blit(bomb_explosion, (450, 300))
if walkCount + 1 >= 27:
walkCount = 0
if left:
screen.blit(walkLeft[walkCount // 3], (x, y))
walkCount += 1
elif right:
screen.blit(walkRight[walkCount // 3], (x, y))
walkCount += 1
elif down:
screen.blit(char, (x, y))
walkcount = 0
elif up:
screen.blit(char, (x, y))
walkcount = 0
else:
screen.blit(char, (x, y))
walkCount = 0
for pos in bombs:
for i in bombs_dict:
if bombs_dict["bomb"+str(bag["bomb"])]:
screen.blit(bomb_pic, pos)
bomb_timer["bomb"+str(bag["bomb"])] += clock.get_time()
if bomb_timer["bomb"+str(bag["bomb"])] >= 3000:
bombs_dict["bomb"+str(bag["bomb"])] = False
explosion_dict["explosion" + str(bag["bomb"])] = True
del bombs_dict["bomb"+str(bag["bomb"])]
else:
if explosion_dict["explosion" + str(bag["bomb"])]:
screen.blit(bomb_explosion, (pos))
if bomb_timer["bomb"+str(bag["bomb"])] >= 5000:
explosion_dict["explosion" + str(bag["bomb"])] = False
del explosion_dict["explosion" + str(bag["bomb"])]
pygame.display.update()
def main():
run = True
pygame.display.set_caption("bomb-mania")
global x
global y
global width
global height
global vel
global isJump
global jumpCount
global left
global right
global down
global up
global walkCount
global bomb_pic
global font
global bombs_dict
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if x + char.get_width() < 60 and y + char.get_height() < 60:
buy = pygame.key.get_pressed()
if buy[pygame.K_b]:
bag["bomb"] += 1
bombs_dict["bomb"+str(bag["bomb"])] = False
print(bag["bomb"])
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and bag["bomb"] >= 1:
bombs.append(((x + (char.get_width()/2)),( y + (char.get_height() - 20))))
bombs_dict["bomb"+str(bag["bomb"])] = True
bag["bomb"] -= 1
redrawGameWindow()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel - 15:
x -= vel
left = True
right = False
down = False
up = False
elif keys[pygame.K_RIGHT] and x < 800 - vel - width:
x += vel
left = False
right = True
down = False
up = False
elif keys[pygame.K_DOWN] and y < 600 - height:
y += vel
left = False
right = False
down = True
up = False
elif keys[pygame.K_UP] and y > vel - 15:
y -= vel
left = False
right = False
down = False
up = True
else:
left = False
right = False
down = False
up = False
walkCount = 0
clock.tick(FPS)
pygame.display.flip()
main()
Look at pygame.time.Clock(). If you set an FPS rate (say 20), All you have to do is:
myClock = pg.time.Clock()
FPS = 20
bomb_placed = True
bomb_timer = 0
main_loop():
myClock.tick(FPS) # This will keep your FPS at 20 or below so you can estimate time
if bomb_placed:
bomb_timer += myClock.get_time()
if bomb_timer >= 3000:
# Draw the bomb explosion to the screen
if bomb_timer >= 5000:
bomb_timer = 0
bomb_placed = False # Stops displaying the bomb explosion
Hope that helped. Feel free to check out the pygame docs on the subject:
https://www.pygame.org/docs/ref/time.html#pygame.time.Clock.get_time
Example for multiple bombs:
myClock = pg.time.Clock()
FPS = 20
bombA, bombB, bombC = False, False, False
bombA_timer, bombB_timer, bombC_timer = 0, 0, 0
bombs = [bombA, bombB, bombC]
bomb_timers = [bombA_timer, bombB_timer, bombC_timer]
main_loop():
myClock.tick(FPS)
for i in len(bombs):
if bombs[i]:
bomb_timers[i] += myClock.get_time()
if bomb_timers[i] >= 3000:
draw_explosion()
if bomb_timer >= 5000:
bomb_timers[i] = 0
bomb_placed[i] = False
This example simply loops through each of the bomb variables that represent the possible bombs on the screen- in this case a max of 3.
For lots of bombs, first create two dictionaries to hold the values of the bombs (active or not active) and their respective timers. Then loop through each of the bombs and, if the bomb is active, update the timer accordingly:
bombs = {"bomb0": False} # Create dictionaries for the bombs and their timers, with 0-1 entries. (I did one to show you what it looks like).
bombTimers = {bombTimer0: 0}
main_loop():
myClock.tick(FPS)
for i in len(bombs): # For each bomb you have created
bombName = "bomb" + str(i) # get the name of the bomb and corresponding timer
timerName = "bombTimer" + str(i)
if bombs[bombName]: # If the bomg has a value of True:
bombTimers[timerName] += myClock.get_time() # Update the timer
if bombTimers[timerName] >= 3000: # Check if you need to draw the explosion
draw_explosion()
if bomb_timer >= 5000: # Check if the bomb animation is over, and reset the bomb so that it can be used again in the future
bombTimers[timerName] = 0
bombs[bombName] = False
This code works exactly the same as the previous example, but it is much easier to work with. You can easily add more bombs while not starting with an unnecessary amount, like so:
bombCount = 1
bombs = {"bomb0": False}
bombTimers = {"bombTimer0": 0}
main_loop():
if player_placed_bomb(): # When the player drops a bomb in your game:
placed = False # Make a variable saying that you have not activaded the bomb and timer yet
for key, val in bombs: # For each bomb in the bombs dictionary:
if not val: # If the value of that bomb is False (Not being used):
val = True # Activates the bomb that was already created
placed = True # Updates the placed variable indicating that you set a bomb to active
break
if not placed: # After looping through the dictionary, if there were no inactive bomb variables:
bombs["bomb" + str(bombCounter)] = True # Create a new bomb in your dictionary, with a unique name.
bombTimers["bombTimer" + str(bombCounter)] = 0 # Created a new corresponding timer
bombCounter += 1 # Add 1 to the bombCounter, which is used to create the unique name of the next bomb you create.
# Rest of main_loop()
This code ensures that you are working with the smallest dictionaries possible to reduce unneeded computation power. When a bomb explodes, it will become false and it's matching timer reset. The first if loop in the code above ensures that all existing bombs are active, and if not reuses the old bomb and timer. If all bombs are being used, It creates new entries in the dictionaries to allow for more bombs.
I added an unnecesarry amount of comments, but I hope it makes it more understandable for you. Let me know if you have more questions on how this works. If you are unfamiliar with python dict() objects, there are lots of resources on the internet that explain them thoughroughly.
Disclaimer: I haven't actually ran the code, but it should function how it is supposed to. Let me know if it doesn't.
Here are some thoughts on the reformed code:
You use "str(bag["bombs"])" quite a bit in your code- consider defining a variable: b = str(bag["bombs"]), and using that. It would make it much simpler.
I don't know why you delete the "bombs_dict" and "explosions_dict" entries after you are finished with them. The way your loop is set up, I will result in an error. I would suggest rather than deleting the entries, you keep them and attempt to reuse them, as shown in the code snippet above.
Or, if you like deleting them, you need to figure out a way to rename certain keys in your dictionaries so that the names are in order. (if you delete bomb2 from bombs_dict, and you have bomb1 and bomb3, you need to change bomb3 to bomb2 or the loop wont work as intended). You will also need to alter your bombCount variable accordingly.

There is an error Decrypting an integer is required

I have been following this tutorial to build a simple 2D game using pygame.
I have checked multiple times my code but I still can't figure out what this error means
import pygame as pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
pygame.display.set_caption('First Game')
pygame.display.update()
Here I set up all commands in response to the user's imput
walkRight = [pygame.image.load('R1.png'), pygame.image.load('R2.png'), pygame.image.load('R3.png'),
pygame.image.load('R4.png'), pygame.image.load('R5.png'), pygame.image.load('R6.png'),
pygame.image.load('R7.png'), pygame.image.load('R8.png'), pygame.image.load('R9.png')]
walkLeft = [pygame.image.load('L1.png'), pygame.image.load('L2.png'), pygame.image.load('L3.png'),
pygame.image.load('L4.png'), pygame.image.load('L5.png'), pygame.image.load('L6.png'),
pygame.image.load('L7.png'), pygame.image.load('L8.png'), pygame.image.load('L9.png')]
bg = pygame.image.load('bg.jpg')
char = pygame.image.load('standing.png')
clock = pygame.time.Clock()
x = 50
y = 50
width = 64
height = 64
vel = 5
isJump = False
jumpCount = 10
left = False
right = False
walkCount = 0
run = True
Here I defined the frames and the corresponding pictures with each movement. The problem is coming from here but I don't understand why
def redrawgamewindow():
global walkCount
window.blit(bg, (0, 0))
pygame.draw.rect(window, (255, 255, 255), (x, y, width, height))
if walkCount + 1 >= 27:
walkCount = 0
if left:
window.blit(walkLeft[walkCount // 3], (x, y))
walkCount += 1
elif right:
window.blit(walkRight[walkCount // 3], (x, y))
walkCount += 1
else:
window.blit(char, (x, y))
walkCount = 0
pygame.display.update()
while run:
clock.tick(27)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel:
x -= vel
right = False
left = True
elif keys[pygame.K_RIGHT] and x < 500 - (width + vel):
x += vel
right = True
left = False
else:
right = False
left = False
walkCount = 0
if not isJump:
if keys[pygame.K_UP] and y > vel:
y -= vel
if keys[pygame.K_DOWN] and y < 500 - (height + vel):
y += vel
if keys[pygame.K_SPACE]:
isJump = True
right = False
left = False
else:
if jumpCount >= -10:
neg = 1
if jumpCount < 0:
neg = -1
y -= (jumpCount * abs( jumpCount))*0.5
jumpCount -= 1
else:
isJump = False
jumpCount = 10
redrawgamewindow()
pygame.quit()
The error displayed is
/Users/Thomas.V/Documents/Documents/Perso/Coding /Python /Pycharm Projects/Pygame.py:40: DeprecationWarning: an integer is required (got type float). Implicit conversion to integers using __int__ is deprecated and may be removed in a future version of Python.
pygame.draw.rect(window, (255, 255, 255), (x, y, width, height))
The warning is caused because y is not an integral value, because of
y -= (jumpCount * abs( jumpCount))*0.5
Get rid of the warning by rounding y (see round):
pygame.draw.rect(window, (255, 255, 255), (x, round(y), width, height))

jumping too fast?

I am messing around with pygame, and trying to create a simple jumping function (no physics yet).
For some reason my "jumps" are not visible in the display, even though the values I am using print out and seem to be working as intended. What could I be doing wrong?
isJump = False
jumpCount = 10
fallCount = 10
if keys[pygame.K_SPACE]:
isJump = True
if isJump:
while jumpCount > 0:
y -= (jumpCount**1.5) / 3
jumpCount -= 1
print(jumpCount)
while fallCount > 0:
y += (fallCount**1.5) / 3
fallCount -= 1
print(fallCount)
else:
isJump = False
jumpCount = 10
fallCount = 10
print(jumpCount, fallCount)
win.fill((53, 81, 92))
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
pygame.display.update()
I shortened the amount of code, but I think this is all that is related to the problem.
You've to turn the while loops to if conditions. You don't want to do the complete jump in a single frame.
You've to do a single "step" of the jump per frame. Use the main application loop to perform the jump.
See the example:
import pygame
pygame.init()
win = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
isJump = False
jumpCount, fallCount = 10, 10
x, y, width, height = 200, 300, 20, 20
run = True
while run:
clock.tick(20)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
isJump = True
if isJump:
if jumpCount > 0:
y -= (jumpCount**1.5) / 3
jumpCount -= 1
print(jumpCount)
elif fallCount > 0:
y += (fallCount**1.5) / 3
fallCount -= 1
print(fallCount)
else:
isJump = False
jumpCount, fallCount = 10, 10
print(jumpCount, fallCount)
win.fill((53, 81, 92))
pygame.draw.rect(win, (255, 0, 0), (x, y, width, height))
pygame.display.flip()

How to fix 'Couldn't open C:\GAME\R1.png' in pygame?

I'm trying to learn how to make a game using python and pygame, but I'm pretty new to this, so I can't understand the jargon that comes with the answers that are similar to my own question.
I'm following a video playlist on YouTube called Tech With Tim and I need to use some images for the character in the game, but the images simply won't load and keeps coming up with 'Couldn't open C:\GAME\R1.png'.
They're already in the same folder why is what makes this so confusing. All the images are also named correctly to the best of my understanding (i.e. they all have the names used in the code below:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 480))
pygame.display.set_caption("First Game")
walkRight = [pygame.image.load('C:\GAME\R1.png'), pygame.image.load('C:\GAME\R2.png'), pygame.image.load('C:\GAME\R3.png'),
pygame.image.load('C:\GAME\R4.png'), pygame.image.load('C:\GAME\R5.png'), pygame.image.load('C:\GAME\R6.png'),
pygame.image.load('C:\GAME\R7.png'), pygame.image.load('C:\GAME\R8.png'), pygame.image.load('C:\GAME\R9.png')]
walkLeft = [pygame.image.load('C:\GAME\L1.png'), pygame.image.load('C:\GAME\L2.png'), pygame.image.load('C:\GAME\L3.png'),
pygame.image.load('C:\GAME\L4.png'), pygame.image.load('C:\GAME\L5.png'), pygame.image.load('C:\GAME\L6.png'),
pygame.image.load('C:\GAME\L7.png'), pygame.image.load('C:\GAME\L8.png'), pygame.image.load('C:\GAME\L9.png')]
bg = pygame.image.load('C:\GAME\Bg.jpg')
char = pygame.image.load('C:\GAME\standing.png')
x = 50
y = 425
width = 64
height = 64
vel = 5
clock = pygame.time.Clock()
isJump = False
jumpCount = 10
left = False
right = False
walkCount = 0
def redrawGameWindow():
global walkCount
win.blit(bg, (0, 0))
if walkCount + 1 >= 27:
walkCount = 0
if left:
win.blit(walkLeft[walkCount // 3], (x, y))
walkCount += 1
elif right:
win.blit(walkRight[walkCount // 3], (x, y))
walkCount += 1
else:
win.blit(char, (x, y))
walkCount = 0
pygame.display.update()
run = True
while run:
clock.tick(27)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel:
x -= vel
left = True
right = False
elif keys[pygame.K_RIGHT] and x < 500 - vel - width:
x += vel
left = False
right = True
else:
left = False
right = False
walkCount = 0
if not (isJump):
if keys[pygame.K_SPACE]:
isJump = True
left = False
right = False
walkCount = 0
else:
if jumpCount >= -10:
y -= (jumpCount * abs(jumpCount)) * 0.5
jumpCount -= 1
else:
jumpCount = 10
isJump = False
redrawGameWindow()
pygame.quit()
I expect to see the game load and work, but instead, the error 'Couldn't open C:\GAME\R1.png' comes up.
I'd appreciate any help!
First, be sure that is the good path to your file.
Also, you should use '/' instead of '\'. Your path should be : 'C:/GAME/R1.png'

How do I fix my 'Jump'?

I am new to this website and pygame so bear with me. I am experimenting with pygame and made a simple platformer. However, whenever I 'Jump', the block jumps frame by frame, so I have to hold down the spacebar. Any help would be greatly appreciated!
here is my code:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
x = 0
y = 490
width = 10
height = 10
vel = 5
pygame.key.set_repeat(1)
isjump = False
jumpcount = 10
while True:
pygame.time.delay(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and x>vel-5:
x -= vel
if keys[pygame.K_d] and x < 500 - width:
x += vel
if not(isjump):
if keys[pygame.K_SPACE]:
isjump = True
else:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= (jumpcount ** 2) /2 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
pygame.quit()
You are mixing your keyboard event handling with your jump-logic. I've done two things, change the spacebar detection to trigger isjump and handle the jump logic irregardless of whether there is a key pressed or not:
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
x = 0
y = 490
width = 10
height = 10
vel = 5
pygame.key.set_repeat(1)
isjump = False
jumpcount = 10
while True:
pygame.time.delay(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and x>vel-5:
x -= vel
if keys[pygame.K_d] and x < 500 - width:
x += vel
# if we're not already jumping, check if space is pressed to start a jump
if not isjump and keys[pygame.K_SPACE]:
isjump = True
jumpcount = 10
# if we're supposed to jump, handle the jump logic
if isjump:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= (jumpcount ** 2) /2 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
pygame.quit()
The line keys = pygame.key.get_pressed() and the whole game logic and drawing code should not be in the event loop (for event in pygame.event.get():), otherwise the code gets executed once per event in the queue, and if no events are in the queue, it won't be executed at all.
You could just dedent keys = pygame.key.get_pressed() and all lines beneath.
Alternatively, you could check in the event loop if the space key was pressed (with if event.type == pygame.KEYDOWN:) and then set isjump to True (that means the player will only jump once per keypress).
import pygame
pygame.init()
win = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
x = 0
y = 490
width = 10
height = 10
vel = 5
isjump = False
jumpcount = 10
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
isjump = True
keys = pygame.key.get_pressed()
if keys[pygame.K_a] and x > vel - 5:
x -= vel
elif keys[pygame.K_d] and x < 500 - width:
x += vel
if isjump:
if jumpcount >= -10:
neg = 1
if jumpcount < 0:
neg = -1
y -= jumpcount**2 / 2 * neg
jumpcount -= 1
else:
isjump = False
jumpcount = 10
win.fill((0, 0, 0))
pygame.draw.rect(win, (255, 255, 255), (x, y, width, height))
pygame.display.update()
clock.tick(30)
pygame.quit()
I also recommend adding a pygame.time.Clock instance and call clock.tick(FPS) to regulate the frame rate.
And I'd rather implement the jumping in this way, with a gravity constant which gets added to the y-velocity each frame.

Categories

Resources