python练习-袭击敌机

python 复制代码
$ python -m pip install --user pygame

1、画游戏框

python 复制代码
class Settings:
    def __init__(self):
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)
python 复制代码
import sys
import pygame
from settings import Settings

class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        # 设置边框 创建一个屏幕对象,并设置其宽度和高度。
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        # 设置窗口标题
        pygame.display.set_caption("外星战机游戏")
    # 绘制
    def _update_screen(self):
        # 绘制背景
        self.screen.fill(self.settings.bg_color)
        # 绘制课件
        pygame.display.flip()

    # 运行
    def run_game(self):
        while True:
            self._update_screen()


AlienInvasion().run_game()

这笔记是我把程序写完才落成笔记的,复盘

这里闪退,百思不得其解

python 复制代码
在 Pygame 中,如果不处理事件(如关闭窗口事件),程序会因为无法响应这些事件而立即退出。

问题分析:
    缺少事件处理:你的 run_game 方法中没有处理任何事件,包括关闭窗口的事件。因此,当窗口关闭事件发生时,程序没有机会响应,导致立即退出。
    缺少必要的更新:虽然你有 _update_screen 方法来更新屏幕,但没有处理游戏逻辑和用户输入。

2、造飞机

在ship类定义飞机属性

python 复制代码
import sys
import pygame
from settings import Settings
from ship import Ship

class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        # 设置边框 创建一个屏幕对象,并设置其宽度和高度。
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        # 设置窗口标题
        pygame.display.set_caption("外星战机游戏")

        self.ship = Ship(self)

    # 绘制
    def _update_screen(self):
        # 绘制背景
        self.screen.fill(self.settings.bg_color)
        # 绘制小飞船
        self.ship.blitme()
        # 绘制课件
        pygame.display.flip()

AlienInvasion().run_game()
python 复制代码
# 管理飞船类
class Ship:
    def __init__(self, ai_name):
        # 飞船和初始位置
        self.screen = ai_name.screen
        self.screen_rect = ai_name.screen.get_rect()

        # 加载飞船图形
        self.image = pygame.image.load("ship.bmp")
        self.rect = self.image.get_rect()

    def blitme(self):
        # 绘制飞船
        self.screen.blit(self.image, self.rect)

    def center_ship(self):
        # 生成飞船在居中底端
        self.rect.midbottom=self.screen_rect.midbottom
        self.x=float(self.rect.x)

3、开飞机

python 复制代码
import sys
import pygame
from settings import Settings
from ship import Ship


class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        # 设置边框 创建一个屏幕对象,并设置其宽度和高度。
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        #  设置窗口标题
        pygame.display.set_caption("外星战机游戏")

        self.ship = Ship(self)

    def run_game(self):
        while True:
            self._check_event()
            self.ship.update()
            self._update_screen()

    # 监控外设
    def _check_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_key_down(event)
            elif event.type == pygame.KEYUP:
                self._check_key_up(event)

    # 按键按下监控
    def _check_key_down(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        if event.key == pygame.K_UP:
            self.ship.moving_up = True
        if event.key == pygame.K_DOWN:
            self.ship.moving_down = True
        if event.key == pygame.K_SPACE:
            self.bullet.launch = True

    # 按键松开监控
    def _check_key_up(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = False
        if event.key == pygame.K_UP:
            self.ship.moving_up = False
        if event.key == pygame.K_DOWN:
            self.ship.moving_down = False

    def run_game(self):
        while True:
            self._check_event()
            self.ship.update()
            self._update_screen()

AlienInvasion().run_game()
python 复制代码
import pygame

# 管理飞船类
class Ship:
    def __init__(self, ai_name):

        # 飞船和初始位置
        self.screen = ai_name.screen
        self.screen_rect = ai_name.screen.get_rect()

        # 加载飞船图形
        self.image = pygame.image.load("C:/Users/MGL/Desktop/py_test/Alien/ship.bmp")
        self.rect = self.image.get_rect()

        # 底部中央
        self.rect.midbottom = self.screen_rect.midbottom
        self.moving_right = False
        self.moving_left = False
        self.moving_up = False
        self.moving_down = False

    # 持续移动 并设置限制
    def update(self):
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.rect.x += 1
        elif self.moving_left and self.rect.left > self.screen_rect.left:
            self.rect.x -= 1
        elif self.moving_up and self.rect.y > self.screen_rect.top:
            # self.screen_rect.top为0
            self.rect.y -= 1
        elif self.moving_down and self.rect.y < self.screen_rect.bottom - 100:
            self.rect.y += 1

4、造导弹

python 复制代码
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet


class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        # 设置边框 创建一个屏幕对象,并设置其宽度和高度。
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        #  设置窗口标题
        pygame.display.set_caption("外星战机游戏")

        self.ship = Ship(self)
        self.bullet = Bullet(self)

    def run_game(self):
        while True:
            self._check_event()
            self.ship.update()
            self.bullet.bullets.update()
            # self._update_aliens()
            self._update_screen()

    # 监控外设
    def _check_event(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_key_down(event)
            elif event.type == pygame.KEYUP:
                self._check_key_up(event)

    # 按键按下监控
    def _check_key_down(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        if event.key == pygame.K_UP:
            self.ship.moving_up = True
        if event.key == pygame.K_DOWN:
            self.ship.moving_down = True
        if event.key == pygame.K_SPACE:
            self.bullet.launch = True

    # 按键松开监控
    def _check_key_up(self, event):
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = False
        if event.key == pygame.K_UP:
            self.ship.moving_up = False
        if event.key == pygame.K_DOWN:
            self.ship.moving_down = False
        if event.key == pygame.K_SPACE:
            self.bullet.launch = False


    # 绘制
    def _update_screen(self):
        # 绘制背景
        self.screen.fill(self.settings.bg_color)
        # 绘制小飞船
        self.ship.blitme()

        self.bullet.launch_bullet(self)

        # 绘制课件
        pygame.display.flip()


AlienInvasion().run_game()
python 复制代码
# 设置类
class Settings:
    def __init__(self):
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

        # 子弹设置
        self.bullet_speed = 2
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        self.bullet_allowed = 5
python 复制代码
import pygame
from pygame.sprite import Sprite


# 管理发射子弹类
class Bullet(Sprite):
    def __init__(self, ai_name):
        super().__init__()
        self.screen = ai_name.screen
        self.settings = ai_name.settings
        self.color = self.settings.bullet_color

        # 连续射击标识符
        self.launch = False

        # 绘画子弹
        self.rect = pygame.Rect(
            0, 0, self.settings.bullet_width, self.settings.bullet_height
        )
        # 子弹在飞船上面
        self.rect.midtop = ai_name.ship.rect.midtop
        # 子弹位置
        self.y = float(self.rect.y)

        # 装弹弹夹
        self.bullets = pygame.sprite.Group()


    def update(self):
        # 子弹移动
        self.y -= self.settings.bullet_speed
        self.rect.y = self.y


    # 装弹
    def _fire_bullet(self, alien):
        if len(self.bullets) < self.settings.bullet_allowed:
            new_bullet = Bullet(alien)
            self.bullets.add(new_bullet)

    # 连续发射
    def launch_bullet(self, alien):
        if self.launch:
            self._fire_bullet(alien)
        for bullet in self.bullets.sprites():
            # 删除触顶的子弹
            if bullet.rect.bottom <= 0:
                self.bullets.remove(bullet)
            bullet.draw_bullet()

    # 绘制子弹
    def draw_bullet(self):
        pygame.draw.rect(self.screen, self.color, self.rect)

5、出现敌机

python 复制代码
# 设置类
class Settings:
    def __init__(self):
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

        # 子弹设置
        self.bullet_speed = 2
        self.bullet_width = 3
        self.bullet_height = 15
        self.bullet_color = (60, 60, 60)
        self.bullet_allowed = 5

        self.alien_sheep = 0.3
        self.fleet_drop_speed = 1
    #     # 1 右移 -1 左移
        self.fleet_drop_direction = 1
python 复制代码
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien


class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        # 设置边框 创建一个屏幕对象,并设置其宽度和高度。
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        #  设置窗口标题
        pygame.display.set_caption("外星战机游戏")

        self.ship = Ship(self)
        self.bullet = Bullet(self)
        self.alien = Alien(self)

    def run_game(self):
        while True:
            self._check_event()
            self.ship.update()
            self.bullet.bullets.update()
            self._update_aliens()
            self._update_screen()

    # 忽略其他代码


    def _create_fleet(self):
        alien_n = Alien(self)
        alien_width = self.alien.rect.width
        alien_height = self.alien.rect.height
        # 一行敌机占多少宽度 给屏幕两边留有移动空间
        available_space_x = self.settings.screen_width - (2 * alien_width)
        # 计算可以放多少量敌机 (每个外星人间隔一个外星人宽度的距离)所以  2 * alien_width
        number_aliens_x = available_space_x // (2 * alien_width)

        # 计算屏幕可容纳多少行
        ship_height = self.ship.rect.height
        # 敌机占据的高度
        available_space_y = (
            self.settings.screen_height - (3 * alien_height) - ship_height
        )
        # 间隔有个敌机
        number_rows = available_space_y // (2 * alien_height)

        # 创建敌机
        for row_num in range(number_rows):
            for alien_num in range(number_aliens_x):
                self._create_alien(alien_num, row_num, alien_width)

    def _create_alien(self, alien_num, row_num, alien_width):
        alien = Alien(self)
        # 2 * alien_width * alien_num 定位起始位置
        alien.x = alien_width + 2 * alien_width * alien_num
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_num
        self.alien.aliens.add(alien)

    def _update_aliens(self):
        self.alien._check_fleet_edges()
        self.alien.aliens.update()

    def _update_bullets(self):

        # 打完敌机再来一群
        if not self.alien.aliens:
            # 清空弹夹并新建敌机
            self.bullet.bullets.empty()
            self._create_fleet()


    # 绘制
    def _update_screen(self):
        # 绘制背景
        self.screen.fill(self.settings.bg_color)
        # 绘制小飞船
        self.ship.blitme()

        self.bullet.launch_bullet(self)

        self.alien.aliens.draw(self.screen)

        self._update_bullets()

        # 绘制课件
        pygame.display.flip()

AlienInvasion().run_game()
python 复制代码
import pygame
from pygame.sprite import Sprite


class Alien(Sprite):
    def __init__(self, ai_name):
        super().__init__()
        self.screen = ai_name.screen
        self.screen_rect = ai_name.screen.get_rect()
        self.image = pygame.image.load("alien.bmp")
        self.rect = self.image.get_rect()
        self.settings = ai_name.settings

        # 敌机 最初位置
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height

        self.x = float(self.rect.x)

        self.aliens = pygame.sprite.Group()

    def update(self):
        # 左移右移
        self.x += self.settings.alien_sheep * self.settings.fleet_drop_direction
        self.rect.x = self.x

    def _check_fleet_edges(self):
        # 有外星人到达边缘时采取相应的措施。
        # self.aliens.sprites() 遍历
        for alien in self.aliens.sprites():
            if alien._check_edges():
                self._change_fleet_direction()
                break

    def _check_edges(self):
        # 如果外星人位于屏幕边缘,就返回True
        # 获取游戏框信息
        screen_rect = self.screen.get_rect()
        # 判断是否有敌机超出游戏框范围
        if self.rect.right >= screen_rect.right or self.rect.left <= 0:
            return True

    def _change_fleet_direction(self):
        # 将整群外星人下移,并改变它们的方向
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
            alien.rect.y += 1
        self.settings.fleet_drop_direction *= -1

6、打敌机

敌机打完重新开局,敌机接触到底部重新开局

python 复制代码
# pygame.sprite.groupcollide(group1, group2, dokill1, dokill2, collided=None)
# group1: 第一个精灵组。通常是一个 pygame.sprite.Group 对象。
# group2: 第二个精灵组。通常也是一个 pygame.sprite.Group 对象。
# dokill1: 一个布尔值,表示是否在发生碰撞后从 group1 中移除发生碰撞的精灵。如果设置为 True,则发生碰撞的精灵会被自动删除。
# dokill2: 一个布尔值,表示是否在发生碰撞后从 group2 中移除发生碰撞的精灵。如果设置为 True,则发生碰撞的精灵会被自动删除。
# collided: 可选参数,一个函数,用于确定两个精灵是否发生碰撞。默认情况下,Pygame 使用矩形碰撞检测。如果提供了一个函数,该函数应该接受两个精灵作为参数,并返回一个布尔值。




pygame.sprite.spritecollideany 是 Pygame 中用于检测单个精灵与一个精灵组之间是否发生碰撞的函数

sprite: 单个精灵对象。通常是一个 pygame.sprite.Sprite 的子类实例。
group: 精灵组。通常是一个 pygame.sprite.Group 对象。
collided: 可选参数,一个函数,用于确定两个精灵是否发生碰撞。默认情况下,Pygame 使用矩形碰撞检测。如果提供了一个函数,该函数应该接受两个精灵作为参数,并返回一个布尔值。
如果 sprite 与 group 中的任何一个精灵发生碰撞,返回 True;否则返回 False。
python 复制代码
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
import time

class AlienInvasion:
    # 忽略其他代码

    def _update_aliens(self):
        self.alien._check_fleet_edges()
        self.alien.aliens.update()

        # 与敌机碰撞判断
        if pygame.sprite.spritecollideany(self.ship, self.alien.aliens):
            self._ship_hit()

        # 检查敌机是否到底部
        self._check_aliens_bottom()

    def _update_bullets(self):
        # 检查是否击中敌机 如果是 则删除
        # 
        collisions = pygame.sprite.groupcollide(
            self.bullet.bullets, self.alien.aliens, True, True
        )

        # 打完敌机再来一群
        if not self.alien.aliens:
            # 清空弹夹并新建敌机
            self.bullet.bullets.empty()
            self._create_fleet()


    def _ship_hit(self):

        self.alien.aliens.empty()
        self.bullet.bullets.empty()

        self._create_fleet()
        self.ship.center_ship()

        time.sleep(0.5)

    def _check_aliens_bottom(self):
        # 检查是否有外星人到达了屏幕底端
        screen_rect = self.screen.get_rect()
        for alien in self.alien.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                # 像飞船被撞到一样处理。
                self._ship_hit()
                break

7、记分

python 复制代码
class GameStats:

    def __init__(self, ai_name):
        self.settings = ai_name.settings
        self.reset_stats()

    def reset_stats(self):

        self.score = 0
python 复制代码
import pygame.font


class ScoreBoard:
    # 显示得分信息的类

    def __init__(self, ai_game):
        # 初始化显示得分涉及的属性
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = ai_game.settings
        self.stats = ai_game.stats

        # 显示得分信息时使用的字体设置
        self.text_color = (30, 30, 30)
        self.font = pygame.font.SysFont(None, 48)
        # 准备初始得分图像
        self.prep_score()

    def prep_score(self):
        # 将得分转换为一幅渲染的图像
        score_str = str(self.stats.score)
        self.score_image = self.font.render(
            score_str, True, self.text_color, self.settings.bg_color
        )

        # 在屏幕右上角显示得分。
        self.score_rect = self.score_image.get_rect()
        self.score_rect.right = self.screen_rect.right - 20
        self.score_rect.top = 20

    def show_score(self):
        # 在屏幕上显示得分
        self.screen.blit(self.score_image, self.score_rect)
python 复制代码
import sys
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
from alien import Alien
from game_stats import GameStats
import time
from score_board import ScoreBoard

class AlienInvasion:
    def __init__(self):
        pygame.init()
        self.settings = Settings()
        # 设置边框 创建一个屏幕对象,并设置其宽度和高度。
        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height)
        )
        #  设置窗口标题
        pygame.display.set_caption("外星战机游戏")

        self.ship = Ship(self)
        self.bullet = Bullet(self)
        self.alien = Alien(self)
        self.stats = GameStats(self)

        self.score = ScoreBoard(self)


    # 忽略部分代码

    def _update_bullets(self):
        # 检查是否击中敌机 如果是 则删除

        collisions = pygame.sprite.groupcollide(
            self.bullet.bullets, self.alien.aliens, True, True
        )

        # 打完敌机再来一群
        if not self.alien.aliens:
            # 清空弹夹并新建敌机
            self.bullet.bullets.empty()
            self._create_fleet()

        if collisions:
            self.stats.score += self.settings.alien_points
            self.score.prep_score()


    def _ship_hit(self):

        # self.stats.ship_left -= 1

        self.alien.aliens.empty()
        self.bullet.bullets.empty()

        self._create_fleet()
        self.ship.center_ship()
        self.stats.score = 0
        self.score.prep_score()

        time.sleep(0.5)


    # 绘制
    def _update_screen(self):
        # 绘制背景
        self.screen.fill(self.settings.bg_color)
        # 绘制小飞船
        self.ship.blitme()

        self.bullet.launch_bullet(self)

        self.alien.aliens.draw(self.screen)

        self._update_bullets()

        # 显示得分
        self.score.show_score()

        # 绘制课件
        pygame.display.flip()

AlienInvasion().run_game()

8、番外

  • 按键
python 复制代码
import pygame.font


class Button:
    def __init__(self, ai_name, msg):
        self.screen = ai_name.screen
        self.screen_rect = ai_name.screen.get_rect()

        # 设置按钮的尺寸和其他属性。
        self.width, self.height = 200, 50
        self.button_color = (0, 255, 0)
        self.text_color = (255, 255, 255)
        self.font = pygame.font.SysFont(None, 48)

        # 创建按钮的rect对象,并使其居中。
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center

        # 按钮的标签只需创建一次。
        self._prep_msg(msg)

    def _prep_msg(self, msg):
        # 将msg渲染为图像,并使其在按钮上居中
        self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
        self.msg_image_rect = self.msg_image.get_rect()
        self.msg_image_rect.center = self.rect.center


    def draw_button(self):
        # 绘制一个用颜色填充的按钮,再绘制文本。
        self.screen.fill(self.button_color,self.rect)
        self.screen.blit(self.msg_image,self.msg_image_rect)
python 复制代码
# from button import Button
#self.play_button = Button(self, "Play")
## 绘制按钮
# self.play_button.draw_button()
## 隐藏鼠标光标
# pygame.mouse.set_visible(false)
相关推荐
Lizhihao_10 分钟前
JAVA-队列
java·开发语言
denghai邓海10 分钟前
红黑树删除之向上调整
python·b+树
远望清一色28 分钟前
基于MATLAB边缘检测博文
开发语言·算法·matlab
封步宇AIGC36 分钟前
量化交易系统开发-实时行情自动化交易-3.4.1.2.A股交易数据
人工智能·python·机器学习·数据挖掘
何曾参静谧36 分钟前
「Py」Python基础篇 之 Python都可以做哪些自动化?
开发语言·python·自动化
Prejudices40 分钟前
C++如何调用Python脚本
开发语言·c++·python
我狠狠地刷刷刷刷刷1 小时前
中文分词模拟器
开发语言·python·算法
wyh要好好学习1 小时前
C# WPF 记录DataGrid的表头顺序,下次打开界面时应用到表格中
开发语言·c#·wpf
AitTech1 小时前
C#实现:电脑系统信息的全面获取与监控
开发语言·c#
qing_0406031 小时前
C++——多态
开发语言·c++·多态