单词炮弹.py (操作大炮打英文单词)

"""本版本新增Sprite类,它定义可旋转360度的角色类,继承自海龟类,使用pillow模块让它旋转360次"""

import os
import sys 
import math
import time
import tempfile
from PIL import Image
from turtle import Turtle,Screen
from bullet import *               # 导入子弹类
from sprite import *               # 导入角色类,建大炮
from word import *                 # 导入单词类
from explosion import *            # 导入爆炸类

def get_mouse_xy():
    """获取鼠标指针的坐标"""
    mousex = Sprite.mousex
    mousey = Sprite.mousey
    return mousex,mousey

def shoot(x,y):
    speed = 10
    position = (x,y)
    image = "bullet.png"
    angle =  sprite.heading()
    Bullet(position,speed,angle,image,bullet_group)

def check_collide(word_group,bullet_group):
    """碰撞检测"""
    global score
    removed_word = set()
    removed_bullet = set()
    wg = word_group.copy()       # 由于在迭代的过程中可能会改变集合所以用副本
    bg = bullet_group.copy()
    for word in wg:
        for bullet in bg:
            if bullet.distance(word) < 100 and bullet.isvisible() and word.isvisible():
                pos = word.position()
                explosion(pos,explosion_images)   # 爆炸效果
                bullet.ht()                       # 隐藏弹药
                word.ht()                         # 隐藏单词
                if word.isgood == True:            # 翻译正确的加10分
                    score +=10
                else:                             # 否则减10分
                    score -=10
                screen.title("得分:" + str(score))
                removed_word.add(word)            # 放到待移除集合
                removed_bullet.add(bullet)        # 放到待移除集合
    removed_word.clear()
    removed_bullet.clear()
       
if __name__ == "__main__":

    score = 0                       # 得分
    explosion_images = glob("explosion/*.gif")
    sprite_image = "大炮.png"       # 大炮图
    word_group = set()
    bullet_group = set()
    
    screen = Screen()
    screen.delay(0)
    screen.setup(800,600)
    screen.colormode(255)
    screen.bgcolor((4,21,104))
    [screen.addshape(image) for image in explosion_images]
    
    sprite = Sprite(sprite_image)   # 新建角色
    sprite.penup()
    screen.onclick(shoot)           # 单击发射子弹
    from wordict import *           # 导入wordict字典
    begin_time = time.time()        # 起始时间
    while True:
       check_collide(word_group,bullet_group)
       if time.time() - begin_time > 2:
           string = list(wordict.keys())
           string = choice(string)        
           Word((0,0),string,wordict[string],word_group) # 生成单词
           begin_time = time.time()
            
       sprite.facemouse()
       x ,y = get_mouse_xy()
       if x ==None and y == None :screen.update();continue
       if sprite.distance(get_mouse_xy())>50:
          sprite.fd(1)
    
    screen.listen()
    screen.mainloop() 


    

单词炮弹作者李兴球操作大炮打英文单词

以下是Sprite类 ,用pillow模块突破海龟画图像块里当海龟造型为图片时不能旋转的“缺憾”:

"""本程序定义可旋转360度的角色类,它继承自海龟类,使用pillow模块让它旋转360次"""

import os
import sys 
import math
import time
import tempfile
from PIL import Image
from turtle import Turtle,Screen
from bullet import *

class Sprite(Turtle):
    screen = Screen()
    mousex = None                 # 类变量,鼠标指针x坐标
    mousey = None                 # 类变量,鼠标指针y坐标
    @classmethod
    def getcursorxy(cls,event):
        Sprite.mousex = Sprite.screen.cv.canvasx(event.x)/Sprite.screen.xscale
        Sprite.mousey = -Sprite.screen.cv.canvasy(event.y)/Sprite.screen.yscale        
         
    def __init__(self,image):
        Turtle.__init__(self,visible=False)       
        self.imagefile = image              # 第一张图,要面向右
        self.path = tempfile.mkdtemp()      # 生成临时文件夹       
        self.allimages = self.rotate360()   # 生成所有方向的图
        self.bat_rename()                   # 如果不是gif全部重命令为gif
        [self.screen.addshape(image) for image in self.allimages]
        self.shape(self.allimages[0])
        self.st()

    def _rotate(self,angle):
        """seth,right,left最终都要调用它,所以重写它就行了"""
        Turtle._rotate(self,angle)         # 调用父类的同名方法
        angle = int(math.degrees(math.atan2(self._orient[1],self._orient[0])))
        self.shape(self.allimages[angle])

    def face(self,x,y):
        """面向x,y坐标"""
        if x == None and y ==None:return
        angle = Turtle.towards(self,x,y)
        self.setheading(angle)
        
    def facemouse(self):
        """面向鼠标指针"""
        self.face(Sprite.mousex,Sprite.mousey)
    
        
    def rotate360(self):
        """旋转图像文件360次,全部保存在path里"""
        images = []
        filename = os.path.basename(self.imagefile)    
        basename = filename.split(".")[0]      # .号前面的字符串
        extname = "." + filename.split(".")[-1]# 扩展名 
        im = Image.open(self.imagefile)
        im = im.convert('RGBA')
        for angle in range(360):
            filename = self.path + os.sep + basename + str(angle) + extname
            im2 = im.rotate(angle,expand=1  )
            im2.save(filename)
            images.append(filename)            
        im.close()
        return images

    def bat_rename(self):
        """成批地把png图像文件扩展名改变为gif"""
        tmp = os.path.splitext(self.imagefile)[-1] # 取扩展名       
        if tmp.lower()==".gif":return              # 判断扩展名
        images = []
        for filename in self.allimages:
            basename = os.path.splitext(filename)[0]
            newfilename = basename + ".gif"
            os.rename(filename,newfilename)
            images.append(newfilename)
        self.allimages = images                   # 重新指向新的列表

def get_mouse_xy():
    """获取鼠标指针的坐标"""
    mousex = Sprite.mousex
    mousey = Sprite.mousey
    return mousex,mousey

def shoot(x,y):
    speed = 10
    position = (x,y)
    image = "bullet.png"
    angle =  sprite.heading()
    Bullet(position,speed,angle,image)
   
Sprite.screen.cv.bind("<Motion>",lambda event:Sprite.getcursorxy(event))
    
if __name__ == "__main__":

    sprite_image = "大炮.png"       # 大炮图
    
    screen = Screen()
    screen.delay(0)
    screen.setup(480,360)
    screen.bgcolor("magenta")
    
    sprite = Sprite(sprite_image)   # 新建角色
    sprite.penup()
    screen.onclick(shoot)           # 单击发射子弹
    while True: 
       sprite.facemouse()
       x ,y = get_mouse_xy()
       if x ==None and y == None :screen.update();continue
       if sprite.distance(get_mouse_xy())>50:
          sprite.fd(1)
    
    screen.listen()
    screen.mainloop()