1. 程式人生 > >python3少兒程式設計學習之_坦克大戰射擊遊戲_turtle版原始碼

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()                         #進入主迴圈       """需要本作品素材請聯絡風火輪少兒程式設計李興球先生"""