[alien Invasion]python小游戏阶段总结

news2025/1/13 16:47:19

以后可能还会进行代码重构,以最终版本为准

本篇文章旨在理清程序脉络,方便以后写类似的程序时提供一个习惯的思路

未经允许,禁止转载

实体区

ship.py

import pygame
class Ship():
    def __init__(self,screen,ai_settings):
        #储存以便后续使用
        self.screen=screen
        self.ai_settings=ai_settings
        self.image=pygame.image.load(r'images\ship.bmp')
        #构建rect主体
        self.rect=self.image.get_rect()
        self.screen_rect=screen.get_rect()
        #放中央
        self.rect.centerx=self.screen_rect.centerx#位置
        self.rect.bottom=self.screen_rect.bottom#位置
        #在飞船的属性center储存,实现高精度  
        self.center=float(self.rect.centerx)
        #移动标志
        self.moving_right=False
        self.moving_left=False
    def update(self):
        #根据ship_speed_factor调整center,并处理边界问题
        if self.moving_right and self.rect.right<self.screen_rect.right:
            self.center+=self.ai_settings.ship_speed_factor
        if self.moving_left and self.rect.left>0:
            self.center-=self.ai_settings.ship_speed_factor
        #根据self.center更新rect对象
        self.rect.centerx=self.center
        
    def blitme(self):#画图  
        self.screen.blit(self.image,self.rect)
        
        

ship主要用来制作在screen中的东西,以后的alien.py和这个代码非常像。

alien.py

import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
    """表示单个外星人的类"""
    def __init__(self,ai_settings,screen):
        """初始化外星人并设置其起始位置"""
        super().__init__()
        
        #存储screen和setting以便后续使用
        self.ai_settings=ai_settings
        self.screen=screen
        self.image=pygame.image.load(r'images\alien.bmp')

        # 加载外星人图像,并设置其rect属性
        self.rect=self.image.get_rect()
        
        # 每个外星人最初都在屏幕左上角附近
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height
        # 存储外星人的准确位置
        self.center=float(self.rect.x)
       
    def blitme(self):
        """在指定位置绘制外星人"""
        self.screen.blit(self.image,self.rect)

 bullet.py

import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
    """一个对飞船发射的子弹进行管理的类"""
    def __init__(self,ai_settings,screen,ship):
        """在飞船所处的位置创建一个子弹对象"""
        #继承的例行公事
        super().__init__()
        self.screen = screen
        # 在(0,0)处创建一个表示子弹的矩形,再设置正确的位置
        self.rect = pygame.Rect(0,0,ai_settings.bullet_width,ai_settings.bullet_height)
        #移动到正确位置-使用rect
        self.rect.centerx = ship.rect.centerx 
        self.rect.top = ship.rect.top 
        #存储用小数表示的子弹位置
        self.y = float(self.rect.y) 
        #颜色和速度
        self.color = ai_settings.bullet_color 
        self.speed_factor = ai_settings.bullet_speed_factor
    def update(self):
        '''向上移动子弹'''
        #更新表示子弹的rect位置
        self.y-=self.speed_factor
        #更新表示子弹的rect位置
        self.rect.y=self.y
    def draw_bullet(self):
        pygame.draw.rect(self.screen,self.color,self.rect)

ship,alien,bullet,这些实体在构建的时候大同小异

python是动态语言,不需要在实体的类内部实现随着键盘操作而移动的方法

bullet的向上移动是一个例外,这个方法只负责向上移动,也只需要向上移动,因此不需再键鼠操作的代码块里定义该函数,仅仅在主循环之中应用该函数即可

功能区(函数操作区)

game_functions.py

在实体区里,实体类内定义了一些函数,这些函数在功能区被调用,构成了一些新的函数,而这些新的函数会在主函数文件被直接使用。

可能会觉得,某一些代码放在实体类内更合适(比如fire_bullets或许应该放在Bullet类内)。但是,我们在game_function区写下的所有函数,大部分会(也有一部分被自身调用了)在主函数main.py(本文是alien_invasion.py)直接调用。

为了main.py简洁,方便理解的特性,应该尽可能使用代码重构,最常用的方法是打包为方法(也就是函数),所以,实体区函数,功能区函数,main区函数的关系应该是这样的:

代码重构大大提高了我们理解代码的效率,也使得功能区更加简洁。

import sys
import pygame
from bullet import Bullet
from alien import Alien
def fire_bullets(ship,ai_settings,screen,bullets):
    if len(bullets)<ai_settings.bullets_allowed:
            new_bullet=Bullet(ai_settings,screen,ship)
            bullets.add(new_bullet)

def check_keydown_events(event,ship,ai_settings,screen,bullets):
    '''响应按键'''
    if event.key==pygame.K_RIGHT:
        ship.moving_right=True
    elif event.key==pygame.K_LEFT:
        ship.moving_left=True
    elif event.key==pygame.K_SPACE:
        fire_bullets(ship,ai_settings,screen,bullets)
    elif event.key==pygame.K_q:
        sys.exit()
    
        
def check_keyup_events(event,ship):
    '''相应松开'''
    if event.key==pygame.K_RIGHT:
                ship.moving_right=False
    elif event.key==pygame.K_LEFT:
                ship.moving_left=False
    
#几类按键
def check_events(ai_settings,screen,ship,bullets):#check events
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            sys.exit()       
        elif event.type==pygame.KEYDOWN:
           check_keydown_events(event,ship,ai_settings,screen,bullets)           
        elif event.type==pygame.KEYUP:
           check_keyup_events(event,ship)
            

def update_screen(ai_settings,screen,ship,bullets,aliens):
    screen.fill(ai_settings.bg_color)
    # 绘制子弹
    for bullet in bullets.sprites():
        bullet.draw_bullet()
    ship.blitme()
    aliens.draw(screen)
    pygame.display.flip()
    
def update_bullets(bullets):
    """更新子弹的位置,并删除已消失的子弹"""
    # 更新子弹的位置
    bullets.update()
    # 删除已消失的子弹
    for bullet in bullets.copy():
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

主体区(main)

alien_invasion.py

再次强调,python是动态语言,这意味着我们不可以按照c++的先声明再使用,没有具体类型就不能用这些的思考习惯来理解和书写python代码。python的动态特性使得我们可以再main.py里仅仅使用一个Settings类(见下文)来存储所有实体所需要的初始化数值,而不必去每一个实体里面一个个用变量来初始化。

如前文所述,几乎所有功能区的函数都会在main里调用,我们又不想把所有功能区的函数名字引进来以函数名直接调用来造成(可能的)混淆,我们确实import了全部,但是没有不负责任的import *, 所以我们起了个别名gf,以成员的方式来调用函数。

class Settings和run_game()函数我分成两个思维导图来写。

 

import sys
import pygame

from ship import Ship
from alien import Alien
import game_functions as gf
from pygame.sprite import Group


class Settings():
    def __init__(self):
        self.screen_width=1600
        self.screen_height=900 
        self.bg_color=(240,240,240)#0~255
        self.ship_speed_factor=1.5#一次移动1.5像素1
        
        self.bullet_speed_factor=1.5
        self.bullet_width=3
        self.bullet_height=15
        self.bullet_color=60,60,60#元组
        self.bullets_allowed=3
        
    
def run_game():
    pygame.init()
    ai_settings=Settings()
    screen=pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
    pygame.display.set_caption('Alien Invasion')
    #创建一艘飞船
    ship=Ship(screen,ai_settings)
    #创建用于存储子弹的编组(Group)创建Group实例,只负责提供容器,不管bullet干啥
    bullets=Group()
    aliens=Alien()
    #实例化一个alien
    alien=Alien(ai_settings,screen)
    #以后再说...
    gf.creat_fleet(ai_settings,screen,aliens)
    
    while True:
        gf.check_events(ai_settings,screen,ship,bullets)                
        ship.update()
        gf.update_bullets(bullets)                                  
        gf.update_screen(ai_settings,screen,ship,bullets,aliens)
        
run_game()


仅仅是阶段总结,以后代码会持续更新知道游戏被做出来,本节项目内容来自:Python编程:从入门到实践 - 埃里克·马瑟斯 - 微信读书本书是一本针对所有层次的Python读者而作的Python入门书。全书分两部分:第一部分介绍用Python编程所必须了解的基本概念,包括matplotlib、NumPy和Pygal等强大的Python库和工具介绍,以及列表、字典、if语句、类、文件与异常、代码测试等内容;第二部分将理论付诸实践,讲解如何开发三个项目,包括简单的Python2D游戏开发,如何利用数据生成交互式的信息图,以及创建和定制简单的Web应用,并帮读者解决常见编程问题和困惑。本书适合对Python感兴趣的任何层次的读者阅读。icon-default.png?t=N7T8https://weread.qq.com/web/reader/19532980715c01921954a54

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2064448.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RocketMQ广播模式消费失败是否会重试?

文章目录 前言继续广播和集群模式的消费流程集群模式&#xff08;默认的&#xff09;广播模式小结 push和pull介绍源码展示 偏移量保存失败情况1. 网络问题2. Consumer本地问题3. 消费进度记录器问题4. 程序设计问题5. 异常终止6. 持久化策略问题7. 同步问题 源码解析OffsetSto…

亚马逊测评号生存法则:如何抵御亚马逊封号风波?

距离黑五购物狂欢节还剩99天&#xff0c;相信各位商家都在紧锣密鼓的筹备相关事宜&#xff0c;然而&#xff0c;亚马逊的封号风波再次席卷而来。那如何在这场风暴中让亚马逊矩阵测评号安全航行亦或是脱颖而出呢&#xff1f;本文将给你一个答案&#xff0c;并帮助你的亚马逊店铺…

【PyTorch快速入门教程】03 PyTorch基础知识

在PyTorch中&#xff0c;最小的计算单元是张量&#xff08;tensor&#xff09;。因此关于张量的学习还是至关重要的。通过本章节学习&#xff0c;希望你对张量有一个更清晰的了解。 文章目录 1 什么是Tensor2 PyTorch中Tensor使用2.1 创建Tensor2.1.1 直接创建Tensor2.1.2 间接…

anaconda上安装pytorch

1、选择anaconda prompt 2、创建虚拟环境 3、激活进入虚拟环境 4、安装pytorch 怎么得到上面的这串命令&#xff1f; 输入nvidia-smi&#xff0c;查看cuda的版本号为11.7 我这里选择安装cuda的版本号为11.3&#xff0c;满足向下兼容即可。 在安装深度学习环境时&#xff0c;要…

探索《黑神话·悟空》背后的AI技术支持:英伟达全景光线追踪技术、DLSS 3.5 与帧生成

引言 2023 年&#xff0c;游戏《黑神话悟空》以其震撼的视觉效果和深度沉浸的游戏体验&#xff0c;成为全球玩家热议的焦点。这款游戏在发布初期就取得了惊人的销量&#xff1a;预售阶段便突破 120 万套&#xff0c;而发售首日更是达到 450 万份的惊人成绩。这个现象级作品背后…

走进 “星星的孩子” 的世界:理解与关爱儿童自闭症

在这个充满生机与活力的世界里&#xff0c;有一群特殊的孩子&#xff0c;他们仿佛来自遥远的星球&#xff0c;沉浸在自己的独特世界中&#xff0c;难以与外界进行有效的沟通和互动。他们是自闭症儿童&#xff0c;也被称为 “星星的孩子”。 自闭症&#xff0c;又称孤独症谱系障…

Linux 软件编程 数据库

1. 大批量数据存储和管理时使用数据库 2.创建表 create table 表名称(列1 数据类型, 列2 数据类型, ...); 3.插入表 insert into 表名称 values(值1, 值2, ...); 4.查看表 select 列1,列2,... from 表名称 where 匹配条件 order by 列名称 asc/desc; 5.删除表 delete from …

种田RPG游戏(五)

一、重新设置物品栏 1、打开Scripts-Inventory文件新建 ItemSlotData.cs using System.Collections; using System.Collections.Generic; using UnityEngine;[System.Serializable] //单独的类 public class ItemSlotData {public ItemData itemData;//ItemData对象&#xff…

Java 入门指南:Queue 接口

Collection 接口 Collection 接口提供了一系列用于操作和管理集合的方法&#xff0c;包括添加、删除、查询、遍历等。它是所有集合类的根接口&#xff0c;包括 List、Set、Queue 等。 Collection 接口常见方法 add(E element)&#xff1a;向集合中添加元素。 addAll(Collecti…

大模型笔记之-XTuner微调个人小助手认知

前言 使用XTuner 微调个人小助手认知 一、下载模型 #安装魔搭依赖包 pip install modelscope新建download.py内容如下 其中Shanghai_AI_Laboratory/internlm2-chat-1_8b是魔搭对应的模型ID cache_dir/home/aistudio/data/model’为指定下载到本地的目录 from modelscope im…

Stable Diffusion的微调方法原理总结

目录 1、Textural Inversion&#xff08;简易&#xff09; 2、DreamBooth&#xff08;完整&#xff09; 3、LoRA&#xff08;灵巧&#xff09; 4、ControlNet&#xff08;彻底&#xff09; 5、其他 1、Textural Inversion&#xff08;简易&#xff09; 不改变网络结构&…

Ciallo~(∠・ω・ )⌒☆第二十五篇 Redis

Redis 是一个高性能的键值存储数据库&#xff0c;它能够在内存中快速读写数据&#xff0c;并且支持持久化到磁盘。它被广泛应用于缓存、队列、实时分析等场景。 一、启动redis服务器 要打开redis服务器&#xff0c;需要在终端中输入redis-server命令。确保已经安装了redis&…

【Java】/* 链式队列 和 循环队列 - 底层实现 */

一、链式队列 1. 使用双向链表实现队列&#xff0c;可以采用尾入&#xff0c;头出 也可以采用 头入、尾出 (LinkedList采用尾入、头出) 2. 下面代码实现的是尾入、头出&#xff1a; package bageight;/*** Created with IntelliJ IDEA.* Description:* User: tangyuxiu* Date: …

mOTA v2.0

mOTA v2.0 一、简介 本开源工程是一款专为 32 位 MCU 开发的 OTA 组件&#xff0c;组件包含了 bootloader 、固件打包器 (Firmware_Packager) 、固件发送器 三部分&#xff0c;并提供了基于多款 MCU (STM32F1 / STM32F407 / STM32F411 / STM32L4) 和 YModem-1K 协议的案例。基…

【文献及模型、制图分享】2000—2020年中国青饲料播种面积及供需驱动因素的时空格局

文献介绍 高产、优质的青饲料对于国家畜牧业发展和食物供给至关重要。然而&#xff0c;当前对于青饲料播种面积时空变化格局及其阶段性特征、区域差异以及影响因素等尚未清楚。 本文基于省级面板数据分析了2000—2020年青饲料种植的时空格局变化&#xff0c;结合MODIS-NPP产品…

Nginx 405 not allowed

问题原因&#xff1a;nginx不允许静态文件被post请求 解决&#xff1a;添加error_page 405 200 $request_uri;

白酒与家庭:团圆时刻的需备佳品

在中国传统文化中&#xff0c;家庭是社会的基石&#xff0c;是每个人心灵的港湾。而团圆&#xff0c;则是家庭生活中较美好的时刻。在这样一个特殊的日子里&#xff0c;白酒&#xff0c;尤其是豪迈白酒&#xff08;HOMANLISM&#xff09;&#xff0c;成为了团圆时刻的需备佳品。…

了解JS数组元素及属性

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、定义数组并输出2、查询数组的长度3、访问数组的第一个元素4、访问数组中第一个元素的xxx属性5、从数组元素中提取ID并存储到搜索参数对象 提示&#xff1a;以下是…

C++设计模式1:单例模式(懒汉模式和饿汉模式,以及多线程问题处理)

饿汉单例模式 程序还没有主动获取实例对象&#xff0c;该对象就产生了&#xff0c;也就是程序刚开始运行&#xff0c;这个对象就已经初始化了。 class Singleton { public:~Singleton(){std::cout << "~Singleton()" << std::endl;}static Singleton* …

KUKA KR C2 中文操作指南 详情见目录

KUKA KR C2 中文操作指南 详情见目录