Problem incrementing counter when car enters an area

Hi im a beginner to using panda,
What im trying to do is to get a text label to update when my car drives into a certain area.
Heres a snippet of my code:

    def checkpoint(self):
        self.cp = self.loader.loadModel("models/box")
        self.cp.setPos((random.randint(-80, 80)), (random.randint(-80, 80)), -1)  # The map of the game is roughly 80x80
        cpLabel = DirectLabel(pos=(-0.9, 0, -0.8))
        counter = 0
        cpLabel['text'] = "Checkpoint: 0/5"

        def cpTask(self, task, counter, cpLabel):
            if counter < 5:
                if (self.cp.getY() + 10) > self.PlayerNP.getY() > (self.cp.getY() - 10) and \
                        (self.cp.getX() + 10) > self.PlayerNP.getX() > (self.cp.getX() - 10):
                    counter = counter + 1
                    cpLabel['text'] = "Checkpoint: " + str(counter) + "/5"
                    return counter, cpLabel
                return Task.cont
                return Task.done

        taskMgr.add(cpTask, 'cpTask', extraArgs=[self,counter, cpLabel], appendTask=True)

If you could help me get it working that would be much appreciated.

Hmm… I think that I may see two potential problems:

First, it looks like you’re placing your check-points on the X-Y plane, but you’re testing positions on the X-Z plane.

Thus, if the car is moving on the X-Y plane, and has a Z-value that’s either greater than 9 or less than -11, then it may never fulfill the condition for incrementing the counter.

And second, I note that you’re setting the value of “counter” and the text of “cpLabel” at the start of “cpTask”. This means that every time that the task updates and the method is run, those values will be reset, and the counter will never exceed 1.

(By the way, note that as an alternative to calling “taskMgr.remove”, you can end a task by having it return “Task.done”, I do believe.)

I’ve edited the code above but it still doesn’t seem to work :confused:

Hmm… You’re currently passing “counter” into the task as an “extraArg”.

However, when an object of a simple type (like an integer) is passed into a method, it’s evaluated immediately, and its value is passed in, rather than a reference to it. Thus you’re not actually passing in the “counter” object, just the value of “counter” at the time that you called “add”.

As a result, I would expect that the version of “counter” that you have in the task-method would still always have a value of 0 when the task-method runs, and thus would again never exceed 1.

(On the other hand, “cpLabel”, being a non-simple type, should indeed be passed by reference and thus should work as expected.)

I see that you’re using “self.” in some places, which indicates that this is taking place within a class of some sort, and that the variables so-marked are members of that class. What I suggest, then, is this:

Make “counter” (and perhaps “cpLabel”) members of the class, too. This would allow you to access “counter” (and “cpLabel”, if included) from within “cpTask” (since “cpTask” is a member of the same class, presumably)–and you would be accessing the variables themselves, not their values at some previous time. Thus changes to “counter” will not be restricted to the bounds of the task-method, and thus will not be lost when it finishes.

By the way, have you confirmed that the code that you use to detect the car’s presence at a checkpoint is working as intended? (It looks fine to me, but it seems worth testing, just in case, and so that we can eliminate it as a potential issue.) You could perhaps place a simple “print”-statement within the relevant “if”-statement, thus showing whether that section of code is reached when you want it to be reached.

The if statement is definitely reached. I have noticed that the self. parts in the if aren’t colour coded in the IDE i’m using. If i un indent cptask taskMgr won’t work but the self. parts do get colourised. I don’t know how to get around that.

It’s not clear to me whether the colourisation is in fact indicative of a problem, I’m afraid. :/

As to un-indenting “cpTask”, doing so may break things simply because your call to “taskMgr.add” is below “cpTask”. Un-indenting “cpTask” thus results in the call to “add” becoming part of “cpTask”, and thus not being called (because “cpTask” is only called when the task is run, and the thing that makes the task run has ended up in “cpTask”).

If this is the problem, then a simple fix might be to just move the call to “taskMgr.add” to a point above “cpTask”, and then un-indent “cpTask”.

All that said… did you try my suggestion of making “counter” (and possibly “cpLabel”) members of the class that you’re working with?

This is what i’ve changes my code to now, this still doesn’t work

     def checkpoint(self):
        self.cp = self.loader.loadModel("models/box")
        self.cp.setPos((random.randint(-80, 80)), (random.randint(-80, 80)), -1)  # The map of the game is roughly 80x80
        self.cpLabel = DirectLabel(pos=(-0.9, 0, -0.8))
        self.cpLabel['text'] = "Checkpoint: 0/5"
        self.counter = 0

        taskMgr.add(self.cpTask, 'cpTask')

    def cpTask(self):
        if self.counter < 5:
            if (self.cp.getY() + 10) > self.PlayerNP.getY() > (self.cp.getY() - 10) and \
                    (self.cp.getX() + 10) > self.PlayerNP.getX() > (self.cp.getX() - 10):
                self.counter = self.counter + 1
                self.cpLabel['text'] = "Checkpoint: " + str(self.counter) + "/5"
                return self.counter, self.cpLabel
            return Task.cont
            return Task.done

Why are you returning “self.counter” and “self.cpLabel” from your task?

I was given advice to do that. :confused: I’ve removed it now
I did some more playing around and testing and I think I’ve found the problem. I put a print statement on each of the coords the CP ones work fine but self.playerNP ones don’t they just stay at 0 when I control my vehicle still

Ah, I see!

The thing is, in the case of a task-method the return-value determines whether the task runs again on the next update. Since you were returning something other than “Task.cont”, I would expect the task to cease working after the first time that it successfully detects a checkpoint.

Ah! Well done on finding what seems likely to be the source of the problem!

In that case, it seems likely to be worth looking at the code that sets up “playerNP”, and the code that moves your vehicle…

Everything’s working now, thanks for the help!

1 Like

Ah, I’m glad that you got it sorted out, and I’m glad if I’ve been of service. :slight_smile: