Strange error. Doesn't appear in release mode...

BlitzMax Forums/BlitzMax Beginners Area/Strange error. Doesn't appear in release mode...

Takis76(Posted 2015) [#1]
Hello,

When I am compiling my game in release mode the game runs very well.
But when I try to compile it in debug mode I have a strange error with description:

Unhandled Exception:Assert failed.

Then when I go to the debug line it goes to the cue sound code (from the audio library of blitzmax)

	Method Cue:TDirectSoundChannel( alloced_channel:TChannel=Null )
		Local t:TDirectSoundChannel=TDirectSoundChannel( alloced_channel )
		If t
			Assert t._static <============= THE ERROR GOES HERE
		Else
			t=TDirectSoundChannel.Create( False )
		EndIf
		t.Cue Self
		Return t
	End Method



The bug is produced when I try to play a sound with channel.

For example I have one code bellow to describe what I do and produce this error.

Produce the error in debug mode
PlaySound(Door_Opening1, Ch_Door_Opening1)
It doesn't produce any error in debug mode but you don't have 3D sounds and other channel playing.
PlaySound(Door_Opening1)


The wav files loaded and get assigned to a channel.

Door_Opening1 = LoadSound("zip::Sounds.zip//Doormech1.wav")
Ch_Door_Opening1 = CueSound(Door_Opening1)


I load my wav and assign it to the channel. with CueSound command.
If I will play the sound without CueSound the error is not appearing.
I tried to allocate the channel to but I have the same error.

Door_Opening1 = LoadSound("zip::Sounds.zip//Doormech1.wav")
Ch_Door_Opening1 = AllocChannel()
Ch_Door_Opening1 = CueSound(Door_Opening1)


Do you know why this error is appearing in debug mode and not in release and how to fix it?

Thank you very much...


GfK(Posted 2015) [#2]
I tried to allocate the channel to but I have the same error.

Door_Opening1 = LoadSound("zip::Sounds.zip//Doormech1.wav")
Ch_Door_Opening1 = AllocChannel()
Ch_Door_Opening1 = CueSound(Door_Opening1)

Pretty sure this code isn't doing what you think it's doing. If you pre-allocate the channel then you pass that channel to CueSound, thus:

Ch_Door_Opening1 = AllocChannel()
CueSound(DoorOpening1, Ch_Door_Opening1)


The way you've done it, is to create a channel then immediately overwrite it with another that's returned from CueSound().

Hit a similar error myself a long time ago and found pre-allocation of the channel to be the work-around.


Takis76(Posted 2015) [#3]
I tried your way and a new error was appeared:

Unhandled Exception:Attempt to access field or method of Null object

It goes to audio.bmx at the code:

Function CueSound:TChannel( sound:TSound,channel:TChannel=Null )
	Return sound.Cue( channel ) <=== THE ERROR IS HERE
End Function


I tried to just rem the Assert t._static line in the post above and the game worked in debug mode.


GfK(Posted 2015) [#4]
Ch_Door_Opening1 is defined as a TChannel, right?


Takis76(Posted 2015) [#5]
Yes

And is a global variable.

Global Door_Opening1:TSound
Global Ch_Door_Opening1:TChannel



GfK(Posted 2015) [#6]
Hm... actually, which variable is showing Null in the debugger? The sound, or the channel? (or both?)


Takis76(Posted 2015) [#7]
It hits the error in debugger to the channel

Function CueSound:TChannel( sound:TSound,channel:TChannel=Null )
	Return sound.Cue( channel )
End Function


Unhandled Exception:Attempt to access field or method of Null object at the channel.
Is it a bug of the language?


GfK(Posted 2015) [#8]
I doubt it - I've never hit this problem in all my years of Blitzmax.

Are you using Linux, by any chance?


Takis76(Posted 2015) [#9]
Windows 7


Derron(Posted 2015) [#10]
"Assert" is ignored in "Release mode", so that is why you only see it in Debug. The "problem" is the same in both cases.

Replace "assert" with a throw-variant and it will raise the exception in both cases.


Unhandled Exception:Attempt to access field or method of Null object at the channel.


Seems not "channel" is null, but "sound", because above clearly states, that something wants to access a METHOD or FIELD of something which is null.

I assume that it failed to load the sound somehow.

Before you do the "CueSound" - could you do a
If not DoorOpening1 then print "DoorOpening1 is null"

and check if that gets print before crashing?


bye
Ron


Takis76(Posted 2015) [#11]
I put the code you said and I added an end command to make the program ends.

Global Door_Opening1:TSound
Global Ch_Door_Opening1:TChannel

Door_Opening1 = LoadSound("zip::Sounds.zip//Doormech1.wav")
If Not Door_Opening1 Then Print "DoorOpening1 is null" End

CueSound(Door_Opening1, Ch_Door_Opening1)


And the error continued and the program hit in other file and other line.
So I discovered the problem is with the channel.
So I added another one line.

If Not Ch_Door_Opening1 Then Print "Ch_Door_Opening1 is null" End

And then the program ended with message "Ch_Door_Opening1 is null"

So the channel is Null not the sound.

	Door_Opening1 = LoadSound("zip::Sounds.zip//Doormech1.wav")
	CueSound(Door_Opening1, Ch_Door_Opening1)
	If Not Door_Opening1 Then Print "Door_Opening1 is null" End
	If Not Ch_Door_Opening1 Then Print "Ch_Door_Opening1 is null" End



Only changing with
Ch_Door_Opening1 = CueSound(Door_Opening1)

Instead of
CueSound(Door_Opening1, Ch_Door_Opening1)


The first cuesound return the channel to Ch_Door_Opening1
And the second one pass the channel Ch_Door_Opening1 as argument.
What is the difference between?

It Doesn't produce the "Unhandled Exception:Attempt to access field or method of Null object at the channel. "
But produce the other with the assert as before.
And when I remove the "Assert t._static" line.
The program works.

I think I will remove this "Assert t._static" thing and I will continue my game :)


GfK(Posted 2015) [#12]
A bit random, but you do have speakers/headphones plugged in? I vaguely recall a problem with DirectSound from years back where Blitzmax would crap out if there wasn't - as if there was no soundcard present at all.


Takis76(Posted 2015) [#13]
I have headphones to test the volume and pan.
And speakers to test the sounds in generic.
I discovered yet another bug in my door sounds and 3d effects.
I will post some demo when I will fix my sound errors.


Takis76(Posted 2015) [#14]
I have another problem about when I try to play 2 same sounds simultaneously I hear the sound distorted.
I will send you a demo. I try to play the same sound for my doors near and far , but when I am playing the same sound during other sound is playing I hear the sound distorted.


Derron(Posted 2015) [#15]
You need to allocate individual channels for them.


I was wondered about your "if bla = null then print X end"... I thought it needs to get chained using ";" ("if bla = null then print X;end") but somehow this isnt true...


@your error.
You posted this previously:
It hits the error in debugger to the channel
Function CueSound:TChannel( sound:TSound,channel:TChannel=Null )
	Return sound.Cue( channel )
End Function




Which is saying: "sound.cue(channel)" is raising the error about access to null-ed child elements. This would mean, that "sound" does not contain "cue()". In all other cases, the debugger would jump to the error within the "Cue" method.

In all cases your debugging pane on the right side will show variable names + content (or memory address) - if something is null, this is printed too.


Ok back to the problem ... FreeAudio does not have this assert in "cue" - it just creates the channel if you did not provide a valid/existing one. Your DX-one instead checks if the existing TChannel is in reality a "TDirectSoundChannel" one ... and then it checks if it got created with a static-flag.


Ok ... so guess what? that "_static" isnt used anywhere - it is used in the "openalaudio"-version to check for a leak, but within Blitzmax the DirectSoundAudio-version isnt using "_static" for anything useful.

If you want to get rid of the assert you might create your channel correspondingly:

local myChannelOne:TChannel
?Win32
myChannelOne = TDirectSoundChannel(true)
?not Win32
myChannelOne = AllocChannel()
?


But ... I just checked "AllocChannel()" and it runs the "AllocChannel"-Method of the individual Audiodriver ...
... did you set the AudioDriver at all? And if YES... do you create all these channels AFTER the audio driver was set?


The channel you are using and which is "not null" but of the type "TDirectSoundChannel" should have a "_static" value of "true" to not alert the "assert".




Short: you could remove that _static portion without problems. A real "debugging"-pane-analysis by you might help which portion of a object was null.


bye
Ron


Takis76(Posted 2015) [#16]
Hello again,
I have to say I haven't set any audio driver and I thought this happens automatically or choose the windows drivers.
How to set audiodrivers?

I have one little demo about what I have created so far with your very precious help. :)

Download a demo , and see how my sounds hear

The code of the doors in my game:

	For All_Doors = 1 To max_doors

		'If Party.direction = 1 Or Party.direction = 2 Then
			If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 1 Then
			Doors[Party.Level, All_Doors].dist_x1 = Doors[Party.Level, All_Doors].x - Party.x
			Doors[Party.Level, All_Doors].dist_y1 = Doors[Party.Level, All_Doors].y - Party.y
			Doors[Party.Level, All_Doors].distance = Sqr((Doors[Party.Level, All_Doors].dist_x1 * Doors[Party.Level, All_Doors].dist_x1) + (Doors[Party.Level, All_Doors].dist_y1 * Doors[Party.Level, All_Doors].dist_y1))
			Doors[Party.Level, All_Doors].direction1 = ATan2(Doors[Party.Level, All_Doors].y - Party.y, Doors[Party.Level, All_Doors].x - Party.x)
			EndIf
		'EndIf
		'If Party.direction = 3 Or Party.direction = 4 Then
			If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 2 Then
			Doors[Party.Level, All_Doors].dist_x2 = Doors[Party.Level, All_Doors].x - Party.x
			Doors[Party.Level, All_Doors].dist_y2 = Doors[Party.Level, All_Doors].y - Party.y
			Doors[Party.Level, All_Doors].distance = Sqr((Doors[Party.Level, All_Doors].dist_x2 * Doors[Party.Level, All_Doors].dist_x2) + (Doors[Party.Level, All_Doors].dist_y2 * Doors[Party.Level, All_Doors].dist_y2))
			Doors[Party.Level, All_Doors].direction2 = ATan2(Doors[Party.Level, All_Doors].y - Party.y, Doors[Party.Level, All_Doors].x - Party.x)
			EndIf
		'EndIf

		'if the distance is from 0 - 5 then hear far and near
		If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 1 Then
			If Doors[Party.Level, All_Doors].distance >= 0 And Doors[Party.Level, All_Doors].distance <= 1.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			End If
			If Doors[Party.Level, All_Doors].distance >= 2 And Doors[Party.Level, All_Doors].distance <= 2.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			End If
			If Doors[Party.Level, All_Doors].distance >= 3 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			End If
			If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			End If
			If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 4.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			End If
			If Doors[Party.Level, All_Doors].distance >= 5 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			End If
		EndIf
		
		'if the distance is from 0 - 5 then hear far and near
		'rem
		If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 2 Then
			If Doors[Party.Level, All_Doors].distance >= 0 And Doors[Party.Level, All_Doors].distance <= 1.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			Ch_Door_Closing2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			Ch_Door_Closed2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			End If
			If Doors[Party.Level, All_Doors].distance >= 2 And Doors[Party.Level, All_Doors].distance <= 2.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			Ch_Door_Closing2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			Ch_Door_Closed2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			End If
			If Doors[Party.Level, All_Doors].distance >= 3 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			Ch_Door_Closing2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			Ch_Door_Closed2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			End If
			If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			Ch_Door_Closing2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			Ch_Door_Closed2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			End If
			If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 4.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			Ch_Door_Closing2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			Ch_Door_Closed2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			End If
			If Doors[Party.Level, All_Doors].distance >= 5 Then
			Ch_Door_Opening2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			Ch_Door_Closing2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			Ch_Door_Closed2.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			End If
		EndIf
		'endrem
		
		'Door animation mechanism , delay the animation a little	
		If (Current_time >= Doors[Party.Level, All_Doors].Door_Deadline_time) Then
			Current_time = MilliSecs()
			Doors[Party.Level, All_Doors].Door_Deadline_time = Current_time + 1
			Doors[Party.Level, All_Doors].Time_Delay = Doors[Party.Level, All_Doors].Time_Delay + 1
			
				'Synchronize the door animation speed according to the FPS
				If fps <= 29 Then door_speed = 10
				If fps >= 30 And fps <= 39 Then door_speed = 15
				If fps >= 40 And fps <= 49 Then door_speed = 20
				If fps >= 50 And fps <= 59 Then door_speed = 25
				
				If fps >= 60 And fps <= 79 Then door_speed = 30
				If fps >= 80 And fps <= 99 Then door_speed = 35
				If fps >= 100 And fps <= 119 Then door_speed = 40
				If fps >= 120 And fps <= 139 Then door_speed = 45
				If fps >= 140 Then door_speed = 50
				
				'Delay 65 millisecs
				If Doors[Party.Level, All_Doors].Time_Delay >= door_speed Then
				Doors[Party.Level, All_Doors].Time_Delay = 0
				'Reset the delay timer
					If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 1 Then

						'If the door is in opening state
						If Doors[Party.Level, All_Doors].State = 1 Then
							'Increase the animation frame
							If Doors[Party.Level, All_Doors].Frame = 1 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 2 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 3 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 4 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 5 Then
							Doors[Party.Level, All_Doors].State = 3 Return
							EndIf
					
						EndIf
								
						'If the door is in closing state
						If Doors[Party.Level, All_Doors].State = 2 Then
							'Decrease the animition frame
							If Doors[Party.Level, All_Doors].Frame = 1 Then
							Doors[Party.Level, All_Doors].State = 4
							'PlaySound(Door_Closed1, Ch_Door_Closed1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 2 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closed1, Ch_Door_Closed1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 3 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing1, Ch_Door_Closing1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 4 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing1, Ch_Door_Closing1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 5 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing1, Ch_Door_Closing1) Return
							EndIf
					
						EndIf
				
					EndIf
					If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 2 Then

						'If the door is in opening state
						If Doors[Party.Level, All_Doors].State = 1 Then
							'Increase the animation frame
							If Doors[Party.Level, All_Doors].Frame = 1 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening2, Ch_Door_Opening2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 2 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening2, Ch_Door_Opening2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 3 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening2, Ch_Door_Opening2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 4 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening2, Ch_Door_Opening2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 5 Then
							Doors[Party.Level, All_Doors].State = 3 Return
							EndIf
					
						EndIf
								
						'If the door is in closing state
						If Doors[Party.Level, All_Doors].State = 2 Then
							'Decrease the animition frame
							If Doors[Party.Level, All_Doors].Frame = 1 Then
							Doors[Party.Level, All_Doors].State = 4
							'PlaySound(Door_Closed1, Ch_Door_Closed1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 2 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closed2, Ch_Door_Closed2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 3 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing2, Ch_Door_Closing2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 4 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing2, Ch_Door_Closing2) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 5 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing2, Ch_Door_Closing2) Return
							EndIf
					
						EndIf
				
					EndIf
					
				EndIf

				
		EndIf

	Next

		
EndFunction 



Derron(Posted 2015) [#17]
I do not understand how the "demo code" will help to narrow down the bug.


In all cases: I think there is some code which could get shortened a bit.
You do things for all cases, so there is no need to have it written each time.

Also pay attention to your "ifs" regarding the state:

if state = 1 then doSomething
if state = 2 then doSomethingElse

if you change "state" within "doSomething" you might trigger that "if state = 2" in the same cycle, so better

if ...
elseif ...

in such cases.


@FPS doorspeed adjustment
??? why don't you "delta" this thing? Just define eg. "0.5seconds for whole animation" and then subtract the delta from a "timer value" which got set to 0.5 on start. It reaches 0 and 0.5seconds there gone. The relative progress is then (1.0 - timeLeft/0.5)


I do not want to teach you how to write code, but just a suggestion to make things more pregnant (you could even shorten that whole "doors" thing by looping through them using
			If Doors[Party.Level, All_Doors].distance >= 0 And Doors[Party.Level, All_Doors].distance <= 1.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 1)
			End If
			If Doors[Party.Level, All_Doors].distance >= 2 And Doors[Party.Level, All_Doors].distance <= 2.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.7)
			End If
			If Doors[Party.Level, All_Doors].distance >= 3 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.4)
			End If
			If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.2)
			End If
			If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 4.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.09)
			End If
			If Doors[Party.Level, All_Doors].distance >= 5 Then
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * 0.0)
			End If



			local volumeMod:float = 1.0
			If Doors[Party.Level, All_Doors].distance >= 0 And Doors[Party.Level, All_Doors].distance <= 1.99 Then
				volumeMod = 1
			Else If Doors[Party.Level, All_Doors].distance >= 2 And Doors[Party.Level, All_Doors].distance <= 2.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
				volumeMod = 0.7
			Else If Doors[Party.Level, All_Doors].distance >= 3 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
				volumeMod = 0.4
			Else If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
				volumeMod = 0.2
			Else If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 4.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then
				volumeMod = 0.09
			'I would prefer an "else" -> in all other cases do a volume=0
			'Else
			Else If Doors[Party.Level, All_Doors].distance >= 5 Then
				volumeMod = 0
			End If
			Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * volumeMod)
			Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * volumeMod)
			Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * volumeMod)




Please show the code creating/allocating the channels.


@Setaudiodriver
No you should not be needed to do so ... but I was not aware that you do not do that, so I assumed a potential flaw in your code (channel allocation before the audio driver is inited -> another audio driver would create a channel then).


bye
Ron


Takis76(Posted 2015) [#18]
This delta timer I have have relation about frames per second.
If for some reason your computer lags in frames per second the I calibrate the
timers so animation speed will be the same if the frames per second drop or increase.

About the creating and allocating channels I don't do anything complex

I just use
Global variables for the channel and the sounds
Global Door_Opening1:TSound
Global Ch_Door_Opening1:TChannel
Global Door_Opening2:TSound
Global Ch_Door_Opening2:TChannel


And then I load my sound from .wav file
	Door_Opening1 = LoadSound("zip::Sounds.eob//Doormech1.wav")
	Ch_Door_Opening1 = CueSound(Door_Opening1)
	Door_Opening2 = LoadSound("zip::Sounds.eob//Doormech1.wav")
	Ch_Door_Opening2 = CueSound(Door_Opening1)


I made a little change in the code and I create to separated sounds for horizontal and vertical doors. In fact the sound is the same but this avoids to play the same channel when you will open 2 doors which are horizontal.
Did you saw the demo?

Then the I am checking if the player is far or near to the door to hear the sound launder or quiet by increasing or decreasing the sound volume.

OK the volumeMod was nice it shortened my code a lot.

About the state of the door is my complex mechanism to tell to engine that my door is opening or closing or closed or opened to reverse the animation or start animation or stop.


Derron(Posted 2015) [#19]
I am on Linux, not on Windows so I wont run your app except in a VM (which I use for building .exe files).


@Globals

I just wanted to know... because you might do some untold things there.

There is nothing wrong with using the "convencience accessors" (cuesound, loadsound) instead of their "oop" ones (Ch_Door_Opening2 = Door_Opening1.cue()). The whole audio-cueing-thing leaves me puzzled everytime so you are not alone.


@State
Yepp, I use states for my "elevator" too. Just make sure you do not forget "cases" and create dead loops or situations the door hangs inbetween states.


@Sound
Maybe Skidracer is able to explain for what the assert is used in the sound core. Think he is more firm regarding this mod.


bye
Ron


Takis76(Posted 2015) [#20]
I made a lots of changes and I improved the code a little.
Now the problem is , when you open the door1 you hear the sound.
When you are opening the door2 and if there is a door1 near you hear the sound. Of the door1
But if you open the door4 which is far from door1 or other doors the code calculates the distance more than 5 because door4 if far from the door1 or 2 and you don't hear nothing.
But the for next loop scans all doors and I should hear the sounds of the doors which are in distance <=5 individually.

If I will not use soundvolume or volumeMod I can hear all the door sound equally but I will not have this near and far sound effect.

The new code is shorter than previously:
The sound distortions wasn't about channel allocations. Also I still work with the assert code removed.

Function Door_Mechanics()

	
	For All_Doors = 1 To max_doors

		'Door animation mechanism , delay the animation a little	
		If (Current_time >= Doors[Party.Level, All_Doors].Door_Deadline_time) Then
			Doors[Party.Level, All_Doors].Door_Deadline_time = Current_time + Doors[Party.Level, All_Doors].Time_Delay

					'If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 And Doors[Party.Level, All_Doors].Orientation = 1 Then

						'If the door is in opening state
						If Doors[Party.Level, All_Doors].State = 1 Then
							'Increase the animation frame
							If Doors[Party.Level, All_Doors].Frame = 1 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 2 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 3 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 4 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame + 1
							PlaySound(Door_Opening1, Ch_Door_Opening1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 5 Then
							Doors[Party.Level, All_Doors].State = 3 Return
							EndIf
					
						EndIf
								
						'If the door is in closing state
						If Doors[Party.Level, All_Doors].State = 2 Then
							'Decrease the animition frame
							If Doors[Party.Level, All_Doors].Frame = 1 Then
							Doors[Party.Level, All_Doors].State = 4
							'PlaySound(Door_Closed1, Ch_Door_Closed1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 2 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closed1, Ch_Door_Closed1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 3 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing1, Ch_Door_Closing1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 4 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing1, Ch_Door_Closing1) Return
							EndIf
							If Doors[Party.Level, All_Doors].Frame = 5 Then
							Doors[Party.Level, All_Doors].Frame = Doors[Party.Level, All_Doors].Frame - 1
							PlaySound(Door_Closing1, Ch_Door_Closing1) Return
							EndIf
					
						EndIf
				
					
		EndIf
	
		'Synchronize the door animation speed according to the FPS
		If fps <= 29 Then Doors[Party.Level, All_Doors].Time_Delay = 100
		If fps >= 30 And fps <= 39 Then Doors[Party.Level, All_Doors].Time_Delay = 150
		If fps >= 40 And fps <= 49 Then Doors[Party.Level, All_Doors].Time_Delay = 200
		If fps >= 50 And fps <= 59 Then Doors[Party.Level, All_Doors].Time_Delay = 250
				
		If fps >= 60 And fps <= 79 Then Doors[Party.Level, All_Doors].Time_Delay = 300
		If fps >= 80 And fps <= 99 Then Doors[Party.Level, All_Doors].Time_Delay = 350
		If fps >= 100 And fps <= 119 Then Doors[Party.Level, All_Doors].Time_Delay = 400
		If fps >= 120 And fps <= 139 Then Doors[Party.Level, All_Doors].Time_Delay = 450
		If fps >= 140 Then Doors[Party.Level, All_Doors].Time_Delay = 500

			If Doors[Party.Level, All_Doors].x > 0 And Doors[Party.Level, All_Doors].y > 0 Then
			Doors[Party.Level, All_Doors].dist_x1 = Doors[Party.Level, All_Doors].x - Party.x
			Doors[Party.Level, All_Doors].dist_y1 = Doors[Party.Level, All_Doors].y - Party.y
			Doors[Party.Level, All_Doors].distance = Sqr((Doors[Party.Level, All_Doors].dist_x1 * Doors[Party.Level, All_Doors].dist_x1) + (Doors[Party.Level, All_Doors].dist_y1 * Doors[Party.Level, All_Doors].dist_y1))
			Doors[Party.Level, All_Doors].direction1 = ATan2(Doors[Party.Level, All_Doors].y - Party.y, Doors[Party.Level, All_Doors].x - Party.x)


				Ch_Door_Opening1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * Doors[Party.Level, All_Doors].volumeMod)
				Ch_Door_Closing1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * Doors[Party.Level, All_Doors].volumeMod)
				Ch_Door_Closed1.SetVolume(Doors[Party.Level, All_Doors].Sound_Volume * Doors[Party.Level, All_Doors].volumeMod)
				If Doors[Party.Level, All_Doors].distance >= 0 And Doors[Party.Level, All_Doors].distance <= 1.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then Doors[Party.Level, All_Doors].volumeMod = 1 Continue
				If Doors[Party.Level, All_Doors].distance >= 2 And Doors[Party.Level, All_Doors].distance <= 2.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then Doors[Party.Level, All_Doors].volumeMod = 0.7 Continue
				If Doors[Party.Level, All_Doors].distance >= 3 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then Doors[Party.Level, All_Doors].volumeMod = 0.4 Continue
				If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 3.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then Doors[Party.Level, All_Doors].volumeMod = 0.2 Continue
				If Doors[Party.Level, All_Doors].distance >= 4 And Doors[Party.Level, All_Doors].distance <= 4.99 And Stairs[Party.Level, All_Doors].transfering = 0 Then Doors[Party.Level, All_Doors].volumeMod = 0.09 Continue
				If Doors[Party.Level, All_Doors].distance >= 5 Then Doors[Party.Level, All_Doors].volumeMod = 0 Continue


			EndIf


	
	Next

EndFunction


Walk around and open some doors.
Click here for next update


Derron(Posted 2015) [#21]
Ok, I adjusted your code - and more important, placed some comments in it.

What I have done is: redone some of the logic to catch previously ignored pitfalls (values differing to your expectations). Often used "array accesses" were shortened using a local variable - exception is if they are used in an "if...elseif...elseif"-part because they then are only used once at the end (for the if-condition which fit).

I also stopped PlaySound to get called in all cases - because this leads to this effect:
- door 1 opens and plays a sound
- door 3 opens and starts a sound too - so the sound of door1 is stopped inbetween

The "new" approach just plays a sound if no other open sound (vice versa for close) is playing.





I will post some kind of "ChannelPool" within the next minutes, so you should be able to play multiple sounds simultaneously. Just have to write one (so it will be a bit of untested and raw).

The pool shouldn't be needed at all, as it is some kind of "software mixing" and no hardware mixer (which then has a limit of eg. 16 channels). So in theory EACH of your doors could have its own channel ... and because this doors cannot be in open,close,closed-state at the same time, you wont need to play 3 sound files at once (for each door).

In my game each of the room-doors in the building has its own channel to play sounds.

bye
Ron


Derron(Posted 2015) [#22]
Ok, here is a simple channel pool including an example.



if you prefer colored code visit my frameworks page:
tchannelpool:
https://github.com/GWRon/Dig/blob/master/base.sfx.channelpool.bmx
sample:
https://github.com/GWRon/Dig/blob/master/samples/channelpool/channelpool.bmx

for your code this means, that you need some slight modifications (no check for already playing etc.).

I will post a modified version of the code soon.


EDIT: here we go, your code incorporating the channel pool and another adjustment (reordered volumeMod-calculation and volume-adjustment)




EDIT2: I extended my TChannelPool to enable "protection" of certain channels (so the "random overwrite of existing channels with channelLimit enabled" wont return these channels -> like "backgroundMusic"-channels). I also created some more convenience-accessors, although I do not like them for this short type names (they are useful to shorten code for the purpose of reclaiming a bit of overview in your code).

Also try to NOT create too long lines of code - most editors present you a vertical line (80 chars) which is a good length of a code line. This is more important if you share your code with others (smaller screens) or want compare DIFF-files (left and right side showing differences between files).
I know this is hard some times but maybe worth to give a try. It eases the path to detect mistakes because it allowes your eyes to focus on a smaller area of the screen (or allows for bigger font sizes :p).

bye
Ron


Takis76(Posted 2015) [#23]
Your code looks nice , is little complex and I forgot to send you the type of those doors.

Type My_doors

	Field x:Byte 'position X on the map
	Field y:Byte 'position Y on the map

	Field dist_x1:Int 'Distance calculation for horizontal doors
	Field dist_y1:Int
	Field dist_x2:Int 'Distance calculation for vertical doors
	Field dist_y2:Int
	Field distance:Int
	Field direction1:Int 'sound direction pan for each horizontal door
	Field direction2:Int 'sound direction pan for each vertical door
	
	
	Field Level:Byte 'Which level is the door on

	Field State:Byte '1 opening 2 closing 3 opened 4 closed
	Field Have_button:Byte 'have a button to open or close it
	Field Time_delay:Int 'animation speed
	Field Locked:String 'L= locked U= unlocked
	
	Field Frame:Byte 'sprite animation frame
	Field Locked_with_item:String 'the item or key to unlock the door
	Field Orientation:Byte '1= horizontal or 2= vertical
	Field Graphic:String 'the graphic of the door "01"=Door graphic1 "02"=Door graphic2 etc..
	Field Button_pressed:Byte 'The button was pressed then start the door mechanics
	Field Door_Deadline_time:Int
	
	Field Sound_Pan:Float
	Field Sound_Volume:Float
	Field volumeMod:Float
	Field volumeMod1:Float
	Field volumeMod2:Float
	
EndType

Global Doors:My_Doors[max_levels + 1, max_doors + 1]
For lvl = 1 To max_levels
	For All_Doors = 1 To max_doors
		Doors[lvl, All_Doors] = New My_doors
	Next
Next


Also I replaced all doors. with Doors[Party.Level, All_Doors].
Because I have my own ready made type.
I removed the
'local door:TDoorObject = Doors[Party.Level, All_Doors]
Because I am already have my types.
I have to change my code again.

I created a new file in my project and I copied the code above.
I remove some multiple Local k:String because the compiler have error with duplicate identifier and I put only once in the Function GetRandomChannelKey:String().

Also I removed some Local channel:TChannel and I put on top of the function GetRandomChannelKey:String() too , because the compiler complained about duplicate identifiers.

I need to change the code about the door states because you have changed a little.
The state=1 means the door is opening and plays the opening sound.
The state=2 means the door is closing and plays the closing sound another sound.
The state=3 means the door is opened and stops the animation
The state=4 means the door is closed and plays the shut door sound another one and stops the animation.

It seems the Channel Pool code did very nice work for a draft changing of my code , I will fix few error in states and some duplicated identifiers.
I hear the sound well now without distortions near and far to all doors.

Now I have and the soundpan commands to make the sound hear from the left or right speaker or both speakers if you are in front of the door or back.

I added and another one line
GetPooledChannel(channelKey).SetPan(Doors[Party.Level, All_Doors].Sound_Pan)
The GetPooledChannel command is very nice.

The code below is for sound pan.
		'skip doors with negative and 0 coordinates and continue to next door
		If Doors[Party.Level, All_Doors].x <= 0 Or Doors[Party.Level, All_Doors].y <= 0 Then Continue

		Doors[Party.Level, All_Doors].dist_x1 = Doors[Party.Level, All_Doors].x - Party.x
		Doors[Party.Level, All_Doors].dist_y1 = Doors[Party.Level, All_Doors].y - Party.y
		Doors[Party.Level, All_Doors].distance = Sqr((Doors[Party.Level, All_Doors].dist_x1 * Doors[Party.Level, All_Doors].dist_x1) + (Doors[Party.Level, All_Doors].dist_y1 * Doors[Party.Level, All_Doors].dist_y1))
		Doors[Party.Level, All_Doors].direction = ATan2(Doors[Party.Level, All_Doors].y - Party.y, Doors[Party.Level, All_Doors].x - Party.x)

		'Pan the sound if the party is on specific direction
		If Doors[Party.Level, All_Doors].Orientation = 1
			'The party faces to the North
			If Party.direction = 1 Then
				'The door direction is in front or in back
				If Doors[Party.Level, All_Doors].direction = -90 Or Doors[Party.Level, All_Doors].direction = 90 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = 0 sound_panned = 1
				'The door direction is to the left or the right
				If Doors[Party.Level, All_Doors].direction < - 90 Or Doors[Party.Level, All_Doors].direction > 90 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = -1 sound_panned = 1
				'The door direction is to the right or the the left
				If Doors[Party.Level, All_Doors].direction > - 90 Or Doors[Party.Level, All_Doors].direction < 90 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = + 1 sound_panned = 1
			'The party faces to the South
			ElseIf Party.direction = 2 Then
				If Doors[Party.Level, All_Doors].direction = 90 Or Doors[Party.Level, All_Doors].direction = -90 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = 0 sound_panned = 1
				ElseIf Doors[Party.Level, All_Doors].direction < 90 Or Doors[Party.Level, All_Doors].direction < - 45 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = -1 sound_panned = 1
				ElseIf Doors[Party.Level, All_Doors].direction > 90 Or Doors[Party.Level, All_Doors].direction > - 45 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = + 1 sound_panned = 1
			'The party faces to the West
			ElseIf Party.direction = 3 Then
				If Doors[Party.Level, All_Doors].direction = 180 Or Doors[Party.Level, All_Doors].direction = 0 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = 0 sound_panned = 1
				ElseIf Doors[Party.Level, All_Doors].direction > 0 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = -1 sound_panned = 1
				ElseIf Doors[Party.Level, All_Doors].direction < 0 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = + 1 sound_panned = 1
			'The party faces to the East
			ElseIf Party.direction = 4 Then
				If Doors[Party.Level, All_Doors].direction = 180 Or Doors[Party.Level, All_Doors].direction = 0 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = 0 sound_panned = 1
				ElseIf Doors[Party.Level, All_Doors].direction < 0 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = -1 sound_panned = 1
				ElseIf Doors[Party.Level, All_Doors].direction > 0 And sound_panned = 0 Then Doors[Party.Level, All_Doors].Sound_Pan = + 1 sound_panned = 1
			EndIf
		End If

But this works for only for the first door.
What do I am making wrong?

You need to wear headsets to see the difference from the left and right speaker.
The updated demo is here.
I have disabled the party collision to travel though walls and step left , right and in front of each door to hear the effect (Only in door1).

Click here for updated demo

I still don't understand when I put elseif. Suppose if there is not any if means else.

Supplementary:
You will open only the horizontal doors (North and South doors) not the vertical one , I haven't done it yet. .orientation is the 1=horizontal or 2=vertical doors
:)


Derron(Posted 2015) [#24]
First of all: there is NO need to remove the whole "door = Doors[...]" part just because I wrote a different type name behind "door:".

Just use
local door:My_doors = Doors[Party.Level, All_Doors]

and there you go...


@else
If 10 < 5 then
  print "this if is skipped !"
ElseIf 10 < 8
  print "this elseIf is skipped !"
ElseIf 10 < 11
  print "this elseif is finally run"
Else
  print "in all other situations not catched by aboves if/elseif this is run"
EndIf


Your chain of "ifs" might ignore the "in all other cases" portion. You tend to use "return" to skip further processing of follow up "ifs". The "else if" makes such things needless.


@locals / double definitions
Yeah, I use "SuperStrict" as much as I can, which does not blame such things. Also my code wasnt test compiled (as I miss much your code to do this)...



So ... I modified your code -- and I am pretty sure that your "sound_panned = 0" is the source of your problem with only the first door getting a panning. Once the first door gets a panning, your "sound_panning" is set to "1". The next door then starts with "sound_panning=1" already and therefor would never pass the conditions in the if-clauses.

If you really need such a sound_panned (eg. to check afterwards if a panning took place) make sure, you reset that variable in the head of the for-loop.


		'RON: replace "My_Doors" with whatever is the name of the door
		'     type
		local door:My_Doors = Doors[Party.Level, All_Doors]

		'skip doors with negative and 0 coordinates and continue to next door
		If door.x <= 0 Or door.y <= 0 Then Continue

		door.dist_x1 = Doors[Party.Level, All_Doors].x - Party.x
		door.dist_y1 = Doors[Party.Level, All_Doors].y - Party.y
		door.distance = Sqr((door.dist_x1 * door.dist_x1) + (door.dist_y1 * door.dist_y1))
		door.direction = ATan2(door.y - Party.y, door.x - Party.x)

		'RON: you checked for "sound_panned = 0" in ALL your following
		'     ifs ... so you can do that ONCE for all
		'     -> just add it to the enclosing "if" ... but I do not know
		'        what is the source of "sound_panned" ? if you do not
		'        reset that for EACH door in the loop, only your first
		'        door will get a pan
		'        I assume you included that because your "ifs" are not
		'        catching all situations and therefore multiple adjustments
		'        are run for a single door.
		'If door.Orientation = 1 And sound_panned = 0 

		'Pan the sound if the party is on specific direction
		'If door.Orientation = 1
			'The party faces to the North
			If Party.direction = 1 Then
				'The door direction is in front or in back
				If door.direction = -90 Or door.direction = 90
					door.Sound_Pan = 0
				'The door direction is to the left or the right
				ElseIf door.direction < - 90 Or door.direction > 90
					door.Sound_Pan = -1
				'The door direction is to the right or the the left
				'RON: there is no need to check for directions: you only
				'     have front, back, left and right as options, and
				'     you already checked for "front/back/left"
				Else
					Then door.Sound_Pan = + 1
				EndIf
			'The party faces to the South
			ElseIf Party.direction = 2 Then
				'RON: Are you sure about that "-45" ? compared to
				'     "faces to the north" this should be similar, with
				'     left and right switched ?
				If door.direction = 90 Or door.direction = -90
					door.Sound_Pan = 0
				ElseIf door.direction < 90 Or door.direction < - 45
					door.Sound_Pan = -1
				ElseIf door.direction > 90 Or door.direction > - 45
					door.Sound_Pan = + 1
				EndIf
			'The party faces to the West
			ElseIf Party.direction = 3 Then
				If door.direction = 180 Or door.direction = 0
					door.Sound_Pan = 0
				ElseIf door.direction > 0
					door.Sound_Pan = -1
				Else
					door.Sound_Pan = + 1
				EndIf
			'The party faces to the East
			ElseIf Party.direction = 4 Then
				If door.direction = 180 Or door.direction = 0
					door.Sound_Pan = 0
				ElseIf door.direction < 0
					door.Sound_Pan = -1
				Else
					door.Sound_Pan = + 1
				EndIf
			EndIf
		End If


Also pay attention to the "south"-part, as it seems to contain a mistake (-45, 45 compared to "north" with -90, 90).



@ChannelPool
Glad it is of help ... but that also proofs that your code contained some flaws regarding the channels (and not the blitz-modules).


PS: I wondered a bit about your code format:


My Blitzcompiler blames the first "elseif" there.
I used this test:
If 1 < 10 Then Print "Ok"
ElseIf 2 < 10 Then Print "ok2"
Else Then Print "ok3"


I know you are able to use a single-line if "if x then do" but you cannot concatenate with "elseif" on a new line. For this you need to separate "condition" and action like I did in the code above and below.

If 1 < 10
  Print "Ok"
ElseIf 2 < 10
  Print "ok2"
Else
  Print "ok3"
EndIf




PPS: If you post such "wide" code portions, use the {codebox} forumcode instead of the {code} variant - this enables scrollbars on both axis. This is nicer for people without fullhd-resolution.


bye
Ron


Takis76(Posted 2015) [#25]
You are right , with the south direction code ,
if the door direction if less than minus 45 means it will be less than 90 too and
when the door direction if greater than 90 it will be also greater then minus 45 so i removed the less than minus 45 and greater than -45 code :P

I will not used a single door object because I would like to see each time my whole array of my door type.
Also you use

local door:TDoorObject = Doors[Party.Level, All_Doors]

But my doors needs to be global and I am already have initialized my doors on my types in other source file.

Your code worked perfectly and now all of my doors have 3D sound and I can hear them near and far and in my left and right speakers.
You deserve a copy of my game when it finishes and your name in my credits. :)


I will try to use the same sound code for my monsters and other sound source for my game.

About the SuperStrict , I will not use it because it drops errors to other codes which I don't see any error.
Also SuperStrict not allows you the goto command.


Derron(Posted 2015) [#26]
Goto ... there is no need to use it ... in no way.

SuperStrict errors: post the portion it errors out and I will try to solve it.


@single door objects
I do not create a "new" door or so ... I just create another reference to the object in the array.

So the only moment you need to access "Doors[level, all_doors]" is if you want to remove a door from the array (or "null" it there). I assume you have a misconception about globals and local variables referencing them.

Such references allow to save processing time. Eg. you could do a "GetPooledChannel(name)" each time - or just store the channel in a local variable for the time of the "loop".

Imagine "GetComplexCalculationResult()" needs 20 ms each time it is called. Now in your code you use that call instead of using a cached result. 20 times used sums up to 400ms, but with the cache you stay at 20ms for the one time calculation.

In this case the performance isn't the reason of my change, it is the shortening of code. Why? You are at a coder level in BlitzMax which still fights with some errors here and there. And a shorter line of code surely eases the process of detecting errors just by viewing it.


Another hint: your door-type could store some helping functions - eg. to return the distance to a given coordinate. Or to return the direction to another object by a given coordinate + viewing direction.

Why? This shortens the code of the function maintaining sounds, animation etc. . It separates functionality and makes it easier to reuse code for other things instead of copying code to here. Also it eases again the readability in more complex portions of your source code.

The earlier you begin teaching yourself the oop-way and benefits of BlitzMax (methods etc.) the more you will improve dev-speed-wise and maybe even enjoy the language a bit more.


Ok, enough "teaching lesson" for now ... post your SuperStrict-errors and we will see if I can be of help.


bye
Ron


Takis76(Posted 2015) [#27]
This superstrict generated errors in places there were no errors.

For example:

Compile Error: Expression of type 'String Array' cannot be invoked

At code:

I don't see any error there.
The array variable was:



This is one example of lots of errors appeared from nowhere.


Derron(Posted 2015) [#28]
Because you try to run "levels" as a function/method ... just look a bit more closer and you see: you mixed "( )" and "[ ]".

If levels(....) is like calling "my array definition"().

Replace
If levels(Party.level, Party.x, Party.y - 1, 1) <> "00"

with
If levels[Party.level, Party.x, Party.y - 1, 1] <> "00"


and the error will be gone.

- I am really sure that the content of this "if ...endif" causes some bugs in the way you use it now - it is either NEVER run or EVERYTIME ... depending on how bcc compiles this ahem.. "stuff".


Up to the next error...


PS: for these short codes, {code} is still the better solution (as it does not have this min-height definition when displayed in the browser).

{codebox} is good for "long lines" to not break out of the posting "default width" (100%) and for codes with many lines.


bye
Ron


Takis76(Posted 2015) [#29]
Ooop it seems I had a type with those brackets. Also I used {codebox} to post my question.
I will fix these brackets and I will tell you if there is any other error.
Why the compiler didn't warn me?

I fixed a lots of typo error with ( instead of [
I fixed a lots of missing or misspelling variables.

And it compiled with superstrict :P


Takis76(Posted 2015) [#30]
I have to do one small fix in sound when I am entering in stairs and changing level with the new code , the sound is not fading out.
If I will fix and this one , this version is free of bugs until the next one :P


Derron(Posted 2015) [#31]

I fixed a lots of typo error with ( instead of [
I fixed a lots of missing or misspelling variables.



that is why I prefer (Super)Strict ... misspelled variables can lead to really unsuspected behaviour.

Glad it works better and better.

bye
Ron