Hi again, this time I need to play a sound. Everything works well for the soundA but the soundB wich follows the same logic but replacing a with b will not work at all.
Everytime I press B while runing the script I get this error :
aud.error: AUD_FileFactory: File couldn’t be read.
import bge
from bge import logic
import aud
#The actual scene in a word
scene = bge.logic.getCurrentScene()
#The controller holding this script
cont = logic.getCurrentController()
own = cont.owner
# my actuator is named SoundA and is used to play the corresponding sound
actA = cont.actuators["SoundA"]
actB = cont.actuators["SoundB"]
# pressA means when letter a is down
pressA = cont.sensors["KeyboardA"]
pressB = cont.sensors["KeyboardB"]
# get a list of the objects in the scene
objList = scene.objects
# get object named A
letterA = objList["Ak"]
letterB = objList["Bk"]
# get object named Score
score = objList["Score"]
# The old score of the player
oldScore = own.get("zScore")
# get the distance between them
distanceA = own.getDistanceTo(letterA)
distanceB = own.getDistanceTo(letterB)
# Create a variable and store the sound you want to reference once
if not 'init' in own:
own['init'] = 1
own['soundA'] = aud.Factory(logic.expandPath('//1.wav'))
own['soundB'] = aud.Factory(logic.expandPath('//2.wav')) # Create a factory (something that stores sounds) from a path.
# The path is created by the bge.logic.expandPath() function. The string begins with "//", which signifies a path relative from the
# blend file. So, "//ASound.wav" is referring to a wave file named "ASound.wav" that's in the same directory as the blend.
#If letter A is in the scene and the key A is pressed compare
#the distance between The letter A and the Amarker
#Than add this value to the score
#Finaly destroy the letter A
if letterA:
if pressA.positive:
# The score given according to the distance
scoreAdd = (int(100-(distanceA*2)))
newScore = (oldScore+scoreAdd)
score.text = str(newScore)
aud.device().play(own['soundA']) # Use the sound device that the aud module retrieves to playback the sound factory; this process
# returns a Handle. You can do a lot with Handle, like pitch individual playbacks of sounds and adjust volumes.
letterA.endObject()
own["zScore"] = newScore
if letterB:
if pressB.positive:
# The score given according to the distance
scoreAdd = (int(100-(distanceB*2)))
newScore = (oldScore+scoreAdd)
score.text = str(newScore)
aud.device().play(own['soundB'])# Use the sound device that the aud module retrieves to playback the sound factory; this process
# returns a Handle. You can do a lot with Handle, like pitch individual playbacks of sounds and adjust volumes.
letterB.endObject()
own["zScore"] = newScore
I just dont get it everything seems to be exactly as for the A key but with B everywhere.
Like Monster mentioned, you should ensure the file exists (i.e. is named “2.wav” and is next to the blend file), and that it plays back fine. Also, you could clean up your script a bit to make it easier to read and deal with (i.e. you don’t need sound actuators since you’re doing everything with Audaspace). Also, you could print out the path to the file to ensure it’s correct (print out the logic.expandPath(’//2.wav’) part).
EDIT: If none of this helps, you could try packing your sounds and the blend file into a zip and uploading it to a file hosting service like Copy, Box, Dropbox, or Mediafire.
in your case (with script mode) try to store the device in a property, or better in globalDict:
if not "init" in own:
own["init"] = 1
bge.logic.globalDict["device"] = aud.device()
if pressA.positive:
bge.logic.globalDict["device"].play(own['soundA'])
If any of the aforementioned solutions do not work, try playing an mp3 file. I was unable to play wav sounds in my builds recently, and I’m sure I didn’t disable any sound codecs
I need to do so because every letters will have the same script with some variations like they spawn at a different location, they also all play a different sound.
For this reason I cant just use the same script over and over for each letters.
So I am creating in a single script (to make it eazy if I have some changes to do) with all the code for each letters.
Obviously I try to set everything as I want it to be for the final result before I create more letters as I dont want to have to rewhrite every lines for each letters if I need a change.
Finally now that I got those 2 letters working I figured a bug witch makes no sence to me yet but has to be fixed before I implement the other letters :S
When playing the game the letters A and B both get created 5 times .
The player will than hit A and B 5 times each. (everytime the player it A if A is in the scene it gets deleted and play
a sound , same for b)
The problem is that for some reason the last letter to stay in the scene doesnt want to get deleted anymore (or play its sound/add score).
*In other words deleting every instance of an object wont let the script run anymore
After reading the console I got that :
If the last letter to be in the screen is A - the console displays: ‘Bk’ not in list
If the last letter to be in the screen is B - the console displays: ‘Ak’ not in list
-this occurs as soon as all the object of an instance are deleted example:
I delete all 5 A’s , I cant delete anny B.
-Also if another A was to appear at that time, the script would work again
so I could delete all the B.
I dont get why the code looks for the letter B when we ask for A and vice versa.
If anyone as a logic explanation for this Id be glad to read about it.
Also if there is a way to solve this .
This happens because your script searches the “objlist” list for “Ak” and “Bk” objects. If you delete them, then they’re no longer available to be found, so the script fails. You need to ensure they’re there before you continue.
letterA = objlist['Ak'] if 'Ak' in objlist else None
# And then later...
if letterA: # In Python a boolean check like this equates to "if letterA is not equal to None or 0, then it's true". So, if letterA is a reference to an existing object.
EDIT: A more efficient way to do this is to make a global dictionary (“logic.letters”, for example) with an empty list for each letter. You store letters as they are created (i.e. when they’re created, they run a simple script that adds their reference in their specific list for you to check). The reference is stored by letter (i.e. logic.letters[‘A’].append(obj) ). When you delete a letter, you remove its reference from the logic.letters dictionary.
I was actualy working on my script to make it look nicer and be clearer to the other python users but I think your script is better XD
Thancks guys this works perfectly and agoose77 you are awesome I just copy pasted the script and it works perfectly I just saved so much lines of coding by your help
(I only changed one thing I was too lazy to convert the 2.mp3 to wav so i changed those 3 letters in your script)
Here look at what I had before you post this script!
import bge
from bge import logic
import aud
#The controller holding this script
cont = logic.getCurrentController()
own = cont.owner
#The actual scene in a word
scene = bge.logic.getCurrentScene()
get a list of the objects in the scene
objList = scene.objects
get the text object named Score
score = objList[“Score”]
The old score of the player (property variable)
oldScore = own.get(“zScore”)
#//--------------------------------------------------\#
# Here we store all the values for the letters
The object itselt: letter()
The keyboard Sensor for that letter: press()
The Distance from the letter to its marker: distance()
Create a variable and store the sound you want to reference once
if not ‘init’ in own:
own['init'] = 1
# The sound location (same as the blend file)
own['soundA'] = aud.Factory(logic.expandPath('//1.wav'))
own['soundB'] = aud.Factory(logic.expandPath('//2.mp3'))
#//--------------------------------------------------\# #If: letter A is in the scene #and: the key A is pressed #Than: compare the distance #between: The letter A and the Amarker #Than: add the distance to the score #and: Play the sound A #Finally: destroy the letter A
#\--------------------------------------------------//#
#Letter A script start---------------------------------#
#Letter A script end---------------------------------#
#//--------------------------------------------------\# #From here the script is the same for every letters. #The only difference is that we replace the letter A #in the variable letterA (x2), pressA, distanceA, #and soundA for the letter used.
#\--------------------------------------------------//#
#Letter B script start---------------------------------#
btw at this point Ill ask one more thing instead of opening a new thread.
basicly i want to print in the console the time that i press a key and wich key was pressed.
To do this I think i’ll use the timer property once more and add a if a key is pressed than print the key and timer
import bge
from bge import logic
ob = bge.logic.getCurrentController().owner
timer = ob.get('Timer')
if #now i dont know how to say on any keypressed
print (the key pressed , (timer)