class Game(object): filename = get_map(MAP_FILENAME) def __init__(self): # true while running self.currentAnim = CurrentAnim.RIGHT # load data from pytmx tmx_data = load_pygame(self.filename) # setup level geometry with simple pygame rects, loaded from pytmx self.walls = list() for object in tmx_data.objects: self.walls.append( pygame.Rect(object.x, object.y, object.width, object.height)) # create new data source for pyscroll map_data = pyscroll.data.TiledMapData(tmx_data) # create new renderer (camera) self.map_layer = pyscroll.BufferedRenderer(map_data, screen.get_size(), clamp_camera=False, tall_sprites=0) self.map_layer.zoom = 1.8 # pyscroll supports layered rendering. our map has 3 'under' layers # layers begin with 0, so the layers are 0, 1, and 2. # since we want the sprite to be on top of layer 1, we set the default # layer for sprites as 2 self.group = PyscrollGroup(map_layer=self.map_layer, default_layer=1) self.doorPosX = 157 self.doorPosY = 208 self.offset = 0 for j in range(2): for i in range(39): doors.append(Door(self.doorPosX, self.doorPosY)) self.doorPosY += 113 - self.offset self.offset += 0.06 self.doorPosX = 270 self.offset = 0 self.doorPosY = 208 self.doorPosX = 457 self.doorPosY = 208 self.offset = 0 for j in range(2): for i in range(39): doors.append(Door(self.doorPosX, self.doorPosY)) self.doorPosY += 113 - self.offset self.offset += 0.06 self.doorPosX = 588 self.offset = 0 self.doorPosY = 208 self.elevatorInitX = 350 self.elevatorInitY = 200 for i in range(20): elevator.append( Elevator(ElevatorImage, self.elevatorInitX, self.elevatorInitY)) self.elevatorInitY += 250 for i in elevator: self.group.add(i) self.playerCharacter = Character(PlayerWalkAnimList[0]) #self.playerCharacter._position = self.map_layer.map_rect.center self.playerCharacter._positionX += 300 self.playerCharacter._positionY += 20 self.group.add(self.playerCharacter) #Variables self.animDelay = 50 self.JumpTimer = 1700 self.FireDelay = 2000 self.lastUpdate = 0 self.SpawnlastUpdate = 0 self.JumplastUpdate = 0 self.AttacklastUpdate = 0 self.ScoreIncreaseTimer = 0 self.playerVel = [0, 0] self.velX = 0 self.velY = 0 self.jumpVel = 0.5 self.Gravity = 0 self.bIsJumping = False self.bCanJump = True self.WalkAnimIndex = 0 self.CrouchAnimIndex = 0 self.AttackAnimIndex = 0 self.bIsWalking = False self.bCollided = False self.bCanMoveRight = True self.bCanMoveLeft = True self.bIsFiring = False self.bHasFired = False self.bCanFire = True self.bAddEnemy = False self.facing = 1 self.PlayeBulletOffset = 0 self.bCanSpawnEnemy = True self.WalkSoundTimer = 0 pygame.display.set_caption("Elevator action") self.clock = pygame.time.Clock() self.score = 0 self.health = 10 self.bHealthCheck = True self.bGameOver = False self.bLevelPassed = False def MovementHandle(self): self.keys = pygame.key.get_pressed() if self.keys[pygame.K_LEFT]: self.bIsWalking = True self.currentAnim = CurrentAnim.LEFT elif self.keys[pygame.K_RIGHT]: self.bIsWalking = True self.currentAnim = CurrentAnim.RIGHT if self.bIsWalking == True: if self.currentAnim == CurrentAnim.LEFT: if self.bCanMoveLeft == True: self.velX = -2.5 elif self.currentAnim == CurrentAnim.RIGHT: if self.bCanMoveRight == True: self.velX = 2.5 def AddEnemy_thread(self): count = 0 if count < 1 and len(Enemies) < 50: for i in doors: if self.playerCharacter._positionY >= i.positionY - random.randrange( 20, 200 ) and self.playerCharacter._positionY <= i.positionY + random.randrange( 20, 200 ) and self.playerCharacter._positionX >= i.positionX - random.randrange( 20, 200 ) and self.playerCharacter._positionX <= i.positionX + random.randrange( 20, 200): enemy = Enemy(WalkAnimList[0]) enemy._positionX = i.positionX enemy._positionY = i.positionY Enemies.append(enemy) self.group.add(enemy) count += 1 self.bCanSpawnEnemy = False if count >= 2: count = 0 def Bullet_thread_player(self): if self.currentAnim == CurrentAnim.LEFT: self.facing = -1 self.PlayeBulletOffset = -10 elif self.currentAnim == CurrentAnim.RIGHT: self.facing = 1 self.PlayeBulletOffset = 10 BulletsPlayer.append( Bullet(BulletImage, self.playerCharacter._positionX + self.PlayeBulletOffset, self.playerCharacter._positionY + 20, self.facing)) self.group.add(BulletsPlayer[len(BulletsPlayer) - 1]) def Bullet_thread_enemy(self): for i in Enemies: BulletsEnemy.append( Bullet(BulletImage, i._positionX, i._positionY + 5, i.facing)) self.group.add(BulletsEnemy[len(BulletsEnemy) - 1]) def run(self, done): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() if self.bIsWalking == True: if pygame.time.get_ticks() - self.WalkSoundTimer > 500: runSound.play(0) self.WalkSoundTimer = pygame.time.get_ticks() self.keys = pygame.key.get_pressed() if self.keys[pygame.K_SPACE]: if self.bCanJump == True: jumpSound.play(0) self.bIsJumping = True self.bCanJump = False if self.keys[pygame.K_z]: if self.bCanFire == True: self.bIsFiring = True self.bHasFired = True self.bCanFire = False pistolFire() else: self.bIsFiring = False else: self.bIsFiring = False self.bCanFire = True if self.bIsWalking == False: self.playerCharacter.setAnim(PlayerIdleAnimList[0], self.currentAnim) if self.keys[pygame.K_x]: pass if self.keys[pygame.K_q]: pass if self.keys[pygame.K_e]: if self.bAddEnemy == False: self.bAddEnemy = True else: self.bIsWalking = False if self.keys[pygame.K_DOWN]: self.playerCharacter.bPlayerCrouching = True else: self.playerCharacter.bPlayerCrouching = False if self.bIsWalking == False: self.velX = 0 if self.bIsJumping == True: self.bIsInAir = True self.bCollided = False if self.jumpVel > 0: self.velY -= self.jumpVel self.jumpVel -= 0.03 else: self.jumpVel = 0.5 self.velY = 0 self.bIsJumping = False self.MovementHandle() for sprite in self.group.sprites(): if sprite.bIsPlayer == ObjectType.PLAYER: for i in elevator: if sprite.feet.collidelist( self.walls) > -1 or i.CollideWithElavator == True: self.bCollided = True if self.bIsJumping == False: self.velY = 0 if self.bCanJump == False: if self.bCollided == True: self.bCanJump = True else: self.bCollided = False elif sprite.bIsPlayer == ObjectType.ENEMY: if sprite.feet.collidelist( self.walls) > -1 and i.CollideWithElavator == False: sprite.bCollided = True else: sprite.bCollided = False for i in elevator: if i.CollideWithElavator == False: if self.bCollided == False: self.velY += 0.1 / len(elevator) else: if i.Dir == ElevatorDir.DOWN: if self.bIsJumping == False: self.velY += 1.0 / len(elevator) + 0.82 else: self.velY -= 1.0 * 1.1 for i in Enemies: if i.bCollided == False: i.velY += 0.1 else: i.velY = 0.0 i.setVelocity() i.result = self.playerCharacter._positionX - i._positionX i.updateDir() #print(i.result) if i.result <= 100 and i.result >= -100 and i._positionY >= self.playerCharacter._positionY - 20 and i._positionY <= self.playerCharacter._positionY + 20: i.AIRotate() i.velocityX = 0 if i.bIsFiring == True and i.result <= 600 and i.result >= -600 and i._positionY >= self.playerCharacter._positionY - 20 and i._positionY <= self.playerCharacter._positionY + 20: thread = threading.Thread(target=self.Bullet_thread_enemy) enemyGun.play(0) thread.start() i.bIsFiring = False if i.bIsFiring == False: if pygame.time.get_ticks( ) - i.FireUpdate > self.FireDelay * random.randrange(2, 8): i.bIsFiring = True i.FireUpdate = pygame.time.get_ticks() i.UpdatePosition() if i.bIsDead == False: if i.velocityX != 0: i.UpdateAnim(self.animDelay) else: i.setAnim(IdleAnimList[0]) else: i.UpdateAnim(self.animDelay) if self.playerCharacter.right.collidelist(self.walls) > -1: self.bCanMoveRight = False else: self.bCanMoveRight = True if self.playerCharacter.left.collidelist(self.walls) > -1: self.bCanMoveLeft = False else: self.bCanMoveLeft = True for i in Enemies: if i.left.collidelist(self.walls) > -1: i.velocityX = 0 i.facing = 1 elif i.right.collidelist(self.walls) > -1: i.velocityX = 0 i.facing = -1 if self.bIsFiring == True: self.playerCharacter.bPlayShootingAnim = True if self.playerCharacter.bPlayShootingAnim == False: if self.playerCharacter.bPlayerCrouching == False: if self.bIsWalking == True: self.playerCharacter.setAnim( PlayerWalkAnimList[self.WalkAnimIndex], self.currentAnim) if self.WalkAnimIndex < len(PlayerWalkAnimList) - 1: if pygame.time.get_ticks( ) - self.lastUpdate > self.animDelay: self.WalkAnimIndex += 1 self.lastUpdate = pygame.time.get_ticks() else: self.WalkAnimIndex = 0 else: self.WalkAnimIndex = 0 else: self.playerCharacter.setAnim( playerCrouchAnimList[self.CrouchAnimIndex], self.currentAnim) if self.CrouchAnimIndex < len(playerCrouchAnimList) - 1: if pygame.time.get_ticks( ) - self.lastUpdate > self.animDelay: self.CrouchAnimIndex += 1 self.lastUpdate = pygame.time.get_ticks() else: self.CrouchAnimIndex = len(playerCrouchAnimList) - 1 else: self.playerCharacter.PlayShootAnim(self.currentAnim) self.playerCharacter.setVelocity(self.velX, self.velY) if self.bCanSpawnEnemy == True: threadAddEnemy = threading.Thread(target=self.AddEnemy_thread) threadAddEnemy.start() if self.bCanSpawnEnemy == False: if pygame.time.get_ticks() - self.SpawnlastUpdate > 8000: self.SpawnlastUpdate = pygame.time.get_ticks() self.bCanSpawnEnemy = True self.group.center(self.playerCharacter.rect.center) self.playerCharacter.UpdatePosition() #print(self.bCanSpawnEnemy) if self.bIsFiring == True: thread = threading.Thread(target=self.Bullet_thread_player) thread.start() if BulletsPlayer: for i in BulletsPlayer: i.UpdatePosition() #print("[ "+str(i.positionX)+", "+str(i.positionY)+" ]") if i.positionX > W or i.positionX < 0: self.group.remove(i) BulletsPlayer.pop(BulletsPlayer.index(i)) if len(BulletsPlayer) > 20: for i in BulletsPlayer: BulletsPlayer.pop(BulletsPlayer.index(i)) if BulletsEnemy: for i in BulletsEnemy: i.UpdatePosition() if i.positionX > W or i.positionX < 0: self.group.remove(i) BulletsEnemy.pop(BulletsEnemy.index(i)) for i in elevator: if self.playerCharacter.rect[ 1] >= i.rect[1] - 20 and self.playerCharacter.rect[ 1] <= i.rect[1] + 20 and self.playerCharacter.rect[ 0] >= i.rect[0] - 50 and self.playerCharacter.rect[ 0] <= i.rect[0] + 50: i.CollideWithElavator = True else: i.CollideWithElavator = False i.setVelocity() i.UpdatePosition() for i in Enemies: if i._positionY >= self.playerCharacter._positionY + 200 or i._positionY <= self.playerCharacter._positionY - 200: self.group.remove(i) Enemies.pop(Enemies.index(i)) if i.velocityY > 20: self.group.remove(i) Enemies.pop(Enemies.index(i)) if i.bDeathAnimCompleted == True: self.group.remove(i) Enemies.pop(Enemies.index(i)) for i in BulletsPlayer: if i.rect.collidelist(self.walls) > -1: self.group.remove(i) BulletsPlayer.pop(BulletsPlayer.index(i)) for i in BulletsEnemy: if i.rect.collidelist(self.walls) > -1: self.group.remove(i) BulletsEnemy.pop(BulletsEnemy.index(i)) for i in BulletsPlayer: for j in Enemies: if (i.rect[1] <= j.rect[1] + 20 and i.rect[1] >= j.rect[1] - 20 ) and (i.rect[0] <= j.rect[0] + 5 and i.rect[0] >= j.rect[0] - 5): j.bIsDead = True if pygame.time.get_ticks( ) - self.ScoreIncreaseTimer > 1000: self.score += 50 self.ScoreIncreaseTimer = pygame.time.get_ticks() self.bHealthCheck = True hitmarkSound.play(0) self.group.remove(i) try: BulletsPlayer.pop(BulletsPlayer.index(i)) except: continue for i in BulletsEnemy: if self.playerCharacter.bPlayerCrouching == False and self.bIsJumping == False: if (i.rect[1] <= self.playerCharacter.rect[1] + 20 and i.rect[1] >= self.playerCharacter.rect[1] - 20 ) and (i.rect[0] <= self.playerCharacter.rect[0] + 5 and i.rect[0] >= self.playerCharacter.rect[0] - 5): #print("PLAYER HIT") self.playerCharacter._positionY -= 4 print(i.facing) if i.facing < 0: self.playerCharacter._positionX -= 5 elif i.facing > 0: self.playerCharacter._positionX += 5 self.health -= 1 self.score -= 75 damageTakenSound.play(0) self.group.remove(i) BulletsEnemy.pop(BulletsEnemy.index(i)) if self.score == 250 and self.bHealthCheck == True: self.health += 1 hpGain.play(0) self.bHealthCheck = False if self.score == 500 and self.bHealthCheck == True: self.health += 1 hpGain.play(0) self.bHealthCheck = False if self.score == 750 and self.bHealthCheck == True: self.health += 1 hpGain.play(0) self.bHealthCheck = False if self.score == 1000 and self.bHealthCheck == True: self.health += 1 hpGain.play(0) self.bHealthCheck = False if self.score == 1500 and self.bHealthCheck == True: self.health += 1 hpGain.play(0) self.bHealthCheck = False if self.score == 2000 and self.bHealthCheck == True: self.health += 2 hpGain.play(0) self.bHealthCheck = False if self.score == 3000 and self.bHealthCheck == True: self.health += 3 hpGain.play(0) self.bHealthCheck = False if self.score == 4000 and self.bHealthCheck == True: self.health += 3 hpGain.play(0) self.bHealthCheck = False if self.score == 5000 and self.bHealthCheck == True: self.health += 3 hpGain.play(0) self.bHealthCheck = False if self.score == 10000 and self.bHealthCheck == True: self.health += 5 hpGain.play(0) self.bHealthCheck = False if self.playerCharacter._positionX >= 687 - 40 and self.playerCharacter._positionX <= 687 + 40 and self.playerCharacter._positionY >= 4657 - 40 and self.playerCharacter._positionY <= 4657 + 40: self.bLevelPassed = True if self.health <= 0: self.bGameOver = True print( str(self.playerCharacter._positionX) + ", " + str(self.playerCharacter._positionY)) self.group.draw(screen) draw_score(screen, 30, 30, self.score) draw_health(screen, 1120, 30, self.health) pygame.display.flip() self.clock.tick(60)
class Invertibles(object): filename = get_map(MAP_FILENAME) def __init__(self): pygame.mixer.pre_init(44100, 16, 1, 4096) pygame.init() pygame.font.init() self.screen = init_screen(800, 600) pygame.display.set_caption('Polaria') # Music channel self.music_channel = pygame.mixer.Channel(1) self.sounds = Sounds() # Store projectiles in a group self.projectiles = Group() # true while running self.running = False # load data from pytmx tmx_data = load_pygame(self.filename) # setup level geometry with simple pygame rects, loaded from pytmx self.walls = list() for object in tmx_data.objects: self.walls.append( pygame.Rect(object.x, object.y, object.width, object.height)) # create new data source for pyscroll map_data = pyscroll.data.TiledMapData(tmx_data) # create new renderer (camera) self.map_layer = pyscroll.BufferedRenderer(map_data, self.screen.get_size()) self.map_layer.zoom = 3.75 # pyscroll supports layered rendering. our map has 3 'under' layers # layers begin with 0, so the layers are 0, 1, and 2. # since we want the sprite to be on top of layer 1, we set the default # layer for sprites as 2 self.group = PyscrollGroup(map_layer=self.map_layer, default_layer=3) self.hero = Hero() self.heroes = list() self.heroes.append(self.hero) # Spawn an npc self.npc = NPC() self.npc.position = self.map_layer.map_rect.move(544, 592).topleft self.group.add(self.npc) self.npcs = list() self.npcs.append(self.npc) # Spawn an elemental below the house self.spawn_elementals() # Spawn the hero outside his house self.hero.position = self.map_layer.map_rect.move(528, 592).topleft # add our hero to the group self.group.add(self.hero) self.projectile_skin = 0 # Which spell the user has selected self.clock = pygame.time.Clock() # Dictionary to hold onto what keys are being held down self.movement_keys = { 'UP': False, 'DOWN': False, 'LEFT': False, 'RIGHT': False } def draw(self, surface, text=None): # center the map/screen on our Hero self.group.center(self.hero.rect.center) # draw the map and all sprites self.group.draw(surface) #self.projectiles.draw(self.screen) score = Text(self.screen, str(len(self.elementals)) + " dark elementals remaining", (0, 0, 0), 650, 10) score.blitme() if text: dialogbox = DialogBox(self.screen) dialogbox.blitme() rendered_text = dialogbox.render_textrect(text) if rendered_text: self.screen.blit(rendered_text, dialogbox.textarea_rect) def handle_input(self): """ Handle pygame input events """ poll = pygame.event.poll event = poll() while event: if event.type == QUIT: self.running = False break elif event.type == KEYDOWN: self.check_keydown_events(event) elif event.type == KEYUP: self.check_keyup_events(event) self.move_hero() if not self.running: break # this will be handled if the window is resized elif event.type == VIDEORESIZE: init_screen(event.w, event.h) self.map_layer.set_size((event.w, event.h)) event = poll() def reset_movement_keys(self): """Reset movement keys to False.""" self.movement_keys = { 'UP': False, 'DOWN': False, 'LEFT': False, 'RIGHT': False } def check_keydown_events(self, event): """Check for keypresses and respond to them.""" if event.key == K_ESCAPE or event.key == K_q: self.running = False # Set movement key flags if event.key == K_a: self.reset_movement_keys() self.hero.reset_velocity() self.movement_keys['LEFT'] = True elif event.key == K_d: self.reset_movement_keys() self.hero.reset_velocity() self.movement_keys['RIGHT'] = True elif event.key == K_w: self.reset_movement_keys() self.hero.reset_velocity() self.movement_keys['UP'] = True elif event.key == K_s: self.reset_movement_keys() self.hero.reset_velocity() self.movement_keys['DOWN'] = True # Cast spells if event.key == K_UP: new_projectile = Projectile(self.screen, self.hero, 'UP', self.projectile_skin) self.group.add(new_projectile) self.sounds.fireball.play() elif event.key == K_LEFT: new_projectile = Projectile(self.screen, self.hero, 'LEFT', self.projectile_skin) self.group.add(new_projectile) self.sounds.fireball.play() elif event.key == K_RIGHT: new_projectile = Projectile(self.screen, self.hero, 'RIGHT', self.projectile_skin) self.group.add(new_projectile) self.sounds.fireball.play() elif event.key == K_DOWN: new_projectile = Projectile(self.screen, self.hero, 'DOWN', self.projectile_skin) self.group.add(new_projectile) self.sounds.fireball.play() # Change spells if event.key == K_1: self.projectile_skin = 0 self.sounds.select_spell.play() elif event.key == K_2: self.projectile_skin = 1 self.sounds.select_spell.play() elif event.key == K_3: self.projectile_skin = 2 self.sounds.select_spell.play() elif event.key == K_4: self.projectile_skin = 3 self.sounds.select_spell.play() def check_keyup_events(self, event): """Check for keyreleases and respond to them.""" # Set movement key flags if event.key == K_a: self.movement_keys['LEFT'] = False if event.key == K_d: self.movement_keys['RIGHT'] = False if event.key == K_w: self.movement_keys['UP'] = False if event.key == K_s: self.movement_keys['DOWN'] = False def move_hero(self): """Only move hero if one movement key is being pressed.""" count = 0 key_pressed = '' for key, pressed in self.movement_keys.items(): if pressed: key_pressed = key count += 1 if count == 1: self.hero.set_direction(key_pressed) else: self.hero.set_idle() def update_projectiles(self): """Update position of projectiles and get rid of old bullets.""" # Update projectile positions self.projectiles.update() # Get rid of projectiles that have gone off screen for projectile in self.projectiles.copy(): if projectile.rect.bottom <= 0: self.projectiles.remove(projectile) def update(self, dt): """ Tasks that occur over time should be handled here""" self.group.update(dt) self.update_projectiles() # check if the sprite's feet are colliding with wall # sprite must have a rect called feet, and move_back method, # otherwise this will fail for sprite in self.group.sprites(): if sprite.name == 'hero': if sprite.feet.collidelist(self.walls) > -1: sprite.move_back(dt) elif sprite.feet.collidelist(self.elementals) > -1: sprite.move_back(dt) elif sprite.feet.collidelist(self.npcs) > -1: sprite.move_back(dt) elif sprite.name == 'elemental': if sprite.feet.collidelist(self.walls) > -1: sprite.move_back(dt) elif sprite.feet.collidelist(self.heroes) > -1: sprite.move_back(dt) elif sprite.name == 'projectile': collide_elemental = sprite.rect.collidelist(self.elementals) if sprite.rect.collidelist(self.walls) > -1: self.group.remove(sprite) elif collide_elemental > -1: self.group.remove(sprite) self.group.remove(self.elementals[collide_elemental]) self.elementals.pop(collide_elemental) self.sounds.monster_kill.play() def run(self): """ Run the game loop""" self.running = True self.music_channel.play(self.sounds.town_theme, -1) text = [ 'We, the people of Polaria have summoned thee, the Lord of Light!\n\nPress enter to continue.', 'Our beloved town has been overrun by evil dark elementals! Their dark magic can only be fought with the magic of Light!\n\nPress Enter to continue.', 'Use WASD to move around and the arrow keys to cast your spells. You can switch spells with keys 1-4.\n\nPress Enter to continue.', 'Good luck! And may the power of Light be with you!\n\nPress enter to continue.' ] self.run_dialog(text) while self.running: dt = self.clock.tick(60) / 1000. self.handle_input() self.update(dt) if len(self.elementals) <= 0: self.run_dialog([ "Congratulations! You saved our town! Polaria is safe once more!" ]) self.running = False else: self.draw(self.screen) pygame.display.update() def run_dialog(self, text): self.update(0) while text: self.clock.tick(60) self.draw(self.screen, text[0]) if self.handle_dialog_box_input(): text.remove(text[0]) pygame.display.update() def spawn_elementals(self): """Spawn elementals in random positions on the map.""" self.elementals = list() count = 0 while count < 100: x = randint(0, 1120) y = randint(0, 1120) elemental = Elementals() elemental.position = self.map_layer.map_rect.move(x, y).topleft elemental.set_rect(x, y) if elemental.rect.collidelist(self.walls) == -1: self.elementals.append(elemental) self.group.add(elemental) count += 1 def handle_dialog_box_input(self): for event in pygame.event.get(): if event.type == QUIT: sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_RETURN: return True if event.key == K_ESCAPE or event.key == K_q: sys.exit() if event.type == VIDEORESIZE: init_screen(event.w, event.h) self.map_layer.set_size((event.w, event.h))
class QuestGame(object): """ This class is a basic game. This class will load data, create a pyscroll group, a hero object. It also reads input and moves the Hero around the map. Finally, it uses a pyscroll group to render the map and Hero. """ filename = get_map(MAP_FILENAME) counter = 1 counter2 = 1 def __init__(self, state): if state == False: self.fullscreen = False # true while running. self.running = False self.clock = pygame.time.Clock() # create all the directio variables self.direction = "still" self.EntityDirection = "still" self.EntityDirection1, self.EntityDirection2 = "still", "still" self.fps = 1000 self.bypass = False entityPos1, heroPos1 = False, False # load data from pytmx tmx_data = load_pygame(self.filename) self.tmx_data = tmx_data mapPlay = load_pygame(get_map(stats['map'])) # create new data source for pyscroll map_data = pyscroll.data.TiledMapData(mapPlay) # setup level geometry with simple pygame rects, loaded from pytmx. self.walls = list() for object in mapPlay.objects: self.walls.append( pygame.Rect(object.x, object.y, object.width, object.height)) # create new renderer (camera) self.map_layer = pyscroll.BufferedRenderer(map_data, screen.get_size()) self.map_layer.zoom = 2 self.group = PyscrollGroup(map_layer=self.map_layer, default_layer=4) self.hero = Hero('Tiles/hero/character_still.png') self.entity = Entity('Tiles/hero/character_still.png') self.hero.position = stats['pos'] self.entity.position = stats['pos'] # add our hero to the group self.group.add(self.hero) #self.group.add(self.entity) self.entVel = (0, 0) def deep_thought(self): # The 'AI' function, needs work if self.counter2 % 75 == 0 or self.bypass == True: self.bypass = False if random.randint(0, 1) == 1: self.entity.velocity[0], self.entity.velocity[1] = 0, 0 movement = random.choice([ "self.entity.velocity[0] = -45; self.EntityDirection = 'left'; self.EntityDirection2 = 'left'", "self.entity.velocity[0] = 45; self.EntityDirection = 'right'; self.EntityDirection2 = 'right'", "self.entity.velocity[1] = -45; self.EntityDirection = 'up'; self.EntityDirection1 = 'up'", "self.entity.velocity[1] = 45; self.EntityDirection = 'down'; self.EntityDirection1 = 'down'" ]) exec(movement) def EntityAnimation(self, direction, number, character="hero"): self.entVel = self.entity.velocity self.counter += 1 if self.EntityDirection1 == "still" and self.EntityDirection2 == "still": if self.EntityDirection == "left": self.entity = Entity('Tiles/' + character + '/walking_left/walking_left1.png') if self.EntityDirection == "right": self.entity = Entity('Tiles/' + character + '/walking_right/walking_right1.png') if self.EntityDirection == "up": self.entity = Entity('Tiles/' + character + '/walking_up/walking_up1.png') if self.EntityDirection == "down": self.entity = Entity('Tiles/' + character + '/walking_down/walking_down1.png') else: self.entity = Entity('Tiles/' + character + '/walking_' + direction + '/walking_' + direction + str(number) + '.png') self.entity.velocity = self.entVel def EntMoveBack(self): #self.deep_thought(self, True) # Comment this to disable the 'AI' pass def map_change(self, map, target=False): # Does what it says on the tin mapfile = get_map(map) tmx_data = load_pygame(mapfile) self.tmx_data = tmx_data map_data = pyscroll.data.TiledMapData(tmx_data) self.walls = list() for object in tmx_data.objects: self.walls.append( pygame.Rect(object.x, object.y, object.width, object.height)) # creates new 'camera' self.map_layer = pyscroll.BufferedRenderer(map_data, screen.get_size()) self.map_layer.zoom = 2 self.group = PyscrollGroup(map_layer=self.map_layer, default_layer=4) #creates a new Hero to go on our new camera self.hero = Hero('Tiles/hero/character_still.png') try: self.hero.position = (target) except TypeError: self.hero.position = self.map_layer.map_rect.center self.map = stats['map'][:-4].lower() self.map = self.map.lstrip( "m") # Fix that stupid bug that changes "maze1" to "ze1" self.map = self.map.lstrip("aps/") def switcher( self ): # Bunch of IF statements to decide if we're at a door or not, then changes the map. if len(objectX) == len(objectY) == len(targetPosX) == len(targetPosY) == len(currentMap) == \ len(targetMap) == len(animationDirection) == len(targetMapFile) == len(objectType): heroPos = [0, 0] heroPos[0], heroPos[1] = self.hero.position[0], self.hero.position[ 1] for i in range(len(objectX)): if self.map == currentMap[i]: if self.hero.position[0] - 15 <= int( objectX[i]) <= self.hero.position[0] + 15: if self.hero.position[1] - 15 <= int( objectY[i]) <= self.hero.position[1] + 15: if objectType[i] == "door": used[i] = True self.map_change(targetMapFile[i]) self.map = targetMap[i] stats['map'] = targetMapFile[i] heroPos = (int(targetPosX[i]), int(targetPosY[i])) self.animation(animationDirection[i], 1) self.hero.position = heroPos return False elif objectType[i] == "chest": keyset, self.menu = "chest", "chest" if used[i] == False: if chestContents[i] == None and used[ i] == False: used[i] = True pickle.dump( used, open( os.path.join( "data", "saves", "used.dat"), "wb")) chestContents[i] = self.genchests() pickle.dump( chestContents, open( os.path.join( "data", "saves", "chestContents.dat"), "wb")) self.chestNo = i return False def generate_surrounding_maps(self): heroPos = [0, 0] heroPos = self.hero.position if int(self.hero.position[0]) in range((self.tmx_data.width * 32) - 64, (self.tmx_data.width * 32)): target = (32, heroPos[1]) self.grid[0] = self.grid[0] + 1 try: self.map_change( str(self.grid[0] + 1) + ", " + str(self.grid[1]) + ".tmx", target) self.map = str(self.grid).lstrip("[").rstrip("]") stats['map'] = self.map + ".tmx" self.animation("right", 1) target = (32, heroPos[1]) #self.hero.position = target except FileNotFoundError: self.generate_new_map(4, 16, 2, self.grid, target) elif int(self.hero.position[1]) in range( (self.tmx_data.height * 32) - 64, self.tmx_data.width * 32): target = (heroPos[0], 32) self.grid[1] = self.grid[1] + 1 try: self.map_change( str(self.grid[0]) + ", " + str(self.grid[1] + 1) + ".tmx", target) self.map = str(self.grid).lstrip("[").rstrip("]") stats['map'] = self.map + ".tmx" heroPos[0], heroPos[1] = self.hero.position[ 0], self.hero.position[1] self.animation("up", 1) except FileNotFoundError: self.generate_new_map(4, 16, 2, self.grid, target) elif int(self.hero.position[0]) in range(0, 64): target = (self.tmx_data.width * 32 - 32, heroPos[1]) self.grid[0] = self.grid[0] - 1 try: self.map_change( str(self.grid[0] - 1) + ", " + str(self.grid[1]) + ".tmx", target) self.map = str(self.grid).lstrip("[").rstrip("]") stats['map'] = self.map + ".tmx" heroPos[0], heroPos[1] = self.hero.position[ 0], self.hero.position[1] self.animation("left", 1) #self.hero.position = target except FileNotFoundError: self.generate_new_map(4, 16, 2, self.grid, target) elif int(self.hero.position[1]) in range(0, 64): target = (heroPos[0], self.tmx_data.height * 32 - 32) self.grid[1] = self.grid[1] - 1 try: self.map_change( str(self.grid[0]) + ", " + str(self.grid[1] - 1) + ".tmx", target) self.map = str(self.grid).lstrip("[").rstrip("]") stats['map'] = self.map + ".tmx" heroPos[0], heroPos[1] = self.hero.position[ 0], self.hero.position[1] self.animation("down", 1) #self.hero.position = target except FileNotFoundError: self.generate_new_map(4, 16, 2, self.grid, target) else: pass def generate_new_map(self, octaves, freq, area, target, position): command = "{}/lib/generate/__init__.py".format(os.getcwd()) if sys.platform.startswith('win32'): executeable = ("Python35\python.exe") elif sys.platform.startswith('linux'): executeable = ("python3.5") for y in range(self.grid[1] + eval("-" + str(area)), self.grid[1] + area): for x in range(self.grid[0] + eval("-" + str(area)), self.grid[0] + area): if os.path.isfile("data/maps/" + str(x) + ", " + str(y) + ".tmx"): pass else: p = subprocess.Popen([ executeable, command, ("data/maps/" + str(x) + ", " + str(y) + ".tmx"), str(octaves), str(freq), str(x), str(y) ], close_fds=True) try: if p is not None: disp_width, disp_height = pygame.display.get_surface( ).get_size() #self.blit_inventory("speach", "Generating Map... Please Wait...") self.speach(disp_width, disp_height, "Generating Map... Please Wait...") pygame.display.update() p.wait() self.map_change( (str(target[0]) + ", " + str(target[1]) + ".tmx"), position) self.map = str(self.grid).lstrip("[").rstrip("]") stats['map'] = self.map + ".tmx" except UnboundLocalError: pass def draw(self, surface): self.group.center(self.hero.rect.center) # draw the map and all sprites self.group.draw(surface) def speach(self, dispWidth, dispHeight, text): ## text = "Laudem bonorum salutandi pri te, tollit melius delicata mel cu,\ ## eu mea ullum legimus. Probo debitis te vel. Labores vulputate \ ## argumentum sea id. Cibo vitae vocent eos no, ne odio molestiae\ ## duo." screen.blit( pygame.transform.scale( load_image(os.path.join("images", "gui", "speach.png")), (dispWidth, 150)), (0, dispHeight - 150)) text = textwrap.wrap(text, width=95) for i, line in enumerate(text): text_blit = pixel_font.render(line, False, pygame.Color('white')) screen.blit(text_blit, (60, dispHeight - 110 + 25 * i)) def map_generate(self, output, octaves, freq, x, y): command = "{}/lib/generate/__init__.py".format(os.getcwd()) if sys.platform.startswith('win32'): executeable = ("Python35\python.exe") elif sys.platform.startswith('linux'): executeable = ("python3.5") subprocess.Popen([ executeable, command, output, str(octaves), str(freq), str(x), str(y) ], close_fds=True) def handle_input(self, keyset): """ Handle pygame input events """ poll = pygame.event.poll event = poll() while event: if event.type == QUIT: self.running = False pygame.quit() break elif event.type == KEYDOWN: if keyset == "game": if event.key == K_EQUALS: self.map_layer.zoom += .25 elif event.key == K_MINUS: value = self.map_layer.zoom - .25 if value > 0: self.map_layer.zoom = value else: self.map_layer.zoom = 0.1 elif event.key == K_KP0: try: if self.switcher() == True: self.generate_surrounding_maps() except FileNotFoundError: print("Exception Caught") pass elif event.key == K_e: self.menu = "inventory" pass if event.key == K_ESCAPE: for i in attack_stats_types: stats[i] = attack_stats[i] pickle.dump( stats, open(os.path.join("data", "saves", "save.dat"), "wb")) pickle.dump( inventory, open( os.path.join("data", "saves", "inventory.dat"), "wb")) self.running = False pygame.quit() print(" ") sleep(0.5) print("Shutdown... Complete") sys.exit() break if keyset != "game": if event.key == K_ESCAPE: self.menu = "game" pass if keyset == "inventory": if event.key == K_r: self.genchests() if keyset == "chest": if event.key == K_r: chestContents[self.chestNo] = self.genchests() if event.key == K_t: if taken[self.chestNo] != True: self.takeChest() taken[self.chestNo] = True pickle.dump( taken, open( os.path.join("data", "saves", "taken.dat"), "wb")) if keyset == "attack": pass #Basically just debug keys if event.key == K_KP1: self.menu = "game" pass elif event.key == K_KP2: self.map_change(FOREST) self.map = "forest" elif event.key == K_KP3: self.generate_new_map(4, 16, 3) pass elif event.key == K_KP4: self.map_generate( str(self.grid[0]) + ", " + str(self.grid[1]) + ".tmx", 4, 16.0, self.grid[0], self.grid[1]) pass elif event.key == K_KP5: self.enemy_stats = self.gen_enemy(attack_stats, enemy_stats) self.menu = "attack" pass elif event.key == K_KP6: print("X :" + str(int(self.hero.position[0])) + ", Y: " + str(int(self.hero.position[1])) + ", Map: " + self.map) pass elif event.key == K_KP7: print(str(pygame.mouse.get_pos())) pass elif event.key == K_KP8: sleep(0.5) elif event.key == K_KP9: editor = db_interface.Editor() conn = sqlite3.connect('data/saves/data.db') c = conn.cursor() for var in vars: exec("del " + var + "[:]") for data in c.execute( "SELECT {} FROM csv".format(var)): data = str(data[0]) exec("{}.append(\"{}\")".format(var, data)) pass elif event.key == K_F11: for m in screeninfo.get_monitors(): displ = str(m) w, h, mx, c = displ.split(", ") if self.fullscreen: self.fullscreen = False screen = init_screen( 1024, 700, pygame.HWSURFACE | pygame.FULLSCREEN) else: self.fullscreen = True screen = init_screen( w, h, pygame.HWSURFACE | pygame.RESIZABLE) pygame.display.toggle_fullscreen() elif event.type == VIDEORESIZE: self.map_layer.set_size((event.w, event.h)) dispHeight = event.h dispWidth = event.w event = poll() # using get_pressed is slightly less accurate than testing for events # but is much easier to use. if keyset == "game": pressed = pygame.key.get_pressed() if pressed[K_UP]: self.hero.velocity[1] = -HERO_MOVE_SPEED self.direction = "up" self.direction2 = "up" elif pressed[K_DOWN]: self.hero.velocity[1] = HERO_MOVE_SPEED self.direction = "down" self.direction2 = "down" elif pressed[K_w]: self.hero.velocity[1] = -HERO_SPRINT_SPEED self.direction = "up" self.direction2 = "up" elif pressed[K_s]: self.hero.velocity[1] = HERO_SPRINT_SPEED self.direction = "down" self.direction2 = "down" else: self.hero.velocity[1] = 0 self.direction2 = "still" if pressed[K_LEFT]: self.hero.velocity[0] = -HERO_MOVE_SPEED self.direction = "left" self.direction1 = "left" elif pressed[K_RIGHT]: self.hero.velocity[0] = HERO_MOVE_SPEED self.direction = "right" self.direction1 = "right" elif pressed[K_a]: self.hero.velocity[0] = -HERO_SPRINT_SPEED self.direction = "left" self.direction1 = "left" elif pressed[K_d]: self.hero.velocity[0] = HERO_SPRINT_SPEED self.direction = "right" self.direction1 = "right" else: self.hero.velocity[0] = 0 self.direction1 = "still" if self.direction1 == "still" and self.direction2 == "still": self.direction = "still" def update(self, dt): """ Tasks that occur over time should be handled here """ self.group.update(dt) # check if the sprite's feet are colliding with wall # sprite must have a rect called feet, and move_back method, # otherwise this will fail for sprite in self.group.sprites(): if sprite.feet.collidelist(self.walls) > -1: sprite.move_back(dt) def animation(self, direction, number): if self.direction1 == "still" and self.direction2 == "still": if self.direction == "left": self.hero = Hero('Tiles/hero/walking_left/walking_left1.png') if self.direction == "right": self.hero = Hero('Tiles/hero/walking_right/walking_right1.png') if self.direction == "up": self.hero = Hero('Tileshero/walking_up/walking_up1.png') if self.direction == "down": self.hero = Hero('Tiles/hero/walking_down/walking_down1.png') else: self.hero = Hero('Tiles/hero/walking_' + direction + '/walking_' + direction + str(number) + '.png') def genchests(self): wr = WeightedRandomizer(itemsProbability) self.taken = False chest.clear() numItems = random.randint(1, random.randint(2, 4)) if random.randint(0, 3) < 1: numItems += 1 elif random.randint(0, 9) < 2: numItems += 2 elif random.randint(0, 18) < 2: numItems += 5 for i in range(0, numItems): item = wr.random() while item in chest: item = wr.random() chest.append(item) return chest def gen_enemy(self, player_stats, enemy_stat): stats = attack_stats_types stat = player_stats for i in range(len(player_stats)): j = stats[i] try: enemy_stat[ stats[i]] = int((stat[j] - (stat[j] * 0.2)) + random.randint(0, int(stat[j] * 0.4))) except TypeError: enemy_stat[j] = choice(attack_types) return enemy_stat pass def player_attack(): type = None while type not in attack_types: type = input("[ QUESTION ] Enter attack type. ") if type not in attack_types: print( "[ ERROR ] Attack type {} not found. Must be {}".format( type, attack_types)) else: break return type pass def attack(self, attacker_stats, defender_stats, player_attack_type): fraction = attacker_stats['strength'] / defender_stats['blocking'] print("[ INFO ] Defender attack type: {}".format( defender_stats['attack'])) if player_attack_type != defender_stats['attack']: if fraction > (0.8 + (randint(0, 40) / 100)): attacker_stats['health'] -= int(fraction * 10) pass # Attacker Win else: defender_stats['health'] -= int(fraction * 10) pass # Attacker Loss elif player_attack_type == attacker_stats[ 'attack']: # Better odds here if fraction > (0.9 + (randint(0, 40) / 100)): attacker_stats['health'] -= int(fraction * 10) pass # Attacker Win else: defender_stats['health'] -= int(fraction * 10) pass # Attacker Loss else: if fraction > (0.70 + (randint(0, 40) / 100)): # Odds are worse here attacker_stats['health'] -= int(fraction * 10) pass # Attacker Win else: defender_stats['health'] -= int(fraction * 10) pass # Attacker Loss print("[ INFO ] Attacker: {} Defender: {}".format( attacker_stats['health'], defender_stats['health'])) print("[ INFO ] Health to be lost: {}".format(int(fraction * 10))) return attacker_stats, defender_stats def blit_inventory(self, screenMode, speach=None): if screenMode != "game": xCounter, counter, OverCounter = 0, 0, 0 dispWidth, dispHeight = pygame.display.get_surface().get_size() guiX = (dispWidth / 2) - 175 guiY = (dispHeight / 2) - 165 screen.blit( load_image(os.path.join("images", "gui", "transparent.png")), (0, 0)) screen.blit( load_image(os.path.join("images", "gui", screenMode + ".png")), (guiX, guiY)) if screenMode == "inventory" or screenMode == "chest": dt = (clock.tick() / 500) clock.tick(self.fps) if len(inventory) > 0: for i in range(0, len(inventory)): OverCounter += 1 if xCounter >= 9: counter += 1 xCounter = 0 screen.blit(load_image(os.path.join("images", "items",\ str(items[inventory[i]])+".png")), (guiX + 16 + 36*xCounter, guiY + 168 + 36*counter)) xCounter += 1 if screenMode == "chest" and chestContents[self.chestNo] != None: itemNo = 0 for i in range(0, len(chestContents[self.chestNo])): screen.blit(load_image(os.path.join("images", "items",\ items[str(chestContents[self.chestNo][i])]\ +".png")), (guiX + 123 + 36*itemNo,\ guiY + 34 + int(35 * (i/3)) - int(35 * (i/3)) % 35)) if itemNo < 2: itemNo += 1 else: itemNo = 0 if screenMode == "speach": self.speach(dispWidth, dispHeight, speach) if screenMode == "attack": picture = load_image( os.path.join("Tiles", "hero", "walking_down", "walking_down1.png")) picture = pygame.transform.scale(picture, (100, 100)) rect = picture.get_rect() rect = rect.move((guiX + 50, guiY + 28)) screen.blit(picture, rect) text = font.render("Player : Enemy", True, pygame.Color('black')) screen.blit(text, (guiX + 172, guiY + 45)) text = "Health: " + str( attack_stats['health']) + " Skill: " + str( attack_stats['skill']) + " Attack: " + str( attack_stats['attack']) text_render = pixel_font.render(text, False, pygame.Color('gray27')) screen.blit(text_render, (guiX + 20, guiY + 290)) for i, attack in enumerate(attack_types): text = load_font(30, "data/PixelFont.ttf").render( attack, False, pygame.Color('black')) screen.blit(text, (guiX + 172, guiY + 25 + 28 * (i + 2))) # if pygame.mouse.get_pressed()[0] == 1: #print(pygame.mouse.get_pos()) mouse_pos = pygame.mouse.get_pos() if guiX + 160 < mouse_pos[0] and guiX + 330 > mouse_pos[0]: for i, attack in enumerate(attack_types): if guiY + 25 + 28 * (i + 2) < mouse_pos[1] and ( guiY + 25 + 28 * (i + 2)) + 28 > mouse_pos[1]: print(attack) self.attack(attack_stats, enemy_stats, attack) else: pass pass def takeChest(self): if len(inventory) < 27: if chestContents[self.chestNo] != None: for i in range(0, (len(chestContents[self.chestNo]))): #print(i) inventory.append(chestContents[self.chestNo][i]) chestContents[self.chestNo][:] = [] pickle.dump( chestContents, open(os.path.join("data", "saves", "chestContents.dat"), "wb")) def run(self): screenMode = pygame.RESIZABLE oldPlay = stats['playTime'] clock = pygame.time.Clock() self.running = True self.grid = [0, 0] debug = True dispWidth, dispHeight = 1024, 768 self.menu = "game" game_time = pygame.time.get_ticks() playTime = font.render("Timer: ", False, pygame.Color('white')) minutes = 0 self.map = stats['map'][:-4].lower() self.map = self.map.lstrip( "m") # Fix that stupid bug that changes "maze1" to "ze1" self.map = self.map.lstrip("aps/") try: while self.running: dt = (clock.tick() / 500) clock.tick(self.fps) if self.menu == "game": #self.deep_thought() if self.counter2 % 7 == 0: heroPos = self.hero.position self.animation(self.direction, self.counter) self.hero.position = heroPos #entityPos = self.entity.position #self.EntityAnimation(self.EntityDirection, self.counter, "princess") #self.entity.position = entityPos self.counter += 1 guiX = (dispWidth / 2) - 175 guiY = (dispHeight / 2) - 165 self.group.remove(self.hero) #self.group.remove(self.entity) self.group.empty() self.group.add(self.hero) #self.group.add(self.entity) self.counter2 += 1 if self.counter > 8: self.counter = 1 stats['pos'] = self.hero.position currentTime = systime() seconds = currentTime - gameStart + oldPlay dispWidth, dispHeight = pygame.display.get_surface().get_size() stats['playTime'] = seconds if debug == True and self.counter2 % 1 == 0: location = font.render( "Position: " + str(round(round(self.hero.position[0], -1) / 10)) + ", " + str(round(round(self.hero.position[1], -1) / 10)), False, pygame.Color('white')) mapdebug = font.render("Map Name: " + str(self.map), False, pygame.Color('white')) minutes = seconds // 60 secondsDisp = seconds % 60 if minutes < 1: minutes = 0 if secondsDisp == 60: secondsDisp = 0 minutes += 1 fps = font.render("FPS:" + str(int(clock.get_fps())), False, pygame.Color('white')) screen.blit(fps, (50, 50)) screen.blit(playTime, (50, 100)) screen.blit(location, (50, 75)) screen.blit(mapdebug, (50, 125)) playTime = font.render( "Timer: " + str(floor(minutes)) + " : " + str(round(secondsDisp)), True, pygame.Color('white')) screen.blit(playTime, (50, 100)) self.blit_inventory(str(self.menu)) pygame.display.update() #pygame,display.flip() self.handle_input(self.menu) self.update(dt) self.draw(screen) except KeyboardInterrupt: self.running = False pygame.quit()