Out of collision

This is the procedure file
https://jmp.sh/mKPFufx
https://jmp.sh/8PxH7Oj

These are two complete files of my game. Now I have a problem: the wooden character has a great chance to rush out of the fence.

When dealing with the collision between the woodman character and the fence, I used the list collision processing method, and by judging whether the collision list is greater than 0, I realized the change of the speed and the movement direction of the woodman character. But the result of the operation is that the woodman character and the fence will collide twice, so that he will move out of the boundary. I tried to change the delay of changing the direction, but it seems that It doesn’t work.

The following is the problem code. The collider mask is set to prevent the interference of player character’s ray Collider, but it has not been improved.
I don’t know if the problem is here.

class Enemy_woodmen(ActorObject):
    def __init__(self,pos):
        ActorObject.__init__(self,
                             pos,
                             "woodmen",
                             {
                                 "walk": "woodmen_walk",
                                 "stand": "woodmen_stand",
                                 "die": "woodmen_die",
                                 "attack": "woodmen_attack"
                             },
                             10,
                             40,
                             1,
                             'wood'
                             )
        self.detectiondistance = 100
        self.changeQueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.collider, self.changeQueue)
        self.accelerationw = -300
        self.acceleration = 300
        self.standard = Vec2(0, -1)
        self.varystandard = Vec2(0, -1)
        self.changeWaitTimer = 1
        self.change = True
        self.HarmValue = -5
        self.attackWaitTimer = 0.3
        self.attackToxiaoke = False
    def update(self, player, xiaoke, dt):
        ActorObject.Move(self, dt)
        position_vevtor = player.actor.getPos() - self.actor.getPos()
        position_vevtorXY = position_vevtor.getXy()
        distanceToplayer = position_vevtor.length()
        position_vevtorXK = xiaoke.actor.getPos() - self.actor.getPos()
        position_vevtorXKXY = position_vevtorXK.getXy()
        distanceToxiaoke = position_vevtorXKXY.length()
        self.actor.enableBlend()  
        if self.changeQueue.getNumEntries() > 0 and self.change:
            self.accelerationw = -self.accelerationw
            self.varystandard = -self.varystandard
            self.change = False
        else:
            self.changeWaitTimer -= dt
            if self.changeWaitTimer <= 0:
                self.changeWaitTimer = 3
                self.change = True
        if self.attackToxiaoke:
            if distanceToxiaoke > self.detectiondistance:
                self.walking = True
                self.velocity.addY(self.accelerationw*dt)
                self.heading = self.standard.signedAngleDeg(self.varystandard)
                self.actor.setControlEffect('walk', 0.7)
                self.actor.setControlEffect('attack', 0.3)

This is what the game needs
https://jmp.sh/4jteO9e

Without checking too carefully, I’ll admit, I suspect that part of the problem is that, when a collision occurs, you’re not immediately placing the character outside of the fence’s collision-object. As a result, even though the character’s velocity is changed, it may nevertheless not “escape” the fence before a new collision is detected, leading to the issue that you’ve observed.

If feasible in your project, I think that a CollisionHandlerPusher might suit your purposes better than a CollisionHandlerQueue. CollisionHandlerPusher specifically prevents collision objects from intersecting (where it can do so, at least), thus (in general) preventing the issue that you’re seeing.

Better yet, CollisionHandlerPusher inherits from CollisionHandlerEvent, allowing you to have a method be called when a collision occurs. You could thus move your velocity-updating code into such a method, and so keep that behaviour.

OK, I’ll test it. Thank you very much!

In addition, another problem is that I found that only one collision processing method can be added to a collision body. By default, it seems that only the last added method is recognized. For example, the following two collision processing I added will only take effect.

class Enemy_woodmen(ActorObject):
    def __init__(self,pos):
        ActorObject.__init__(self,
                             pos,
                             "woodmen",
                             {
                                 "walk": "woodmen_walk",
                                 "stand": "woodmen_stand",
                                 "die": "woodmen_die",
                                 "attack": "woodmen_attack"
                             },
                             10,
                             40,
                             1,
                             'wood'
                             )
        self.detectiondistance = 100
        self.pusher = CollisionHandlerPusher()
        self.pusher.addCollider(self.collider, self.actor)
        base.cTrav.addCollider(self.collider, base.pusher)
        self.changeQueue = CollisionHandlerQueue()
        base.cTrav.addCollider(self.collider, self.changeQueue)
        
        self.accelerationw = -300
        self.acceleration = 300
        self.standard = Vec2(0, -1)
        self.varystandard = Vec2(0, -1)
        self.changeWaitTimer = 1
        self.change = True
        self.HarmValue = -5
        self.attackWaitTimer = 0.3
        self.attackToxiaoke = False
    def update(self, player, xiaoke, dt):
        ActorObject.Move(self, dt)
        ...

That’s correct, indeed. (I don’t think that it’s a bug, as such; just a limitation of the collision system.)

But then, that’s where tricks like using a CollisionHandlerPusher as a CollisionHandlerEvent prove useful: you can have a handler that both keeps objects out of obstacles and provides events that allow you to react to collisions.

OK, I see. Thank you very much!

1 Like