Problem with making a sprinting function in python Ursina - python

I'm making a Mineclone, but am stuck in the sprinting bit.
I want code that will put the player in 'sprinting' mode when you press Ctrl, as long as you have w pressed, and exit sprinting when w is released. Releasing Ctrl while sprinting should do nothing. I tried this code among many others, but when I test it, it freezes.
def update():
global block_pick
if held_keys['control'] and held_keys['w']:
while held_keys['w']:
player.speed = 10
So the code would check every frame.

I'm not very familiar with gaming with Python, but if this is vanilla Python and not using some additional library that has to be written differently;
First your code needs to be indented under the update function.
Second the code is updating every frame, that means that the whole execution is being re-run every frame rate. So the while loop will prevent frame from updating again.
I can suggest you introduce a global boolean for sprinting, which changes based on which buttons are pressed.
sprint = False # global boolean
def update():
global block_pick
global sprint
if held_keys['control'] and held_keys['w']:
sprint = True
player.speed = 10
if sprint and not held_keys['w']: # check for button pressed while sprinting.
sprint = False
player.speed = 1

Related

How can I make the movement faster if I press the key?

I'm making a Tetris game now. I want to implement it so that if I press the down key , the block falls quickly, and if I press the left and right keys, the block moves quickly. Pressing the key used the pygame.key.get_pressed() function and used pygame.time.set_timer() function to make speed change. The game speed was set to 600 for the interval of pygame.time.set_timer(), but if I press the down key, the block drops quickly because the interval was set to 150 to speed up the game so that the block drops quickly. The problem is to implement the function on the left and right direction keys. It is also possible to move the left and right keys quickly if I change the interval. The problem is that the pygame.time.set_timer() function changes the speed of the entire game, so the block falls quickly as well as the left and right movements of the block. Is there a way to speed up left and right movements without touching the speed of other things? I'd appreciate it if you let me know, thanks!
code
elif start:
for event in pygame.event.get():
attack_stack = 0
pos = pygame.mouse.get_pos()
if event.type == QUIT:
done = True
elif event.type == USEREVENT:
# Set speed
if not game_over:
keys_pressed = pygame.key.get_pressed()
# Soft drop
if keys_pressed[K_DOWN]:
pygame.time.set_timer(pygame.USEREVENT, 100)
elif keys_pressed[K_RIGHT]:
pygame.time.set_timer(pygame.USEREVENT, 100)
if not is_rightedge1(dx, dy, mino_en, rotation, matrix):
ui_variables.move_sound.play()
dx += 1
elif keys_pressed[K_LEFT]:
pygame.time.set_timer(pygame.USEREVENT, 100)
if not is_leftedge1(dx, dy, mino_en, rotation, matrix):
ui_variables.move_sound.play()
dx -= 1
else:
pygame.time.set_timer(pygame.USEREVENT, 600)
Waiting a long time (100 ms is already long) before reacting to user input feels bad, so you don’t want to wait a full piece-movement time before checking for input again just because there is none at the moment you check. Instead, poll for input at a steady pace of (say) 30 Hz; for simplicity, the usual approach is to just run the whole game at that frequency even if nothing needs to change on the screen for some (or even most) frames. (This technique also naturally allows smooth animations of or between piece movements.)
The usual implementation of “nothing” on a frame is to adjust the piece’s position every frame but integer-divide that position by some constant before using it for anything other than keeping track of its progress toward the next movement (like drawing it or checking for collisions). You might use pixels as the “invisible unit” when movement must be by whole tiles; games where sprites can be drawn at any pixel divide each into some convenient number of subpixels in the same fashion.
It looks to me that the reason your piece is dropping faster when you press a button is because if the user doesn't press a button the timer is set to 600ms. If they do press a button then the timer is set to 100ms.
As for how to fix this, you'll need to decouple the downward piece movement and user-input movement. I'd suggest making another event that only handles downward movement.
DROPEVENT = pygame.USEREVENT + 1
elif event.Type == DROPEVENT:
pygame.time.set_timer(DROPEVENT, 600)
# Your piece drop logic.
This snippet is not complete nor tested at all, but I hope it get the idea across. You don't seem to have posted the logic that handles dropping the piece, but you would need to move this into the new event.

Pygame seems to skip an if statement on whether or not I click again

In making my chess game function for moving pieces, I've created a system that should:
Look for a click
See if a piece was clicked on
Determine what piece was clicked on
Click on a square to move to
Move said piece to said square
I've written the follow code for this:
if event.type == pygame.MOUSEBUTTONDOWN and moving == False:
mousepos = pygame.mouse.get_pos()
roundedmouse1 = rounddown80(mousepos[0]) #function to found out what square was clicked
roundedmouse2 = rounddown80(mousepos[1]) #function to found out what square was clicked
mousecoords = [roundedmouse1,roundedmouse2]
for key,value in piecepositionsdict.items():
if int(value[0]) == int(mousecoords[0]) and int(value[1]) == int(mousecoords[1]):
x = coordstosquaredict[str(mousecoords)]
print("You have clicked",whatpiece(x),"on square",x)
print("Click a square to move the piece to:")
moving = True
time.sleep(0.5)
#this should be where the program stops until it gets another click
if event.type == pygame.MOUSEBUTTONDOWN and moving == True:
mousepos2 = pygame.mouse.get_pos()
roundedmouse21 = rounddown80(mousepos2[0])
roundedmouse22 = rounddown80(mousepos2[1])
mousecoords2 = [roundedmouse21, roundedmouse22]
print(mousecoords2)
print(piecepositionsdict[whatpiece(x)+"pos"])
piecepositionsdict[whatpiece(x)+"pos"] = mousecoords2
print(piecepositionsdict[whatpiece(x) + "pos"])
However, the program goes right past the second click check, as shown by how it prints out mousecoords 2 etc. when I have only clicked once.
What have I done wrong to cause this error?
Games are event driven applications. In event driven application you have a main loop checking for all events, and code executed when an event is detected. The starting point of your logic is always the event.
In your case the event is the clicking of the button. You have to check for the click only once in your code (in the main loop) and then determine the action the code has to do. If different actions may be triggered by the same event, you need some additional logic or flags to determine which action should be executed.
In your case you have an event (mouse click) and two possible actions, check what pieces has been clicked, or move the piece.
So the code should be designed like this:
def check_and_grab(position):
# code here
def move_piece(position):
# code here
piece_grabbed = None
while True:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTODOWN:
if piece_grabbed is None:
check_and_grab(event.pos)
else:
move_piece(event.pos)
piece_grabbed is a variable storing the piece grabbed: if is None, no piece has been grabbed.
check_and_grab(position) should check if there is a piece at the clicked position and, if so, set piece_grabbed to that piece. It implements your points 2 and 3.
move_piece(position) should move the grabbed piece at the new position and after that, set again grabbed_piece = None. It implements your point 5.
Your code will run in a single frame and the code will only register one click during that frame. You need to have a function thats gets called everytime you click on the screen.
See my sort of example bellow:
#Holder for the piece you have selected
currentPiece = piece
##Mouse click event/function##
if currentPiece == None:
getPiece()
else:
movePiece()
##Get piece function##
def getPiece():
#Your function here which sets
#currentPiece to what you selected.
##Move function##
def movePiece():
#Moves the currentPieece to the selected spot

stop self.after when interrupt happens

I started coding snake in python 3. As GUI i use Tkinter.
I got a timer which waits for a second an then calls the method again. Well now my question is how to i stop the self.wait?
I know i could work around this pretty easily, but i had this problem already somewhere else, so it would be nice to know how i can stop this.
This is the method which moves the snake around. (Only the timer is critical). The timer is here so it moves every second.
def move_snake(self):
self.after(1000, self.move_snake)
# code goes on
Now if i change the direction (by pressing a button) i do following:
def change_direction(self, event):
self.pressed = event.keysym
self.move_snake()
If i do this this way the "old" timer still is active and therefore the method gets called multiple times (it adds an additional timer when you press an button).
It would be nice that just the latest timer is activated.
Do you need more information?
Assuming that move_snake uses self.pressed, you don't need to call move_snake inside of change_direction.
However, if you really want to stop the old loop and start a new loop, you can save the id that is returned from after and give that to after_cancel:
def move_snake(self):
self.after_id = self.after(1000, self.move_snake)
# code goes on
def change_direction(self, event):
self.pressed = event.keysym
# cancel the old loop
self.after_cancel(self.after_id)
# start a new loop
self.move_snake()

How do I pause code in an if function in pygame?

How do you make the code stop for a moment before checking for something else? (I'm new to code)
if BonusTime==True and Drop==True:
if event.type == pygame.MOUSEBUTTONDOWN:
window.blit(Fired,(mouseX-12,mouseY-12))
Cankill=True
#I want it to delay here
Cankill=False
There is a cross hair that follows the mouse and when I click it, it fires. The problem is, you can just hold the mouse down and leave the cross hair in one place. Whenever an enemy walks into the cross hair, they die. I need it so even when you hold it will only fire once. I plan to make it delay the if statement, to set "Cankill" to true and then wait a second, after waiting, it should set "Cankill" to false. I've already looked through a lot of other people's questions similar to this and haven't found something I can understand. So if you could please help me find out how to delay it in the way I need.
"Pausing" is not what you want - if you do that, your game will just freeze, and nothing will move (since you are usign the OS mouse pointer, maybe it could move).
Anyway, the function to "pause" inside a game is pygame.time.wait(1000) - the number is in miliseconds.
Waht you actually need is to mark down the time the click was made, continue with the game, and when 1 second has passed, reset the variable back to the other state.
Something along:
last_trigger = 0
while True:
# game updating code goes here (getting events, and such)
...
if Cankill and pygame.time.get_ticks() - last_trigger > 1000:
Cankill = False
if event.type == pygame.MOUSEBUTTONDOWN:
window.blit(Fired,(mouseX-12,mouseY-12))
Cankill=True
last_trigger = pygame.time.get_ticks()
The "get_ticks" call returns the number of miliseconds that passed since pygame was initialized - and is usefull for this time of timers.

Let an image appear with key stroke and stay [pygame]

I'm currently working on a school project and I'm stuck with this problem.
The problem is in this line of code:
if pressed[pygame.K_SPACE]:
a = 1
while a == 1:
gameDisplay.blit(bulletIMG, (x,y))
I know what that problem is, the loop will go on forever.
Is there a way to break out of this loop? or should I try a different approach.
If I understand you correctly, you want to have the user press a button and an image displays permanently:
display_image = False
while game_running:
if pressed[pygame.K_SPACE]:
display_image = True
if display_image:
gameDisplay.blit(bulletIMG, (x,y))
now the image will always be displayed because the flag will always be true once the user hits the space bar (the key is bringing the flag outside the game loop).

Categories

Resources