this seemed like a really simple code, this is why I'm even more confused that it won't work. I'm creating a game that draws different lines of a picture and, after each shape, asks the user what it could be. My problem is that it won't even draw the first circle once I have the input()-part included, but without the input, it works perfectly fine.
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1000, 600))
pygame.display.set_caption('PyDoodle')
clock= pygame.time.Clock()
clock.tick(30)
#importing background pictures:
backPimg = pygame.image.load('Wood.jpg')
backPimg = pygame.image.load('Paper.jpg')
backWx = 0
backWy = 0
backPx = 250
backPy = 0
screen.blit(backWimg, (backWx, backWy))
screen.blit(backPimg, (backPx, backPy))
#colors
black = (0, 0, 0)
#solutions
snowman = ('snowman'.capitalize(), 'snow man'.upper(), 'snowman', 'snow man')
#MAIN GAME
while True:
for event in pygame.event.get()
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
#DRAWING #1: SNOWMAN
#circle 1 - the part that's getting on my nerves
pygame.draw.circle(screen, black, (500,400), 70, 2)
guess1 = raw_input('Your guess:\n')
It'd be really nice if you could have a look at it, maybe you have some suggestions.
The problem is, that pygame does not receive any events while raw_input is waiting for input. (You are not in the event-loop at that point.) As a result you never execute pygame.display.update().
Add pygame.display.update() after pygame.draw.circle(screen, black, (500,400), 70, 2). However then if a redraw of the window is necessary it will not be executed until the input is finished still.
Probably you should use input mechanisms provided by pygame instead.
Related
I am trying to write a little digits game using pygame. The idea of the game is to guess the four-digit number randomly chosen by computer. But I am stuck at the very beginning I started by creating all the essential elements: colours, fonts, surfaces, etc. I used blit to 'simulate' computer choice and to show the user's guess. And interestingly enough, not all the inputs are displayed. E.g. '1234' and '9999' is displayed. However, '5738' and '7365' are not. Looking forward to hearing opinions of the experienced users.
import random
import pygame
pygame.init()
width = 900
height = 500
black = (0,0,0)
pastel_blue = (200,205,230)
win = pygame.display.set_mode((width,height))
pygame.display.set_caption("Bulls and Cows")
digit_font = pygame.font.SysFont('comicsans', 30)
a = (random.randint(1000, 10000))
print(a)
def display():
win.fill((pastel_blue))
number = digit_font.render("_ _ _ _", 1, black)
win.blit(number, (width//2-number.get_width()//2, height//4))
pygame.display.update()
display()
def guess_number():
global c
c = input("Guess the number: ")
guess_number()
def guess_display():
text = digit_font.render(c, 1, black)
print(text.get_width()//2)
win.blit(text, [width//2-text.get_width()/2, 300]) #this seems to be the part that doesn't work correctly
pygame.display.update()
pygame.time.delay(2000)
guess_display()
You have to handle the events in the application loop. See pygame.event.get() respectively pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system.
def guess_display():
text = digit_font.render(c, 1, black)
print(text.get_width()//2)
win.blit(text, [width//2-text.get_width()/2, 300]) #this seems to be the part that doesn't work correctly
pygame.display.update()
pygame.event.pump() # <---
pygame.time.delay(2000)
However, the usual way is to use an application loop. Also see Why is my PyGame application not running at all?:
def guess_display():
text = digit_font.render(c, 1, black)
print(text.get_width()//2)
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
win.blit(text, [width//2-text.get_width()/2, 300])
pygame.display.update()
Also see:
Why is my display not responding while waiting for input?
Why does pygame.display.update() not work if an input is directly followed after it?
How to create a text input box with pygame?
My program is a 'Piano Hero' game in pygame which works in the same way as guitar hero except that it is for a computer keyboard and its based on playing the piano rather than the guitar. I am using a design similar to Synthesia for my interface where rectangles come down to a 'hitline' and you have to press the key at the right time.
My problem is that although the rectangles are drawing and working as intended at first, they do not seem to update so that the top ever stops. In other words, every note in the song is infinitely long.
I feel like this is probably where the error is although I am not 100% sure.
def Draw(self,hitLine):
if self.coords[2][1]<hitLine:
self.coords[0][1]+=2
self.coords[1][1]+=2
self.coords[2][1]+=2
self.coords[3][1]+=2
elif self.coords[2][1]>=hitLine and self.coords[0][1]<hitLine:
self.coords[0][1]+=2
self.coords[1][1]+=2
else:
self.drawing = False
pygame.draw.polygon(screen,BLUE,self.coords,0)
pygame.display.update()
This line is inside a while loop which just updates all of the rectangles in the song one at a time.
for z in notes:
if z.drawing:
z.Draw(hitLine)
I found you're question quite fun to work on and is very interesting!
Some items to consider.
It doesn't seem that there is any reason to use a "pygame polygon" for your Note objects which are clearly rectangles. In my code below I used "pygame Rect" objects.
You're main loop doesn't clear the screen every frame.
In your main loop you need to clear the screen every frame. In my code I used Rect objects. The Note stops drawing itself when it's top hits the hitLine.
import pygame
pygame.init()
gameScreen = pygame.display.set_mode((1100, 692))
hitLine = 500
class Note:
def __init__(self, rect):
self.rect = rect
self.drawing = True
def draw(self):
if self.rect.y < hitLine:
self.rect.y += 2
else:
self.drawing = False;
pygame.draw.rect(gameScreen, (0, 0, 255), self.rect, 0)
fNote = Note(pygame.Rect(500, -550, 80, 550))
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
gameScreen.fill((0, 0, 0))
if fNote.drawing:
fNote.draw()
pygame.display.update()
UPDATED ISSUE
I have discovered the issue appears to be with the fact that I am using the FULLSCREEN display flag to create the window. I added a rectangle to be drawn in the top left of the scree (0, 0), but when I run the program, It is mostly off the screen. Then, when I Alt-Tab away and back, the rectangle is appropriately placed at 0,0 and the turret is off center.
So basically, when the program starts, the game screen is larger than my actual screen, but centered. Then after Alt-Tab, the game screen is lined up with 0,0 but since the game screen is larger than my screen, the turret looks off center, but is actually centered relative to the game.
So the real question is why does using the FULLSCREEN display flag make a screen larger than my computer screen?
ORIGINAL ISSUE
I am building a simple demonstration of a turret in the center of the screen which follows the location of the cursor as if to fire where it is. Everything works perfectly until I Alt-Tab away from the screen, and then Alt-Tab back. At this point to turret is now off center (down and to the right)
import pygame, math
pygame.init()
image_library = {}
screen_dimen = pygame.display.Info()
print("Screen Dimensions ", screen_dimen)
def get_image(name):
if name not in image_library:
image = pygame.image.load(name)
image_library[name] = image
else:
image = image_library[name]
return image
robot_turret_image = get_image('robot_turret.png')
screen = pygame.display.set_mode((0, 0), pygame.`FULLSCREEN`)
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEMOTION:
print(event.pos)
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
done = True
screen.fill((0, 0, 0))
pos = pygame.mouse.get_pos()
angle = 360 - math.atan2(pos[1] - (screen_dimen.current_h / 2),
pos[0] - (screen_dimen.current_w / 2)) * 180 / math.pi
rot_image = pygame.transform.rotate(robot_turret_image, angle)
rect = rot_image.get_rect(center=(screen_dimen.current_w / 2, screen_dimen.current_h / 2))
screen.blit(rot_image, rect)
color = (0, 128, 255)
pygame.draw.rect(screen, color, pygame.Rect(0, 0, 200, 200))
pygame.display.update()
clock.tick(60)
It seems that the center is now off. I have printed out the screen dimensions before and after the Alt-Tab and they are the same, so I can't figure out why the image moves. I believe I am missing something regarding state changes with Pygame, but can't figure out what. If it is relevant, I am on Windows 10.
Alright, I discovered a solution from gamedev.stackexchange
And I will re-hash it here. The issue was that Using the fullscreen tag was making a screen larger than my computer screen. The following code solves this
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
true_res = (ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1))
pygame.display.set_mode(true_res,pygame.FULLSCREEN)
It is important to note that this is potentially just a windows fix, but I do not have another system with which to test it on. But It works on Windows 10 with python 3.5.1 and pygame 1.9.2a0
How can i prevent the sprite image from flickering uncontrollably? (image name is plumbers). when you run the program the only image flickering is the sprite.
import pygame
import os, sys
import itertools
import pygame
from pygame.sprite import Sprite
cloud_background = pygame.image.load('clouds.bmp')
brick_tile = pygame.image.load('brick_tile.png')
plumbers = pygame.image.load('Mario_sideways_sprite_2xL.png')
pink = (255, 64, 64)
w = 640
h = 480
screen = pygame.display.set_mode((w, h))
running = 1
def setup_background():
screen.fill((pink))
screen.blit(cloud_background,(0,0))
brick_width, brick_height = brick_tile.get_width(), brick_tile.get_height()
for x,y in itertools.product(range(0,640,brick_width),
range(390,480,brick_height)):
# print(x,y)
screen.blit(brick_tile, (x,y))
def show_sprites():
screen.blit(plumbers,(50,337))
pygame.display.flip()
while running:
show_sprites()
setup_background()
pygame.display.flip()
event = pygame.event.poll()
if event.type == pygame.QUIT: sys.exit()
I don't really know pygame, but whilst you wait for answer from someone with more experience in this area. I can offer this advice which might help.
Your setting up the background from scratch each time which is a processor intensive process. The best approach is to instead actually only re-render the part of the background required. I.e the parts where your plumber sprite occupied before.
Normally you do this by creating two variables called old X, old Y. This the rendering process is spend up.
Currently your render the entire screen every loop cycle.
ive been following a tutorial to learn pygame. the code below is to make a window (640 by 400) that s green. The program is also exposed to draw a red line across the screen. so far i have not been sucessfull in having the line appear. any suggestions?
#! /usr/bin/env python
import pygame
screen = pygame.display.set_mode((640, 400))
running = 1
green = 0, 255, 0
red = 255, 0, 0
point1 = 639, 479
point2 = 0, 0
while running:
event = pygame.event.poll()
if event.type == pygame.QUIT:
running = 0
screen.fill(green)
pygame.display.flip()
pygame.draw.line(screen, red, point1, point2)
You need to call draw.line before the display.flip(), as it is now you are copying the data from the buffer to the display before the lines is drawn.
in order for some functions to work you have to change your code at the beginning to:
import pygame
from pygame.locals import *
pygame.init()
this makes sure you have all of the essentials and that you "initialize" pygame.
without pygame.init() it wouldn't "turn on" most of the functions