I am using Python 3.4.0 and I have Mac OSX 10.9.2. I have the following code saved as sublimePygame in Sublime Text.
import pygame, sys
from pygame.locals import *
pygame.init()
#set up the window
DISPLAYSURF = pygame.display.set_mode((400, 300))
pygame.display.set_caption('Drawing')
# set up the colors
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
# Draw on surface object
DISPLAYSURF.fill(WHITE)
pygame.draw.polygon(DISPLAYSURF, GREEN, ((146, 0), (291, 106), (236, 277), (56, 277), (0, 106)))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAYSURF, BLUE, (120, 60), (60, 120))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 120), (120, 120), 4)
pygame.draw.circle(DISPLAYSURF, BLUE, (300, 50), 20, 0)
pygame.draw.ellipse(DISPLAYSURF, RED, (300, 250, 40, 80), 1)
pygame.draw.rect(DISPLAYSURF, RED, (200, 150, 100, 50))
pixObj = pygame.PixelArray(DISPLAYSURF)
pixObj[480, 380] = BLACK
pixObj[482, 382] = BLACK
pixObj[48, 384] = BLACK
pixObj[486, 386] = BLACK
pixObj[488, 388] = BLACK
del pixObj
while True: # main game loop
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.display.update()
I ran the code in my terminal and the python window opened for a second and then closed.
I got this error in the terminal.
Traceback (most recent call last):
File "sublimePygame", line 29, in <module>
pixObj[480, 380] = BLACK
IndexError: invalid index
Segmentation fault: 11
I checked the pygame documentation and my code seemed ok. I googled the error and Segmentation Error 11 seems to be a bug in python but I read that it was fixed in Python 3.4.0.
Does Anyone know what went wrong?
Thanks in advance!
Edit: Marius found the bug in my program, however when I run it it opens a blank Python window and not what it was supposed top open. Does anyone know why this happened?
I can see a definite bug in your code, but I'm not sure if that's causing a segmentation fault, which is a more serious error.
The bug in your code is that you create a 400x300 window:
DISPLAYSURF = pygame.display.set_mode((400, 300))
And then try to set colour values for pixels that are outside the bounds of that window
pixObj[480, 380] = BLACK
Again, this might not be causing the segmentation fault.
Your blank python window problem is here:
while True: # main game loop
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
pygame.display.update()
pygame.display.update() will only be executed if QUIT is activated. You need to remove some of the indents so that it is outside the for loop, but within the while loop.
Related
I was trying to print out just a simple title page using pygame.
My original code looked like:
import pygame
import pygame.freetype
pygame.init()
pygame.display.set_caption('hello world')
screen = pygame.display.set_mode((800, 600), 0, 32)
title_font = pygame.font.Font(".../Montserrat-BlackItalic.ttf", 24)
title = title_font.render('sup', False, (250, 250, 250))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.quit:
running = False
screen.fill((25, 25, 25))
screen.blit(title, (0, 0))
pygame.display.update()
pygame.quit()
And it works. However, the font was super blurry. I read that using freetype font will help to make it less blurry but when I tried, I received this error:
File ".../untitled1.py", line 22, in <module>
screen.blit(title, (0, 0))
TypeError: argument 1 must be pygame.Surface, not tuple
I only changed my code to look for the font type so that it looked like that:
title_font = pygame.freetype.Font(".../Montserrat-BlackItalic.ttf", 24)
How do I get less blurry fonts now?
The API interface of pygame.freetype is different from that of pygame,fon. The pygame.freetype module has 2 options to display the text. It can either create a Surface like the pygame.fornt module or it can render the text directly on the screen (respectively a Surface). pygame.freetype.Font.render returns a tuple with the rendered text and a rectangle size of the surface. The equivalent of
title_font = pygame.font.Font(".../Montserrat-BlackItalic.ttf", 24)
title = title_font.render('sup', False, (250, 250, 250))
screen.blit(title, (0, 0))
is either
ft_font = pygame.freetype.Font(".../Montserrat-BlackItalic.ttf", 24)
title_surf, title_rect = ft_font.render('sup', (250, 250, 250))
screen.blit(title_surf, title_rect)
or
ft_font = pygame.freetype.Font(".../Montserrat-BlackItalic.ttf", 24)
ft_font.render_to(screen, (0, 0), 'sup', (250, 250, 250))
So I'm trying to make tetris in pygame, and it was running really slow. I isolated the function that draws everything and even that is running really slow, how can I fix this? (And by running I mean I get a black screen and the desired images just load slowly from the bottom over the course of several minutes.)
P.S. There are some unused variables because I was too lazy to comment them out, but I don't imagine a couple variables make a big difference
import random
import time
import pygame
pygame.init()
win=pygame.display.set_mode((420, 840))
clock= pygame.time.Clock()
score= 0
level= 0
lines= 0
field= [[1]*10 for _ in range(22)]
run= True
play= True
setState= False
t= 48
frameCounter= 0
font= pygame.font.SysFont('arial', 30)
def drawWin():
tempY= 40
for y in range(2 ,22):
tempX= 10
for x in field[y]:
if(x==1):
win.fill((255, 255, 255), (tempX, tempY, 40, 40))
pygame.draw.rect(win, (0, 0, 255), (tempX, tempY, 40, 40), 5)
tempX+=40
tempY+=40
pygame.draw.rect(win, (255, 255, 255), (10, 40, 400, 800), 2)
text= font.render('Score: '+ str(score)+ '\nLevel: '+ str(level), 1, (255, 255, 255))
while True:
drawWin()
for event in pygame.event.get():
if event.type== pygame.QUIT:
break
time.sleep(1)
clock.tick(t)
pygame.quit()
Try adding pygame.display.update() to the end of your while loop
I've had a similar issue running Pygame before :))
Simple fix, forgot the update display command for pygame.
This question already has answers here:
How can I create a text input box with Pygame?
(5 answers)
Closed 5 years ago.
I'm doing a project that using Python and Pygame. I want to ask some question about the key in Pygame.
Thank you Shubhitgarg. I use his/her suggestions(use pygame_textinput), it succeed. Now I want to change the text input position with pressed an enter, but it can't detect the enter. How can I fix it? My real code:
# installing package
import pygame
from pygame import *
import pygame_textinput
pygame.init()
# colour settings
red = (255, 0, 0)
green = (0, 255, 0)
grass_green = (112, 173, 71)
blue = (0, 0, 255)
yellow = (255, 255, 0)
white = (255, 255, 255)
black = (0, 0, 0)
# screen settings
window = pygame.display.set_mode((680, 600))
window.fill(grass_green)
pygame.display.flip()
# font settings
default_font = pygame.font.get_default_font()
big_font = pygame.font.Font(default_font, 96)
font_a = pygame.font.Font(default_font, 50)
font_b = pygame.font.Font(default_font, 30)
font_c = pygame.font.Font(default_font, 18)
# text input settings
textinput = pygame_textinput.TextInput("freeansbold.ttf", 96, True, black, white, 400, 35)
# timer
start = pygame.time.get_ticks()
# text
please_guess_a_number = font_a.render("Please guess a number. ", 1, white)
text_range = font_c.render("from to", 1, white)
wrong_bigger = font_b.render("Sorry, You haven’t guess it rightly. Please try again.(The answer must be bigger.)", 1, white)
wrong_smaller = font_b.render("Sorry, You haven’t guess it rightly. Please try again.(The answer must be smaller.)", 1, white)
correct = font_b.render("Congratulations! You guess it correctly!!", 1, white)
# game
ask_you_to_set_range_1 = True
ask_you_to_set_range_2 = False
while True:
if ask_you_to_set_range_1:
window.blit(please_guess_a_number, (60, 80))
pygame.draw.rect(window, yellow, [60, 200, 230, 300])
pygame.draw.rect(window, yellow, [390, 200, 230, 300])
window.blit(text_range, (10, 550))
pygame.display.flip()
while True:
events = pygame.event.get()
textinput.update(events)
window.blit(textinput.get_surface(), (110, 300))
pygame.display.flip()
if ask_you_to_set_range_2:
while True:
events = pygame.event.get()
textinput.update(events)
window.blit(textinput.get_surface(), (440, 300))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if ask_you_to_set_range_1 and event.key == pygame.K_KP_ENTER:
ask_you_to_set_range_1 = False
ask_you_to_set_range_2 = True
if textinput.update(event):
num1 = textinput.get_text()
text1 = big_font.render(num1, 1, black)
window.blit(text1, (110, 300))
Can anyone teach me to solve it?
You see this https://github.com/ShubhitGarg/pygame-text-input .
You can import this and use the text_input class and blit it on the same or next page
Use this
textinput = pygame_textinput.TextInput()
while True:
screen.fill((225, 225, 225))
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
exit()
# Feed it with events every frame
textinput.update(events)
# Blit its surface onto the screen
screen.blit(textinput.get_surface(), (10, 10))
pygame.display.update()
So, I'm following a tutorial which currently has me building the following for a quick look at drawing using pygame functions.
import pygame, sys
from pygame.locals import *
pygame.init() #has to be called before any other pygame functions
#setup the window
DISPLAYSURF = pygame.display.set_mode((500,400), 0, 32)
pygame.display.set_caption('Drawing')
#colors
black = (0, 0, 0, 0)
white = (255, 255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
BLUE = (0, 0, 255)
#draw on the surface object
DISPLAYSURF.fill(white)
pygame.draw.polygon(DISPLAYSURF, green, ((146,0), (291,106), (236,277),
(56,277), (0,106))
pygame.draw.line(DISPLAYSURF, BLUE, (60, 60), (120, 60), 4)
pygame.draw.line(DISPLAYSURF, BLUE,(120,60), (60,120))
pygame.draw.line(DISPLAYSURF, BLUE,(60,120), (120,120), 4)
pygame.draw.circle(DISPLAYSURF, BLUE, (300,500), 20, 0)
pygame.draw.ellipse(DISPLAYSURF, red, (300, 250, 40, 80), 1)
pygame.draw.rect(DISPLAYSURF, red, (200,150,100,50))
pixObj = pygame.pixelarray(DISPLAYSURF)
pixObj[480][380] = black
pixObj[482][382] = black
pixObj[484][384] = black
pixObj[486][386] = black
pixObj[488][388] = black
del pixObj
#run game loop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
My problem is that in attempting to run this code, I get an invalid syntax error pointing to the first pygame.draw.line. If this is somehow a typo, I'll be kinda surprised, I retyped those lines several times to make sure they were correct, even double checked the docs to make sure that was still the valid syntax. Any ideas?
Focusing on that line:
pygame.draw.polygon(DISPLAYSURF, green, ((146,0), (291,106), (236,277),
(56,277), (0,106))
Let's make some changes to it, that take valid syntax to valid syntax.
pygame.draw.polygon(DISPLAYSURF, green, ((), (), (), (), ())
pygame.draw.polygon(DISPLAYSURF, green, ()
pygame.draw.polygon(
There are more open parentheses than closing.
If the following lines are correct, you should remove an open paren after "green".
I'm using pygame for interface display and controller input on a project I'm working on. Currently everything works sufficiently well so this isn't a major concern, but if it accidentally happens during actual use there might be some problems so I'd like to fix it possible.
When I run my code, the pygame window appears, displays, and updates exactly as expected. However, if I click on it or it gains focus some other way the window freezes and becomes (Not Responding). The code itself continues running, including the thread that is responsible for updating the display, until I close the window so Python itself is still running fine, but the window stops working.
My code for the update loop is here, in all its really ugly glory:
while(1):
print "thread is fine"
pygame.event.pump()
if LOV_Flag == 1:
videoColor = (255, 0, 0)
else:
videoColor = (0, 255, 0)
# Refresh the screen and redraw components
screen.fill((255, 255, 255))
pulseLabel = pulseFont.render("Pulse: ", 1, (0, 0, 0))
videoLabel = videoFont.render("Video: ", 1, (0, 0, 0))
motorsLabel = labelFont.render("Motors", 1, (0, 0, 0))
motorLabel = captionFont.render("L R", 1, (0, 0, 0))
armLabel = captionFont.render("Arm", 1, (0, 0, 0))
gripperLabel = captionFont.render("Gripper", 1, (0, 0, 0))
screen.blit(motorsLabel, (55, 50))
screen.blit(motorLabel, (60, 75))
screen.blit(pulseLabel, (300, 19))
screen.blit(videoLabel, (300, 45))
screen.blit(armLabel, (250, 75))
screen.blit(gripperLabel, (235, 255))
leftBar = (50, 200 - drive.getSpeed()[0], 25, drive.getSpeed()[0])
rightBar = (100, 200 - drive.getSpeed()[1], 25, drive.getSpeed()[1])
armBar = (250, 200 - (100 * arm.report()), 25, (100 * arm.report()))
upperArmBar = (250, 200 - (100 * arm.reportUp()), 25, 2) # 100 is the value on the bar
lowerArmBar = (250, 200 - (100 * arm.reportDown()), 25, 2) # 135 (65) is the value on the bar
gripperBar = (212, 225, (100 * hand.report()), 25)
leftGripperBar = (212 + (100 * hand.reportClosed()), 225, 2, 25)
rightGripperBar = (212 + (100 * hand.reportOpen()), 225, 2, 25)
pygame.draw.rect(screen, (255, 0, 0), leftBar, 0)
pygame.draw.rect(screen, (255, 0, 0), rightBar, 0)
pygame.draw.rect(screen, (255, 0, 0), armBar, 0)
pygame.draw.rect(screen, (0, 0, 0), upperArmBar, 0)
pygame.draw.rect(screen, (0, 0, 0), lowerArmBar, 0)
pygame.draw.rect(screen, (255, 0, 0), gripperBar, 0)
pygame.draw.rect(screen, (0, 0, 0), leftGripperBar, 0)
pygame.draw.rect(screen, (0, 0, 0), rightGripperBar, 0)
pygame.draw.circle(screen, pulseColor, [370, 32], 10)
pygame.draw.circle(screen, videoColor, [370, 58], 10)
pygame.display.update()
time.sleep(0.1)
if killFlag:
return
An image for how the window looks, in case that helps you understand the code better.
Unfortunately I can't run the code you've posted to test myself, but there a few things I'd like to point out that might help. Firstly, that's not the right way to kill a program, at least not the way I know. What I use in pygame is:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
Is the time.sleep(1) at the end of your loop to try to control framerate? If so, you'd be much better served by utilizing a pygame clock. initialize a clock before your main loop as follows:
clock = pygame.time.Clock()
Then within the main loop use this:
clock.tick(60)
What this does is set the program to run at your desired fps. In this case it's set to 60.
Lastly, i honestly don't know why your window would stop responding once it receives mouse input, but if that's indeed the culprit you could simply block mouse events. Try this before your while loop:
pygame.mouse.set_visible(False)
pygame.event.set_blocked(pygame.MOUSEMOTION)
pygame.event.set_blocked(pygame.MOUSEBUTTONDOWN)
pygame.event.set_blocked(pygame.MOUSEBUTTONUP)
This should disregard all input from your mouse, you won't even be able to see it over your window.
I moved this code to main instead of a thread, it works now. I did end up needing the pygame.event.pump() line, and I now use clock.tick() for rate control, but it's otherwise identical but moved. Apparently pygame just doesn't play well with threading.
Thanks for all the help though, the actual solution may have been discovered accidentally but having things to try kept me trying long enough to try the thing I didn't expect to work.
The event queue is probably filled up and no more events can be handled, and thus the OS says the window is not responding.
You should clear the event queue by calling pygame.event.clear() if you're not interested in any events, but maybe you want to least handle pygame.QUIT, so calling pygame.event.get() (without an argument) will also do the trick.
The problem is threads, I had the same problem, if I run pygame updates in a thread, it locks up when I change focus, if I run it without threads the same code works fine. The work around is to make sure 'pygame' is only called from your main original thread, and then other code can be in other threads, but anything related to pygame should all come from the main thread. That worked for me anyway.