python学习笔记(七) 类和pygame实现打飞机游戏
python中类声明如下:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def printinfo(self):
print('name is %s, score is %d'%(self.name, self.score))
Student类有两个成员变量,name和score,类的成员函数第一个参数都为self,用来实现成员变量的赋值,__init__是类的初始化函数,初始化成员变量。
类的使用:
s1 = Student('niuniu',78)
print(s1.name)
print(s1.score)
s1.printinfo() s2 = Student('gg',100)
s2.printinfo()
s2.age = 100
print('s2 age is %s'%(s2.age))
定义s2对象,并且通过s2.age=100,定义了s2的成员变量age,并且初始化为100
类的成员变量有两种方式定义,一个是在__init__函数中,一个是通过类的对象初始化。
类的权限设置:
class Student2(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def getname(self):
return self.__name
def getscore(self):
return self.__score def printinfo(self):
print('name is %s, score is %d' %(self.__name, self.__score))
__name通过在变量名前边加上__表示该变量为私有变量,python没有严格的权限限制,只不过通过重命名将__name变为其他的名字了,这样在外部就访问不到这个变量了。
通过添加getname和getscore函数获取成员变量。
s3 = Student2('s3',99)
s3.printinfo()
name = s3.getname()
print(name)
s3.__name = 'iloveu'
print(s3.__name)
name = s3.getname()
print(name)
s3.printinfo()
虽然通过s3.__name = 'iloveu'赋值后,并没有改变类的私有变量__name的数值,因为类的私有变量__name的名称被改为其他的名字,用户无法知道。所以打印出的名字和s3.__name数值不同。
python类同样支持继承
class Peaple(object):
def __init__(self, name):
self.__name = name
def job(self):
pass class Worker(Peaple):
def job(self):
print("worker") class Student(Peaple):
def job(self):
print("student") s1 = Student('student')
s1.job w1 = Worker('worker')
w1.job p = Peaple("abc")
w = Worker("abc")
s = Student("abc")
可以通过isinstance判断类对象是否是一个类型的实例
print(isinstance(p, Peaple))
print(isinstance(w,Peaple))
print(isinstance(s,Peaple))
print(isinstance(s,Worker))
print(isinstance(p,Student))
子类对象是基类类型的实例,而基类对象不一定是子类类型的实例。比如Student继承于Peaple,学生是人,但是人不一定是学生。
类的属性控制:
class Designer(Worker):
def __init__(self,name,age):
self.__name = name
self.age = age
def job(self):
print("Designer") designer = Designer('David',18)
获取属性,设置属性,判断是否含有某个属性
#判断类中是否有某个实例print(hasattr(designer, 'age') )
print(hasattr(designer,'job'))
print(hasattr(designer,'name')) #设置sex属性,属性值为'female'
setattr(designer, 'sex', 'female') print(designer.sex) #获取job属性,返回值为job函数对象
fn = getattr(designer, 'job')
#调用fn函数
fn()
类的公有属性,为所有对象共有,类似于C++的static成员变量
#通过self变量或者实例自身可以实现实例属性绑定
#在类中直接定义一个变量,这个属性归类所有,类似于C++的static变量。
class Temple(object):
staticmember = 1000 temp1 = Temple()
#temp1没有自身属性成员staticmember,
#而Temple类含有共享属性
#下面这种方式打印的是类的共有属性
print(temp1.staticmember)
#为实例temp1绑定其自身的成员staticmember
#并且设置数值为2048
temp1.staticmember = 2048
#打印实例temp1的成员staticmember
print(temp1.staticmember)
#打印类的共享成员
print(Temple.staticmember)
#删除实例的属性staticmember
del temp1.staticmember
#打印出类共享的属性
print(temp1.staticmember)
可以为类绑定成员函数,也可以只为类的一个实例绑定成员函数
def setage(self, age):
self.__age = age
def getage(self):
return self.__age
###给实例绑定方法
temp1.setage = MethodType(setage, temp1)
temp1.getage = MethodType(getage,temp1)
temp1.setage(125)
print(temp1.getage()) def setname(self, name):
self.__name = name def getname(self):
return self.__name #给类绑定方法
Temple.setname= setname
Temple.getname = getname temp2 = Temple()
temp2.setname('name')
print(temp2.getname())
可以通过@property的方式,通过属性访问的方式就可以调用函数
class Definetion(object):
def __init__(self, member):
self.__member = member
@property
def member(self):
print("call getter")
return self.__member
@member.setter
def member(self, member):
print("call setter")
if not isinstance(member,int):
raise TypeError("member must be int type")
self.__member = member
@member.deleter
def member(self):
print("call deleter")
raise AttributeError("Cann't delete member")
definetioner = Definetion(3)
print(definetioner.member)
definetioner.member = 1024
print(definetioner.member)
将member分别实现为返回属性__member,设置__member,以及删除__member的函数。在每个member上添加对应格式的@property,@member.setter, @member.deleter。
通过属性访问的方式就可以调用对应的函数, definetioner.member返回__member值, definetioner__member = 1024调用设置__member的函数。deleter definetioner.member调用的是删除函数。
实战:用pygame库做一个打飞机的小游戏
pygame是python的一个做游戏的库,安装方法自行百度。
实现子弹类
# 设置游戏屏幕大小
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 800 # 子弹类
class Bullet(pygame.sprite.Sprite):
def __init__(self, bullet_img, init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = bullet_img
self.rect = self.image.get_rect()
self.rect.midbottom = init_pos
self.speed = 10 def move(self):
self.rect.top -= self.speed
写玩家的飞机类
# 玩家飞机类
class Player(pygame.sprite.Sprite):
def __init__(self, plane_img, player_rect, init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = [] # 用来存储玩家飞机图片的列表
for i in range(len(player_rect)):
self.image.append(plane_img.subsurface(player_rect[i]).convert_alpha())
self.rect = player_rect[0] # 初始化图片所在的矩形
self.rect.topleft = init_pos # 初始化矩形的左上角坐标
self.speed = 8 # 初始化玩家飞机速度,这里是一个确定的值
self.bullets = pygame.sprite.Group() # 玩家飞机所发射的子弹的集合
self.img_index = 0 # 玩家飞机图片索引
self.is_hit = False # 玩家是否被击中
实现飞机类的几个功能函数
# 发射子弹
def shoot(self, bullet_img):
bullet = Bullet(bullet_img, self.rect.midtop)
self.bullets.add(bullet) # 向上移动,需要判断边界
def moveUp(self):
if self.rect.top <= 0:
self.rect.top = 0
else:
self.rect.top -= self.speed # 向下移动,需要判断边界
def moveDown(self):
if self.rect.top >= SCREEN_HEIGHT - self.rect.height:
self.rect.top = SCREEN_HEIGHT - self.rect.height
else:
self.rect.top += self.speed # 向左移动,需要判断边界
def moveLeft(self):
if self.rect.left <= 0:
self.rect.left = 0
else:
self.rect.left -= self.speed # 向右移动,需要判断边界
def moveRight(self):
if self.rect.left >= SCREEN_WIDTH - self.rect.width:
self.rect.left = SCREEN_WIDTH - self.rect.width
else:
self.rect.left += self.speed
实现敌方飞机类
# 敌机类
class Enemy(pygame.sprite.Sprite):
def __init__(self, enemy_img, enemy_down_imgs, init_pos):
pygame.sprite.Sprite.__init__(self)
self.image = enemy_img
self.rect = self.image.get_rect()
self.rect.topleft = init_pos
self.down_imgs = enemy_down_imgs
self.speed = 2
self.down_index = 0 # 敌机移动,边界判断及删除在游戏主循环里处理
def move(self):
self.rect.top += self.speed
实现游戏主逻辑
# 初始化 pygame
pygame.init() # 设置游戏界面大小、背景图片及标题
# 游戏界面像素大小
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # 游戏界面标题
pygame.display.set_caption('飞机大战') # 背景图
background = pygame.image.load('resources/image/background.png').convert() # Game Over 的背景图
game_over = pygame.image.load('resources/image/gameover.png') # 飞机及子弹图片集合
plane_img = pygame.image.load('resources/image/shoot.png')
由于资源采用大图的方式,敌机和飞机,子弹都绘制在一站图片上,需要裁剪,pygame提供裁剪函数
# 设置玩家飞机不同状态的图片列表,多张图片展示为动画效果
player_rect = []
player_rect.append(pygame.Rect(0, 99, 102, 126)) # 玩家飞机图片
player_rect.append(pygame.Rect(165, 360, 102, 126))
player_rect.append(pygame.Rect(165, 234, 102, 126)) # 玩家爆炸图片
player_rect.append(pygame.Rect(330, 624, 102, 126))
player_rect.append(pygame.Rect(330, 498, 102, 126))
player_rect.append(pygame.Rect(432, 624, 102, 126))
player_pos = [200, 600]
player = Player(plane_img, player_rect, player_pos) # 子弹图片
bullet_rect = pygame.Rect(1004, 987, 9, 21)
bullet_img = plane_img.subsurface(bullet_rect) # 敌机不同状态的图片列表,多张图片展示为动画效果
enemy1_rect = pygame.Rect(534, 612, 57, 43)
enemy1_img = plane_img.subsurface(enemy1_rect)
enemy1_down_imgs = []
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(267, 347, 57, 43)))
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(873, 697, 57, 43)))
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(267, 296, 57, 43)))
enemy1_down_imgs.append(plane_img.subsurface(pygame.Rect(930, 697, 57, 43)))
管理敌机和敌机被击中的等对象
#存储敌机,管理多个对象
enemies1 = pygame.sprite.Group() # 存储被击毁的飞机,用来渲染击毁动画
enemies_down = pygame.sprite.Group() # 初始化射击及敌机移动频率
shoot_frequency = 0
enemy_frequency = 0 # 玩家飞机被击中后的效果处理
player_down_index = 16 # 初始化分数
score = 0 # 游戏循环帧率设置
clock = pygame.time.Clock() # 判断游戏循环退出的参数
running = True
通过循环控制游戏逻辑,不断生成敌机和子弹,刷新场景等。
给大家个建议,也是忠告,pygame实现的游戏循环体中一定要捕捉事件消息,不然会因为死循环而一直卡顿,甚至崩溃。先实现循环体中事件捕捉
# 游戏主循环
while running:
# 控制游戏最大帧率为 60
clock.tick(60) # 更新屏幕
pygame.display.update() # 处理游戏退出
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit() # 获取键盘事件(上下左右按键)
key_pressed = pygame.key.get_pressed() # 处理键盘事件(移动飞机的位置)
if key_pressed[K_w] or key_pressed[K_UP]:
player.moveUp()
if key_pressed[K_s] or key_pressed[K_DOWN]:
player.moveDown()
if key_pressed[K_a] or key_pressed[K_LEFT]:
player.moveLeft()
if key_pressed[K_d] or key_pressed[K_RIGHT]:
player.moveRight()
在while running循环中添加子弹和敌机生成逻辑
# 生成子弹,需要控制发射频率
# 首先判断玩家飞机没有被击中
if not player.is_hit:
if shoot_frequency % 15 == 0:
player.shoot(bullet_img)
shoot_frequency += 1
if shoot_frequency >= 15:
shoot_frequency = 0 # 生成敌机,需要控制生成频率
if enemy_frequency % 50 == 0:
enemy1_pos = [random.randint(0, SCREEN_WIDTH - enemy1_rect.width), 0]
enemy1 = Enemy(enemy1_img, enemy1_down_imgs, enemy1_pos)
enemies1.add(enemy1)
enemy_frequency += 1
if enemy_frequency >= 100:
enemy_frequency = 0
在while running循环中子弹和敌机移动逻辑
for bullet in player.bullets:
# 以固定速度移动子弹
bullet.move()
# 移动出屏幕后删除子弹
if bullet.rect.bottom < 0:
player.bullets.remove(bullet) for enemy in enemies1:
#2. 移动敌机
enemy.move()
#3. 敌机与玩家飞机碰撞效果处理
if pygame.sprite.collide_circle(enemy, player):
enemies_down.add(enemy)
enemies1.remove(enemy)
player.is_hit = True
break
#4. 移动出屏幕后删除飞机
if enemy.rect.top < 0:
enemies1.remove(enemy) #敌机被子弹击中效果处理
# 将被击中的敌机对象添加到击毁敌机 Group 中,用来渲染击毁动画
enemies1_down = pygame.sprite.groupcollide(enemies1, player.bullets, 1, 1)
for enemy_down in enemies1_down:
enemies_down.add(enemy_down)
在while running循环中添加自己飞机动态逻辑
# 绘制玩家飞机
if not player.is_hit:
screen.blit(player.image[player.img_index], player.rect)
# 更换图片索引使飞机有动画效果
player.img_index = shoot_frequency // 8
else:
# 玩家飞机被击中后的效果处理
player.img_index = player_down_index // 8
screen.blit(player.image[player.img_index], player.rect)
player_down_index += 1
if player_down_index > 47:
# 击中效果处理完成后游戏结束
running = False # 敌机被子弹击中效果显示
for enemy_down in enemies_down:
if enemy_down.down_index == 0:
pass
if enemy_down.down_index > 7:
enemies_down.remove(enemy_down)
score += 1000
continue
screen.blit(enemy_down.down_imgs[enemy_down.down_index // 2], enemy_down.rect)
enemy_down.down_index += 1
效果显示:
源码下载地址:https://github.com/secondtonone1/python-/tree/master/plane
谢谢关注我的公众号:
python学习笔记(七) 类和pygame实现打飞机游戏的更多相关文章
- python学习笔记4_类和更抽象
python学习笔记4_类和更抽象 一.对象 class 对象主要有三个特性,继承.封装.多态.python的核心. 1.多态.封装.继承 多态,就算不知道变量所引用的类型,还是可以操作对象,根据类型 ...
- python学习笔记(15)--pygame的安装
说明: 1. 现在是2017.3.9号,最新的python版本是3.6,最新的pygame是1.9.3,这两个最好都用32位的. 2. pygame1.9.3下载地址:http://www.lfd.u ...
- Python学习笔记 - day7 - 类
类 面向对象最重要的概念就是类(Class)和实例(Instance),比如球类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同.在Python中,定义类 ...
- python学习笔记(七):面向对象编程、类
一.面向对象编程 面向对象--Object Oriented Programming,简称oop,是一种程序设计思想.在说面向对象之前,先说一下什么是编程范式,编程范式你按照什么方式来去编程,去实现一 ...
- Python学习笔记七-错误和异常
程序员总是和各种错误打交道,学习如何识别并正确的处理程序错误是很有必要的. 7.1错误和异常 1.错误 从软件方面来看,错误分为语法错误和逻辑错误两种.这两种错误都将导致程序无法正常进行下去,当Pyt ...
- Python学习笔记七
面向对象编程 面向对象的特性如下: 类:具有相同属性和方法的一类事物,成为类. 对象:类的实例化后的结果,一个类可以实例化多个对象,每个对象也可以不同的属性. 封装:在类中对数据的赋值,类里面包含着类 ...
- python学习笔记1-元类__metaclass__
type 其实就是元类,type 是python 背后创建所有对象的元类 python 中的类的创建规则: 假设创建Foo 这个类 class Foo(Bar): def __init__(): ...
- Python学习笔记12—类
典型的类和调用方法: #!/usr/bin/env Python # coding=utf-8 __metaclass__ = type #新式类 class Person: #创建类 def __i ...
- Python 学习笔记 - 10.类(Class) 1
定义 Python 的 Class 比较特别,和我们习惯的静态语言类型定义有很大区别. 1. 使用一个名为 __init__ 的方法来完成初始化.2. 使用一个名为 __del__ 的方法来完成类似析 ...
随机推荐
- Zabbix_agnet部署
原文发表于cu:2016-05-18 参考文档: zabbix监控linux主机:http://www.osyunwei.com/archives/8035.html 一.环境 Server:基于C ...
- 【ZABBIX】Zabbix触发器的告警原理及创建方法
概述: 触发器中的表达式使用很灵活,我们可以创建一个复杂的逻辑测试监控,触发器表达式形式如下: {<server>:<key>.<function>(& ...
- C++:this指针的简单理解
一.什么是this指针 要想理解什么是this指针,首先必须理解在C++中是如何为类的对象分配内存空间的. #include<iostream> using namespace std; ...
- tomcat启动时,报java.io.EOFException
在启动Tomcat的时候突然报出IO异常,具体异常如下图 在网上找了解决方法,测试了好几种,都不行,到最后看了一个博客解决了,在此记录一下. 百度了下,网上都是说去Tomcat目录下:将tomcat5 ...
- 周总结<3>
经过了一周的学习,我们在html以及C语言方面又有的新的知识点的学习,包括计算机导论也学会了路由器的设置. html 鼠标事件 C 二叉树的遍历代码 计算机导论 路由器的设置 Html案例: < ...
- C#控制台应用程序
使用C#创建控制台应用程序的基本步骤: (1)创建项目: (2)编辑C#源代码: (3)编译运行: 例题:在控制台输出“Hello world!”. 第一步:文件→新建→项目:选择“项目类型”为Vis ...
- 经典SQL语句基础50题
很全面的sql语句大全.都是很基础性的,今天特意整理了下.大家互相学习.大家有好的都可以分享出来, 分享也是一种快乐. --创建数据库 create database SQL50 --打开SQL50 ...
- week1读构建之法-读书笔记
最开始听见杨老师说邹欣老师这个名字总觉得很熟悉,后来看见博客上老师的头像恍然大悟,原来机缘巧合已经在微博上关注邹老师许久,一直觉得邹老师是个很有意思的人,兴趣一定十分广泛,看了老师的书确实能感觉到邹老 ...
- 转载-C++ vector 用法
转自:http://www.cnblogs.com/wang7/archive/2012/04/27/2474138.html 在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. ...
- BZOJ 1266 上学路线(最短路+最小割)
给出n个点的无向图,每条边有两个属性,边权和代价. 第一问求1-n的最短路.第二问求用最小的代价删边使得最短路的距离变大. 对于第二问.显然该删除的是出现在最短路径上的边.如果我们将图用最短路跑一遍预 ...