Recently started trying to learn pygame with the goal of making a simple platformer. So far, I've created a player that can move left and right and is affected by gravity. I haven't yet implemented object collision. Right now I'm trying to make a simple jump script. My current script for vertical movement is the following:
if man.y + man.height < ground:
man.yvel += man.velInc
elif man.y + man.height >= ground:
if man.isJump == True:
man.isJump == False
man.yvel = 0
if keys[pygame.K_SPACE] and man.isJump == False:
man.yvel = -20
man.isJump = True
man.y += man.yvel
This is run in a loop along with other stuff such as horizontal movement. ground is a variable that determines the y-coordinate of the ground, and is currently set to 350. The height of the window is 450. man.velInc is set to 1 and man.height is set to 32 I can provide any other info if necessary.
My problem is that when I run the program, I can only jump once, and then never again. I can still move left and right normally. I put in a script to print out man.x, man.y, and man.isJump. Before the jump, man.isJump is "False", and after, True. It never goes back to False. man.y also reads as 328. The jump itself however seems to work perfectly. I would appreciate any help to fix the issue, and maybe some advice on how to avoid things like this in the future.
You are confusing the == (Boolean equality) with = (set variable)
if man.y + man.height < ground:
man.yvel += man.velInc
elif man.y + man.height >= ground:
if man.isJump == True:
man.isJump = False # replace == with =
man.yvel = 0
if keys[pygame.K_SPACE] and man.isJump == False:
man.yvel = -20
man.isJump = True
man.y += man.yvel
Related
#Bounce bullet when it reaches corners.
def bullet_bounce(rect):
bottom_corner = False
if bottom_corner == False:
rect.y +=5
if rect.bottom == 400:
bottom_corner = True
if bottom_corner == True:
rect.y -=5
if rect.top == 0:
bottom_corner = False
While working with pygame to create Pong I want to make a rectangle bounce every time it reaches the corner of the screen. I came up with this code and it works as intented when I initialize bottom_corner outside the game loop and then run the rest of the code inside the loop. But since it would look much cleaner I want to implement this code inside as a function. The problem is since the function is called inside the loop bottom_corner is initialized as False every time the loop runs which leads to only the first half of the code being iterated. Do you have any recommendations on how to fix this issue?
You should define variable outside function and send to function as parameter and get it back with return
def bullet_bounce(rect, bottom_corner):
if not bottom_corner:
rect.y +=5
if rect.bottom == 400:
bottom_corner = True
else:
rect.y -=5
if rect.top == 0:
bottom_corner = False
return bottom_corner
# --- start program ---
bottom_corner = False
# --- some loop ---
while True:
bottom_corner = bullet_bounce(rect, bottom_corner)
I am not sure if I understood your question. But I recommend you avoid making equality comparisons between boolean values(True, False) and boolean variables. Instead of saying if bottom_corner == True use if bottom_corner: and else:
And to switch boolean variables you can use the not operator
#Bounce bullet when it reaches corners.
def bullet_bounce(rect):
if bottom_corner: rec.y -=5
else rec.y += 5
if (rec.bottom == 400) or (rect.top == 0):
# switch it based on previous value
bottom_corner = not bottom_corner
Im running Python 3.8.2 and Pygame 2.0.0.dev6 in Pycharm.
I read a few of the other threads on similar issues but couldn't figure out why I'm getting this error in this instance. The purpose of this post is two-fold: 1 is that I would like to understand this error (I am very new to programming), and 2 is that I would like to know if there is a better method to accomplish what I am trying to do.
I am trying to make enemies that sway back and forth in the x-direction, their change being triggered either by a certain amount of time passing or (haven't added this yet) a certain number of collisions with other enemies.
The error seems to be triggered by the second if statement in the movement method here:
class EnemyShip(ShipGeneral):
MOVEMENT_TIME = 180
SHIP_TYPE_DIC = {
'pawn': Images().pawn_ship_img,
'boss': Images().boss_ship_img
}
def __init__(self, x, y, enemy_type=None):
super().__init__(x, y, enemy_type)
self.ship_img = self.SHIP_TYPE_DIC[enemy_type]
self.mask = pygame.mask.from_surface(self.ship_img)
self.health = 100
self.movement_time_counter = 0 # Defaut set to zero
def movement_timer(self):
if self.movement_time_counter >= self.MOVEMENT_TIME:
self.movement_time_counter = 0
elif self.movement_time_counter > 0:
self.movement_time_counter +=1
def movement(self): # TODO fix enemy movement to prevent overlapping and allow for advances
y_vel = 10
x_vel = 2
boundaries = Settings()
if self.y <= 100:
self.y += y_vel
if self.movement_time_counter == 0: # should be true and run first in the while loop
x_direction = random.choice(['R', 'L'])
self.movement_time_counter += 1
if x_direction == 'R' and self.x + self.ship_img.get_width() + x_vel < boundaries.screen_width:
self.x += x_vel
if x_direction == 'L' and self.x > 0:
self.x -= x_vel
I call the class and the functions in the game's main while loop here:
enemies = []
running = True
while running:
clock.tick(FPS)
gf.check_events() # checks for user quit event
if len(enemies) == 0: # updates level and spawns new enemies after each wave
level += 1
fleet_size += 5
for enemy in range(fleet_size):
enemy = EnemyShip(
random.randrange(20, 800 - 20),
random.randrange(-1000, -100, 10),
enemy_type=random.choice(['pawn', 'pawn', 'pawn', 'pawn', 'boss'])
)
enemies.append(enemy)
for enemy in enemies: # enables each enemy to move
enemy.movement()
enemy.move_missile(7, playership)
enemy.movement_timer()
if enemy.health <=0:
enemies.remove(enemy)
If I run this I get the following error:
File >"/Users/aaronbastian/Documents/PythonCode/Part_II_Projects/alien_invasion/ships.py", line 114, in movement
if x_direction == 'R' and self.x + self.ship_img.get_width() + x_vel < boundaries.screen_width:
UnboundLocalError: local variable 'x_direction' referenced before assignment
I don't understand the error because I thought self.movement_time_counter == 0 should evaluate to True and thus assign x_direction before the following if statements were run.
If someone could explain to me my error, I would greatly appreciate it! Also, I apologize if this is a redundant post, I just couldn't understand the other similar threads.
This error is raised during compilation because you have not initialized the variable anywhere. Just initialize the variable with some default value in the ____init____().
Example:
self.x_direction = None
I'm trying to make a game were there is this little robot that shoots. The problem is that it shoots only when it's not moving, when I move left or right or when I jump it doesn't shoot. Is there something that I can do for let my barspace key works when I'm pressing the other keys? I tried to put another if key statement in a key statement that already exist but it doesn't work, like this I mean:
elif keys[py.K_LEFT] and man.x >= 0:
man.x -= man.vel
man.right = False
man.left = True
man.standing = False
man.idlecount = 0
man.direction = -1
if keys [py.K_SPACE] and shootloop == 0:
if man.left:
facing = -1
elif man.right:
facing = 1
if len(bullets) < 5:
man.standing = True
man.shooting = True
bullets.append(bulletss(round(man.x + man.lenght//2), round(man.y + man.lenght//2), facing))
shootloop = 1
I left my github here so you can run the program. Thank you for the help and sorry for my code that is a mess.
https://github.com/20nicolas/Game.git
The if keys [py.K_SPACE] and shootloop == 0: statement should not be inside of the elif keys[py.K_LEFT] and man.x >= 0: clause, otherwise you can only shoot when you press the left arrow key.
Also, in your repo it's actually,
if keys[py.K_RIGHT] and man.x <= 700:
# ...
elif keys[py.K_LEFT] and man.x >= 0:
# ...
elif keys [py.K_SPACE] and shootloop == 0:
which means that it will only be executed when neither K_LEFT nor K_RIGHT are pressed, because these statements are in the same if...elif sequence.
This version works for me:
elif keys[py.K_LEFT] and man.x >= 0:
man.x -= man.vel
man.right = False
man.left = True
man.standing = False
man.idlecount = 0
man.direction = -1
else:
man.standing = True
if keys [py.K_SPACE] and shootloop == 0:
if man.left:
facing = -1
elif man.right:
facing = 1
if len(bullets) < 5:
man.standing = True
man.shooting = True
bullets.append(bulletss(round(man.x + man.lenght//2), round(man.y + man.lenght//2), 1))
shootloop = 1
else:
man.shooting = False
I'm trying to make a platformer, and in the code below I'm trying to move one image ('bird.png') around on the background. However, every time I try to launch pygame it crashes without even loading any of the images. I checked out the other pages and it still didn't fix the problem. There are probably a few mistakes in the code, but I can't check if it's working properly because as I said, pygame keeps crashing. Is there anything I can do to fix it?
PS. Sorry if it's a bit messy, and for the french words in the code :)
import pygame
from pygame import *
pygame.init()
TE=[]
def perso(X):
X = [0,448]
while X != [640,0]:
w=int(input("Déplacement: "))
#Right#
if w==0:
if X[1] == 608:
print("You can't leave the map")
else:
X[1] += 32
print(X)
#Left#
elif w==1:
if X[1] == 0:
print("You can't leave the map")
else:
X[1] -= 32
print(X)
#Down#
elif w==2:
if X[0] == 456:
print("You can't leave the map")
else:
X[0] += 24
print(X)
#Up#
elif w==3:
if X[0] == 0:
print("You can't leave the map")
else:
X[0] -= 24
print(X)
else:
print("non valable")
print("Bravo!")
screen = pygame.display.set_mode((680, 488)) background_image = pygame.image.load("C:/Python34/Scripts/Images & Sounds/background(680x480).jpg").convert()
screen.blit(background_image,[0,0])
character = pygame.image.load("C:/Python34/Scripts/Images & Sounds/bird(40x40).png").convert()
screen.blit(character, (X[0],X[1]))
perso(TE)
flag
I run the code and when the pygame window opens, it's black and after a few seconds I get the 'not responding' message (for the pygame window). However, the w=int(input("Déplacement: ")) part seems to work as it asks for an input. Maybe it's something to do with the images?
One of the simplest game loops consists of an "update" sequence and a "render" sequence that are called each time through the loop. Both of these sequences should take very little time to complete (the faster the better). It could be that Python's built in input function is stopping the "update" sequence and causing the game to crash because it can't continue the loop.
The easiest way to solve this would be to just use Pygame's built-in key input methods. It's also a good idea to break out the "render" and "update" sequences to help distinguish between the game logic and the rendering of images.
import pygame
from pygame import *
pygame.init()
screen = pygame.display.set_mode((680, 488))
background_image = pygame.image.load("C:/Python34/Scripts/Images & Sounds/background(680x480).jpg").convert()
character = pygame.image.load("C:/Python34/Scripts/Images & Sounds/bird(40x40).png").convert()
def move(X):
keys = pygame.get_pressed()
#Right#
if keys[pygame.K_RIGHT] != 0:
if X[1] == 608:
print("You can't leave the map")
else:
X[1] += 32
print(X)
#Left#
elif keys[pygame.K_LEFT] != 0:
if X[1] == 0:
print("You can't leave the map")
else:
X[1] -= 32
print(X)
#Down#
elif keys[pygame.K_DOWN] != 0:
if X[0] == 456:
print("You can't leave the map")
else:
X[0] += 24
print(X)
#Up#
elif keys[pygame.K_UP] != 0:
if X[0] == 0:
print("You can't leave the map")
else:
X[0] -= 24
print(X)
else:
print("non valable")
return X
def draw(X):
screen.blit(background_image,[0,0])
screen.blit(character, (X[0],X[1]))
Running = True
X = [0,448]
while Running:
# Updated and draw
X = move(X)
draw(X)
# Allow for the user to exit the game
for i in pygame.event.get():
if i.type==QUIT:
Running = False
exit()
# End the game if
if X == [640, 0]:
Running = False
exit()
I am having a lot of difficulty at the moment with updating the score on the GUI of my basic game in python.
I currently have the code such that it appears in the top left hand corner, with the score appearing as "O". However, the score remains at 0 for the entirety of the program (as it is only getting rendered once. I am unsure how to constantly rerender the score to update it? I have tried many methods and have been unsuccessful. The part of the code with the score render and my attempt at keeping track of the score using the variable conlisionNumber is:
new = bears[:]
for bear in new: #this makes a copy of the array
if player.colliderect(bear):
windowSurface.blit(bearImageTwo, bear)
windowSurface.blit(playerImageTwo, player)
def explosion():
for bear in bears:
if player.colliderect(bear) and (moveLeft == False and moveRight == False and moveUp == False and moveDown == False):
bears.remove(bear)
colisionNumber += 1
if player.colliderect(bear) and (moveLeft == False and moveRight == False and moveUp == False and moveDown == False):
t = Timer(1, explosion)
t.start()
scoreFont = pygame.font.SysFont("impact", 20)
score = scoreFont.render("SCORE:" + str(colisionNumber), True, (192,192,192))
windowSurface.blit(score, (10,10))
Please note: at the start of the program I put:
global colisionNumber
colisionNumber = 0
This was done because if I defined colisionNumber within explosion, then colisionNumber would not be defined in the score variable.
Any help would be greatly appreciated.
colisionNumber = 0
def explosion():
global colisionNumber
colisionNumber += 1