'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 |
|---|
