'How to implement a map design on a side scrolling platform game on pygame

I want to add a level design for my platform side scrolling game on pygame I have managed to add a platform so the characters can stand. However, I have no idea how to implement this for the whole game, I have drawn the structure of it in a list and I am wondering with my code how I may be able to add this onto my game and the relevant physics necessary for the character to stand on it when it stands/collides on the block.

Any suggestions would be very appreciated.

import pygame,random
map_design = [
'                        XX                           ',
'                        XX                           ',
'                        XX              XXXXXXX      ',
'   XX                   XX                           ',
'    XXX                 XX      XXXXXXX              ',
'          XXXXXXXXXXX   X     XXX                    ',
'         XXXXXXXXXXXX   X    XXXX                    ',
'       XXXX             XX                           ',
'      XXX               XX                           ',
'                        XXXX     XXX                 ',
'XXXX                    XX             XX            ',
'XXXX                                 XXXX            ',
'XXXX     XXXXX          XXXXXXXXXX                   ']

#variables for player
moveright = False  #declared a variable to store boolean value for if player is moving 
right
moveleft = False  #declared a variable to store boolean value for if player is moving 
left
fire = False #declared a variable to store boolean value for if character attacks

#constant variables
brick_size = 64
width = 1500 #declared a variable to store width of game screen
height = len(level_map) * brick_size #declared a variable to store height of game 
screen
size_of_screen = (width, height)  #declared a variable to store the height and width 
of the screen
bg_colour = (222, 203, 104)  #declared a variable to store the bg colour of screen
pf_colour = (0, 0, 0) #
FPS = 60  #declared variable to store the speed at which game runs
gravity = 0.5 #declared variable to store the rate at which player falls down
list_of_heals = [20,40,50,10,-5,-10,-20,30]
list_of_powerups = [1, 0.01, 0.5, 0, -0.5, -1]
damage_coefficient = 0

#init
pygame.init()  #all imported python modules are initialised
screen = pygame.display.set_mode(size_of_screen)  #a game window is initialised
pygame.display.set_caption("Platform Game")  #game windows caption is set
system_clock = pygame.time.Clock()  #declared variable to control speed of game
health_brick = pygame.image.load('health brick.png').convert_alpha()
powerup_brick = pygame.image.load("powerup.png").convert_alpha()
bricks = {
  'heal' : health_brick,
  'powerup' : powerup_brick
}
font = pygame.font.SysFont("", 30)

def draw_writings(writings, font, colour, x, y):
      image = font.render(writings, True, colour)
      image = pygame.transform.scale(image, (120, 20))
      screen.blit(image, (x,y))

class Characters(pygame.sprite.Sprite):  #base class is created and inherits from sprite class
   def __init__(self, char, x, y, scale, speed, health):  #values are put in the constructor method
    pygame.sprite.Sprite.__init__(self)  #constructor from sprite class is called
    self.idle = False
    self.idle_counter = 0
    self.counter = 0
    self.health = health #attribute initialised to store health of character
    self.max_health = self.health #attribute initialised to store max_health of character
    self.attack_cooldown = 0 #attribute initialised to store cooldown of each character attack
    self.direction = 1 #attribute initialised to store direction characters face when they move left/right
    self.air = True #attribute initi
    self.char = char
    self.life = True  #attribute initialised to store state of characters life
    self.jump = False
    self.vv = 0
    self.speed = speed  #attribute for character is initialised to store speed of character
    self.spin = False  #attribute initialised to store direction character is moving
    self.animation_list = []  #attribute initialised to store all sequence of animations for sprites within 2D list
    self.index = 0  #attribute initialised to locate index of sequences within specific animation
    self.activity = 0  #attribute initialised to locate index of animation sequences within animation list
    self.time = pygame.time.get_ticks()  #attribute declared to store current time game has been running
    types_of_animation = ['idle', 'moving', 'jump', "death"]
    for ani in types_of_animation:
        templist = []  #declared a variable which will be used to store a temporary list
        for x1 in range(10):  #loops through numbers 0-10
            try:
                img = pygame.image.load(f'{self.char}/{self.char}.{ani}.sprite_{x1}.png').convert_alpha() #loads an image from your file
                img = pygame.transform.scale(img, (int(scale), int(scale)))  #resizes your image
                templist.append(img)  #resized image is added to temporary list
            except:
                break
        self.animation_list.append(templist)  #adds all images passed into temporary list to main one
    self.img = self.animation_list[self.activity][self.index]  #attribute initialised to store intial image of sprite
    self.rect = self.img.get_rect()  #a rectangle is formed around sprite
    self.rect.center = (x, y)  #centre of rectangle varies with the position of sprite
    self.rect = self.rect.inflate(-10,-10)
  
   def movecharacter(self, moveleft, moveright):  #new method defined to move character
     #change in movement variables
     dy = 0  #declared a variable to store the change in distance travelled in the vertical direction
     dx = 0  #declared a variable to store the change in distance travelled in the horizontal direction

     #movement variables are updated if there are movements left or right
     if moveleft:  #checks to see if user has inputted "a" key
        dx -= self.speed  #character has moved backwards
        self.direction = -1
        self.spin = True  #character changed direction(faces left)
     if moveright:  #checks to see if the user has inputted "d" key
        dx += self.speed  #character has moved forward
        self.spin = False  #character changed direction(faces right)
        self.direction = 1
     #these variables are for jumping
     if self.jump and not self.air:  #checks to see if user has inputted "w" key and is in mid-air
        self.vv = -10  #determines how high the character can jump
        self.jump = False  #this variable is set to false so character doesn't fly of the screen
        self.air = True  #this variable is set to true so character can't infinitely jump while in mid-dair

     #gravity is applied here
     self.vv += gravity  #vertical velocity is incremented until character starts to move in opposite direction
     if self.vv > 9:  #checks to see if character's vertical velocity has passed 9
        self.vv = 9  #vertical velocity is capped to 9
     dy += self.vv  #change in distance travelled in vertical direction is increased

     if self.rect.bottom + dy > 400:  #checks if distance the player travelled
        dy = 400 - self.rect.bottom
        self.air = False

     #rectangle position is updated
     self.rect.x += dx  #position of rectangle has changed in horizontal direction
     self.rect.y += dy  #position of rectangle has changed in vertical direction 

    def alive_check(self):
       if self.health <=0:
         self.life = False
         self.speed = 0
         self.health = 0
         self.update_activity(3)

    def attack(self):  
         if not self.attack_cooldown:
         self.attack_cooldown = 50
         ball = Fireball(self.rect.centerx + self.rect.size[0] * self.direction, self.rect.centery, self.direction, self.spin)
         fireball_group.add(ball)

    def collision_checker(self):
      if pygame.sprite.spritecollide(player, fireball_group, False):
       if player.life:
          player.health -=1
          fireball_group.remove()

      for enemy in enemies_group:
         if pygame.sprite.spritecollide(enemy, fireball_group, False):
                 if enemy.life: 
                        enemy.health -=1 + damage_coefficient
  
    def cooldown(self):
       if self.attack_cooldown > 0:
           self.attack_cooldown -=1

    def animation(self):  #new method defined to change characters animation
      animation_timer = 100  #declared variable to store time for how long character is in each animation
      self.img = self.animation_list[self.activity][self.index]  #characters animation is updated
      if pygame.time.get_ticks() - self.time > animation_timer:  #checks to see if it is time to update sprites
        self.time = pygame.time.get_ticks()  #time game has been running for is redefined
        self.index += 1  #index for current animation sequence is increased so next animation can be outputted
      if self.index >= len(self.animation_list[self.activity]):  #checks to see if index value has passed the highest index of animation sequence list
         if self.activity == 3:
             self.index = len(self.animation_list[self.activity]) -1
         else:
             self.index = 0  #index is reset back to initial value

    def update_activity(self, updated_activity):  #new method defined to update which animation sequence character is in
             if updated_activity != self.activity:  #checks if current activity is equal to new activity
                  self.activity = updated_activity  #value for activity is updated
                  self.index = 0  #index is reset to initial value
                  self.time = pygame.time.get_ticks()  #time game has been running is updated

    def enemy_ai(self):
           if self.life and player.life:
             if random.randint(1, 300) == 1 and self.idle_counter <= 0:
                 self.idle = True
                 self.idle_counter = 100
                 self.update_activity(0)
           
             if self.idle == False:
                  if self.direction == 1:
                       moving_rightai = True
                  else:
                       moving_rightai = False
                  moving_leftai = not moving_rightai
                  self.movecharacter(moving_leftai, moving_rightai)
                  self.update_activity(1)
                  self.counter += 1

                  if self.counter > brick_size:
                     self.direction *= -1
                     self.counter *= -1 
             else:
               self.idle_counter -= 1
               if self.idle_counter <= 0:
                     self.idle = False

     def draw(self):  #new method defined to draw images to screen
         screen.blit(pygame.transform.flip(self.img, self.spin, False), self.rect)  #draws image to screen
         pygame.draw.rect(screen, "red", self.rect, 1)

 class Health_bar():
      def __init__(self, x, y, health, maxhealth):
           self.x = x
           self.y = y
           self.maxhealth = maxhealth
           self.health = health

      def draw(self, health):
          self.health = health
          hratio = self.health/self.maxhealth
          pygame.draw.rect(screen, 'black', (self.x-2, self.y-2, 154, 24))
          pygame.draw.rect(screen, 'red', (self.x, self.y, 150, 20))
          pygame.draw.rect(screen, 'green', (self.x, self.y, 150*hratio, 20))

 class Cubes(pygame.sprite.Sprite):
         def __init__(self, item, x, y):
              pygame.sprite.Sprite.__init__(self)
              self.item = item
              self.x = x
              self.y = y
              self.image = bricks[self.item]
              self.image = pygame.transform.scale(self.image, (50,50))
              self.rect = self.image.get_rect()
              self.rect.center = (x, y)

         def update(self):
             global damage_coefficient  
             if pygame.sprite.collide_rect(self, player):
                if self.item == "heal":
                    player.health += list_of_heals[random.randint(0,7)]
                    if player.health > player.max_health:
                               player.health = player.max_health
                if self.item =="powerup":
                       damage_coefficient += list_of_powerups[random.randint(0,5)]
                       if damage_coefficient > 2.5:
                                damage_coefficient = 2.4
                       elif damage_coefficient > 1.1:
                                damage_coefficient = 1.1
                self.kill()

 class Fireball(pygame.sprite.Sprite):
      def __init__(self, x, y, direction, spin):
           pygame.sprite.Sprite.__init__(self)
           self.spin = spin    
           self.direction = direction
           self.speed = 10
           self.images = []
           self.index = 0
           for x1 in range(1, 9):
                 img = pygame.image.load(f'fireball images/fireball_{x1}.png').convert_alpha()
                 img = pygame.transform.flip(img, self.spin, False)
                 img = pygame.transform.scale(img, (50,50))
                 self.images.append(img)
           self.index = 0
           self.image = self.images[self.index]
           self.rect = self.image.get_rect()
           self.rect.center = (x,y)
           self.counter = 0

      def update(self):
         if self.counter >= self.speed and self.index < len(self.images) - 1:
             self.counter = 0
             self.index += 1
             self.image = self.images[self.index]
         if self.index >= len(self.images) - 1 and self.counter >= self.speed:
            self.kill()
         self.rect.x += (self.direction * self.speed)
         if self.rect.right < 0 or self.rect.left > width:
                 self.kill()
         self.counter+=1

 fireball_group = pygame.sprite.Group() 
 enemies_group = pygame.sprite.Group()
 item_cube_group = pygame.sprite.Group()

 item_cube = Cubes("heal", 500, 300)
 item_cube_group.add(item_cube)
 item_cube2 = Cubes("powerup", 300, 300)
 item_cube_group.add(item_cube2)
  
 player = Characters("player", 200, 450, 75, 3, 100)
 health_cube = Health_bar(10, 10, player.health, player.max_health)
 enemy = Characters("enemy", 300, 350, 75, 3, 100)
 enemy2 = Characters("enemy", 100, 350, 75, 3, 100)
 enemies_group.add(enemy)
 enemies_group.add(enemy2)

 run = True  #declared a variable to store a boolean value to determine state of game
 while run:  #game loop-infinite loop which runs game until game is finished
       #draw
       screen.fill(bg_colour)  #displays the specified bg colour
       pygame.draw.line(screen, pf_colour, (0, 400), (width, 400))
       draw_writings(f'DAMAGE_BOOST: {damage_coefficient}', font, "white", 10, 35)
       health_cube.draw(player.health)
       item_cube_group.update()
       item_cube_group.draw(screen)
       player.draw()  #calls the draw method from base class so character can move
       for enemy in enemies_group:
            enemy.enemy_ai()
            enemy.collision_checker()
            enemy.alive_check()
            enemy.animation()
            enemy.draw()
       fireball_group.update()
       fireball_group.draw(screen)
       pygame.display.flip()  #the contents of entire display are updated
       system_clock.tick(FPS)  #function declared to limit the speed game runs at
       player.alive_check()
       player.animation()  #calls animation method from base class so characters animation is updated
       player.cooldown()
       if player.life:  #checks to see if player is alive
        if fire:
          player.attack() 
        if player.air:  #checks to see if player is in air
               player.update_activity(2)  #updates the value of activity attribute within base class
        elif moveleft or moveright:  #checks if player is moving
               player.update_activity(1)  #updates the value of activity attribute within base class
        else:
             player.update_activity(0)  #current value of acitivity remains 0
        player.movecharacter(moveleft, moveright)  #calls movecharacter method from base class so character can move

       #input
       for event in pygame.event.get():  #loops through all the events registered by user
           #quit game
           if event.type == pygame.QUIT:  #checks to see if user has selected the exit button
                run = False  #state of game is set to false to signal game window has been closed
           #keyboard inputs
           if event.type == pygame.KEYDOWN:  #checks to see if user has inputted a key
                  if event.key == pygame.K_a:  #checks to see if user has inputted "a" key
                           moveleft = True  #variable is set to true so character moves left
                  if event.key == pygame.K_d:  #checks to see if user has inputted "d" key
                           moveright = True  #variable is set to true so character moves right
                  if event.key == pygame.K_w and player.life:  #checks to see if the user has inputted "w" key
                         player.jump = True  #variable is set to true so character jumps
                  if event.key == pygame.K_SPACE:
                         fire = True
           if event.type == pygame.KEYUP:  #checks to see if user released a key
                   if event.key == pygame.K_a:  #checks to see if user has inputted "a" key
                           moveleft = False  #variable is set to false so character stops moving left
                   if event.key == pygame.K_d:  #checks to see if user has inputted the "d" key
                           moveright = False  #variable is set to false so character stops moving right
                   if event.key == pygame.K_SPACE:
                             fire = False

#quit
pygame.quit()  #all pygame modules are uninitialised


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source