利用python3 的pygame模組實現塔防遊戲
阿新 • • 發佈:2020-01-09
利用python3的pygame模組基本實現塔防遊戲的基本功能,包括血量和分數顯示,bgm,防禦塔建造,防禦塔攻擊範圍內的敵軍,暫停和加速功能。由於實在沒有素材,用的都是自己截圖P的,所以美化不好。但基本保證功能,其中有一個BUG,但不影響遊戲效果。
1.執行主類
"""主程式""" from pygame.locals import * from TowerDefend.enemy import * from TowerDefend.towerposSet import * from TowerDefend.tower import * import pygame def run(): """執行函式""" pygame.init() size = width,height = 1200,600 screen = pygame.display.set_mode(size) background_img = pygame.image.load(r'image/background.png').convert_alpha() background_img = pygame.transform.scale(background_img,(width,height)) # 建立分數和血量 health_count = 5 score_count = 0 score = pygame.font.Font('font/score_health.ttf',30) health = pygame.font.Font('font/score_health.ttf',30) # 建立背景音樂 bg_music = pygame.mixer.music bg_music.load('media/bg.mp3') bg_music.set_volume(2) # 建立敵軍類 enemies = pygame.sprite.Group() ENEMY_NUM = 5 position = [[258,600],[258,670],740],810],880]] for i in range(ENEMY_NUM): enemies.add(Enemy(position[i])) # 建立炮塔 towers = pygame.sprite.Group() # 載入暫停鍵 pause_img = pygame.image.load('image/pause.png').convert_alpha() pause_rect = pause_img.get_rect() pause_rect.left,pause_rect.top = 1145,0 # 載入血量和金幣顯示 health_money_img = pygame.image.load('image/health_money.png').convert_alpha() health_money_rect = health_money_img.get_rect() health_money_rect.left,health_money_rect.top = 0,0 # 載入加速鍵 speed_img = pygame.image.load('image/speed.png').convert_alpha() speed_rect = speed_img.get_rect() speed_rect.left,speed_rect.top = 1090,0 # 設定炮塔位置 towers_pos = pygame.sprite.Group() position_list = [[225,495],[264,428],[312,[362,[410,[460,[508,[561,373],[377,373]] for i in range(len(position_list)): towers_pos.add(Position(position_list[i])) # 設定迴圈條件 running = True clock = pygame.time.Clock() paused = False # 播放音樂 if not bg_music.get_busy(): bg_music.play(-1) while running: clock.tick(100) for event in pygame.event.get(): if event.type == QUIT: running = False if event.type == MOUSEBUTTONDOWN: if event.button == 1: if speed_rect.collidepoint(event.pos): for each in enemies: each.accelerate *= 2 if pause_rect.collidepoint(event.pos): paused = not paused for each in towers_pos: if each.rect.collidepoint(event.pos): tower = Tower([each.rect.left,each.rect.top]) towers.add(tower) towers_pos.remove(each) if not paused: for enemy in enemies: if enemy.active: enemy.move() else: if enemy.rect.top <= 180: health_count -= 1 if enemy.rect.top > 180: score_count += 20 enemies.remove(enemy) # 繪製介面設定 screen.blit(background_img,(0,0)) screen.blit(health.render(str(health_count),True,(255,255,255)),(60,0.3)) screen.blit(score.render(str(score_count),(130,0.5)) screen.blit(health_money_img,health_money_rect) screen.blit(pause_img,pause_rect) screen.blit(speed_img,speed_rect) # 繪製炮塔 for each in towers: each.draw(screen,enemies) each.hit(enemies) # 繪製炮塔位置 towers_pos.draw(screen) # 敵軍若存活則繪製其和血量 for enemy in enemies: if enemy.active: screen.blit(enemy.img,enemy.rect) enemy.drawhealth(screen) pygame.display.flip() pygame.quit() if __name__ == "__main__": run() 2.炮塔類 """TOWER""" import pygame import math class Tower(pygame.sprite.Sprite): """tower""" def __init__(self,pos): pygame.sprite.Sprite.__init__(self) self.img0 = pygame.image.load('image/tower0.png') self.img1 = pygame.image.load('image/tower1.png') self.img2 = pygame.image.load('image/tower2.png') self.rect = self.img0.get_rect() self.rect.left,self.rect.top = pos self.count = 1 def draw(self,screen,enemies): """繪製""" if self.count > 90: self.count = 1 if 1 <= self.count < 30: screen.blit(self.img0,self.rect) elif 30 <= self.count < 60: screen.blit(self.img1,self.rect) else: screen.blit(self.img2,self.rect) for enemy in enemies: distance = math.sqrt( math.pow((self.rect.left - enemy.rect.left),2) + math.pow((self.rect.top - enemy.rect.top),2)) if distance < 50 and enemy.active is True: self.count += 1 def hit(self,enemies): """攻擊""" for enemy in enemies: distance = math.sqrt( math.pow((self.rect.left - enemy.rect.left),2)) if distance < 50: enemy.health -= 1 if enemy.health == 0: enemy.active = False
3.敵軍類
import pygame class Enemy(pygame.sprite.Sprite): """小兵類""" def __init__(self,position): pygame.sprite.Sprite.__init__(self) self.img = pygame.image.load(r'image/enemy.png').convert_alpha() self.rect = self.img.get_rect() self.init_pos = position self.rect.left,self.rect.top = self.init_pos self.accelerate = 1 self.speed = [0,-self.accelerate] self.active = True self.health = 500 # 豎直 self.status = 'UP' def move(self): """移動""" self.rect = self.rect.move(self.speed) if self.rect.top <= 448 and self.rect.left == 258: self.rect.top = 448 self.status = 'R' self.img = pygame.transform.rotate(self.img,270) self.speed = [self.accelerate,0] if self.rect.top == 448 and self.rect.left >= 597: self.rect.left = 597 self.status = 'UP' self.img = pygame.transform.rotate(self.img,90) self.speed = [0,-self.accelerate] if 320 < self.rect.top <= 335 and self.rect.left == 597: self.rect.top = 335 self.status = 'L' self.img = pygame.transform.rotate(self.img,90) self.speed = [-self.accelerate,0] if self.rect.top == 335 and self.rect.left <= 370: self.rect.left = 370 self.status = 'UP' self.img = pygame.transform.rotate(self.img,270) self.speed = [0,-self.accelerate] if self.rect.top <= 216 and self.rect.left == 370: self.rect.top = 216 self.status = 'R' self.img = pygame.transform.rotate(self.img,0] if self.rect.top == 216 and 800 > self.rect.left >= 746: self.rect.left = 746 self.status = 'DW' self.img = pygame.transform.rotate(self.img,self.accelerate] if self.rect.top >= 330 and self.rect.left == 746: self.rect.top = 330 self.status = 'R' self.img = pygame.transform.rotate(self.img,90) self.speed = [self.accelerate,0] if self.rect.top == 330 and self.rect.left >= 930: self.rect.left = 930 self.status = 'UP' self.img = pygame.transform.rotate(self.img,-self.accelerate] if self.rect.top < 180: self.active = False def drawhealth(self,screen): """繪製血量""" BLACK = (0,0) RED = (255,0) GREEN = (0,0) health_percentage = float(self.health) / 500 if self.status == 'UP': start = self.rect.left + 8 pygame.draw.line(screen,BLACK,(start,self.rect.top - 3),(start + 32,4) if health_percentage > 0.5: pygame.draw.line(screen,GREEN,(start + 32 * health_percentage,4) else: pygame.draw.line(screen,RED,4) elif self.status == 'DW': start = self.rect.left + 8 pygame.draw.line(screen,self.rect.bottom + 3),4) elif self.status == 'R': start = self.rect.bottom - 8 pygame.draw.line(screen,(self.rect.right + 3,start),start - 32),start - 32 * health_percentage),4) else: start = self.rect.bottom - 8 pygame.draw.line(screen,(self.rect.left - 3,start - 30),start - 30 * health_percentage),4) def reset(self): """reset the position""" self.rect.left,self.rect.top = self.init_pos
4.炮塔建造位置類
"""初始化炮塔可佔據的位置""" import pygame class Position(pygame.sprite.Sprite): """pos""" def __init__(self,pos): pygame.sprite.Sprite.__init__(self) self.image = pygame.image.load('image/pt.png') self.rect = self.image.get_rect() self.rect.left,self.rect.top = pos
5.說明
本遊戲通過滑鼠左鍵點選炮塔可以建造的位置倆建造炮塔。
6.效果圖
可以看到圖確實不好看,但美術功底不夠,所以不怎麼好看。當然需要素材的也可以給你。