I'm working on a small game in Python called "Blank Screen Simulator" (but it won't just be a black screen, I want to have events. Like a time where random images pop up, but for now I only have a time where you click the mouse alot and a time where you press buttons alot) anyway, I need to make these random. Here's my system I tried:
import pygame
from pygame.locals import *
import time
import random
pygame.init()
width, height = 640, 480
screen=pygame.display.set_mode((width, height))
Event1 == False
Event2 == False
screen_rect=screen.get_rect()
player=pygame.Rect(180, 180, 20, 20)
mouseClickNumber = 0
keyPressNumber = 0
a = random.choice(Event1, Event2)
a = True
def Event1:
if pygame.mouse.get_pressed(button 1):
mouseClickNumber = mouseClickNumber + 1
time.sleep(20)
clickHappyFunTime = False
print mouseClickNumber
mouseClickNumber = 0
def Event2:
if pygame.key.get_pressed:
keyPressNumber = keyPressNumber + 1
time.sleep(20)
buttonPressTime = False
print keyPressNumber
keyPressNumber = 0
My system involves having two events as False, then having a random.choice pick between the two variables, Event1 and Event2, but then when I run it, def Event2: is an invalid syntax. Am I just doing something wrong?
Function definitions must contain a parameter list, even if it's empty. Like this:
def Event1():
However, you've got a lot of other problems here.
Event1 == False doesn't assign False to Event1, it just compares Event1 to False—which is going to raise NameError because you don't have anything named Event1 yet, but even if you did, this wouldn't do anything useful, especially since you ignore the result.
If you fix that, a = random.choice(Event1, Event2) is going to fail because choice takes a single argument, a sequence to choose from, not a separate argument for each choice; you wanted a = random.choice([Event1, Event2]).
If you fix that, it's going to choose between False and False. Maybe you wanted it to choose between the two functions you're going to define later? But you can't choose between them before you define them. Defining them to some different value earlier doesn't help; it's just choosing the earlier value. (Also, reusing the same name for a normal value and a function is very confusing.)
If you fix that, it doesn't matter anyway, because a = True is just going to replace the value you chose.
You never call the functions directly, or attach them to events so they'll be called indirectly by PyGame, so they aren't doing much good.
The functions will raise an UnboundLocalError if you call them, because assigning to mouseClickNumber inside a function makes it a local variable, hiding the global variable of that name. To avoid that, you need to add global mouseClickNumber.
time.sleep inside a GUI application freezes the entire GUI, preventing it from updating the screen.
Related
I'm editing a Turtle Pong template and realized that two paddles can't move at the same time, so I'm trying to fix that bug by having it so, when a key is pressed, a boolean is set to true, and that is referenced in an if statement to move up or down if True. However, whenever I try to create this system, the boolean will always stay as it is declared, so I start off declaring it as False and no matter how many times I set it to True using the key press, it gets set back to False. I am confused about this, because I tried placing a print below the declaration and that never ran at all, but this False declaration seems to keep running over and over again. I wonder if it's because of the window.listen function, but then the print would theoretically run too. I'm just confused so any assistance would be greatly appreciated, thank you! Here' the relevant code.
import turtle
wn = turtle.Screen()
wn.title('Pong')
wn.bgcolor('black')
WIDTH, HEIGHT = 800, 600
wn.setup(width=WIDTH, height=HEIGHT)
wn.tracer(0)
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape('square')
paddle_a.color('white')
paddle_a.penup()
paddle_a.goto(-WIDTH/2, 0)
paddle_a.shapesize(5, 1)
#THIS here is the bit where I'm stuck
paddle_a_up = False
print(paddle_a_up)
def move_paddle_a_up():
paddle_a_up = True
print("I cant understand you")
print(paddle_a_up)
def move_paddle_a_down():
print(paddle_a_up)
wn.onkeypress(move_paddle_a_up, 'w')
wn.onkeypress(move_paddle_a_down, 's')
wn.listen()
if paddle_a_up == True:
y = paddle_a.ycor()
y += 20
paddle_a.sety(y)
while True:
wn.update()
The way to use a global variable in python is different than in other languages. To use the global variable inside a method, You must need to declare the variable as global inside the method otherwise python will consider it as a new local variable.
So, to use the global variable inside the method, you need to make these changes in your method move_paddle_a_up
def move_paddle_a_up():
global paddle_a_up
paddle_a_up = True
print("I can understand you now")
print(paddle_a_up)
If the pygame program is just a basic entity you can move normally with arrow keys, how could i make it so that if space is pressed, based on the arrow key that was being held at the moment of pressing, a player dashes slightly to the specified direction? My idea is that when the space is pressed, program checks if other keys are being held down and based on that it rapidly increases the x and/or y coordinate and then stops at specific time, but I don't know how to make it stop as all of this is happening inside a main game loop. Any insight is highly appreciated.
You can use time.perf_counter.
So for using that function you will need to import module time
import time
And now you can store the value of time.perf_counter in a variable when space is pressed.
import time
jumping = False
start_time = 0
while True:
if ("space is pressed"): # Replace condition with what you want
jumping = True
start_time = time.perf_counter()
# Add your code here
if jumping:
# change of x, y and other jumping mechanism code here
if jumping and time.perf_counter() - start_time > 1: # Replace 1 with the amount you want this if condition to trigger, also add value in seconds
jumping = False
I'm not sure what your code is like, but this is how I'd go about it:
def dash(self):
keys = pygame.keys.get_pressed()
if keys[pygame.K_SPACE] and not self.dashing and self.jumping:
# ^^ Can be any key
if self.facing_right:
self.x += 20
if self.facing_left:
self.x -= 20
self.dashing = True
Make sure that when you hit the ground it does self.dashing = False else you will be able to dash forever.
Just put this function in the player class if you are doing it OOP.
Else if you are not using classes, put it anywhere in the file and take out all self..
having issues trying to get threading working in python using the awesome Appjar package.
The following program needs to count through a list, and update a progress bar simultaneously. I've followed the appjar documentation for threading, but it's returning NameError: name 'percent_complete' is not defined in the app.thread (line 35), in which you're meant to insert function params - my code is below:
from appJar import gui
import time
# define method the counts through a list of numbers, and updates the progress meter
def press(btn):
objects = [1,3,6]
total = len(objects)
current_object = 0
for i in objects:
print(i)
current_object += 1
current_percent_complete = (current_object / total) * 100
updateMeter(current_percent_complete)
time.sleep(1)
def updateMeter(percent_complete):
app.queueFunction(app.setMeter, "progress", percent_complete)
# create a GUI variable called app
app = gui("Login Window")
app.setBg("orange")
app.setFont(18)
# add GUI elements : a label, a meter, & a button
app.addLabel("title", "COUNTER")
app.setLabelBg("title", "blue")
app.setLabelFg("title", "orange")
app.addMeter("progress")
app.setMeterFill("progress", "green")
app.addButton("START COUNTING", press)
# put the updateMeter function in its own thread
app.thread(updateMeter, percent_complete)
# start the GUI
app.go()
I can get rid of the error by defining percent_complete like so:
from appJar import gui
import time
# define method the counts through a list of numbers, and updates the progress meter
percent_complete = 0
def press(btn):
...
However, when GUI loads and button is pressed it doesn't thread. Instead it iterates through the list, then updates the progress bar afterwards.
Has anyone come across the same issue? any insight would be awesomely appreciated!
Thanks!
There are a couple of issues here:
First, I'm not sure your maths result in good percentages to update the meter with, so you might not see much change - should you be using i?
Second, the GUI won't be updated until the loop (and the sleeps inside it) all complete. Instead, you should try counting how many items to process, and iterating through them with an after() function, see here: http://appjar.info/pythonLoopsAndSleeps/#conditional-loops
Third, the call to app.thread() at the end doesn't achieve much - it calls the update_meter() function with a parameter that doesn't exist, it can be removed.
Fourth, the actual update_meter() function isn't necessary, as you're not really using a thread - that can be removed as well...
Give this a try, once you've had a look at the maths:
current_object = 0
def press(btn):
global current_object
current_object = 0
processList()
def processList():
global current_object
objects = [1,3,6]
total = len(objects)
if current_object < total:
i = objects[current_object]
print(i)
current_object += 1
current_percent_complete = (current_object / total) * 100
app.setMeter("progress", current_percent_complete)
app.after(1000, processList)
UPDATE: just to clarify on the maths issue, you're dividing one integer by another: 0/3, 1/3, 2/3, 3/3 and so on. In python2 this will result in 0, in python3 you'll get fractions.
I have created the following function that allows the user to change the shape of the Python turtle to an image he/she selects from a file dialog file dialog that pops up when a specific button is pressed:
def TurtleShape(iop = None):
# "iop" is supposed to be an image path
try:
manipulateimage.config(state = NORMAL)
flipButton.config(state = NORMAL)
mirrorButton.config(state = NORMAL)
originalButton.config(state = NORMAL)
resetturtle.config(state = NORMAL)
rotateButton.config(state = NORMAL)
global klob
# The following "if-else" statement uses the "iop" argument's value as the value for "klob" if `iop` is NOT `None`
if iop != None:
klob = iop
print("lmcv")
else:
klob = filedialog.askopenfilename()
print("klobby")
global im
im = Image.open(klob)
pictures.append(im)
edited.clear()
print(im)
im.save(klob + '.gif', "GIF")
register_shape(klob + '.gif')
shape(klob + '.gif')
update()
except:
pass
The above function is also supposed to use the iop argument's value as the turtle's image if it is not None.
Now, consider this situation; you draw a bunch of things, set the turtle to an image, and just when you are about to stamp the image, you accidentally press the button that resets the turtle to its normal shape (yes, that button exists in my program). Oh no! How would you get it back without going through all the steps to open and edit it again? Well, that is where my undoHandler function (shown below) comes in. It just essentially undoes the last function called using many stacks, which I created as deques. It is pretty straightforward if you are proficient in Python:
def undoHandler():
if len(function) > 0 and draw.drawing == True:
undoHandler.handling = True
if not hasattr(undoHandler, "counter"):
undoHandler.counter = 0
undoHandler.counter += 1
# clear the canvas
Clear()
# Pop a point object from function deque
function.pop()
penup()
goto(-200, 100)
pendown()
try:
# Execute everything up to point before last function called
for i in function:
# Set canvas and turtle to previous state
tsd = i.recieveshape()
shape(tsd)
mndf = i.recieveheading()
setheading(mndf)
hk = i.getletterheight()
global letter_height
letter_height = hk
rk = i.getletterwidth()
global letter_width
letter_width = rk
milk = i.getspacewidth()
global space_width
space_width = milk
hw = i.getwidth()
width(hw)
op = i.getcolor()
try:
color(op)
except:
for g in colors:
cp = g.getcolor2()
colormode(255)
color(cp)
# Get function wrapped in Point object and execute it
j = i.getfunction()
j()
# Following is the code block where the issue occurs. Basically, if the function being run is equal to `TurtleShape`, then do the following...
if j.__name__ == "TurtleShape":
# `hfl` is a deque that holds all of the `pictures` deque's contents as it is cleared when the turtle is set to its default state
pictures.extend(hfl)
lmcv = pictures.pop()
pictures.append(lmcv)
try:
# Resize image to previous size if user changes it. Otherwise, skip this.
bun = picwidth.pop()
picwidth.append(bun)
mun = picheight.pop()
picheight.append(mun)
clob = lmcv.resize((int(bun), int(mun)), Image.ANTIALIAS)
except:
clob = lmcv
clob.save(klob + str(undoHandler.counter) + ".gif")
# Use the `clob.save` output from above as source image in `TurtleShape` function (this is where issue occurs)
TurtleShape(klob + str(undoHandler.counter) + ".gif")
print("Undone!")
else:
pass
except:
pass
Basically what happens here is that it takes the function (wrapped in a Point object) from a queue through which the main functions go through as they are called. The functions then get appended to the function deque, after which, when undoHandler is called by the user, the screen gets cleared, and latest value is popped from the function deque so that all the other actions except the last one will be executed again. This issue I am facing occurs specifically in the if j.__name__ == "TurtleShape": code block. Basically, for some reason, when the user chooses to undo the resetting of the turtle to its original shape, it works as it should until the TurtleShape function is executed by the undoHandler. For some reason, when the undoHandler executes the TurtleShape function, even when I give a valid argument for the iop attribute of the TurtleShape function (as you can see in the if j.__name__ == "TurtleShape": code block), the else statement is executed first (i.e. the file dialog comes up instead of continuing from the if statement). Only if the user clicks cancel in that dialog will the turtle get set to the previous image.
What is wrong in my code that is leading to this occurrence, and how would I stop this from happening? I have tried changing the klob attribute in the function where the output is saved in the undoHandler function to, for example, "SaveImage", but still no luck. I have also tried to add an if-elif statement in the TurtleShape when it is supposed to choose between iop or a file dialog as the value for klob, but still the issue occurs. Apparently, it executes the elif statement even when it is not necessarily true. Therefore, any help is very much appreciated in remedying this issue! :)
It's happening here:
j = i.getfunction()
j()
If the function you've just gotten is the TurtleShape() function, then you're calling it once with its default arguments (i.e., iop = None). Then you go into your big if j.__name__ == "TurtleShape": statement and call it again inside the if block.
Move that j() call into the else: block of your big if j.__name__ == "TurtleShape": statement, and your problem should go away.
Does that brief explanation make enough sense for you to understand why the problem is happening? Or do you need me to explain a bit more in-depth how calling j() is calling TurtleShape with the parameter iop = None?
I'm drawing my name using turtles and I have a bunch of different functions for each of the letters
like so (for letter r)
def letter_r(t):
def letter_r_top(t):
turtle.lt(90)
turtle.fd(150)
turtle.rt(90)
turtle.circle(-37.5,180)
turtle.lt(130)
def letter_r_leg(t):
csquare = ((75**2) + (37.5**2))
sidec = math.sqrt(csquare)
turtle.fd(sidec)
letter_r_top(rob)
letter_r_leg(rob)
After each letter, i need to move the turtle into the right place to setup for the next letter. Because each of the letters are different sizes I need to make custom movements depending on what the previous letter is but I dont want to make separate functions for each of those movements.
At the end of my code I have the list of functions to be called in the correct order to spell my name
letter_t(rob)
letter_setup(rob)
letter_r(rob)
letter_setup(rob)
.....
Is there a way that I can do something like this so that I will only need 1 setup function.(Not real code, just a conceptualization of what I'm thinking
def letter_setup(t):
if previously executed function A
turtle.fd(75)
if previously executed function B
turtle.fd(75)
turtle.lt(90)
if previously executed function C
turtle.fd(75)
turtle.lt(90)
Why not the movement to the right place for the next letter at the end of the previous letter?
Perhaps there is a better way to do this but you could make a variable last_function_called and in each function you give it a different value then you'll know wich one was the last called :
last_function_called = NONE;
def function1():
last_function_called = FUNCTION1
blablabla
...
if (last_function_called == FUNCTION1):
call another one
and before of course something like :
NONE = 0
FUNCTION1 = 1
FUNCTION2 = 2
ect...