Jun-27-2020, 08:59 PM
Contoler examples are hard to find, so I'm sharing this.
Plug in your controller and run the file. "Start" resets and "B" jumps.
It's meant to be an example/template for beginners to customize and take off from (ie. add sound, sprite images/animation, new levels, etc.)
Plug in your controller and run the file. "Start" resets and "B" jumps.
It's meant to be an example/template for beginners to customize and take off from (ie. add sound, sprite images/animation, new levels, etc.)
import pygame as pg import sys from os import path vec = pg.math.Vector2 import random map1 = ("11111111111111111111111111111111111111111111111111111111111111111111111111111111", "1..............................................................................1", "1..............................................................................1", "1.............k..k...k...............................................k.........1", "1........................................111...................................1", "1...b................b...........................111...................b.......1", "1..............................................................................1", "1...........................................b...................m..............1", "1.........1111111111111111111111m..........111.111.111.......1LLLLLLLLLLLLLLLLL1", "1......1111............................................1111111111111111111111111", "1....................................b.........................................1", "1....................................k....k....................................1", "1...111................b...................................b...................1", "1..............................k..m.......................................111111", "1..............................1...............................................1", "1...P.....1111............................1....................................1", "1...........................1.......................1....1111...............k..1", "1....................m.........................................m.........1111111", "111111111111111111111LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL11111", "11111111111111111111111111111111111111111111111111111111111111111111111111111111", "11111111111111111111111111111111111111111111111111111111111111111111111111111111") class Block(pg.sprite.Sprite): def __init__(self, game, col, row): self.groups = game.all_sprites, game.blocks pg.sprite.Sprite.__init__(self, self.groups) self.layer = 5 self.game = game self.visability = 1 self.image = pg.Surface((game.tile_size, game.tile_size)) self.image.fill((120, 120, 100)) self.rect = self.image.get_rect() self.rect.x = col * game.tile_size self.rect.y = row * game.tile_size self.pos = vec(self.rect.center) self.state = "normal" def update(self): if self.visability == 1: self.rect.center = self.pos else: self.rect.center = self.pos + (-10000, -10000) class Moving_platform(pg.sprite.Sprite): def __init__(self, game, col, row, w, h, movement): self.groups = game.all_sprites, game.blocks pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.image = pg.Surface((w, h)) self.image.fill((200, 120, 200)) self.rect = self.image.get_rect() self.rect.x = col * game.tile_size self.rect.y = row * game.tile_size self.vel = vec(0, 0) self.frame = 0 self.movement = vec(movement) def update(self): self.frame += 1 if self.frame < 100: self.vel = self.movement if self.frame > 100: self.vel = self.movement * -1 if self.frame == 200: self.frame = 0 self.rect.center += self.vel self.rect.y -= 2 ride = self.rect.colliderect(self.game.player) self.rect.y += 2 if ride: self.game.player.rect.center += vec(self.vel) else: self.game.player.platform_movement = vec(0, 0) class Lava(pg.sprite.Sprite): def __init__(self, game, col, row): self.groups = game.all_sprites, game.lava pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.image = pg.Surface((game.tile_size, game.tile_size - 4)) self.image.fill((255, 120, 0)) self.rect = self.image.get_rect() self.rect.x = col * game.tile_size self.rect.y = row * game.tile_size + 4 def update(self): hit = self.rect.colliderect(self.game.player) if hit: self.frame = 0 self.game.player.die() class Player(pg.sprite.Sprite): def __init__(self, game, col, row): self.groups = game.all_sprites pg.sprite.Sprite.__init__(self, self.groups) self._layer = 5 self.game = game self.width = 18 self.height = 40 self.original_image = pg.Surface((self.width, self.height)) self.image = self.original_image self.image.fill((250, 200, 250)) pg.draw.rect(self.original_image, (0, 0, 0), (self.width - 8, 10, 4, 4)) pg.draw.rect(self.original_image, (0, 0, 0), (self.width - 6, 21, 6, 3)) self.rect = self.image.get_rect() self.acc = vec(0, 0) self.vel = vec(0, 0) self.last_update = pg.time.get_ticks() self.rect.center = (col * self.game.tile_size, row * self.game.tile_size) self.frame = 0 self.frame_rate = 60 self.friction = -.12 self.move_right = False self.move_left = False self.jump = False self.jumping = False self.jump_strength = 15 self.gravity = .7 self.friction = -.7 self.terminal_vel = 10 self.state = "normal" self.jump_safety = 0 self.platform_movement = vec(0, 0) self.current_image = self.original_image self.pushing = False self.hit_rect = self.rect def update(self): if self.state == "dying": self.die() if self.state == "normal": self.acc = vec(0, self.gravity) self.hit_rect.center += self.platform_movement if self.move_right == True: self.acc.x = 4 if self.move_left == True: self.acc.x = -4 self.acc.x += self.vel.x * self.friction if self.vel.y > self.terminal_vel: self.vel.y = self.terminal_vel self.vel.x += self.acc.x self.hit_rect.x += self.vel.x if self.vel.x > -.1 and self.vel.x < .1: self.vel.x = 0 for block in self.game.blocks: hit = self.hit_rect.colliderect(block) if hit: if isinstance(block, Block): if self.vel.x > 0: self.hit_rect.right = block.rect.left if self.vel.x < 0: self.hit_rect.left = block.rect.right self.vel.x = 0 self.acc.x = 0 self.hit_rect.x -= self.vel.x else: if self.vel.x < 0: self.image = pg.transform.flip(self.original_image, True, False) if self.vel.x > 0: self.image = self.original_image self.vel.y += self.acc.y self.hit_rect.y += self.vel.y for block in self.game.blocks: hit = self.hit_rect.colliderect(block) if hit: if self.vel.y > self.gravity: self.done_squishing = False if self.vel.y > 0: self.hit_rect.bottom = block.rect.top self.vel.y = 0 self.jump_safety = pg.time.get_ticks() self.jumping = False if self.vel.y < 0: self.hit_rect.top = block.rect.bottom self.vel.y = 0 if self.jump == True and self.jumping == False: self.jump_function() self.rect.midbottom = self.hit_rect.midbottom def die(self): if self.frame == 0: self.state = "dying" for i in range(13): Sparkle(self) self.image.fill((0, 0, 0)) self.frame += 1 if self.frame == 120: self.game.new() def jump_function(self): now = pg.time.get_ticks() if now - self.jump_safety < 250: self.jumping = True self.jump = False self.vel.y -= self.jump_strength class Pickup(pg.sprite.Sprite): def __init__(self, game, col, row): self.groups = game.all_sprites, game.items pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.image = pg.Surface((16, 16)) self.rect = self.image.get_rect() self.rect.centerx = col * self.game.tile_size + self.game.tile_size/2 self.rect.centery = row * self.game.tile_size + self.game.tile_size/2 pg.draw.circle(self.image, (3, 255, 255), (8, 8), 8) self.game.coin_count += 1 self.state = 1 def update(self): self.pos = vec(self.rect.center) hit = self.rect.colliderect(self.game.player) if hit: self.game.coin_count -= 1 for i in range(5): Sparkle(self) self.kill() class Sparkle(pg.sprite.Sprite): def __init__(self, start): self.start = start self.image = pg.Surface((16, 16)) self.rect = self.image.get_rect() self.radius = 7 self.rect.center = start.rect.center speeds = [-3, -2, -1, 1, 2, 3] self.dir = vec(random.choice(speeds), random.choice(speeds)) self.frame_rate = 60 self.start.game.effects.append(self) self.last_update = 0 self.spawntime = pg.time.get_ticks() self.life_span = 500 def update(self): now = pg.time.get_ticks() if now - self.spawntime > self.life_span: self.start.game.effects.remove(self) if now - self.last_update > self.frame_rate: self.last_update = now if self.radius > 1: self.radius -= 1 self.rect.center += self.dir + (0, 2) class Bouncer(pg.sprite.Sprite): def __init__(self, game, col, row): self.groups = game.all_sprites, game.items pg.sprite.Sprite.__init__(self, self.groups) self.game = game self.image = pg.Surface((20, 20)) self.image.fill((255, 155, 0)) self.rect = self.image.get_rect() self.radius = 7 self.rect.centerx = col * game.tile_size self.rect.centery = row * game.tile_size speeds = [-3, -2, -1, 1, 2, 3] self.dir = vec(random.choice(speeds), random.choice(speeds)) self.frame_rate = 60 self.last_update = 0 def update(self): self.rect.centerx += self.dir.x hits = pg.sprite.spritecollide(self, self.game.blocks, False) if len(hits) > 0: self.dir.x *= -1 self.rect.x += self.dir.x self.rect.y += self.dir.y hits = pg.sprite.spritecollide(self, self.game.blocks, False) if len(hits) > 0: self.dir.y *= -1 self.rect.y += self.dir.y hit = self.rect.colliderect(self.game.player) if hit: self.game.player.die() class TileMap: def __init__(self, game): self.game = game self.map_data = map1 self.game.map_width = len(self.map_data[0]) * self.game.tile_size def make_map(self): map_surface = pg.Surface((600, 500)) self.render(map_surface) return map_surface def render(self, surface): for row, tiles in enumerate(self.map_data): for col, tile in enumerate(tiles): if tile == '1': Block(self.game, col, row) if tile == "k": Pickup(self.game, col, row) if tile == "L": Lava(self.game, col, row) if tile == "P": self.game.player = Player(self.game, col, row) if tile == "b": Bouncer(self.game, col, row) if tile == "m": Moving_platform(self.game, col, row, self.game.tile_size * 3, self.game.tile_size/2, (2, 0)) class Camera: def __init__(self, width, height): self.camera = pg.Rect(0, 0, width, height) self.width = width self.height = height def apply(self, entity): return entity.rect.move(self.camera.topleft) def update(self, target): x = -target.rect.centerx + int(300) y = -target.rect.bottom + int(250) # limit scrolling to map size x = min(0, x) # left y = min(0, y) # top x = max(-(self.width - 600), x) # right y = max(-(self.height - 100), y) # bottom self.camera = pg.Rect(x, y, self.width, self.height) class States(object): share = 'share' def __init__(self): self.done = False self.next = None self.quit = False self.previous = None class Game(States): def __init__(self): States.__init__(self) self.next = 'start screen' self.width = 800 self.height = 600 self.screen = pg.display.set_mode((self.width, self.height)) self.level = 0 self.load_data() self.new() def cleanup(self): pass def startup(self): self.new() def load_data(self): self.tile_size = 32 self.game_folder = path.dirname(__file__) self.main_font = pg.font.SysFont("comicsansms", 45) self.large_font = pg.font.SysFont("comicsansms", 76) self.coin_count = 0 def new(self): if self.coin_count == 0: self.level += 1 if self.level > 1: self.level = 1 else: self.coin_count = 0 self.all_sprites = pg.sprite.LayeredUpdates() self.blocks = pg.sprite.LayeredUpdates() self.lava = pg.sprite.Group() self.items = pg.sprite.LayeredUpdates() self.effects = [] self.camera = Camera(2500, 800) self.tilemap = TileMap(self) self.tilemap.render(self.screen) self.my_joystick = pg.joystick.Joystick(0) self.my_joystick.init() self.start_time = pg.time.get_ticks() def get_event(self, event, dt): if self.my_joystick.get_button(0) == True: pass if self.my_joystick.get_button(0) == False: pass if self.my_joystick.get_button(7) == True: self.coin_count = 0 self.new() if self.my_joystick.get_button(0) == True and self.player.jumping == False: self.player.jump = True if self.my_joystick.get_button(0) == False and self.player.jumping == True: if self.player.vel.y < 0: self.player.vel.y *= .5 if self.my_joystick.get_button(2) == True: if self.play_music == 1: pg.mixer.music.play(loops=-1) else: pg.mixer.music.stop() self.play_music *= -1 horiz_axis_pos = self.my_joystick.get_axis(0) vert_axis_pos = self.my_joystick.get_axis(1) if round(horiz_axis_pos) == 1: self.player.move_right = True self.player.move_left = False if round(horiz_axis_pos) == -1: self.player.move_left = True self.player.move_right = False if round(horiz_axis_pos) == 0: self.player.move_right = False self.player.move_left = False def update(self, screen, dt): self.all_sprites.update() self.camera.update(self.player) self.draw(screen) def draw(self, screen): screen.fill((2, 20, 1)) for sprite in self.all_sprites: screen.blit(sprite.image, self.camera.apply(sprite)) textsurface = self.main_font.render(f'{self.coin_count} LEFT', True, (250, 250, 255)) screen.blit(textsurface, (20, 20)) if self.coin_count == 0: textsurface = self.large_font.render('yOu WiN!!', True, (250, 250, 255)) screen.blit(textsurface, (150, 200)) textsurface = self.main_font.render('press START', True, (250, 250, 255)) screen.blit(textsurface, (275, 300)) for effect in self.effects: effect.update() location = self.camera.apply(effect) pg.draw.circle(self.screen, (255, 255, 255), (location.x, location.y), effect.radius) pg.draw.rect(screen, ((255, 255, 255)), (0, 0, self.width, self.height), 2) class Control: def __init__(self): self.done = False self.fps = 60 self.clock = pg.time.Clock() pg.mixer.pre_init(44100, -16, 1, 2048) pg.init() def setup_states(self, state_dict, start_state): self.state_dict = state_dict self.state_name = start_state self.state = self.state_dict[self.state_name] def flip_state(self): self.state.done = False previous,self.state_name = self.state_name, self.state.next self.state.cleanup() self.state = self.state_dict[self.state_name] self.state.startup() self.state.previous = previous def update(self, dt): if self.state.quit: self.done = True elif self.state.done: self.flip_state() self.state.update(self.state_dict["game"].screen, dt) def event_loop(self, dt): for event in pg.event.get(): if event.type == pg.QUIT: self.done = True self.state.get_event(event, dt) def main_game_loop(self): while not self.done: delta_time = self.clock.tick(self.fps)/1000.0 self.event_loop(delta_time) self.update(delta_time) pg.display.update() app = Control() state_dict = {'game': Game()} app.setup_states(state_dict, 'game') app.main_game_loop() pg.quit() sys.exit()