python3少兒程式設計學習之_坦克大戰射擊遊戲_turtle版原始碼
"""坦克大戰,小坦克被一群大坦克包圍,情況十分危急。小坦克的優勢在於速度快,能連續發射。
"""
#從海龜模組匯入所有命令
from turtle import * import math from random import randint
def load_sound(): """載入聲音與播放背景音樂""" sound_normal = True explode_sound= None shoot_sound = None try: import pygame pygame.mixer.init() pygame.mixer.music.load("音效/newgrounds.wav") pygame.mixer.music.play(-1,0) explode_sound = pygame.mixer.Sound("音效/Boom.wav") shoot_sound = pygame.mixer.Sound("音效/榴彈炮.wav") except: print("播放背景音樂或載入音訊出現錯誤.") sound_normal = False """返回聲音是否正常,爆炸聲,射擊聲三個物件""" return sound_normal,explode_sound,shoot_sound def init_screen(): """初始化螢幕,註冊坦克形狀""" screen = Screen() screen.setup(width,height) p = ((0,0),(50,0),(50,80),(10,80),(10,150),(-10,150),(-10,80),(-50,80),(-50,0)) screen.addshape("tank",p) #註冊tank形狀 screen.bgcolor("blue") #螢幕背景色 screen.title(gametitle) #設定螢幕標題 screen.colormode(255) #設定顏色模式 screen.delay(0) #螢幕延時為0 screen.bgpic("封面設計.png") #封面載入 """新增爆炸造型圖片列表到形狀列表""" explosion_images = ["explosion-" + str(i) + ".gif" for i in range(17)] [screen.addshape(image) for image in explosion_images ] #註冊爆炸造型到形狀列表 return screen,explosion_images
class Bullet(Turtle): """炮彈類,炮彈生成後會自己移動,直到碰到邊緣。""" def __init__(self,x,y,h): Turtle.__init__(self,visible=False,shape="circle") self.penup() self.dead = False self.goto(x,y) self.setheading(h) self.showturtle() self.move() def move(self): """炮彈移動,碰到邊緣就‘死亡’""" self.fd(10) if self.bumpedge():self.dead = True if self.dead: self.hideturtle() del self else: screen.ontimer(self.move,10)
def bumpedge(self): """碰到邊緣返回True,否則False""" return abs(self.xcor())>width/2 or abs(self.ycor())>height/2 class NPCtank(Turtle): deadcount = 0 #統計數量的類變數 def __init__(self,mytank,my_bullet): """敵方坦克的敵人就是mytank,my_bullet是我方炮彈列表""" Turtle.__init__(self,shape='tank',visible=False) self.shapesize(0.3,0.3) color1 = randint(0,255),randint(0,255),randint(0,255) self.color("black",color1) self.penup() self.setheading(randint(1,360)) self.fd(randint(200,height*0.4)) #配合隨機方向讓npc隨機移到一個地方 self.enemy = mytank self.enemy_bullet = my_bullet self.face_enemy() #一出生就面向mytank self.dead = False self.move() def move(self): """移動npc坦克,有時會面向mytank""" self.fd(1) self.shoot() # 設定一定的機率發射炮彈 self.bumpedge() # 碰到螢幕邊緣就向後轉 self.bumpenemy() # 碰到敵人(mytank)後會爆炸,mytank當然也會爆炸,遊戲結束 self.bumpbullet() # 碰到我方炮彈就爆炸 if self.dead: self.hideturtle() #死了後,顯示爆炸效果 bomb = Bomb(self.xcor(),self.ycor(),explosion_images) NPCtank.deadcount = NPCtank.deadcount + 1 info ="當前擊毀敵方坦克數:" + str(NPCtank.deadcount) top_turtle.print(info) if NPCtank.deadcount == tanksamount: bottom_turtle.print("遊戲成功結束,作者:李興球") else: screen.ontimer(self.move,10) def bumpenemy(self): """碰到敵人就兩方都死亡,npc的敵人就是mytank""" r = self.distance(self.enemy) if r <20 and not self.enemy.dead: self.hideturtle() self.dead = True self.enemy.hideturtle() self.enemy.dead = True #mytank爆炸,我方坦克陣亡,在死的位置上顯示爆炸效果 x = self.enemy.xcor() y = self.enemy.ycor() Bomb(x,y,explosion_images) bottom_turtle.print("突圍失敗! 作者:李興球") def bumpbullet(self): """碰到我方炮彈就死亡""" for b in self.enemy_bullet: r = self.distance(b) if r <20: self.hideturtle() self.dead = True break def bumpedge(self): """bumpedge就掉頭""" faraway = abs(self.xcor())>width/2 or abs(self.ycor())>height/2 if faraway:self.right(180) #掉轉頭 def face_enemy(self): """面向敵人,NPC的敵人就是mytank,可以增加程式碼讓轉向更平滑""" self.setheading(self.towards(self.enemy.position())) def shoot(self): """敵坦克的發射方法,同時把‘死了’的炮彈移去""" if randint(0,100) == 1: #有時間會面向mytank self.face_enemy() if randint(0,20) ==1 : b = Bullet(self.xcor(),self.ycor(),self.heading()) #生成炮彈 enemybullet.append(b) #新增到敵方炮彈列表 #移去dead為True的敵方炮彈 for b in enemybullet: if b.dead :enemybullet.remove(b) class Bomb(Turtle): """炸彈類,它例項化後,自己就會切換造型,從而“爆炸”""" def __init__(self,x,y,images): """x,y是爆炸的座標,images是已註冊到螢幕形狀列表的造型圖片""" Turtle.__init__(self,visible=False) self.penup() self.goto(x,y) self.index = 0 #造型索引編號從0開始 self.amount = len(images) #造型數量 self.images = images #造型列表 self.showturtle() #顯示 if snd_normal: explode_sound.play() self.next_costume() #利用螢幕的定時器功能使之迴圈一定的次數 def next_costume(self): if self.index < self.amount: #小於總數量就換造型 self.shape(self.images[self.index]) #從列表取指定索引的圖片,設為海龜的形狀 self.index = self.index + 1 screen.ontimer(self.next_costume,50) else: self.hideturtle() del self def make_mytank(): """生成我方坦克物件,並返回到主程式""" blue= Turtle(shape='tank',visible=False) blue.shapesize(0.2,0.2) #"親生"的形狀可以縮放 blue.penup() blue.pencolor("black") blue.fillcolor("blue") blue.pensize(2) blue.dead = False #增加額外的dead屬性 return blue
def mytank_wait_bump_enemybullet(): """我方坦克每隔10豪秒等待是否碰到敵方炮彈""" if not mytank.dead: for b in enemybullet: #對敵方陣營炮彈列表中的每顆炮彈進行檢測 if b.distance(mytank)<20: #如果炮彈到mytank的距離小於20,認為碰到了炮彈 mytank.hideturtle() #隱藏 mytank.dead = True #標記為“死亡” Bomb(b.xcor(),b.ycor(),explosion_images) #顯示爆炸效果 bottom_turtle.print("突圍失敗! 作者:李興球") break screen.ontimer(mytank_wait_bump_enemybullet,10) #10毫秒檢測一次
def follow_mouse(event): """本函式讓小海龜面朝滑鼠指標移動""" if not mytank.dead: x = event.x - width/2 #轉換成海龜座標系中的x座標 y = height/2 - event.y #轉換成海龜座標系中的y座標 dy = y - mytank.ycor() dx = x - mytank.xcor() angle = math.degrees(math.atan2(dy,dx)) mytank.setheading(angle) if mytank.distance(x,y)>20 :mytank.fd(2) else: screen.cv.bind("<Motion>",None) #取消繫結滑鼠移動事件 def shoot(x,y): """mytank發射函式,被繫結在screen.onclick事件上""" if not mytank.dead: if snd_normal : shoot_sound.play() #如果聲音載入正常,則播放發射聲 b = Bullet(mytank.xcor(),mytank.ycor(),mytank.heading()) mybullet.append(b) #移去dead屬性為True的炮彈 for b in mybullet: if b.dead :mybullet.remove(b) else: screen.onclick(None) #取消單擊事件的函式繫結
class Writer(Turtle): """用來在螢幕上寫字的海龜物件""" def __init__(self,y): Turtle.__init__(self,visible = False) self.penup() self.sety(y) self.color("cyan") self.font = ("黑體",20,"normal") def print(self,string): self.clear() self.write(string,align='center',font=self.font)
def start_game(): screen.bgpic("草地.png") screen.cv.bind("<Motion>",follow_mouse) #畫布繫結滑鼠移動事件 screen.onclick(shoot) #單擊螢幕,繫結發射函式 mytank.showturtle() """生成敵方坦克""" npc = [NPCtank(mytank,mybullet) for i in range(tanksamount)] [enemy.showturtle() for enemy in npc] #顯示每個npc坦克 screen.onkeypress(None,"space") #取消按鍵註冊事件 if __name__ =="__main__": gametitle = "坦克大戰_海龜畫圖版" tanksamount = 20 #坦克數量 width,height=800,700 #螢幕寬度,高度 enemybullet = [] #敵方炮彈列表 mybullet = [] #我方炮彈列表 """聲音是否正常,爆炸聲,射擊聲""" snd_normal,explode_sound,shoot_sound = load_sound() #載入聲音 screen,explosion_images = init_screen() #初始化螢幕,顯示封面,返回screen和爆炸造型列表 mytank = make_mytank() #我方坦克 top_turtle = Writer(310) #頂部寫字龜 top_turtle.print("當前擊毀敵方坦克數:0") #在頂部寫些字 bottom_turtle = Writer(-330) #底部寫字龜 screen.onkeypress(start_game,"space") #註冊按空格事件,生成敵方坦克等等 mytank_wait_bump_enemybullet() #等待碰到敵方炮彈 screen.listen() #給螢幕設定焦點 screen.mainloop() #進入主迴圈 """需要本作品素材請聯絡風火輪少兒程式設計李興球先生"""