Pygame how to enable and disable a function with the same key? - pygame

while making a pause menu, I've noticed that I can't pause and continue the game with the same key.
Let's say that I want to do that with the escape key.
Then, if I just press it, the game will pause for some microseconds but will continue as the pause() function ends also with the escape key.
I have also noticed that if I change the key used to end the execution of the pause() function to a one that's different from which had paused the game, everything would work, but I don't want this.
So what should I do in order to prevent this and be able to pause and continue the game with one key?

Add a paused state. Implement the event handling dependent on the state of paused.
Use pygame.time.get_ticks() to measure the time. Calculate the time after which the pause mode should end. Set paused = False when the time is reached:
paused = False
pause_end_time = 0
while running:
current_time = pygame.time.get_ticks()
if current_time > pause_end_time:
paused = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = not paused
pause_end_time = current_time + 3000 # pause for 3 seconds
if not paused:
# game event handling
if event.type == pygame.KEYDOWN:
# [...]
# [...]

Related

using a function from an outside script in love2d gives me an error

I'm making an action RPG in Love2d, and I moved all of my player code into a separate Lua script for the sake of organization - but now upon attempting to use player.load, I get this error:
Error
main.lua:22: attempt to index global 'player' (a boolean value)
Traceback
main.lua:22: in function 'load'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
this is my main.lua script:
-- RPG PROJECT IN LOVE2D
-- debug mode
debug = true -- SET FALSE BEFORE SHIPPING
-- ROOM CHART:
-- 0 - Title
-- 1 - Overworld
-- 2 - Shop
-- 3 - Boss Room
Room = 0
-- PLAYER STATE CHART:
-- 0 - free
-- 1 - attacking
-- 3 - can't move
function love.load(dt)
player = require 'Scripts/player'
player.load()
sti = require 'Libraries/sti'
gameMap = sti('Maps/overworld.lua')
menuImg = love.graphics.newImage('Assets/Menu.png')
love.window.setMode(800, 600)
end
function love.draw(dt)
if Room == 0 then
love.graphics.draw(menuImg, 0, 0)
end
if Room == 1 then
gameMap:draw()
player.draw()
end
if debug == true then
love.graphics.print("Current FPS: "..tostring(love.timer.getFPS( )), 10, 10)
end
end
function love.update(dt)
if Room == 0 then
if love.keyboard.isDown('space') then
Room = 1
end
end
if Room == 1 then
player.Update(dt)
if love.keyboard.isDown('escape') then
Room = 0
end
end
if love.keyboard.isDown('t') then
debug = not debug
end
end
and this is my player.lua script:
-- PLAYER SCRIPT
player = {x = 50, y = 50, speed = 3, state = 0, img = nil}
function player.load()
playerRight = love.graphics.newImage('Assets/playerRight.png')
playerLeft = love.graphics.newImage('Assets/playerLeft.png')
playerUp = love.graphics.newImage('Assets/playerUp.png')
playerDown = love.graphics.newImage('Assets/playerDown.png')
player.img = playerDown
end
function GetInput()
if player.state == 0 or player.state == 1 then
if love.keyboard.isDown('w') then
player.y = player.y - player.speed
player.img = playerUp
elseif love.keyboard.isDown('s') then
player.y = player.y + player.speed
player.img = playerDown
end
if love.keyboard.isDown('a') then
player.x = player.x - player.speed
player.img = playerLeft
elseif love.keyboard.isDown('d') then
player.x = player.x + player.speed
player.img = playerRight
end
end
end
function player.update(dt)
GetInput()
end
function player.draw()
love.graphics.draw(player.img, player.x, player.y)
end
Any help would be much appreciated!
Here's my folders as well, just in case it's a path issue:
UPDATE:
I solved it by renaming the player object to oPlayer, that was what was giving me an error.
I have severall Hints for you
Unclear
It looks you write it under Linux but should it also run under Windows?
If so, use OS independent folder delimiter ( the dot ) in require().
Example
player = require 'Scripts.player'
In General: Dont use Slash / Backslash \ in require()
Tip: LÖVE uses LuaJIT with modified Lua 5.1 check the Windows OS is easy
(For deciding to use Slash or Backslash (not in/for require()))
Clear
As #Luke100000 mentioned...
A Script for require has to return something.
If not than only a true wil be cached and a next require returns only true.
Therefore your player.lua content should be...
-- player.lua
local player = {x = 50, y = 50, speed = 3, state = 0, img = nil}
-- player.load() will be local
-- GetInput() wil be global
-- And the last line...
return(player)

How can I run through all these ifs in python?

When I run the program It will only run the first If and make those specific changes. Noticed when i switched them around and only the first one gives me what I want... Thanks for the help.
if SW1 != r['SW1']: #check the received value of SW1 & change it on the App if there is a mismatch
print("Changing SW1 status to the value in the database.")
if self.sw1.active == True:
self.sw1.active = False
else:
self.sw1.active = True
else:
return
if LED1 != r['LED1']: #check the received value of led1 & change it on the App if there is a mismatch
print("Changing LED1 status to the value in the database.")
if self.led1.active == True:
self.led1.active = False
else:
self.led1.active = True
else:
return
if LED2 != r['LED2']: #check the received value of led2 & change it on the App if there is a mismatch
print("Changing LED2 status to the value in the database.")
if self.led2.active == True:
self.led2.active = False
else:
self.led2.active = True
else:
if LED3 != r['LED3']: #check the received value of led3 & change it on the App if there is a mismatch
print("Changing LED3 status to the value in the database.")
if self.led3.active == True:
self.led3.active = False
else:
self.led3.active = True
else:
return
You should not return in else after every if. This will make the function to close after the first if is failed. I will explain it further with one example.
Take this function which checks if a number is even.
def foo_bar(n):
if n%2==0:
print("Even")
else:
return
print("I have been reached")
If an even number is passed, you will see the below output
>>> foo_bar(10)
Even
I have been reached
If the Odd number is passed, you will not see any output as the function is returning None and Terminated in else.
Now if you have multiple ifs in the function,
def foo_bar(n):
if n%2==0:
print("Even")
else:
return
if n%3==0:
print("Divisible by 3")
print("I have been reached")
If you pass 9 as an argument, the above function prints nothing. It is because after one condition is checked , you are returning None which terminates the function.
Hope this answers your question.

Q values overshoot in Double Deep Q Learning

I am trying to teach the agent to play ATARI Space Invaders video game, but my Q values overshoot.
I have clipped positive rewards to 1 (agent also receives -1 for losing a life), so the maximum expected return should be around 36 (maybe I am wrong about this). I have also implemented the Huber loss.
I have noticed that when my Q values start overshooting, the agent stops improving (the reward stops increasing).
Code can be found here
Plots can be found here
Note:
I have binarized frames, so that I can use bigger replay buffer (my replay buffer size is 300 000 which is 3 times smaller than in original paper)
EDIT:
I have binarized frames so I can use 1 bit(instead of 8 bits) to store one pixel of the image in the replay buffer, using numpy.packbits function. In that way I can use 8 times bigger replay buffer. I have checked if image is distorted after packing it with packbits, and it is NOT. So sampling from replay buffer works fine. This is the main loop of the code (maybe the problem is in there):
frame_count = 0
LIFE_CHECKPOINT = 3
for episode in range(EPISODE,EPISODES):
# reset the environment and init variables
frames, _, _ = space_invaders.resetEnv(NUM_OF_FRAMES)
state = stackFrames(frames)
done = False
episode_reward = 0
episode_reward_clipped = 0
frames_buffer = frames # contains preprocessed frames (not stacked)
while not done:
if (episode % REPORT_EPISODE_FREQ == 0):
space_invaders.render()
# select an action from behaviour policy
action, Q_value, is_greedy_action = self.EGreedyPolicy(Q, state, epsilon, len(ACTIONS))
# perform action in the environment
observation, reward, done, info = space_invaders.step(action)
episode_reward += reward # update episode reward
reward, LIFE_CHECKPOINT = self.getCustomReward(reward, info, LIFE_CHECKPOINT)
episode_reward_clipped += reward
frame = preprocessFrame(observation, RESOLUTION)
# pop first frame from the buffer, and add new at the end (s1=[f1,f2,f3,f4], s2=[f2,f3,f4,f5])
frames_buffer.append(frame)
frames_buffer.pop(0)
new_state = stackFrames(frames_buffer)
# add (s,a,r,s') tuple to the replay buffer
replay_buffer.add(packState(state), action, reward, packState(new_state), done)
state = new_state # new state becomes current state
frame_count += 1
if (replay_buffer.size() > MIN_OBSERVATIONS): # if there is enough data in replay buffer
Q_values.append(Q_value)
if (frame_count % TRAINING_FREQUENCY == 0):
batch = replay_buffer.sample(BATCH_SIZE)
loss = Q.train_network(batch, BATCH_SIZE, GAMMA, len(ACTIONS))
losses.append(loss)
num_of_weight_updates += 1
if (epsilon > EPSILON_END):
epsilon = self.decayEpsilon(epsilon, EPSILON_START, EPSILON_END, FINAL_EXPLORATION_STATE)
if (num_of_weight_updates % TARGET_NETWORK_UPDATE_FREQ == 0) and (num_of_weight_updates != 0): # update weights of target network
Q.update_target_network()
print("Target_network is updated!")
episode_rewards.append(episode_reward)
I have also checked the Q.train_network and Q.update_target_network functions and they work fine.
I was wondering if problem can be in hyper parameters:
ACTIONS = {"NOOP":0,"FIRE":1,"RIGHT":2,"LEFT":3,"RIGHTFIRE":4,"LEFTFIRE":5}
NUM_OF_FRAMES = 4 # number of frames that make 1 state
EPISODES = 10000 # number of episodes
BUFFER_SIZE = 300000 # size of the replay buffer(can not put bigger size, RAM)
MIN_OBSERVATIONS = 30000
RESOLUTION = 84 # resolution of frames
BATCH_SIZE = 32
EPSILON_START = 1 # starting value for the exploration probability
EPSILON_END = 0.1
FINAL_EXPLORATION_STATE = 300000 # final frame for which epsilon is decayed
GAMMA = 0.99 # discount factor
TARGET_NETWORK_UPDATE_FREQ = 10000
REPORT_EPISODE_FREQ = 100
TRAINING_FREQUENCY = 4
OPTIMIZER = RMSprop(lr=0.00025,rho=0.95,epsilon=0.01)

pygame is not defined, now just a syntax error

hope you guys can help. Initially the error raised by shell was 'nameError: 'pygame' is not defined', which seemed odd as without too great a change my code had previously ran fine. Now after fiddling with the code - commenting out lines, nothing too drastic - executing it from the python idle raises a basic syntax error. offending code:
pygame.display.update()
If this line is commented out, then a new syntax error is raised on the next line; offending code:
if isItSnap(middleDeck):
I looked at this post - 'pygame' is not defined - but the answer did not apply.
Please let me know if i should post the whole program. pygame was of course imported and initialised.
#loop for actual gameplay
while True:
for event in pygame.event.get():
#event.type, check identifier the 'type' of event it is
#pygame.QUIT, all 'type's that an event can be are stored as constants
#in pygame.locals module in fact the 'pygame' preceeding QUIT is unnecessary
#QUIT is contant variable in pygame.locals module. now in our global namespace
#finally to generate an event with type 'QUIT' user clicks red boxed cross on window
if event.type == pygame.QUIT:
terminate()
if event.type == pygame.KEYDOWN and event.key == K_ESCAPE:
terminate()
if event.type == pygame.KEYDOWN:#check
if event.key == pygame.turnCardButton:#anyone can turn card over
#lets us know user wants to flip card
turnCard = True
#turn card, only for computer atm
if turnCard:
turnCard(currentPlayer, middleDeck)
turnCard = False
#draw everything to screen, only need to blit latest card, no need whole screen
#or draw everything end prog just draw the latest card here???
windowSurface.fill(GREEN)#clear screen
displayRect = windowSurface.get_rect()
for cards in middleDeck:
card = pygame.image.load(imageLocator[cards])
#atm there is no rotation, all cards aligned perfectly
windowSurface.blit(card, (displayRect.centerx - CARDX, displayRect.centery - CARDY)
#update screen for user, this when they will try call snap
pygame.display.update()
if isItSnap(middleDeck):
#need users to see card before we enter into loop
#check rules snap, maybe need to timer if noone called can continue turning cards
#clear event list as we want to find player with the QUICK DRAW YEEHAA
pygame.event.clear()
while True:
#CURRENTLY NO SCORE CALLING SLOW IN PLAY
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
#who has one this round!?
if event.key == playerOneSnapButton:
#player one takes all the cards
player1 = middleDeck + player1
middleDeck = []
#just for now UNTIL ALL DRAWING HAS BEEN OPTIMIZED
windowSurface.fill(GREEN)
pygame.display.update()
break
elif event.key == playerTwoSnapButton:
player2 = middleDeck + player2
middleDeck = []
windowSurface.fill(GREEN)
pygame.display.update()
break
else:
time.sleep(playSpeed)#to slow game a little
The issue is caused by a typo. The closing parenthesis missing after
windowSurface.blit(card, (displayRect.centerx - CARDX, displayRect.centery - CARDY)
windowSurface.blit(card, (displayRect.centerx - CARDX, displayRect.centery - CARDY))

python multiprocessing execute code in child process when termination occurs

I want to know if there's a way to run some code on the child process when the parent process tries to terminate the child process. Is there a way we can write an Exception maybe?
My code looks something like this:
main_process.py
import Process from multiprocessing
def main():
p1 = Process(target = child, args = (arg1, ))
p1.start()
p1.daemon = True
#blah blah blah code here
sleep(5)
p1.terminate()
def child(arg1):
#blah blah blah
itemToSend = {}
#more blah blah
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
Since the job never finishes, child process keeps running. I have to terminate it from the parent process since child process never terminates on its own. However, I want to send itemToSend to parent process before child process terminates. Can I return it to parent process somehow?
UPDATE: Let me explain how runDispatcher() of pysnmp module works
def runDispatcher():
while jobsArePending(): # jobs are always pending because of jobStarted() function
loop()
def jobStarted(jobId):
if jobId in jobs: #This way there's always 1 job remaining
jobs[jobId] = jobs[jobId] + 1
This is very frustrating. Instead of doing all this, is it possible to write an snmp trap listener on our own? Can you point me to the right resources?
The .runDispatcher() method actually invokes a mainloop of an asynchronous I/O engine (asyncore/twisted) which terminates as soon as no active pysnmp 'jobs' are pending.
You can make pysnmp dispatcher to cooperate with the rest of your app by registering your own callback timer function which will be invoked periodically from mainloop. In your callback function you could check if a termination event arrived and reset pysnmp 'job' what would make pysnmp mainloop to complete.
def timerCb(timeNow):
if terminationRequestedFlag: # this flag is raised by an event from parent process
# use the same jobId as in jobStarted()
snmpEngine.transportDispatcher.jobFinished(1)
snmpEngine.transportDispatcher.registerTimerCbFun(timerCb)
Those pysnmp jobs are just flags (like '1' in your code) that mean to tell I/O core that asynchronous applications still need this I/O core to run and serve them. Once the last of potentially many apps is no more interested in I/O core operation, the mainloop terminates.
If the child process may cooperate then you could use multiprocessing.Event to inform the child that it should exit and multiprocessing.Pipe could be used to send itemToSend to the parent:
#!/usr/bin/env python
import logging
import multiprocessing as mp
from threading import Timer
def child(stopped_event, conn):
while not stopped_event.wait(1):
pass
mp.get_logger().info("sending")
conn.send({'tosend': 'from child'})
conn.close()
def terminate(process, stopped_event, conn):
stopped_event.set() # nudge child process
Timer(5, do_terminate, [process]).start()
try:
print(conn.recv()) # get value from the child
mp.get_logger().info("received")
except EOFError:
mp.get_logger().info("eof")
def do_terminate(process):
if process.is_alive():
mp.get_logger().info("terminating")
process.terminate()
if __name__ == "__main__":
mp.log_to_stderr().setLevel(logging.DEBUG)
parent_conn, child_conn = mp.Pipe(duplex=False)
event = mp.Event()
p = mp.Process(target=child, args=[event, child_conn])
p.start()
child_conn.close() # child must be the only one with it opened
Timer(3, terminate, [p, event, parent_conn]).start()
Output
[DEBUG/MainProcess] created semlock with handle 139845842845696
[DEBUG/MainProcess] created semlock with handle 139845842841600
[DEBUG/MainProcess] created semlock with handle 139845842837504
[DEBUG/MainProcess] created semlock with handle 139845842833408
[DEBUG/MainProcess] created semlock with handle 139845842829312
[INFO/Process-1] child process calling self.run()
[INFO/Process-1] sending
{'tosend': 'from child'}
[INFO/Process-1] process shutting down
[DEBUG/Process-1] running all "atexit" finalizers with priority >= 0
[DEBUG/Process-1] running the remaining "atexit" finalizers
[INFO/MainProcess] received
[INFO/Process-1] process exiting with exitcode 0
[INFO/MainProcess] process shutting down
[DEBUG/MainProcess] running all "atexit" finalizers with priority >= 0
[DEBUG/MainProcess] running the remaining "atexit" finalizers