Panda3d hangs (with no error message) when altering variables within the same function (Solved)

STORY: Hello to the Panda3d Community, I,m new here, and this is my first post, you see i,m a beginner at python and panda3d, but I really wanted to make a 3d game that would not be hard on my laptop, so I looked up a couple of python tutorials to get a bit of what is going on.

So I just went with it on panda3d following the tutorial given in the manual on this website, I managed to get a test plane as well a test model that I created both in blender to run in panda3d, so I started work on creating a sample game, I was going to create a sample based on the popular nintendo 64 game “Super Mario 64” since it was such a simple 3d game.

Thanks to the sample “Roaming Ralph” I was able to look at the code and understand what was happening (mostly), so I copied (typed myself) some code from it into my own script to get things going, everything was fine until it came to the movement, I tired some mathematical concepts to emulate Mario’s movement, but panda didn’t want to play ball for some reason.

Now, I do not know if it had anything to my inexperience with python, but I wonder if functions have a limitation with dealing with variable changes or something, I later discovered that global variables work to a certain extent, so I eventually settled with changing the character rotation being a increment of rotational positions leading to one final position.

Which looked ugly, but if it worked, it worked, so I moved onto the camera, roaming ralph’s camera is great but needed a bit of tweaking, like for example if you rotated the camera and tried to move in a direction, the character would move in the direction based on the character’s point of view, not the camera’s point of view, which is not the case in Mario 64.


PROBLEM: so my problem is, I set up 2 global variables, and created a question where it asks if the camera controls are pressed, then it asks which of them are pressed, if one of the keys were pressed it moves the camera and copies that movement as a calculation to variable 1.

Then when you let go of the keys, the “if not” statement of that question was to kick in and record the variable 1 result into variable 2, the variable 2 is then transferred to the movement code, the idea was to track camera movement but not alter the directional perspective until the camera stopped, then reshape player movement based on where the camera is facing just like in Mario 64

By calculating based on the last recorded movement of the camera, that is where I would have went, if I did not run into this problem, you see I tested this theory on panda3d, and it hanged not even giving a error, it was not python because the python IDLE went off without a hitch, it seemed to stem from panda itself and what is worse, is, I did not get a error message to tell what I did wrong.

So I tweaked the code just to use simple numbers as I thought “self.camera.gettX()” which was my original attempt, was outputting a vary large number that was causing panda3d to freak out, but no, even a simple number still made panda3d hang without a error message, so I ask what do you think went wrong, was it me and my inexperience with python?

Or is there a quirk in panda that I do not know about, that causes panda not to work with variables inside functions? sadly I would have provided my complete project but the forum would not let me upload due to me being a new user, I could upload it on my website if requested, and to anyone who listens (and helps) thanks vary much, and have a nice day.

Hi, welcome to the community! :slight_smile:

Would it be possible for you to share your code? This would be the easiest way for us to be able to see if there is anything wrong about the way you’re doing things, or perhaps see if there might be a bug in Panda3D.

I’ve raised your trust level on the forums, so you should be able to upload attachments now.

sorry for the long post, sure, but it still says I cannot upload.errordemo.zip (374.7 KB)

Edit: okay I just did, I needed to log out and in the restart the status, thanks

what you are looking for is variable 1 which is “CamPar” and variable 2 which is "CamPos"which are set up on line 150 and 151 as global variables, A and D move the camera which the question takes place on line 160. the movement code itself is located on line 221.

I believe I found the issue, it was the “while” statements, maybe in a function, it causes it to hang?, I have switched code to use a number to track movement instead of stating direct numbers, sadly I found a new problem, if anyone is up to task, it seems that a if statement is not working hmmm.

Forgive this code is meaningless:

    if self.keyMap["east"]: 
        while not self.pactor.getH() == -90:
                if self.pactor.getH() == 0:
                    self.pactor.setH(-15)
                    self.pactor.setH(-30)
                    self.pactor.setH(-45)
                    self.pactor.setH(-60)
                    self.pactor.setH(-75)
                    self.pactor.setH(-90)
                if self.pactor.getH() == -45:
                    self.pactor.setH(-60)
                    self.pactor.setH(-75)
                    self.pactor.setH(-90)
                if self.pactor.getH() == -135:
                    self.pactor.setH(-120)
                    self.pactor.setH(-105)
                    self.pactor.setH(-90)
                if self.pactor.getH() == -180:
                    self.pactor.setH(-165)
                    self.pactor.setH(-150)
                    self.pactor.setH(-135)
                    self.pactor.setH(-120)
                    self.pactor.setH(-105)
                    self.pactor.setH(-90)
                if self.pactor.getH() == -225:
                    Turn = True
                    self.pactor.setH(-90)
                if self.pactor.getH() == -270:
                    Turn = True
                    self.pactor.setH(-90)
                if self.pactor.getH() == -315:
                    Turn = True
                    self.pactor.setH(-90)

This is equivalent to:

    if self.keyMap["east"]: 
        while not self.pactor.getH() == -90:
                if self.pactor.getH() == 0:
                    self.pactor.setH(-90)
                if self.pactor.getH() == -45:
                    self.pactor.setH(-90)
                if self.pactor.getH() == -135:
                    self.pactor.setH(-90)
                if self.pactor.getH() == -180:
                    self.pactor.setH(-90)
                if self.pactor.getH() == -225:
                    Turn = True
                    self.pactor.setH(-90)
                if self.pactor.getH() == -270:
                    Turn = True
                    self.pactor.setH(-90)
                if self.pactor.getH() == -315:
                    Turn = True
                    self.pactor.setH(-90)

You probably expect a smooth turn, but it does not work.
You can watch this source, I think it will give you the right idea about the implementation of the movement of the character.

Demo: https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/panda-rpg-tutorial/source-archive.zip

Thank you for the suggestion, but the problem I having was the “while” statement, for some reason my copy panda3d did not want to play it, I switch it out for just a “if” statement because I was not sure panda was going to repeat the code if I continue to hold down the directional key (but it worked).

Just earlier today, I changed my code base back to using single number to map out the rotation (as a different way to rotate smoothly, as of now I,m still working on it). I wish I just knew the exact numbers, I will take a look at your example though, to see if it will give me any clues. Much thanks for the tip.

Regarding the hang itself, at a guess, I imagine this happened because your program never managed to get out of that while-loop.

Specifically, while you do set the Actor’s h-value to “90”, I think that you’ll find that due to either the maths involved or simple imprecision in floating-point numbers, when you check its h-value later, it’s not quite 90 degrees. Thus the test for equality fails, and the code runs through the loop again and again.

To check this, try reverting your code to the form that uses the while-loop, and then have it print out the h-value of the Actor. Something like this:

if self.keyMap["east"]: 
        while not self.pactor.getH() == -90:
                print self.pactor.getH()
                # or print (self.pactor.getH()) if you're using Python 3
                <the rest of your code here...>

I think that you’ll find that it repeatedly prints out values like “89.99999999”, or “90.00000001”, etc.

(To be clear, this doesn’t reflect Panda having an issue with while-loops, or while-loops within functions. Floating-point issues are generally something to beware of when dealing with values that might be floating-point, and while-loops can easily trap your code.)

I think it is also important to note that Panda calls your task function expecting it to return right away, so that it can get on with other things, such as rendering. The changes you apply in this task will only take effect once you return from the function and Panda continues to render the frame. Then, in the next frame, it call the task again asking you to set the values for the next frame, etc.

The moment you add a while loop to that function that does not return, it will simply block the entire render loop; you never return from that task, so Panda will never be able to call other tasks, such as the task that renders a single frame to the window.

That said, you can yield from your task to let Panda continue and get back to that point in the task in the next frame, or you can even use await in a coroutine task, but these are quite complex concepts to grasp. If you are trying to implement a gradual rotation, it is probably better to either use an interval, or establish a target angle in a variable and rotate the actor a little closer towards it every time the task runs.

I know from the Manuel panda3d has it’s own debugging tools, in such tools, is there a feature to display exact numbers? I got a hint that the number would be something large because from the original “roaming ralph” demo rotation was achieved from multiplying something like 300 to the time spent running (game wise), so it had to be something insane to just cause a small rotation.

I,m wondering if I should include a period and seven digits just like you showed me to achieve my rotation hmmm.

Edit: looking at the script, you would see that I tried such a thing with my own debugging code, by taking the roaming ralph instructional text and changing to debugging information, but I did not get far, because panda hanged, I still need to figure out what went wrong, thanks for the insight on the number length, I thought I was much shorter, this will help.

Oh, okay, so I trapped myself into that loop, so yielding would tell panda to pass the while question once every frame to check on it to see if the question was true, instead halting everything until said question was true, is this what I,m getting so far? thanks for the advice.

If I’m looking at the right place in Roaming Ralph’s code, that’s not quite what’s happening, I believe: It’s not multiplying 300 by the time that the game has spent running, but by the time since the last update. Since the game updates very quickly, the time between updates is very small, and so we multiply it by a large number to get a reasonable rate of rotation, if I’m not much mistaken.

(If the game is running at 60 frames per second, then the value of “dt” in a given update should be about 0.0167–that is, about 16.7ms–if I’m not much mistaken. Multiplying this by 300 then gives us a rotation of about 5 degrees.)

I don’t think that this would be likely to be reliable. Instead, I recommend being wary about testing for equality when dealing with floating-point numbers. Rather than testing for equality, you might test for how close the h-value is to the target. In short, once the difference between the two values is less than some very small value, allow the test to pass. (But watch out for negative values–you may find the “abs” function, which gives an absolute value, to be useful here.)

As rdb said, since the code was getting stuck in the while-loop, Panda wasn’t getting to update. Thus the on-screen text was presumably not being updated.

This shouldn’t be a problem for Python print-statements, such as I suggested: you should still see output from them in the console (or your IDE’s output panel, if available).

More or less (aside from the problem with floating-point values, as I mentioned above). However, I’m inclined to agree with rdb that it would likely be simpler to just update the Actor a little bit on each update via a “target angle”, or to use an interval and have Panda do the work for you.

oh, so if I used “number period 4 digit number” to manipulate, there would be results, I was using negative numbers because they worked in the test I was conducting for some reason, I got a hint that panda was not calculating in degrees as I would have wished, it seems I need to do a bit more math in my idea then, once again, thanks for the insight.

Edit: I did not read the post right, you said mili seconds my bad!

It’s my pleasure. :slight_smile:

A few points of clarification, if I may:

When I referred to negative numbers, I was referring to the results of comparing two floating-point numbers, rather than the target that you were using. Let me illustrate:

Let’s say that I want to end a loop when a floating-point value is close to 0.5. I might have a test like this:

while someValue - 0.5 > 0.0001:
    #  Whatever I want to have happen in the loop follows here

When “someValue” is, say, 0.7, we get 0.7 - 0.5, which is 0.2. 0.2 is greater than 0.0001, so the loop runs. However, if the value in “someValue” drops to, say, 0.500001, we get 0.500001 - 0.5, which is 0.000001. This is less than 0.0001, and so the loop ends.

However, there’s a problem: what happens if the value in “someValue” drops below 0.5? For example, let’s say that its value is -0.7. -0.7 - 0.5 is -0.9. Being negative, -0.9 is less than 0.0001, and so the loop ends–even though -0.7 isn’t sufficiently close to 0.5.

So, instead of just subtracting one value from the other, we take the absolute value of the subtraction–in a sense, we throw away the “negative sign”. Like this:

while abs(someValue - 0.5) > 0.0001:
    #  Whatever I want to have happen in the loop follows here

The “abs” function returns the “absolute value” of the number given to it–simply put, that number, but positive.

Panda does indeed work in degrees, primarily. (I’m guessing that you’ve figured this out, but I wanted to mention it just in case you weren’t aware of it.)

I think I got it, adding positive numbers into negative would reduce the negative number kind of like a meter, anyway, I,m glad panda uses degrees numbers, but how would that be typed? would the number style work like this? “0.0”, I just wanted to stay on simple terms for now and use simple numbers.

I know the camera code from the roaming ralph demo features numbers in the style of “X.X”, so I have begun to test those today, I,m starting to get a clearer picture of what is going on. thanks for the reply.

Edit: the numbering style works, adding got the character to rotate counter clockwise, many thanks for everyone who had helped.

Once again, thanks to everyone for had helped, I just wanted to show my progress, and to confirm that this issue has been solved.

download to fixed demo:jnpfixeddemo.zip (454.8 KB)

Edit: sorry forgot to post the controls.
the directional keys move the character.
“J” makes the character Jump.
“A” and “D” rotate the camera.
“W” and “X” zooms in and out the camera.