Pygame and Livewires button press not working? - python

so in my menu in a game I'm creating a picture is displayed which shows how to play the game, and I have some code so that when the player presses the b button it returns to the main menu, but this doesn't work, can someone help me please?
def manual():
image = games.load_image("options.jpg")
games.screen.background = image
if games.keyboard.is_pressed(games.K_b):
menu()
games.screen.mainloop()
the 'menu()' is another function which has all the main menu code in it
Here is the menu function
def menu():
pygame.init()
menubg = games.load_image("menubg.jpg", transparent = False)
games.screen.background = menubg
# Just a few static variables
red = 255, 0, 0
green = 0,255, 0
blue = 0, 0,255
size = width, height = 640,480
screen = pygame.display.set_mode(size)
games.screen.background = menubg
pygame.display.update()
pygame.key.set_repeat(500,30)
choose = dm.dumbmenu(screen, [
'Start Game',
'Manual',
'Show Highscore',
'Quit Game'], 220,150,None,32,1.4,green,red)
if choose == 0:
main()
elif choose == 1:
manual()
elif choose == 2:
print("yay")
elif choose == 3:
print ("You choose Quit Game.")

I think is_pressed() in manual() doesn't wait for your press so you call mainloop() so I think you never leave that loop.
I see other bad ideas in your code like:
menu() call manual() which call menu() which call manual() etc. - use return and use loop in menu()
every time you call menu() you call pygame.init() and pygame.display.set_mode() - you should use it only once.
EDIT:
I don't know how games.keyboard.is_pressed() works (because there is no that function in PyGame) but I think manual() could be:
def manual():
image = games.load_image("options.jpg")
games.screen.background = image
while not games.keyboard.is_pressed(games.K_b):
pass # do nothing
# if `B` was pressed so now function will return to menu()
and you have to create loop in menu:
running = True
while running:
choose = dm.dumbmenu(screen, [
'Start Game',
'Manual',
'Show Highscore',
'Quit Game'], 220,150,None,32,1.4,green,red)
if choose == 0:
main()
elif choose == 1:
manual()
# if 'B' was press manual() will return to this place
elif choose == 2:
print("yay")
elif choose == 3:
running = False
print ("You choose Quit Game.")

Related

create a button that can only be pressed once

i am trying to create a button that can only be pressed once for a game in python but i cant figure out how to set a variable that works in the def and does not change every time the function is run.
tut = turtle.Screen()._root
def bt1():
pressed = 1
x_turn = True
if (pressed == 1):
if (x_turn is True):
print("this button has not been pressed as player1")
x_turn == False
pressed = 0
else:
print ("this button has not been pressed as player2")
pressed = 0
x_turn == True
else:
print("this button has been pressed")
photo1 = Image.open(r"C:\image.png")
resize_photo1 =photo1.resize((50,50), Image.ANTIALIAS)
print_photo1 = itk.PhotoImage(resize_photo1)
Button(tut, image= print_photo1,command=bt1).pack(side= LEFT)
what i am gathering is that when this button is pressed you want it to set pressed to 0 so it can not run again but since you put the variable at the top every time the button is bressed it will set it to 1. to fix this all you want to do is....
tut = turtle.Screen()._root
global pressed
pressed = 1
global x_turn
x_turn = True
def bt1():
if (pressed == 1):
if (x_turn is True):
print("this button has not been pressed as player1")
x_turn == False
pressed = 0
This might work let me know if it does
x_turn = True
Try using this :
x_turn == True
I think here you’re missing the equals to sign and that’s why it is creating a problem.

Code beyond the Onclick and Listen doesn't get executed

this is my first time posting here.
I'm trying to make a Title Screen before getting the user in my game. When I hit enter, I want to break out of the While loop into a the main game loop, or go into the next section of the While loop. However, when I hit enter and the onkey use my Enter function which sets the In_title to False, it doesn't seem to respond with anything. (this is in python with turtle, also I'm working using replit.)
I've created a variable named in_title = True.
I've tried breaking out of the while loop using if in_title == false then break.
import turtle
import random
import math
import time
#set up for the screen title.
screen_size = [500,500]
screen_color = "#1a2645"
t = turtle.Turtle()
screen = t.getscreen()
screen.setup(screen_size[0],screen_size[1])
screen.bgcolor(screen_color)
screen.tracer(0)
t.ht()
game_state = 1 #to see if the game is still runninng. #0, 1 are no, yes.
in_title = True #to see if the game is in title or not.
select = turtle.Turtle()
select.color("yellow")
select.speed(0)
select.up()
select.setx(-80) #putting it in the middle of the text.
select.sety(30)
#all of the entity here:
player = {"p": turtle.Turtle(), "lives": 3, "color": "white", "rad": 15}
player["p"].ht()
harm = {"color": "red", "rad": 10}
num_harm = 10
good = {"g": turtle.Turtle(), "color": "white", "rad": 8}
good["g"].ht()
#universal movement function.
def moving_harm(h,rad): #function to move the harm objects.
if h.ycor() == (250 + rad/2):
h.up()
h.setx(random.randrange(-250,250))
h.sety(h.ycor() - 5)
screen.update()
if (h.ycor() != 250 + rad/2) and (h.ycor() != -250 - rad/2):
h.sety(h.ycor() - 5)
if (h.ycor() == (-250 - rad/2)):
h.sety(250 + rad/2)
screen.update()
def up():
if game_state == 1:
select.sety(30) #hard coded the number so it's in the middle.
print(select.ycor())
screen.update()
# def down():
# def left():
# def right():
def enter():
global in_title
if (game_state == 1):
if(select.ycor() == 30):
select.down()
select.forward(150)
select.setheading(180)
select.color("white")
select.forward(150)
screen.update()
time.sleep(0.2)
screen.clear()
screen.update()
time.sleep(0.1)
screen.setup(screen_size[0],screen_size[1])
screen.bgcolor(screen_color)
in_title = False
#main menu operation:
def main_game():
global game_state
#writing out the tittle screen.
menu = turtle.Turtle()
menu.up()
menu.sety(150)
menu.color("white")
menu.write("Sorta a Side Scroller Game", align="center", font=("Arial", 22, "normal"))
menu.sety(100)
menu.write("By Silver", align="center", font=("Arial", 15, "normal"))
menu.ht()
menu.sety(25)
menu.write("Start game", align="center", font=("Arial", 15, "normal"))
#create all the harm turtles:
for i in range(num_harm):
h = "h"+str(i+1)
harm[str(h)] = turtle.Turtle()
harm[str(h)].up()
harm[str(h)].ht()
#handle control at the title screen.
screen.onkey(enter, "Enter")
if in_title == False:
print("got passed that")
main_game()
screen.listen()
screen.update()
screen.mainloop()
no error message where given.
The way you have it, main_game() only is called once, right before screen's main loop begins. That means that this fragment
if in_title == False:
print("got passed that")
happens once and then control flow leaves main_game() forever, and the screen main loop begins.
Since the fragment only exists in main_game(), and main_game() isn't set to be called on any button press or called from anywhere else in the code, that fragment will never be called ever again. So, the if in_title == False: will never be encountered and print("got passed that") will never happen, even when in_title is False.
In this case, there is a place you already know is going to have control flow when in_title == False, and that is at the end of enter. So, you could put the code you have in mind there. This is the solution I suggested in the comments:
def enter():
global in_title
if (game_state == 1):
if(select.ycor() == 30):
# ...
in_title = False
print("got passed that")
#main menu operation:
def main_game():
# ...
screen.onkey(enter, "Enter")

Windows updating breaks drawing on them with Python Xlib

I'm trying to write a fun project for myself, which is a screenshot tool written in Python. I've run into an issue with one part of this, which is that I want to draw a rectangle on the screen, get the coordinates, then take a screenshot of this region. I have this working for the most part, but when the window underneath the selection updates, it breaks the drawing of the rectangle.
Here is a video displaying the issue: https://gfycat.com/EmotionalThankfulFlycatcher
I've tried reading the Xlib documentation to see if there's a way I can comfortably handle this, but wasn't able to find anything. Another alternative I could try would be to take a screenshot of the entire screen, and then take a selection of that instead of taking a region of the live desktop.
Is there anyway I can handle this, without going the route of taking a screenshot of the entire desktop and cropping that?
import sys
from Xlib import X, display, Xutil, xobject, Xcursorfont
class xselect:
def __init__(self):
# X display
self.d = display.Display()
# Screen
self.screen = self.d.screen()
# Draw on the root window (desktop surface)
self.window = self.screen.root
def select_region(self):
# Set cursor to crosshair
font = self.d.open_font('cursor')
cursor = font.create_glyph_cursor(font, Xcursorfont.crosshair,
Xcursorfont.crosshair+1,
(65535, 65535, 65535), (0, 0, 0))
self.window.grab_pointer(1, X.PointerMotionMask|X.ButtonReleaseMask|X.ButtonPressMask,
X.GrabModeAsync, X.GrabModeAsync, X.NONE, cursor, X.CurrentTime)
colormap = self.screen.default_colormap
color = colormap.alloc_color(0, 0, 0)
# Xor it because we'll draw with X.GXxor function
xor_color = color.pixel ^ 0xffffff
self.gc = self.window.create_gc(
line_width = 1,
line_style = X.LineSolid,
fill_style = X.FillOpaqueStippled,
fill_rule = X.WindingRule,
cap_style = X.CapButt,
join_style = X.JoinMiter,
foreground = xor_color,
background = self.screen.black_pixel,
function = X.GXxor,
graphics_exposures = False,
subwindow_mode = X.IncludeInferiors,
)
done = False
started = False
start = dict(x=0, y=0)
end = dict(x=0, y=0)
last = None
while not done:
e = self.d.next_event()
# Window has been destroyed, quit
if e.type == X.DestroyNotify:
sys.exit(0)
# Mouse button press
elif e.type == X.ButtonPress:
# Left mouse button?
if e.detail == 1:
start = dict(x=e.root_x, y=e.root_y)
started = True
# Right mouse button?
elif e.detail == 3:
sys.exit(0)
# Mouse button release
elif e.type == X.ButtonRelease:
end = dict(x=e.root_x, y=e.root_y)
if last:
self.draw_rectangle(start, last)
done = True
pass
# Mouse movement
elif e.type == X.MotionNotify and started:
if last:
self.draw_rectangle(start, last)
last = None
last = dict(x=e.root_x, y=e.root_y)
self.draw_rectangle(start, last)
pass
# Keyboard key
elif e.type == X.KeyPress:
sys.exit(0)
elif e.type == X.EnterNotify:
print(' EnterNotify')
self.d.ungrab_pointer(0)
self.d.flush()
coords = self.get_coords(start, end)
if coords['width'] <= 1 or coords['height'] <= 1:
sys.exit(0)
else:
return coords
def get_coords(self, start, end):
safe_start = dict(x=0, y=0)
safe_end = dict(x=0, y=0)
if start['x'] > end['x']:
safe_start['x'] = end['x']
safe_end['x'] = start['x']
else:
safe_start['x'] = start['x']
safe_end['x'] = end['x']
if start['y'] > end['y']:
safe_start['y'] = end['y']
safe_end['y'] = start['y']
else:
safe_start['y'] = start['y']
safe_end['y'] = end['y']
return {
'start': {
'x': safe_start['x'],
'y': safe_start['y'],
},
'end': {
'x': safe_end['x'],
'y': safe_end['y'],
},
'width' : safe_end['x'] - safe_start['x'],
'height': safe_end['y'] - safe_start['y'],
}
def draw_rectangle(self, start, end):
coords = self.get_coords(start, end)
self.window.rectangle(
self.gc,
coords['start']['x'],
coords['start']['y'],
coords['end']['x'] - coords['start']['x'],
coords['end']['y'] - coords['start']['y']
)
I'm still new to X11 myself, but the X11 tag on stackoverflow is pretty much dead so I'll try to answer anyway.
For taking screenshots, look at this. You want to use XGetImage, which allows you to specify the rectangle you want.
Now for drawing the rectangle, as far as I know drawing on the root window can be pretty iffy. You could instead create a fullscreen window with a transparent background. This would also allow you to give the area around the rectangle a darker tint, for example.

Pygame text input not on screen

I need to kb input onto a pygame screen
at the moment it appears on the idle shell
any advice would be appreciated.
This code is extracted from a larger program
mostly screen based but i need to input some
data (numeric) from the kb at times
import sys
import pygame
from pygame.locals import *
pygame.init()
N= ''
screen = pygame.display.set_mode((600,600))
font= pygame.font.Font(None,40)
screen.fill((255,255,255))
pygame.display.flip
pygame.display.update()
def score(C,y):
SetWnd = font.render( C,True,(0,0,255))
screen.blit(SetWnd, (15, 100+y))
pygame.display.update()
def start():
while True:
name=''
for evt in pygame.event.get():
if evt.type == KEYDOWN:
if evt.unicode.isalnum(): # unicode
name+=evt.unicode
print name,
elif evt.key == K_BACKSPACE:
name = name[:-1]
print name,
elif evt.key == K_RETURN:
return N
elif evt.type == QUIT:
pygame.quit()
sys.exit()
def Pchange(c,y):
block = font.render(N, True, (0,0,0))
rect = block.get_rect()
rect.move_ip(75,100 + y)
screen.blit(block,rect)
pygame.display.flip()
score('wind', 0)
score('elev',20)
N = start()
Pchange(N,0)
Pchange(N,20)
Firstly you draw the score twice, which i assume works well.
The problem lies in you start function.
You are not calling any draw or update function in your while loop.
In your event foreach, you add a digit to name, and exit the while loop when enter is pressed. Then you draw twice with Pchange, but you are the function does not use the right parameters. You have:
def Pchange(c,y):
block = font.render(N, True, (0,0,0))
you are using the global N which is ''. So to fix that, you need to change N to c.
The next problem is that the game quits right after pressing enter. Since you pasted only a part of the program, this might not be the case. If it is, make another while loop, and just wait for the ESC key to call pygame.quit() and sys.exit()

Combining Code from two programs in Python

My question is kinda complicated as I run it through my head but I will try to explain it as best I can. I have 2 python codes, one that I created with Python for a Mastermind game and then the other in Pygame for a Mastermind board to play it on. My question is simply this: How can I combine both of these codes into 1 to have it play from Pygame and not the command prompt window I usually get?
I'm sorry if this sounds all gibberishy, but thats my question. I merely want to take my Python code and implement it into the Pygame code and have the game run like it's supposed to.
Heres the code for the game:
import random
class InvalidMove(Exception):pass
class Game:
def __init__(self):
self.colors=('r','g','b','y')
self.to_guess=[random.choice(self.colors) for i in range(4)]
def match_guess(self,guess):
if len(guess)!=len(self.to_guess) or [g for g in guess if g not in self.colors]:
raise InvalidMove()
ret=[0,0]
usedindexes=[]
for i,g in enumerate(guess):
if g==self.to_guess[i]:
ret[0]+=1
usedindexes.append(i)
for i,g in enumerate(guess):
if i in usedindexes: continue
for j,c in enumerate(self.to_guess):
if c==g and j not in usedindexes:
ret[1]+=1
usedindexes.append(j)
return ret
class UI:
def make_move(self):
guess=raw_input("Guess: ")
return guess.split()
def main(self):
print("The game begins...")
print("Possible colors (enter first letter): [r]ed [g]reen [b]lue [y]ellow")
print("Enter your guess like: r g b y")
g=Game()
while True:
guess=self.make_move()
try:
bp,wp=g.match_guess(guess)
except InvalidMove:
print("Invalid guess, try again")
continue
print("Black pegs %s"%bp)
print("White pegs %s"%wp)
if bp==4:
print("You won!")
if __name__=="__main__":
u=UI()
u.main()
And here's the code for the board I made in Pygame:
import pygame
from pygame.locals import *
def draw_current(men, turn, spacing, corner):
current = len(men) - 1
pos = corner[0] + current * spacing[0], turn * spacing[1] + corner[1]
screen.blit(images[men[-1]], pos)
images = { K_r: pygame.image.load('red.png'), K_g: pygame.image.load('green.png'),
K_b: pygame.image.load('blue.png'), K_y: pygame.image.load('yellow.png'),
K_SPACE: pygame.image.load('empty.png') }
pygame.init()
SCREEN_SIZE = (640, 480)
background_image_filename = 'mastermind_board.jpg'
screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
background = pygame.image.load(background_image_filename).convert()
screen.blit(background, (0, 0))
pygame.display.update()
men = []
margin = 5, 3
spacing = [x + m for m, x in zip(margin, images[K_r].get_size())]
corner = 74, 74
turn = 0
quit = False
while not quit:
for event in pygame.event.get():
if event.type == QUIT:
quit = True
break
if event.type == KEYUP:
if event.key in images:
#print event.key
men.append(event.key)
# update
draw_current(men,turn, spacing, corner)
if len(men) == 4:
turn += 1
men = []
pygame.display.update()
elif event.key in (K_q, K_ESCAPE):
quit = True
break
pygame.quit()
Any and all help/suggestions would be more than greatly appreciated.
As I'm sure you know, you can't just put it all in one file and have it run. You need to encapsulate the Mastermind game so you can run/update it from the pygame loop. It'd be cleaner if you keep the Mastermind game logic in a separate file and just import it, but it's not required.
Here's some semi-psuedocode:
import pygame
class Mastermind(object):
def update(self, *args):
pass #do stuff
pygame.init()
while not quit:
if event:
if event == "quit":
quit = True
else:
#update the game
Mastermind.update(args)
#update the board
pygame.display.update()
pygame.quit()
Of course, this won't work for you exactly, but I hope the idea that I'm explaining comes through.
Step 1. Fix your board so that it's a proper class definition.
Step 2. Write a third file that import the board and the game.
They're now "combined".
Now you have to do the hard work of fixing the Game to use the new, fancy Board you built.

Categories

Resources