猫史档案馆


【Python作品分享】tkinter制成的飞机大战

用户:就在天边等待你就在天边等待你查看:2 回复:5 评论:2 创建时间:2023-10-28T09:53:16


源代码

from tkinter import *
import random
import pygame


# 初始化pygame
pygame.mixer.init()
pygame.mixer.music.load(r"C:\Users\IBM\Desktop\程序文件\Python文件\小游戏\飞机大战\background music\background_music.mp3")  # 替换为你的背景音乐文件路径
pygame.mixer.music.play(-1)  # 循环播放背景音乐,-1代表无限循环

root = Tk()
canvas_width = 570
canvas_height = 800
c = Canvas(root, width=canvas_width, height=canvas_height)
speed = 5
interval = 5
Prompt = ["加油!胜利就在前方","撑住!","前面就是胜利的曙光……不要放弃!","一鼓作气,消灭他们!"]

# 加载背景图片
bg = PhotoImage(file=r"C:\Users\IBM\Desktop\程序文件\Python文件\小游戏\飞机大战\picture\background\background.png")
c.create_image(0, 0, anchor=NW, image=bg)


class Fighter:
    def __init__(self):
        self.image = PhotoImage(file=r"C:\Users\IBM\Desktop\程序文件\Python文件\小游戏\飞机大战\picture\material\主战飞机.png")
        self.x = canvas_width // 2
        self.y = 600
        self.image = self.image.subsample(2)  # 缩小一半
        self.object = c.create_image(self.x, self.y, anchor="center", image=self.image)
        self.hp = 100
        self.disappeared = False  # 记录是否处于消失状态
        self.disappear_timer = None  # 消失计时器ID
        self.hp_text = c.create_text(70, 40, text="Hp:{}".format(self.hp), font=("Helvetica", 20), fill="white")
        self.score = 0  # 用户分数

    def disappear_and_appear(self, count):
        if count > 0:
            if self.disappeared:
                c.itemconfigure(self.object, state="normal")  # 将主战飞机设置为可见
                self.disappeared = False
            else:
                c.itemconfigure(self.object, state="hidden")  # 将主战飞机设置为隐藏
                self.disappeared = True

            count -= 1
            self.disappear_timer = root.after(250, lambda: self.disappear_and_appear(count))  # 0.25秒后继续调用函数

    def move_left(self, event):
        self.x -= 5
        c.move(self.object, -5, 0)

    def move_right(self, event):
        self.x += 5
        c.move(self.object, 5, 0)

    def shoot(self, event):
        bullet = Bullet(self)
        bullets.append(bullet)

    def hurt(self, degree_of_injury):
        self.hp -= degree_of_injury
        c.itemconfigure(self.hp_text, text="hp:{}".format(self.hp))  # 更新文本对象的文本内容
        if self.hp <= 0:
            self.destroy()
            c.create_text(canvas_width / 2, canvas_height / 2, text="GAME OVER", font=("Helvetica", 48),
                          fill="red")
            c.create_text(canvas_width / 2, canvas_height / 2 + 60, text="Score: {}".format(self.score),
                          font=("Helvetica", 36), fill="white")  # 显示最终分数
            return
        else:
            self.disappear_and_appear(4)  # 调用消失重新出现的函数,执行4次

    def destroy(self):
        c.delete(self.object)
        c.delete(self.hp_text)  # 删除用于显示血量值的文本对象
        self.object = None  # 将对象设置为None,在主循环中进行判断,如果对象为None,则从列表中删除


class Enemy:
    def __init__(self):
        self.image = PhotoImage(file=r"C:\Users\IBM\Desktop\程序文件\Python文件\小游戏\飞机大战\picture\material\敌机.png")
        self.explosion_image = PhotoImage(file=r"C:\Users\IBM\Desktop\程序文件\Python文件\小游戏\飞机大战\picture\material\敌方爆炸.png")
        self.x = random.randint(50, 520)  # 随机生成x坐标
        self.y = 50
        self.image = self.image.subsample(2)  # 缩小一半
        self.explosion_image = self.explosion_image.subsample(2)
        self.object = c.create_image(self.x, self.y, anchor="center", image=self.image)
        self.hp = 100
        self.explosion_object = None  # 用于保存敌机爆炸图像的对象

    def move(self):
        global main_fighter

        # 判断敌机和主战飞机是否发生碰撞
        if (self.y + 50) >= main_fighter.y and (self.y - 50) <= main_fighter.y and \
                (self.x + 50) >= main_fighter.x and (self.x - 50) <= main_fighter.x:
            main_fighter.hurt(20)  # 主战飞机减少20点生命值
            self.destroy()  # 销毁敌机
        else:
            c.move(self.object, 0, speed)  # 向下移动5个单位
            self.y += 5

            if self.y >= canvas_height + 50:  # 判断是否到达画布底部(加上一些余量)
                self.destroy()

    def destroy(self):
        c.delete(self.object)
        c.create_image(self.x, self.y, anchor="center", image=self.explosion_image)  # 创建爆炸效果图像
        self.object = None  # 将对象设置为None,在主循环中进行判断,如果对象为None,则从列表中删除


class Bullet:
    def __init__(self, fighter):
        self.image = PhotoImage(file=r"C:\Users\IBM\Desktop\程序文件\Python文件\小游戏\飞机大战\picture\material\子弹.png")
        self.x = fighter.x
        self.y = fighter.y - 50
        self.image = self.image.subsample(3)  # 缩小为原来的1/3
        self.object = c.create_image(self.x, self.y, anchor="center", image=self.image)

    def move(self):
        c.move(self.object, 0, -10)  # 向上移动10个单位
        self.y -= 10

        # 判断子弹是否碰到敌机
        for enemy in enemies:
            if (self.y - 50) <= enemy.y and (self.x + 50) >= enemy.x and (self.x - 50) <= enemy.x:
                enemy.destroy()  # 销毁敌机
                self.destroy()  # 销毁子弹
                main_fighter.score += 1  # 击中敌机,喵k

        # 判断子弹是否碰到画布上边缘
        if self.y <= 0:
            self.destroy()

    def destroy(self):
        c.delete(self.object)
        self.object = None


main_fighter = Fighter()
enemies = []
enemies.append(Enemy())

root.bind("<KeyPress-a>", main_fighter.move_left)
root.bind("<KeyPress-d>", main_fighter.move_right)

root.bind("<KeyPress-space>", main_fighter.shoot)

bullets = []  # 子弹列表

score_text = None

def generate_enemy():
    enemy = Enemy()
    enemies.append(enemy)
    root.after(random.randint(1000, 1000 + interval*1000), generate_enemy)  # 随机生成下一个敌机的时间间隔(1-5秒)

root.after(random.randint(1,5)*1000, generate_enemy)  # 游戏开始时生成第一架敌机

def game_loop():
    global enemies
    global bullets
    global score_text
    global speed
    global interval
    

    # 移动敌机
    for enemy in enemies:
        enemy.move()

    # 移动子弹
    for bullet in bullets:
        bullet.move()

    # 删除已经销毁的敌机对象
    enemies = [enemy for enemy in enemies if enemy.object is not None]

    # 删除已经销毁的子弹对象
    bullets = [bullet for bullet in bullets if bullet.object is not None]

    # 处理击中敌机后的操作
    for enemy in enemies:
        if enemy.hp <= 0:
            c.delete(enemy.object)  # 删除击中的敌机
            c.create_image(enemy.x, enemy.y, anchor="center", image=enemy.explosion_image)  # 创建爆炸效果图像
            root.after(2000,lambda:enemies.remove(enemy))
             

    c.itemconfigure(main_fighter.hp_text, text="Hp:{}".format(main_fighter.hp))  # 更新主战飞机的血量文本
    c.itemconfigure(score_text, text="Score: {}".format(main_fighter.score))  # 更新分数文本


    root.after(50, game_loop)  # 每50毫秒更新一次游戏循环

game_loop()

score_text = c.create_text(canvas_width - 80, 40, text="Score: 0", font=("Helvetica", 20), fill="white")  # 创建分数文本

c.grid(row=0, column=0)
root.mainloop()

 

为了让程序正常跑起来,还需要一些图片文件。见下:center_image

(背景)

center_image

(主战飞机)

center_image

(敌机)

center_image

子弹center_image

(敌机爆炸图案,文件应命名为“敌方爆炸”)

还有,千万不要用海龟编辑器运行!用Python IDLE运行,具体可以到https://www.python.org/下载


回复

上一页1 页 / 共 1下一页
就在天边等待你就在天边等待你

下载网址:www.python.org

 

点赞0


评论


就在天边等待你就在天边等待你

这个游戏需要一定的游戏目录才能跑起来。目录格式见下:center_image

另外,这个游戏目录被保存在C:\Users\IBM\程序文件\Python文件\小游戏 里面。如果你没有相同的目录,就要考虑改变这个目录,否则程序会找不到素材

 

点赞0


评论


FexcodeFexcode

狠人

 

点赞0


评论


FexcodeFexcode

支持

点赞0


评论


就在天边等待你就在天边等待你

至于音乐,需要下载pygame才能播放,按下键盘上的Win+r,输入cmd,按下回车,进入终端。
输入"pip install pygame"然后等它自己下载。

如果得到的反应是“pip不是可执行的程序,也不是命令提示符”等报错,请在电脑上选中PythonIDLE(在www.python.org下载)图标,单击右键选择“打开文件所在的位置”,你会看到一些文件夹。找到pip文件夹,复制他的路径。找到控制面板,编辑环境变量,找到用户的环境变量里面的Path,编辑它,新建一个路径,粘贴刚才复制的路径,此时你的这条路径是位于最下方的,请把它上移到顶端

点赞0


评论