"""坦克大战,小坦克被一群大坦克包围,情况十分危急。小坦克的优势在于速度快,能连续发射。
"""
#从海龟模块导入所有命令
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() #进入主循环
"""需要本作品素材请联系风火轮少儿编程李兴球先生"""