Collision detection or variable call problem

63 Views Asked by At

I've started to create a simple open-world game using the arcade module and maps created with Tiled Map Editor. I'm already a bit advanced but I'm having a problem. I've looked everywhere on the internet but can't find anything... Here's my problem: the character moves with the arrow keys, the map ground is divided into two categories: grass and paths (for the moment), and the character detects which ground he's on and if he's on a path he moves twice as fast. But it turns out that if you're on a path and you go onto grass, your speed won't change once you're on the grass. In other words, the character doesn't detect the ground until you release the key and press again. If you could help me, that would be great! I've already asked this question on https://openclassrooms.com/forum/sujet/probleme-de-detection-de-collision-c00dc#message-94985889 but nobody's found the solution...

import arcade
 
class MyGame(arcade.Window):
    def __init__(self):
        ###
 
    def setup(self):
        ###
    def on_draw(self):
        ###
 
    def on_key_press(self, key, modifiers):
        if key == arcade.key.UP:
            self.player_sprite.change_y = self.speed
            self.player_sprite.change_x = 0
            self.player_sprite.texture = arcade.load_texture(self.texture_paths["up"])
        if key == arcade.key.DOWN:
            self.player_sprite.change_x = 0
            self.player_sprite.change_y = -self.speed
            self.player_sprite.texture = arcade.load_texture(self.texture_paths["down"])
        if key == arcade.key.LEFT:
            self.player_sprite.change_y = 0
            self.player_sprite.change_x = -self.speed
            self.player_sprite.texture = arcade.load_texture(self.texture_paths["left"])
        if key == arcade.key.RIGHT:
            self.player_sprite.change_y = 0
            self.player_sprite.change_x = self.speed
            self.player_sprite.texture = arcade.load_texture(self.texture_paths["right"])
 
    def on_key_release(self, key, modifiers):
        if key == arcade.key.UPorkey == arcade.key.DOWN:
            self.player_sprite.change_y = 0
        if key == arcade.key.LEFTorkey == arcade.key.RIGHT:
            self.player_sprite.change_x = 0
 
    def center_camera_to_player(self):
        ###
 
    def update(self, deltatime):
       ways_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.scene[LAYER_NAME_WAYS])
 
       if ways_hit_list:
           self.speed = 2
       else:
           self.speed = 1
        
       ###
 
def main():
    window = MyGame()
    window.setup()
    arcade.run()
 
if __name__ == "__main__":
    main()

I did a few tests, and I found something: the speed does change depending on the ground the character is on. The problem is that when I press a key to move, the speed taken into account for the entire movement until the key is released is the speed recorded just as the key was pressed... I've tried moving the function to a different place and creating a new function to call up speed detection, but nothing works...

1

There are 1 best solutions below

1
Alderven On BEST ANSWER

You need to recalculate player speed on every iteration (not only at the beginning of the move). Simple example (green background is low speed, red - high speed):

enter image description here

Code:

import arcade


class Game(arcade.Window):
    def __init__(self):
        super().__init__()
        self.player_sprite = arcade.Sprite(':resources:images/animated_characters/male_person/malePerson_idle.png', center_x=100, center_y=300)
        self.left_pressed = False
        self.right_pressed = False
        self.up_pressed = False
        self.down_pressed = False

    def on_draw(self):
        self.clear()
        arcade.draw_rectangle_filled(200, 300, 400, 600, arcade.color.GREEN)
        arcade.draw_rectangle_filled(600, 300, 400, 600, arcade.color.RED)
        self.player_sprite.draw()

    def update_player_speed(self):
        self.player_sprite.change_x = 0
        self.player_sprite.change_y = 0

        if self.player_sprite.center_x < 400:
            speed = 5
        else:
            speed = 10

        if self.up_pressed and not self.down_pressed:
            self.player_sprite.change_y = speed
        elif self.down_pressed and not self.up_pressed:
            self.player_sprite.change_y = -speed
        if self.left_pressed and not self.right_pressed:
            self.player_sprite.change_x = -speed
        elif self.right_pressed and not self.left_pressed:
            self.player_sprite.change_x = speed

    def on_key_press(self, key, modifiers):
        if key == arcade.key.UP:
            self.up_pressed = True
            self.update_player_speed()
        elif key == arcade.key.DOWN:
            self.down_pressed = True
            self.update_player_speed()
        elif key == arcade.key.LEFT:
            self.left_pressed = True
            self.update_player_speed()
        elif key == arcade.key.RIGHT:
            self.right_pressed = True
            self.update_player_speed()

    def on_key_release(self, key, modifiers):
        if key == arcade.key.UP:
            self.up_pressed = False
            self.update_player_speed()
        elif key == arcade.key.DOWN:
            self.down_pressed = False
            self.update_player_speed()
        elif key == arcade.key.LEFT:
            self.left_pressed = False
            self.update_player_speed()
        elif key == arcade.key.RIGHT:
            self.right_pressed = False
            self.update_player_speed()

    def update(self, deltatime):
        self.player_sprite.update()
        self.update_player_speed()


Game()
arcade.run()