• xvid

    @ccc makes no difference in this case. Have tried it already.

    posted in Pythonista read more
  • xvid

    @cvp Thanks! I tried it but unfortunately this doesn't help much the player is now even more glitching. I'll read through the tutorial which @JonB mentioned maybe this give me some more insight.

    posted in Pythonista read more
  • xvid

    @cvp I tried this before no good result unfortunately but thanks :)

    @JonB thanks for the link! Really appreciate this, will have a look :)

    posted in Pythonista read more
  • xvid

    UPDATE:

    So, I managed to create a function (based on this) which indicates which edge of the wall is hit called HitTest.

    Now, in the first option (current state) the problem is that I can't jump anymore.
    The other option: when I change in the Player class the jump method from if touch.location in buttons[2].bbox and self.onGround to if touch.location in buttons[2].bbox, which basically means I don't have to be on the ground to jump, gravity & jump is working fine. The only problem now is as soon as I move and jump I can glitch through the walls.

    Both option aren't optimal but the last one is definitely closer to my aim.

    Any tipps? Or did I miss something crucial?

    Here is the code:

    import scene
    from scene import *
    import sound
    import random
    import math
    import level
    import ui
    A = Action
    
    # Constants
    PI = math.pi
    #Screen Size
    SCREEN_W = get_screen_size().w
    SCREEN_H = get_screen_size().h
    # Amount of frames till you can shoot again
    WAIT_TIME = 30
    BULLET_SPEED = 10
    ROTATION_LEFT = PI/2
    ROTATION_RIGHT = 3*PI/2
    # Gravity
    GRAVITY = 4
    
    def HitTest(entity, object, output = 0):
        ''' max_x = right edge, min_x = left edge, max_y = top edge, min_y = bottom edge '''
        rect_1 = entity.bbox
        rect_2 = object.bbox
        if rect_1.max_x >= rect_2.x and rect_1.x <= rect_2.max_x:
            if rect_1.max_y >= rect_2.y and rect_1.y <= rect_2.max_y:
                output = 1
        if output:
            origin_1 = rect_1.center()
            origin_2 = rect_2.center()
            dx = origin_1.x - origin_2.x
            dy = origin_1.y - origin_2.y
            if dx <= 0:
                #print("Hit from Right")
                output_1 = 1
            if dx >= 0:
                #print("Hit from Left")
                output_1 = 2
            if dy <= 0:
                #print("Hit from Top")
                output_2 = 1
            if dy >= 0:
                #print("Hit from Bottom")
                output_2 = 2
            if abs(dx) > abs(dy):
                #print("Hit Right or Left")
                output = output_1
            if abs(dx) < abs(dy):
                #print("Hit Top or Bottom")
                output = output_2 + 2
        return output
    
    class Buttons(SpriteNode):
        ''' Buttons Class '''
        def __init__(self, name, appearance, position, scale, alpha, buttons):
            SpriteNode.__init__(self, appearance)
            self.name = name
            self.position = position
            self.z_position = 3
            self.scale = scale
            self.alpha = alpha
            buttons.append(self)
        def __str__(self):
            return self.name
    
    class Buttons_Text(LabelNode):
        def __init__(self, name, text, button, buttons_text):
            LabelNode.__init__(self, text, font=('Futura', 13), color='white')
            self.name = name
            self.position = (button.position.x, button.position.y - 50)
            self.z_position = 1
            buttons_text.append(self)
    
    class Brick(ShapeNode):
        def __init__(self, name, position, z_position, brick_w, brick_h):
            path = ui.Path.rect(position[0], position[1], brick_w, brick_h)
            ShapeNode.__init__(self, path, '#b7b7b7', 'clear')
            self.name = name
            self.position = position
            self.z_position = z_position
        def __str__(self):
            return self.name
    
    class Map(ShapeNode):
        def __init__(self, walls):
            ''' Generates the map '''
            lines = level.level.splitlines()
            brick_w = 40
            brick_h = 40
            col = 0
            row = 0
            for line in lines:
                for i in line:
                    if i == "W":
                        x = 17 + row * brick_w
                        y = 800 - col * brick_h
                        wall = Brick('Brick', (x, y), 0, brick_w, brick_h)
                        walls.append(wall)
                        row += 1
                    else:
                        x = 17 + row * brick_w
                        y = 800 - col * brick_h
                        row += 1
                col += 1
                row = 0
    
    class Entity(SpriteNode):
        ''' Generate an Entity '''
        def __init__(self, appearance):
            SpriteNode.__init__(self, appearance)
    
    class Bullet(Entity):
        def __init__(self, name, appearance, x, y, rotation):
            super().__init__(appearance)
            self.position = (x, y)
            self.rotation = rotation
        def update(bullets_left, bullets_right):
            for bullet in list(bullets_left):
                new_x = bullet.position.x - BULLET_SPEED
                if new_x >= 0 and new_x <= SCREEN_W:
                    bullet.position = (new_x, bullet.position.y)
                else:
                    bullet.remove_from_parent()
                    bullets_left.remove(bullet)
            for bullet in list(bullets_right):
                new_x = bullet.position.x + BULLET_SPEED
                if new_x >= 0 and new_x <= SCREEN_W:
                    bullet.position = (new_x, bullet.position.y)
                else:
                    bullet.remove_from_parent()
                    bullets_right.remove(bullet)
    
    class Player(Entity):
        ''' Player Class '''
        def __init__(self, name, appearance, position, z_position):
            super().__init__(appearance)
            self.name = name
            self.position = position
            self.z_position = z_position
            self.velocity = Vector2(0, 0)
            self.speed = 5
            self.jump_strength = 100
            self.onGround = False
            # Controls
            self.leftKey = False
            self.rightKey = False
            self.jumpKey = False
            self.shootKey = False
    
        def move_left(self, buttons, touches):
            for touch in touches.values():
                if touch.location in buttons[0].bbox:
                    self.leftKey = True
                    self.velocity.x = -self.speed
                    new_x = self.position.x + self.velocity.x
                    if new_x >= 0 and new_x <= SCREEN_W:
                        self.position = (new_x, self.position.y)
    
        def move_right(self, buttons, touches):
            for touch in touches.values():
                if touch.location in buttons[1].bbox:
                    self.rightKey = True
                    self.velocity.x = self.speed
                    new_x = self.position.x + self.velocity.x
                    if new_x >= 0 and new_x <= SCREEN_W:
                        self.position = (new_x, self.position.y)
    
        def jump(self, buttons, touches):
            for touch in touches.values():
                if touch.location in buttons[2].bbox and self.onGround:
                    self.jumpKey = True
                    self.onGround = False
                    self.velocity.y = self.jump_strength
                    new_y = self.position.y + self.velocity.y
                    action = A.move_to(self.position.x, new_y, 1, TIMING_LINEAR)
                    if new_y <= SCREEN_H:
                        self.run_action(action)
    
        def shoot(self, instance, player_direction, buttons, touches, bullets_left, bullets_right):
            for touch in touches.values():
                if touch.location in buttons[3].bbox:
                    self.shootKey = True
                    if player_direction.position.x < self.position.x and instance.frame_counter >= WAIT_TIME:
                        bullet = Bullet("Bullet Right", 'spc:LaserRed10', self.position.x - 20, self.position.y - 40, ROTATION_LEFT)
                        bullets_left.append(bullet)
                        instance.add_child(bullet)
                        instance.frame_counter = 0
                    if player_direction.position.x > self.position.x and instance.frame_counter >= WAIT_TIME:
                         bullet = Bullet("Bullet Left", 'spc:LaserRed10', self.position.x + 20, self.position.y - 40, ROTATION_RIGHT)
                         bullets_right.append(bullet)
                         instance.add_child(bullet)
                         instance.frame_counter = 0
    
        def check_touch(self, buttons, touches):
            if len(touches.values()) > 0:
                for touch in touches.values():
                    if touch.location not in buttons[0].bbox:
                        self.leftKey = False
                    if touch.location not in buttons[1].bbox:
                        self.rightKey = False
                    if not touch.location in buttons[2].bbox:
                        self.jumpKey = False
                    if not touch.location in buttons[3].bbox:
                        self.shootKey = False
            else:
                self.leftKey = False
                self.rightKey = False
                self.jumpKey = False
                self.shootKey = False
    
        def check_velocity(self):
            #print(self.velocity)
            if not self.leftKey and not self.rightKey:
                self.velocity = Vector2(0, self.velocity.y)
            if not self.jumpKey and self.onGround:
                self.velocity = Vector2(self.velocity.x, 0)
    
        def collision_right(self, player_bbox, w):
            new_x = w.bbox.min_x - self.bbox.w / 2
            self.position = (new_x, self.position.y)
            self.velocity.y = 0
            #print("collide right")
            return
    
        def collision_left(self, player_bbox, w):
            new_x = w.bbox.max_x + self.bbox.w / 2
            self.position = (new_x, self.position.y)
            self.velocity.y = 0
            #print("collide left")
            return
    
        def collision_top(self, player_bbox, w):
            new_y = w.bbox.min_y - self.bbox.h / 2
            self.position = (self.position.x, new_y)
            self.onGround = False
            #print("collide top", self.onGround)
            return
    
        def collision_bottom(self, player_bbox, w):
            new_y = w.bbox.max_y + self.bbox.h / 2
            self.position = (self.position.x, new_y)
            self.onGround = True
            self.velocity.y = 0
            #print("collide down", self.onGround)
            return
    
        def collision(self, player_bbox, walls):
            for w in walls:
                result = HitTest(self, w)
                '''0 : No Collision,  1 : Collision from Right, 2 : Collision from Left, 3 : Collision from Top, 4 : Collision from Bottom '''
                if result == 0:
                    self.onGround = False
                if result == 1:
                    self.collision_right(player_bbox, w)
                if result == 2:
                    self.collision_left(player_bbox, w)
                if result == 3:
                    self.collision_top(player_bbox, w)
                if result == 4:
                    self.collision_bottom(player_bbox, w)
    
        def gravity(self):
            ''' Describes the Gravity'''
            if not self.onGround:
                self.velocity.y = -GRAVITY
                new_y = self.position.y + self.velocity.y
                if new_y >= 0:
                    self.position = (self.position.x, new_y)
    
    class Hitbox(ShapeNode):
        ''' Creates a visible hitbox for an entity based on the bbox of the entity.
            entity = Object, Player, Enemy etc.
            entity_objects = List of objects for that entity
            dw, dh = how much smaller the widht/height of the hitbox should be (based on the bbox of the entity)
        '''
        def __init__(self, entity, entity_objects, dw, dh):
            self.dw = dw
            self.dh = dh
            self.width = entity.bbox.w - self.dw
            self.height = entity.bbox.h - self.dh
            path = ui.Path.rect(0, 0, self.width, self.height)
            ShapeNode.__init__(self, path)
            self.fill_color = 'white'
            self.stroke_color = 'clear'
            self.position = (entity.position.x, entity.position.y - self.dh/2)
            self.alpha = 0.1
            entity_objects.append(self)
        def bbox(self, entity):
            box = Rect(self.position.x, self.position.y, self.width, self.height)
            return box
        def update(self, entity, rect):
            self.position = (entity.position.x, entity.position.y - self.dh/2)
            rect.x = self.position.x - entity.bbox.w / 2
            rect.y = self.position.y - entity.bbox.h / 2
    
    class Entity_Direction(ShapeNode):
        ''' Creates a object which indicates the direction of entity
            dh = for adjusting the height
        '''
        def __init__(self, entity, entity_objects):
            path = ui.Path.rect(0, 0, entity.size.w, 20)
            ShapeNode.__init__(self, path)
            self.dh = 40
            self.fill_color = 'white'
            self.stroke_color = 'clear'
            self.position = (entity.position.x + 20, entity.position.y - self.dh)
            self.alpha = 0.1
            # Last position (True = right, False = left)
            self.last_direction = True
            entity_objects.append(self)
        def update(self, entity):
            if entity.velocity.x > 0:
                self.position = (entity.position.x + 20, entity.position.y - self.dh)
                self.last_direction = True
            if entity.velocity.x < 0:
                self.position = (entity.position.x - 20, entity.position.y - self.dh)
                self.last_direction = False
            if entity.velocity.x == 0:
                if self.last_direction:
                    self.position = (entity.position.x + 20, entity.position.y - self.dh)
                if not self.last_direction:
                    self.position = (entity.position.x - 20, entity.position.y - self.dh)
    
    class Game (Scene):
    
        def setup(self):
            # Game running
            self.game_running = False
            # Frame Counter to limit the amount of shot bullets
            self.frame_counter = 0
            # Lists for handling different actions & other functions
            self.walls = []
            self.buttons= []
            self.buttons_text = []
            self.player_objects = []
            self.bullets_left = []
            self.bullets_right = []
            # Generate Map
            map = Map(self.walls)
            # Buttons (order is important)
            self.left_button = Buttons("Left Button", 'iow:arrow_left_a_256', (80, 80), 0.5, 0.25, self.buttons)
            self.right_button = Buttons("Right Button", 'iow:arrow_right_a_256', (200, 80), 0.5, 0.25, self.buttons)
            self.jump_button = Buttons("Jump Button", 'iow:nuclear_256', (1000, 80), 0.3, 0.25, self.buttons)
            self.shoot_button = Buttons("Shoot Button", 'iow:ios7_plus_256', (1100, 80), 0.3, 0.25, self.buttons)
            self.jump_text = Buttons_Text('Jump Text', 'Jump', self.jump_button, self.buttons_text)
            self.shoot_text = Buttons_Text('Shoot Text', 'Shoot', self.shoot_button, self.buttons_text)
            # Player Objects
            self.player = Player('Player', 'plf:AlienGreen_front', (100, 200), 1)
            self.player_visible_bbox = Hitbox(self.player, self.player_objects, 10, 50)
            self.player_bbox = self.player_visible_bbox.bbox(self.player)
            print(self.player_bbox)
            print(self.player_visible_bbox.position)
            print(self.player.position)
            self.player_direction = Entity_Direction(self.player, self.player_objects)
            # Add Childs
            self.add_child(self.player)
            for p in self.player_objects:
                self.add_child(p)
            for b in self.buttons:
                self.add_child(b)
            for b_t in self.buttons_text:
                self.add_child(b_t)
            for w in self.walls:
                self.add_child(w)
    
        def did_change_size(self):
            pass
    
        def update(self):
            if self.game_running == True:
                # Frame Counter, 60 frames == 1 sec
                self.frame_counter += 1
                # Game Gravity
                self.player.gravity()
                # Player Objects
                self.player_direction.update(self.player)
                self.player_visible_bbox.update(self.player, self.player_bbox)
                # Controls
                self.player.move_left(self.buttons, self.touches)
                self.player.move_right(self.buttons, self.touches)
                self.player.jump(self.buttons, self.touches)
                self.player.shoot(self, self.player_direction, self.buttons, self.touches, self.bullets_left, self.bullets_right)
                self.player.check_touch(self.buttons, self.touches)
                self.player.check_velocity()
                # Bullets
                Bullet.update(self.bullets_left, self.bullets_right)
                # Game Collision
                self.player.collision(self.player_bbox, self.walls)
    
        def touch_began(self, touch):
            if touch.location > (0, 0):
                self.game_running = True
    
        def touch_moved(self, touch):
            pass
    
        def touch_ended(self, touch):
            pass
    
    if __name__ == '__main__':
        run(Game(), LANDSCAPE, show_fps=True)
    

    posted in Pythonista read more
  • xvid

    @JonB I already feared I have to do something like this. I assume the method where I check for future collision might be the best but not the easiest one, right?

    I probably have to check out some more advanced tutorials for this 🙃.

    posted in Pythonista read more
  • xvid

    Ah you were faster haha thanks!
    Yes exactly, so I kinda need a function which distinguish which collision should be triggered, right?

    posted in Pythonista read more
  • xvid

    @cvp Thank you very much! Yeah it could be also because velocity.y is 0. Your code seem to get the gravity problem fixed but now the collision_left_right isn't working probably. You see the alien is teleported to the top of the tile if I run against it from left/rigth.

    Here is a clip with what I mean: GIF

    posted in Pythonista read more
  • xvid

    @cvp Yes correct, as soon as the alien touch the ground self.onGround = True but will not change anymore expect you press jump.

    posted in Pythonista read more
  • xvid

    @cvp ah I see! Yeah I'm using an iPad Pro 11". It could be maybe not compatible in this case with other devices. There should be a "Left", "Right", "Jump" and "Shoot" key on the device screen.

    posted in Pythonista read more
  • xvid

    @cvp for real? 🤔 I commented/removed all prints, it should work in this state as no function rely on a print statement. If you have a look would be great maybe you have more experience :)

    BTW it's not a "game" in this current state, just an environment to check if the collision and controls are working.

    posted in Pythonista read more
  • xvid

    @cvp ups sorry, have edited now it should be working with the given code :)
    If there are still some errors, hopefully not, let me know!

    posted in Pythonista read more
  • xvid

    Hey! I started my first little project with Pythonista, my goal at the moment is to create a working template for a 2D platformer-type game. It's more or less running fine there just some problems with the gravity and collision.

    The problems are:

    • The gravity effects the player at the beginning which is fine and as soon as the player collide with the ground the variable self.onGround = True. The problem is this variable don't get reset to False after the player is not on the ground anymore which results in the player floating in the sky. As soon as I jump, the gravity is working again till I hit the ground. I tried to change the self.onGround = False in the update method but this results that other functions don't work probably.

    • The other problem is that as soon as I'm falling and move left or right the collision_left_right don't work anymore which results that the player get spawned on top of the tile when I hit it on the right or left. I guess this might due that I change velocity.xand velocity.y at the same time.

    I have the bad feeling I need something like a hitTestfunction which checks where I hit the tile.
    Some side bugs: LANDSCAPEdon't really work probably for me.

    I'm also open for some recommendations regarding coding style, first time I work with Classes and Methods. I want the code as clean as possible.

    Thanks in advance!
    (Sorry for my English)

    If you want to try out the code, the game is running as soon as you touch the screen.

    Code:

    import scene
    from scene import *
    import sound
    import random
    import math
    import level
    import ui
    A = Action
    
    # Constants
    PI = math.pi
    #Screen Size
    SCREEN_W = get_screen_size().w
    SCREEN_H = get_screen_size().h
    # Amount of frames till you can shoot again
    WAIT_TIME = 30
    BULLET_SPEED = 10
    ROTATION_LEFT = PI/2
    ROTATION_RIGHT = 3*PI/2
    # Gravity
    GRAVITY = 4
    
    class Buttons(SpriteNode):
        ''' Buttons Class '''
        def __init__(self, name, appearance, position, scale, alpha, buttons):
            SpriteNode.__init__(self, appearance)
            self.name = name
            self.position = position
            self.z_position = 3
            self.scale = scale
            self.alpha = alpha
            buttons.append(self)
        def __str__(self):
            return self.name
    
    class Buttons_Text(LabelNode):
        def __init__(self, name, text, button, buttons_text):
            LabelNode.__init__(self, text, font=('Futura', 13), color='white')
            self.name = name
            self.position = (button.position.x, button.position.y - 50)
            self.z_position = 1
            buttons_text.append(self)
    
    class Brick(ShapeNode):
        def __init__(self, name, position, z_position, brick_w, brick_h):
            path = ui.Path.rect(position[0], position[1], brick_w, brick_h)
            ShapeNode.__init__(self, path, '#b7b7b7', 'clear')
            self.name = name
            self.position = position
            self.z_position = z_position
        def __str__(self):
            return self.name
    
    class Map(ShapeNode):
        def __init__(self, walls):
            ''' Generates the map '''
            lines = level.level.splitlines()
            brick_w = 40
            brick_h = 40
            col = 0
            row = 0
            for line in lines:
                for i in line:
                    if i == "W":
                        x = 17 + row * brick_w
                        y = 800 - col * brick_h
                        wall = Brick('Brick', (x, y), 0, brick_w, brick_h)
                        walls.append(wall)
                        row += 1
                    else:
                        x = 17 + row * brick_w
                        y = 800 - col * brick_h
                        row += 1
                col += 1
                row = 0
    
    class Entity(SpriteNode):
        ''' Generate an Entity '''
        def __init__(self, appearance):
            SpriteNode.__init__(self, appearance)
    
    class Bullet(Entity):
        def __init__(self, name, appearance, x, y, rotation):
            super().__init__(appearance)
            self.position = (x, y)
            self.rotation = rotation
        def update(bullets_left, bullets_right):
            for bullet in list(bullets_left):
                new_x = bullet.position.x - BULLET_SPEED
                if new_x >= 0 and new_x <= SCREEN_W:
                    bullet.position = (new_x, bullet.position.y)
                else:
                    bullet.remove_from_parent()
                    bullets_left.remove(bullet)
            for bullet in list(bullets_right):
                new_x = bullet.position.x + BULLET_SPEED
                if new_x >= 0 and new_x <= SCREEN_W:
                    bullet.position = (new_x, bullet.position.y)
                else:
                    bullet.remove_from_parent()
                    bullets_right.remove(bullet)
    
    class Player(Entity):
        ''' Player Class '''
        def __init__(self, name, appearance, position, z_position):
            super().__init__(appearance)
            self.name = name
            self.position = position
            self.z_position = z_position
            self.velocity = Vector2(0, 0)
            self.speed = 5
            self.jump_strength = 100
            self.onGround = False
            # Controls
            self.leftKey = False
            self.rightKey = False
            self.jumpKey = False
            self.shootKey = False
    
        def move_left(self, buttons, touches):
            for touch in touches.values():
                if touch.location in buttons[0].bbox:
                    self.leftKey = True
                    self.velocity.x = -self.speed
                    new_x = self.position.x + self.velocity.x
                    if new_x >= 0 and new_x <= SCREEN_W:
                        self.position = (new_x, self.position.y)
    
        def move_right(self, buttons, touches):
            for touch in touches.values():
                if touch.location in buttons[1].bbox:
                    self.rightKey = True
                    self.velocity.x = self.speed
                    new_x = self.position.x + self.velocity.x
                    if new_x >= 0 and new_x <= SCREEN_W:
                        self.position = (new_x, self.position.y)
    
        def jump(self, buttons, touches):
            for touch in touches.values():
                if touch.location in buttons[2].bbox and self.onGround:
                    self.jumpKey = True
                    self.onGround = False
                    self.velocity.y = self.jump_strength
                    new_y = self.position.y + self.velocity.y
                    action = A.move_to(self.position.x, new_y, 1, TIMING_LINEAR)
                    if new_y <= SCREEN_H:
                        self.run_action(action)
    
        def shoot(self, instance, player_direction, buttons, touches, bullets_left, bullets_right):
            for touch in touches.values():
                if touch.location in buttons[3].bbox:
                    self.shootKey = True
                    if player_direction.position.x < self.position.x and instance.frame_counter >= WAIT_TIME:
                        bullet = Bullet("Bullet Right", 'spc:LaserRed10', self.position.x - 20, self.position.y - 40, ROTATION_LEFT)
                        bullets_left.append(bullet)
                        instance.add_child(bullet)
                        instance.frame_counter = 0
                    if player_direction.position.x > self.position.x and instance.frame_counter >= WAIT_TIME:
                         bullet = Bullet("Bullet Left", 'spc:LaserRed10', self.position.x + 20, self.position.y - 40, ROTATION_RIGHT)
                         bullets_right.append(bullet)
                         instance.add_child(bullet)
                         instance.frame_counter = 0
    
        def check_touch(self, buttons, touches):
            #print(touches.values())
            #print(self.leftKey, self.rightKey, self.jumpKey, self.shootKey, self.onGround)
            if len(touches.values()) > 0:
                for touch in touches.values():
                    if touch.location not in buttons[0].bbox or touch:
                        self.leftKey = False
                    if touch.location not in buttons[1].bbox:
                        self.rightKey = False
                    if not touch.location in buttons[2].bbox:
                        self.jumpKey = False
                    if not touch.location in buttons[3].bbox:
                        self.shootKey = False
            else:
                self.leftKey = False
                self.rightKey = False
                self.jumpKey = False
                self.shootKey = False
    
        def check_velocity(self):
            if not self.leftKey and not self.rightKey:
                self.velocity = Vector2(0, self.velocity.y)
            if not self.jumpKey and self.onGround:
                self.velocity = Vector2(self.velocity.x, 0)
    
        def collision_left_right(self, player_bbox, walls):
            for w in walls:
                if self.bbox.intersects(w.bbox):
                    if self.velocity.x > 0:
                        new_x = w.bbox.min_x - self.bbox.w / 2
                        self.position = (new_x, self.position.y)
                        self.velocity.y = 0
                        #print("collide right")
                    if self.velocity.x < 0:
                        new_x = w.bbox.max_x + self.bbox.w / 2
                        self.position = (new_x, self.position.y)
                        self.velocity.y = 0
                        #print("collide left")
    
        def collision_up_down(self, player_bbox, walls):
            for w in walls:
                if self.bbox.intersects(w.bbox):
                    if self.velocity.y > 0:
                        new_y = w.bbox.min_y - self.bbox.h / 2
                        self.position = (self.position.x, new_y)
                        self.onGround = False
                        #print("collide top", self.onGround)
                    if self.velocity.y < 0:
                        new_y = w.bbox.max_y + self.bbox.h / 2
                        self.position = (self.position.x, new_y)
                        self.onGround = True
                        self.velocity.y = 0
                        #print("collide down", self.onGround)
    
        def gravity(self):
            ''' Describes the gravity'''
            if not self.onGround:
                self.velocity.y = -GRAVITY
                new_y = self.position.y + self.velocity.y
                if new_y >= 0:
                    self.position = (self.position.x, new_y)
    
    class Hitbox(ShapeNode):
        ''' Creates a visible hitbox for an entity based on the bbox of the entity. Goal is a better fitted hitbox in the future for collision.
            entity = Object, Player, Enemy etc.
            entity_objects = List of objects for that entity
            dw, dh = how much smaller the widht/height of the hitbox should be (based on the bbox of the entity)
        '''
        def __init__(self, entity, entity_objects, dw, dh):
            self.dw = dw
            self.dh = dh
            self.width = entity.bbox.w - self.dw
            self.height = entity.bbox.h - self.dh
            path = ui.Path.rect(0, 0, self.width, self.height)
            ShapeNode.__init__(self, path)
            self.fill_color = 'white'
            self.stroke_color = 'clear'
            self.position = (entity.position.x, entity.position.y - self.dh/2)
            self.alpha = 0.1
            entity_objects.append(self)
        def bbox(self, entity):
            box = Rect(self.position.x, self.position.y, self.width, self.height)
            return box
        def update(self, entity, rect):
            self.position = (entity.position.x, entity.position.y - self.dh/2)
            rect.x = self.position.x - entity.bbox.w / 2
            rect.y = self.position.y - entity.bbox.h / 2
    
    class Entity_Direction(ShapeNode):
        ''' Creates a object which indicates the direction of entity.
            dh = for adjusting the height
        '''
        def __init__(self, entity, entity_objects):
            path = ui.Path.rect(0, 0, entity.size.w, 20)
            ShapeNode.__init__(self, path)
            self.dh = 40
            self.fill_color = 'white'
            self.stroke_color = 'clear'
            self.position = (entity.position.x + 20, entity.position.y - self.dh)
            self.alpha = 0.1
            # Last position (True = right, False = left)
            self.last_direction = True
            entity_objects.append(self)
        def update(self, entity):
            if entity.velocity.x > 0:
                self.position = (entity.position.x + 20, entity.position.y - self.dh)
                self.last_direction = True
            if entity.velocity.x < 0:
                self.position = (entity.position.x - 20, entity.position.y - self.dh)
                self.last_direction = False
            if entity.velocity.x == 0:
                if self.last_direction:
                    self.position = (entity.position.x + 20, entity.position.y - self.dh)
                if not self.last_direction:
                    self.position = (entity.position.x - 20, entity.position.y - self.dh)
    
    class Game (Scene):
    
        def setup(self):
            # Game running
            self.game_running = False
            # Frame Counter to limit the amount of shot bullets
            self.frame_counter = 0
            # Lists for handling different actions & other functions
            self.walls = []
            self.buttons= []
            self.buttons_text = []
            self.player_objects = []
            self.bullets_left = []
            self.bullets_right = []
            # Generate Map
            map = Map(self.walls)
            # Buttons (order is important)
            self.left_button = Buttons("Left Button", 'iow:arrow_left_a_256', (80, 80), 0.5, 0.25, self.buttons)
            self.right_button = Buttons("Right Button", 'iow:arrow_right_a_256', (200, 80), 0.5, 0.25, self.buttons)
            self.jump_button = Buttons("Jump Button", 'iow:nuclear_256', (1000, 80), 0.3, 0.25, self.buttons)
            self.shoot_button = Buttons("Shoot Button", 'iow:ios7_plus_256', (1100, 80), 0.3, 0.25, self.buttons)
            self.jump_text = Buttons_Text('Jump Text', 'Jump', self.jump_button, self.buttons_text)
            self.shoot_text = Buttons_Text('Shoot Text', 'Shoot', self.shoot_button, self.buttons_text)
            # Player Objects
            self.player = Player('Player', 'plf:AlienGreen_front', (100, 200), 1)
            self.player_visible_bbox = Hitbox(self.player, self.player_objects, 10, 50)
            self.player_bbox = self.player_visible_bbox.bbox(self.player)
            self.player_direction = Entity_Direction(self.player, self.player_objects)
            # Add Childs
            self.add_child(self.player)
            for p in self.player_objects:
                self.add_child(p)
            for b in self.buttons:
                self.add_child(b)
            for b_t in self.buttons_text:
                self.add_child(b_t)
            for w in self.walls:
                self.add_child(w)
    
        def did_change_size(self):
            pass
    
        def update(self):
            if self.game_running == True:
                # Frame Counter, 60 frames == 1 sec
                self.frame_counter += 1
                #self.player.onGround = False
                # Game Gravity
                self.player.gravity()
                # Player Objects
                self.player_direction.update(self.player)
                self.player_visible_bbox.update(self.player, self.player_bbox)
                # Controls
                self.player.move_left(self.buttons, self.touches)
                self.player.move_right(self.buttons, self.touches)
                self.player.jump(self.buttons, self.touches)
                self.player.shoot(self, self.player_direction, self.buttons, self.touches, self.bullets_left, self.bullets_right)
                self.player.check_touch(self.buttons, self.touches)
                #self.player.check_velocity()
                # Bullets
                Bullet.update(self.bullets_left, self.bullets_right)
                # Game Collision
                self.player.collision_up_down(self.player_bbox, self.walls)
                self.player.collision_left_right(self.player_bbox, self.walls)
    
        def touch_began(self, touch):
            if touch.location > (0, 0):
                self.game_running = True
    
        def touch_moved(self, touch):
            pass
    
        def touch_ended(self, touch):
            pass
    
    if __name__ == '__main__':
        run(Game(), LANDSCAPE, show_fps=True)
    

    And level (save this as level.py):

    level = '''
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W
    W                 WWWW 
    W          WWW
    WWWWWWWWWW     WWWWWWW     WWWWW   WWWW
    '''

    posted in Pythonista read more
Internal error.

Oops! Looks like something went wrong!