Weird Keyboard Interrupt error that happens after ending program [duplicate] - python

This question already has an answer here:
How to get if a key is pressed pygame [duplicate]
(1 answer)
Closed 2 years ago.
I'm able to run the game and all of the graphics work but I cant get keyboard input to work even though it worked briefly the first time I used it. Additionally, it only gives the error after I close the program. Other pygame features, such as closing the program with the red x also don't work
import pygame
from essentials import *
import random
pygame.init()
screen_height = 640
screen_width = 640
win = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("The Room")
# button class
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
player_width = 25
player_height = 25
player_pos_x = 600
player_pos_y = 600
vel = 40 # set to ten for release
keys = pygame.key.get_pressed()
run2 = True
while run2:
win.fill((0, 0, 0))
# the circle
circle = pygame.draw.circle(win, GREEN, (50, 50), 5)
# the player square
player = pygame.draw.rect(win, RED, (player_pos_x, player_pos_y, player_width, player_height))
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if keys[pygame.K_LEFT] and player_pos_x > vel:
player_pos_x -= vel
if keys[pygame.K_RIGHT] and player_pos_x < screen_width - player_width - vel:
player_pos_x += vel
if keys[pygame.K_UP] and player_pos_y > vel:
player_pos_y -= vel
if keys[pygame.K_DOWN] and player_pos_y < screen_height - player_height - vel:
player_pos_y += vel
if isOver(player, (50, 50)):
print("Ding!")
pygame.display.update()
isOver:
def isOver(self, pos):
if pos[0] > self.x and pos[0] < self.x + self.width:
if pos[1] > self.y and pos[1] < self.y + self.height:
return True
*note that I am using Ubuntu and am fairly new to it

keys = pygame.key.get_pressed() returns the current state of the keys. You have to retrieve the state of the keys continuously in the main application loop, rather than once before the loop:
# keys = pygame.key.get_pressed() <--- REMOVE
while run2:
keys = pygame.key.get_pressed() # <--- INSERT
Furthermore there is a type. In the condition of the while loop the variable run2 is evaluated, but in the event loop run is set:

Related

Pygame Not Respounding

I am a newbie in Pygame (I use many libraries in python) There is a severe problem I face that is My pygame window is not responding I don't know why but this is happening every time I
run the code.
Here is the window
here is the code:
import pygame
pygame.init()
win = pygame.display.set_mode((500,500))
pygame.display.set_caption("First Game")
x = 50
y = 50
width = 20
height = 60
vel = 5
x1 = 100
y1 = 100
width1 = 20
height1 = 60
vel1 = 5
run = True
while run:
pygame.time.delay(100)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel:
x -= vel
if keys[pygame.K_RIGHT] and x < 245 - vel - width:
x += vel
if keys[pygame.K_UP] and y > vel :
y -= vel
if keys[pygame.K_DOWN] and y < 500 - height - vel:
y += vel
win.fill((255,255,255)) # Fills the screen with black
pygame.draw.circle(win , (255,0,0), (x,y), width)
pygame.draw.circle(win , (255,0,0), (x1,y1), width)
pygame.draw.rect(win, (0,0,0), (245, 0, 20, 500))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
Could you just please help to deal wit this problem.
It's just a matter of Indentation. You have implemented an infinite loop, therefore the window does not respond. You need to draw the scene and handle the event in the application loop instead of after the application loop.
import pygame
pygame.init()
win = pygame.display.set_mode((500,500))
pygame.display.set_caption("First Game")
x = 50
y = 50
width = 20
height = 60
vel = 5
x1 = 100
y1 = 100
width1 = 20
height1 = 60
vel1 = 5
run = True
while run:
pygame.time.delay(100)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel:
x -= vel
if keys[pygame.K_RIGHT] and x < 245 - vel - width:
x += vel
if keys[pygame.K_UP] and y > vel :
y -= vel
if keys[pygame.K_DOWN] and y < 500 - height - vel:
y += vel
# INDENTATION
#-->|
win.fill((255,255,255)) # Fills the screen with black
pygame.draw.circle(win , (255,0,0), (x,y), width)
pygame.draw.circle(win , (255,0,0), (x1,y1), width)
pygame.draw.rect(win, (0,0,0), (245, 0, 20, 500))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
Your issue is caused by the indentation of your script.
pygame.display.update() will update the screen, that should be inside the while run!
The 'Fills screen with black' can be done above the while, since you want that just once.
Same story for the for loop that will set run = False, the button and event's is something you want to check every iteration, so move it inside the while
import pygame
pygame.init()
win = pygame.display.set_mode((500,500))
pygame.display.set_caption("First Game")
x = 50
y = 50
width = 20
height = 60
vel = 5
x1 = 100
y1 = 100
width1 = 20
height1 = 60
vel1 = 5
run = True
win.fill((255,255,255)) # Fills the screen with black
pygame.draw.circle(win , (255,0,0), (x,y), width)
pygame.draw.circle(win , (255,0,0), (x1,y1), width)
pygame.draw.rect(win, (0,0,0), (245, 0, 20, 500))
while run:
# pygame.time.delay(100)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and x > vel:
x -= vel
if keys[pygame.K_RIGHT] and x < 245 - vel - width:
x += vel
if keys[pygame.K_UP] and y > vel :
y -= vel
if keys[pygame.K_DOWN] and y < 500 - height - vel:
y += vel
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()

My character runs out of the scrolling view, how can i fix this? [duplicate]

Apologies for asking so many questions recently. I'm just starting to get into pygame.
With my previous questions I don't think I've been wording it properly for what I am trying to do.
Here is a quick picture I did to try demonstrate
This is a single background image or map that I would like the player to move across. The red X is just a starting place for the character.
I'm try to make it so when I move the player the background will also follow as if the player is moving through the map. I've already limited the player from not being able to go off the borders of the actual screen. Just having a bit of trouble now trying to make it so the single image will move along the player and if the player reaches the end of the map picture movement stops. I have seen people use scrolling and duplicating the image when the player moves. I just want to see it to the single image that the player will move across. I don't want to worry about collisions just be able to get the movement working.
This is the code I am currently using:
from pygame.locals import *
from math import sin
pygame.display.set_caption("TEST")
clock = pygame.time.Clock()
time_passed = 0
class Player():
def __init__(self,x,y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def getX(self):
return self.rect.x
def getY(self):
return self.rect.y
def handle_keys(self,screenHeight,screenWidth):
key = pygame.key.get_pressed()
dist = 2
if key[K_LEFT] and self.x > 0:
self.x -= 500 * time_passed
if key[K_RIGHT] and self.x < screenWidth -20:
self.x += 500 * time_passed
if key[K_UP] and self.y > 0:
self.y -= 500 * time_passed
if key[K_DOWN] and self.y < screenHeight -20:
self.y += 500 * time_passed
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (int(self.x), int(self.y)))
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
self.rect = self.Image.get_rect()
self.x = 0
self.y = 0
def draw(self, game_window,screenHeight,screenWidth):
self.x = min(max(self.x, player.x - 2 * screenWidth / 2), player.x - screenWidth / 2)
self.y = min(max(self.y, player.y -2 * screenHeight / 2), player.y - screenHeight / 2)
game_window.blit(self.Image,(-self.x,-self.y))
class Enemy():
def __init__ (self,x,y):
self.Image = pygame.image.load("WC.jpg").convert()
self.rect = self.Image.get_rect(topleft = (x,y))
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (self.rect.x, self.rect.y))
pygame.init()
clock = pygame.time.Clock()
screenWidth = 400
screenHeight = 400
game_window = pygame.display.set_mode((screenWidth,screenHeight))
player = Player(200,200)
map = Map()
enemy = Enemy(250,250)
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
player.handle_keys(screenHeight,screenWidth)
game_window.fill((0,0,0))
map.draw(game_window,screenHeight,screenWidth)
#enemy.draw(game_window)
player.draw(game_window)
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()
quit()
Thanks
Shay
The player's movement depends on the size of the map. The x and y attributes of the "player" store the position on the map and are limited to the size of the map (map_size). The player is always drawn in the center of the screen, except it is near the boarders of the map:
class Player():
def __init__(self, x, y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def handle_keys(self, map_size):
key = pygame.key.get_pressed()
self.x += (key[K_RIGHT] - key[K_LEFT]) * 500 * time_passed
self.y += (key[K_DOWN] - key[K_UP]) * 500 * time_passed
self.x = max(0, min(map_size[0]-20, self.x))
self.y = max(0, min(map_size[1]-20, self.y))
def draw(self, game_window, map_size):
window_size = game_window.get_size()
center = window_size[0] // 2, window_size[0] // 2
pos = [self.x, self.y]
for i in range(2):
if center[i] < pos[i] <= map_size[i]-center[i]:
pos[i] = center[i]
elif pos[i] > map_size[i] - center[i]:
pos[i] = window_size[i] - map_size[i] + pos[i]
game_window.blit(self.Image, (int(pos[0]), int(pos[1])))
The player's position on the map is centered in the window:
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
def draw(self, game_window):
window_size = game_window.get_size()
map_size = self.Image.get_size()
x = max(0, min(map_size[0] - window_size[0], player.x - 200))
y = max(0, min(map_size[1] - window_size[1], player.y - 200))
game_window.blit(self.Image, (-x, -y))
Application loop:
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
leave = True
player.handle_keys(map.Image.get_size())
game_window.fill((0,0,0))
map.draw(game_window)
#enemy.draw(game_window)
player.draw(game_window, map.Image.get_size())
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()

Bullet not moving upwards because of OOP

I have a simple shooter game using pygame. I'm having some problems making the bullet's y coordinate slowly increasing up. I know this is something to do with the way I've programmed the Player class even though a bullet Rect is in it. I think I have to change the update function inside it. This is my code:
import pygame, random, sys, time
pygame.init()
#Constants
WIDTH = 800
HEIGHT = 500
BLACK = (0, 0, 0)
WHITE = (255, 255, 255) # Background Colour
RED = (255, 0, 0)
GREEN = (0, 255, 0)
window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Pygame Shooter Game")
clock = pygame.time.Clock()
fps = 60
run = True
class Player():
def __init__(self, width, colour, x, y):
self.width = width
self.colour = colour
self.x = x
self.y = y
self.vel = 5
self.shoot = False
self.player = pygame.Rect(self.x, self.y, self.width, self.width)
self.cartridge = pygame.Rect(0, 0, self.width/2, self.width/2)
self.bullet = pygame.Rect(0, 0, 10, 20)
self.shoot = False
def draw(self, win):
self.win = win
pygame.draw.rect(self.win, self.colour, self.player) # Draw player(rect)
pygame.draw.rect(self.win, GREEN, self.cartridge) #Draw cartridge
if self.shoot:
pygame.draw.rect(self.win, BLACK, self.bullet)
def move(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.x > 0: self.x -= self.vel # We don't do elif cuz we want them to be able to move diagonally
if keys[pygame.K_RIGHT] and self.x < WIDTH-self.width: self.x += self.vel
if keys[pygame.K_UP] and self.y > 0: self.y -= self.vel
if keys[pygame.K_DOWN] and self.y < HEIGHT-self.width: self.y += self.vel
if keys[pygame.K_SPACE]:
self.shoot = True
def update(self):
self.player = pygame.Rect(self.x, self.y, self.width, self.width)
self.cartridge.midbottom = self.player.midtop
self.bullet.midbottom = self.cartridge.midtop
if self.shoot:
while self.bullet.y > 0:
self.bullet.y -= 1
def main(win):
run = True
player = Player(50, RED, WIDTH/2, HEIGHT/2)
while run:
win.fill(WHITE)
clock.tick(fps)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
player.move()
player.update()
player.draw(win)
pygame.display.update()
pygame.quit()
sys.exit()
main(window)
Also, how can I make the create classes for each individual Cartridge and Bullet, to make the whole code more efficient?
update is invoked continuously in the main application loop. Therefore, no additional animation loops are required for the update. Change the loop to a selection (change while to if):
while self.bullet.y > 0:
if self.bullet.y > 0:
self.bullet.y -= 1
The starting position of the bullet must be set when the bullet is shot, rather than continuously when the bullet is updated:
class Player():
# [...]
def move(self):
# [...]
if keys[pygame.K_SPACE]:
self.shoot = True
self.bullet.midbottom = self.cartridge.midtop # <--- INSERT
def update(self):
self.player = pygame.Rect(self.x, self.y, self.width, self.width)
self.cartridge.midbottom = self.player.midtop
# self.bullet.midbottom = self.cartridge.midtop <--- DELETE
if self.shoot:
if self.bullet.y > 0: # <--- if (not while)
self.bullet.y -= 1
See also:
How can i shoot a bullet with space bar?
How do I stop more than 1 bullet firing at once?

How to stop screen scrolling and start moving character [duplicate]

Apologies for asking so many questions recently. I'm just starting to get into pygame.
With my previous questions I don't think I've been wording it properly for what I am trying to do.
Here is a quick picture I did to try demonstrate
This is a single background image or map that I would like the player to move across. The red X is just a starting place for the character.
I'm try to make it so when I move the player the background will also follow as if the player is moving through the map. I've already limited the player from not being able to go off the borders of the actual screen. Just having a bit of trouble now trying to make it so the single image will move along the player and if the player reaches the end of the map picture movement stops. I have seen people use scrolling and duplicating the image when the player moves. I just want to see it to the single image that the player will move across. I don't want to worry about collisions just be able to get the movement working.
This is the code I am currently using:
from pygame.locals import *
from math import sin
pygame.display.set_caption("TEST")
clock = pygame.time.Clock()
time_passed = 0
class Player():
def __init__(self,x,y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def getX(self):
return self.rect.x
def getY(self):
return self.rect.y
def handle_keys(self,screenHeight,screenWidth):
key = pygame.key.get_pressed()
dist = 2
if key[K_LEFT] and self.x > 0:
self.x -= 500 * time_passed
if key[K_RIGHT] and self.x < screenWidth -20:
self.x += 500 * time_passed
if key[K_UP] and self.y > 0:
self.y -= 500 * time_passed
if key[K_DOWN] and self.y < screenHeight -20:
self.y += 500 * time_passed
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (int(self.x), int(self.y)))
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
self.rect = self.Image.get_rect()
self.x = 0
self.y = 0
def draw(self, game_window,screenHeight,screenWidth):
self.x = min(max(self.x, player.x - 2 * screenWidth / 2), player.x - screenWidth / 2)
self.y = min(max(self.y, player.y -2 * screenHeight / 2), player.y - screenHeight / 2)
game_window.blit(self.Image,(-self.x,-self.y))
class Enemy():
def __init__ (self,x,y):
self.Image = pygame.image.load("WC.jpg").convert()
self.rect = self.Image.get_rect(topleft = (x,y))
def draw(self, game_window):
self.Image = pygame.transform.scale(self.Image,(20,20))
game_window.blit(self.Image, (self.rect.x, self.rect.y))
pygame.init()
clock = pygame.time.Clock()
screenWidth = 400
screenHeight = 400
game_window = pygame.display.set_mode((screenWidth,screenHeight))
player = Player(200,200)
map = Map()
enemy = Enemy(250,250)
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
running = False
player.handle_keys(screenHeight,screenWidth)
game_window.fill((0,0,0))
map.draw(game_window,screenHeight,screenWidth)
#enemy.draw(game_window)
player.draw(game_window)
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()
quit()
Thanks
Shay
The player's movement depends on the size of the map. The x and y attributes of the "player" store the position on the map and are limited to the size of the map (map_size). The player is always drawn in the center of the screen, except it is near the boarders of the map:
class Player():
def __init__(self, x, y):
self.Image = pygame.image.load("myAvatar.png").convert()
self.x = 200
self.y = 200
def handle_keys(self, map_size):
key = pygame.key.get_pressed()
self.x += (key[K_RIGHT] - key[K_LEFT]) * 500 * time_passed
self.y += (key[K_DOWN] - key[K_UP]) * 500 * time_passed
self.x = max(0, min(map_size[0]-20, self.x))
self.y = max(0, min(map_size[1]-20, self.y))
def draw(self, game_window, map_size):
window_size = game_window.get_size()
center = window_size[0] // 2, window_size[0] // 2
pos = [self.x, self.y]
for i in range(2):
if center[i] < pos[i] <= map_size[i]-center[i]:
pos[i] = center[i]
elif pos[i] > map_size[i] - center[i]:
pos[i] = window_size[i] - map_size[i] + pos[i]
game_window.blit(self.Image, (int(pos[0]), int(pos[1])))
The player's position on the map is centered in the window:
class Map():
def __init__(self):
self.Image = pygame.image.load("test2.png").convert()
def draw(self, game_window):
window_size = game_window.get_size()
map_size = self.Image.get_size()
x = max(0, min(map_size[0] - window_size[0], player.x - 200))
y = max(0, min(map_size[1] - window_size[1], player.y - 200))
game_window.blit(self.Image, (-x, -y))
Application loop:
leave = False
while not leave:
for event in pygame.event.get():
if event.type == pygame.QUIT:
leave = True
player.handle_keys(map.Image.get_size())
game_window.fill((0,0,0))
map.draw(game_window)
#enemy.draw(game_window)
player.draw(game_window, map.Image.get_size())
pygame.display.update()
pygame.display.flip()
time_passed = clock.tick() / 1000
pygame.quit()

How do you draw a shape in pygame that wont be erased when I update the game display? [duplicate]

This question already has answers here:
Why is my pygame application loop not working properly?
(1 answer)
Why is my PyGame application not running at all?
(2 answers)
Why is nothing drawn in PyGame at all?
(2 answers)
Closed 2 years ago.
I am trying to make my own version of brick breaker using python and pygame and I have found that my computer struggles to draw each of the bricks that make up the level every single time I run the main loop. I need to know how I can draw them and keep them drawn until I actually need to update them.
import pygame
from random import randint
pygame.init()
pygame.mouse.set_visible(True)
#Time
FPS = 60
clock = pygame.time.Clock()
#Colors
black = (0, 0, 0)
grey = (127, 127, 127)
white = (255, 255, 255)
#Display
displayInfo = pygame.display.Info()
displayWidth = displayInfo.current_w - 200
displayHeight = displayInfo.current_h - 100
borderB = 10
borderS = 1
gameDisplay = pygame.display.set_mode((displayWidth, displayHeight)) #,pygame.FULLSCREEN)
pygame.display.set_caption("Brick Breaker")
gameDisplay.fill(white)
pygame.display.update()
#Blocks
blocks = []
blockSize = 20
blockCount = 20
speed = int(blockSize / 2)
"""Classes"""
#Player
class Player():
def __init__(self):
#Size
self.width = blockSize * 5
self.height = blockSize
#Pos
self.x = displayWidth / 2 - self.width / 2
self.y = displayHeight - borderB - self.height
def move(self):
mousePos = pygame.mouse.get_pos()
#Check border left
if not mousePos[0] >= borderS:
mousePos = (borderS, mousePos[1])
#Check border right
elif not mousePos[0] + self.width <= displayWidth - borderS:
mousePos = (displayWidth - borderS - self.width, mousePos[1])
self.x = mousePos[0]
class Block():
def __init__(self, x = 0, y = 0):
#Size
self.width = blockSize * 2
self.height = blockSize
#Position
self.x = x
self.y = y
def giveDetails(self):
print(self.x, self.y, self.width, self.height)
class Ball():
def __init__(self):
self.radius = int(blockSize / 2)
self.width = blockSize
#Co-ordinates
self.x = int(playerBoard.x + playerBoard.width / 2)
self.y = int(playerBoard.y - self.radius)
self.yChange = - speed
self.xChange = 10
def move(self):
if self.x - self.radius + borderS <= 0 or self.x + self.radius >= displayWidth - borderS:
self.xChange *= -1
if self.y - self.radius <= 0 or self.y + self.radius >= displayHeight - borderB:
self.yChange *= -1
self.x += self.xChange
self.y += self.yChange
"""Functions"""
def create_level():
global blocks
blocks = []
xPos = blockSize
yPos = blockSize
#Down, across
accross = int((displayWidth - blockSize * 2 - borderS * 2) / (blockSize * 2 + 2))
levelData = [1, accross]
for row in range(levelData[0]):
yPos += blockSize + 1
xPos = blockSize
for num in range(levelData[1]):
xPos += blockSize * 2 + 1
_ = Block(xPos, yPos)
_.name = "block" + str(num)
blocks.append(_)
def main_loop():
global playerBoard, ball
gameExit = False
pygame.mouse.set_visible(False)
playerBoard = Player()
ball = Ball()
#This creates a list called 'blocks' with all the block objects
create_level()
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
break
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
menu()
gameExit = True
break
if event.type == pygame.MOUSEMOTION:
playerBoard.move()
ball.move()
gameDisplay.fill(white) #Clear Screen
#Draw Player
pygame.draw.rect(gameDisplay, grey, (playerBoard.x, playerBoard.y,
playerBoard.width, playerBoard.height))
"""Draw Blocks, this is where the main problem is as it runs this loop 100
times or so as there are about 100 blocks. This obviously means that the
display.update has a hard time."""
for item in blocks:
pygame.draw.rect(gameDisplay, black, (item.x, item.y, item.width, item.height))
#Draw ball
pygame.draw.circle(gameDisplay, black, (ball.x, ball.y), ball.radius)
pygame.display.update()
clock.tick(FPS)
main_loop()
pygame.quit()
quit()

Categories