[pygame] pygame设计联机对战桌游(1-2)
本系列总目录:https://blog.csdn.net/wxlxy316/article/details/104246724
内容概要
一、学习pygame提供的官方教程(2)
官方教程
3.3 设计伊始
3.3.1 加载模块
启动游戏,首先应该加载模块
#!/usr/bin/env python
#
# Tom's Pong
# A simple pong game with realistic physics and AI
# http://www.tomchance.uklinux.net/projects/pong.shtml
#
# Released under the GNU General Public License
VERSION = "0.4"
try:
import sys
import random
import math
import os
import getopt
import pygame
from socket import *
from pygame.locals import *
except:
print("couldn't load module.")
sys.exit(2)
3.3.2 资源处理
对于资源加载,由于它们和游戏逻辑并无关系,我们常常将它独立为一些函数,并且最先设计,从而为之后的设计开发所用。通常,我将所有这种性质的代码放在自己的无类函数中;一般来说,这些将是资源处理功能。您当然可以为它们创建类,以便可以将它们分组在一起,并且可能有一个可以控制所有资源的对象。与任何良好的编程环境一样,由您自己制定最佳实践和风格。
编写自己的资源处理功能总是一个好主意,因为尽管pygame有打开图像和声音的方法,并且其他模块将有打开其他资源的方法,但是这些方法可能占用多个行,但是它们可能需要一致的自行修改,它们通常无法提供令人满意的错误处理。编写资源处理功能可以为您提供复杂的,可重用的代码,并可以更好地控制资源。以图像加载功能为例:
def load_png(name):
""" Load image and return image object"""
fullname = os.path.join('data', name)
try:
image = pygame.image.load(fullname)
if image.get_alpha() is None:
image = image.convert()
else:
image = image.convert_alpha()
except:
print('Cannot load image:', fullname)
raise SystemExit
return image, image.get_rect()
pygame.image.load()
与从文件中加载新图像所提供的功能相比,这里我们提供了一种更为复杂的图像加载功能。请注意,该函数的第一行是一个文档字符串,描述该函数的功能以及它返回的对象。该函数假定所有图像都在名为data
的目录中,因此它将使用文件名并创建完整路径名,例如data/ball.png
,使用os
模块以确保跨平台兼容性。然后,它尝试加载图像,并转换任何alpha
区域,以便获得透明性,如果存在问题,它将返回更容易理解的错误。最后,它返回图像对象及其rect
。
您可以执行类似的功能来加载其他资源,例如加载声音。您还可以创建资源处理类,以使用更复杂的资源为您提供更大的灵活性。例如,您可以制作一个音乐课,其__init__
功能是加载声音(也许是从load_sound()
功能中借用的),暂停音乐的功能和重新启动音乐的功能。另一个方便的资源处理类是用于网络连接。打开套接字,通过适当的安全性和错误检查传递数据,关闭套接字,手指地址和其他网络任务的功能可以使编写具有网络功能的游戏相对轻松。
请记住,这些函数/类的主要任务是确保在开始编写游戏对象类和主循环时,几乎没有任何事情要做。类继承可以使这些基本类特别方便。但是不要太过分;仅将由一个类使用的函数应写为该类的一部分,而不是全局函数。
3.4 游戏对象类
加载模块并编写资源处理功能后,您将要继续编写一些游戏对象。这样做的方法相当简单,尽管乍一看似乎很复杂。您为游戏中每种类型的对象编写一个类,然后为这些对象创建这些类的实例。然后,您可以使用这些类的方法来操作对象,从而为对象提供一些运动和交互功能。因此,您的游戏(采用伪代码)将如下所示:
#!/usr/bin/python
# [load modules here]
# [resource handling functions here]
class Ball:
# [ball functions (methods) here]
# [e.g. a function to calculate new position]
# [and a function to check if it hits the side]
def main:
# [initiate game environment here]
# [create new object as instance of ball class]
ball = Ball()
while 1:
# [check for user input]
# [call ball's update function]
ball.update()
当然,这是一个非常简单的示例,您需要放入所有代码,而不是那些放在方括号中的注释。但是您应该了解基本概念。您创建一个类,在其中放置了球的所有功能,包括__init__
,它将创建球的所有属性,update
将放到该位置,然后将其移动到新位置,然后将其移动到新位置。
然后,您可以为所有其他游戏对象创建更多类,然后创建它们的实例,以便可以在main
函数和主程序循环中轻松处理它们。将其与在main
函数中启动球进行比较,然后具有许多无类函数来操纵设定的球对象,您将希望看到为什么使用类是一个优点:它允许您将每个对象的所有代码放入一个地方; 它使使用对象更容易;它使添加新对象并对其进行操作更加灵活。您可以为每个新的球对象简单地创建Ball
类的新实例,而不是为每个新的球对象添加更多的代码。魔法!
3.4.1 球类
class Ball(pygame.sprite.Sprite):
"""A ball that will move across the screen
Returns: ball object
Functions: update, calcnewpos
Attributes: area, vector"""
def __init__(self, vector):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_png('ball.png')
screen = pygame.display.get_surface()
self.area = screen.get_rect()
self.vector = vector
def update(self):
newpos = self.calcnewpos(self.rect,self.vector)
self.rect = newpos
def calcnewpos(self,rect,vector):
(angle,z) = vector
(dx,dy) = (z*math.cos(angle),z*math.sin(angle))
return rect.move(dx,dy)
该类具有__init__
设置球的update
函数,将球的矩形更改为新位置的calcnewpos
函数,以及根据球的当前位置和其向量计算球的新位置的函数
3.4.1.1 精灵(sprite)对象
您在游戏中渲染的每个图像都是一个sprite对象,因此,每个对象的类都应该继承Sprite该类。
这是Python非常好的特性之一,类继承。现在,Ball
该类具有Sprite
该类随附的所有功能,并且该类的任何对象实例都Ball
将被Pygame注册为sprite
。对于文本和背景(不会移动),可以将对象着色到背景上,而Pygame以不同的方式处理子对象,当您查看整个程序的代码时,您会看到。
基本上,您既创建了一个球对象,又为该球创建了一个精灵对象,然后在该精灵对象上调用了球形的update函数,从而更新了精灵。
精灵还为您提供确定两个对象是否碰撞的复杂方法。通常,您可能只需要检查主循环以查看其矩形是否重叠,但这将涉及大量代码,这将是浪费的,因为Sprite该类提供了两个函数(spritecollide
和groupcollide
)为您执行此操作。
3.4.1.2 矢量
球具有一个属性vector,该属性由angle和z(速度)组成,angle从x轴正半轴顺时针旋转计算
Pygame本身不支持角度移动,我们需要利用calcnewpos
函数解析出球在x,y轴上移动的长度,告知sprite对象移动
3.5 用户控制对象
到目前为止,您可以创建一个Pygame窗口,并渲染一个将在屏幕上飞行的球。下一步是制作一些用户可以控制的球棒。
3.5.1 球棒类
球棒类的原理与球类相似。您需要一个__init__
函数来初始化球(以便您可以为每个球棒创建对象实例);一个update
函数,在将蝙蝠放到屏幕上之前对球棒进行逐帧更改;以及实现该类其他特性的函数。
class Bat(pygame.sprite.Sprite):