Game

How I Fix a Callback Error When Creating My Speech Recognition Game

How I Fix a Callback Error When Creating My Speech Recognition Game

I’ve always wanted to build an interactive voice controlled game something fun, spooky, and immersive. So, I started experimenting with pyttsx3, speech_recognition, and some simple logic to bring my idea to life. Everything was going great until I hit a frustrating and confusing error just when my player chose the “knife” in the game.

Here’s how I diagnosed it, fixed it, and ended up with a more reliable and feature rich version of the game.

The Mysterious Callback Error

As soon as I reached the part where the player picks the “knife,” I got this error:

Exception ignored on calling ctypes callback function: <function catch_errors.<locals>.call_with_this at ...>
TypeError: 'NoneType' object is not callable

What made it even more confusing was that the game didn’t crash, but it just stopped responding properly. It took me a bit of debugging to trace the problem.

What Was Really Causing It

The message was pointing me toward ctypes, comtypes, and logging, but the root cause was much simpler:

time.sleep(a)

I had used a variable a for the pause duration without defining it. Since this line was buried in a speech callback function (pyttsx3 uses them internally), the actual exception was suppressed, leading to a cryptic traceback and silent failure.

Lesson learned: Always define your variables before using them and never assume a callback will surface exceptions the way normal code does.

How I Fix the Problem

Define a clear variable

I replaced a with a proper pause_time = 2, so the pause duration is clearly managed and can be reused.

Update command logic

I noticed I wasn’t capturing new voice input properly during nested choices (e.g when asking for the weapon or the next action). I fixed that by creating a function to handle all voice input and calling it every time I needed a command.

Add better error handling

I added try-except blocks for speech_recognition to handle things like microphone issues or misunderstood speech.

Final Working Version of the Game

import time
import pyttsx3
import speech_recognition as sr

# Initialize TTS engine
engine = pyttsx3.init()
voices = engine.getProperty("voices")
engine.setProperty("voice", voices[1].id)
engine.setProperty("rate", 150)

# Define pause duration
pause_time = 2

# Function to speak text
def speak(text):
engine.say(text)
engine.runAndWait()

# Function to listen and recognize speech
def get_voice_command(prompt=""):
if prompt:
speak(prompt)
listener = sr.Recognizer()
with sr.Microphone() as source:
print("Listening...")
listener.adjust_for_ambient_noise(source)
voice = listener.listen(source)
try:
command = listener.recognize_google(voice)
return command.lower()
except sr.UnknownValueError:
speak("Sorry, I didn't catch that.")
return None
except sr.RequestError:
speak("Speech service is unavailable.")
return None

# Game logic
def play_game():
name = "Player" # Placeholder name
speak("As you head down the dark alleyway, the light you saw quickly gets further and further away. You then notice two doors.")
time.sleep(pause_time)
command = get_voice_command("Say Left or Say Right")
if not command:
return

if "left" in command:
speak("You think just because this path isn't as dark it is safer. But you may be in for a surprise.")
time.sleep(pause_time)
speak("The door opens and you are faced with the brightest light you have ever seen.")
time.sleep(3)
speak("GAME OVER")
elif "right" in command:
speak("You are headed down a dark path but the reward may be great!")
time.sleep(pause_time)
weapon = get_voice_command("Say Knife or say Bow and Arrow to choose your weapon")
if not weapon:
return
if "knife" in weapon:
speak("You pick up the knife and notice it already has dried blood on it. Whose blood is this, you wonder.")
time.sleep(pause_time)
speak(f"You head further into the dark room and you hear very faintly your name being called. {name}... {name}... Please come help me.")
time.sleep(pause_time)
choice = get_voice_command("Say voice to head towards the voice, or say room to keep exploring the room")
if choice:
if "voice" in choice:
speak("You follow the voice. It's getting louder... but suddenly the door slams shut behind you.")
speak("GAME OVER.")
elif "room" in choice:
speak("You keep exploring and discover a hidden staircase. The adventure continues...")
else:
speak("Invalid choice.")
elif "bow" in weapon or "arrow" in weapon:
speak("You take the bow and arrow. A classic choice for the careful adventurer.")
speak("You hear a noise from above... something is watching.")
else:
speak("You didn't choose a valid weapon.")
else:
speak("You didn't say left or right clearly.")

# Run the game
play_game()

What I Want to Add Next

Now that the base works, I have tons of ideas to expand the game:

  • Use gTTS for smoother, pre-generated voices if I want better narration.
  • Add sound effects using playsound() to make things feel more intense.
  • Track player choices to build branching story paths and outcomes.
  • Handle “Repeat” or “Help” commands for accessibility.
  • Use a GUI with tkinter or pygame to give players visual feedback and atmosphere.

Final Thought

Debugging this callback error taught me a lot not just about error handling, but also about how voice interfaces behave under the hood. It’s a totally different world from traditional input-based games, but with a little care and structure, it can be incredibly rewarding.

author-avatar

About Sneed Cody

Versatile Game Developer specializing in creating captivating 2D and 3D games using Unity and Unreal Engine. With a passion for turning concepts into immersive gaming experiences, I bring expertise in both realms, offering seamless Unity 2D development, Unreal 3D magic, and everything in between. From innovative mechanics to stunning visuals, let's collaborate to bring your gaming visions to reality.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments