Python游戏开发(三)


python游戏开发之色彩与绘图

pygame色彩机制

  1. 使用pygame.Color类表示色彩
    Color类使用RGB或者RGBA(A代表透明度,可选)色彩模式。
    可以使用色彩名字:
    色彩的RGB或RBGA值:Color(190, 190, 190, 255)
    色彩的名字:Color("grey")
    RGB即红绿蓝三原色,范围从0~255之间。
    A为α通道,参考值为0~255,越高越不透明

  2. pygame.Color的属性
    pygame.Color.r Color类的R值
    pygame.Color.g Color类的G值
    pygame.Color.b Color类的B值
    pygame.Color.a Color类的A值
    pygame.Color.normalize 可以使得所有的参数归一化一个0~1之间的浮点数

  3. 修改小球的背景颜色
    需求:通过小球运动的位置不同,分别改变其背景中R,G,B三原色的值。

import sys, pygame
pygame.init()
size = width, height = (600, 400)
speed = [1, 1]
bgcolor = pygame.Color("black")
fps = 300
still = False
icon = pygame.image.load("滑稽球1.jpg")
pygame.display.set_icon(icon)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("壁球小游戏鼠标版")
ball = pygame.image.load("滑稽球1.jpg")
ballrect = ball.get_rect()
fclock = pygame.time.Clock()

def RGBChannel(a):
    return 0 if a<0 else(255 if a>255 else(int(a)))
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] if speed[0] == 0 else (abs(speed[0]) - 1) * int(speed[0] / abs(speed[0]))
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1 if speed[0] > 0 else speed[0] - 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1 if speed[1] > 0 else speed[1] - 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] if speed[1] == 0 else (abs(speed[1]) - 1) * int(speed[1] / abs(speed[1]))
            elif event.key == pygame.K_ESCAPE:
                sys.exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                still = True
        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                still = False
                ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)
        elif event.type == pygame.MOUSEMOTION:
            if event.buttons[0] == 1:
                ballrect = ballrect.move(event.pos[0] - ballrect.left, event.pos[1] - ballrect.top)

    if ballrect.left < 0 or ballrect.right > width:
        speed[0] = -speed[0]
        if ballrect.right > width and ballrect.right + speed[0] > ballrect.right:
            # 因为对于鼠标的控制而言,我们是设置的鼠标位置为矩形框的左上角,所以只考虑右下方突破边界的情况
            speed[0] = -speed[0]
    elif ballrect.top < 0 or ballrect.bottom > height:
        speed[1] = -speed[1]
        if ballrect.bottom > height and ballrect.bottom + speed[1] > ballrect.bottom:
            speed[1] = -speed[1]
    if pygame.display.get_active():
        if not still:
            ballrect = ballrect.move(speed[0], speed[1])
    bgcolor.r = RGBChannel(ballrect.left/width*255)
    bgcolor.g = RGBChannel(ballrect.top/height*255)
    bgcolor.b = RGBChannel(min(speed[0], speed[1])/max(speed[0], speed[1], 1))
    screen.fill(bgcolor)
    screen.blit(ball, ballrect)
    pygame.display.update()
    fclock.tick(fps)

pygame的图形绘制机制

所有图形绘制之后,欧pygame都会使用一个rect类(矩形类)来表示一个范围。

pygame.rect

表示一个矩形范围,因而有四个基本的参数值:(left, top)矩形左上角的坐标,width,height宽度与高度,通过这四个值唯一确定矩形的位置。
同样rect类也提供了一些方法例如:rect.move(),rect.copy()等等

pygame.draw

pygame 通过pygame.draw来绘制不同的图形,包括矩形、圆形、椭圆等等。

  1. pygame.draw.rect(surface, color, rect, width=0)
    surface 表示的是绘制在什么区域,一般而言就是当前的屏幕screen
    color表示矩形的颜色
    rect表示矩形的区域,通过一个四元素的元组确定即左上角坐标与宽、高
    width表示的是矩形的线条宽度,默认为0即矩形全部为color颜色,如果不为0,那么就会绘制一个空心区域
import sys, pygame

pygame.init()
size = width, height = (600, 400)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("pygame图形绘制")
gold = 255, 251, 0
red = pygame.Color("red")

rect1 = pygame.draw.rect(screen, gold, (100, 100, 200, 100), 5)
rect2 = pygame.draw.rect(screen, red, (210, 210, 200, 100))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
    pygame.display.update()

以上是在pygame中绘制矩形的示例代码。
2. pygame.draw.polygon(surface, color, pointlist, width=0)
多边形需要给一个pointlist即一个顶点坐标的列表。

  1. pygame.draw.circle(surface, color, pos, radicus, width=0)
    圆形通过一个圆心坐标和半径来绘制。

  2. pygame.draw.ellipse(surface, color, rect, width=0)
    椭圆形的定义方式是通过一个外切矩形来确定。
    rect表示一个矩形区域

  3. pygame.draw.arch(surface, color, rect, start_angle, stop_angle, width=0)
    这里绘制的是一个椭圆形的部分。
    同样通过一个外切矩形来确定唯一的椭圆。
    start_angle来表示起始角度;
    stop_angle来表示终止角度;仍然使用的是笛卡尔坐标系。

  4. pygame.draw.line(surface, color, start_pos, end_pos, width=1)
    start_pos表示的是起始坐标;
    end_pos 表示的是终点坐标;
    默认的线条宽度是1。

  5. pygame.draw.lines(suraface, color, closed, pointlist, width=1)
    closed 如果为True会把起始和终止点连接使得多线形成闭合图形。

  6. pygame.draw.aaline(surface, color, start_pos, end_pos, blend=1)
    直线绘制需要跨越像素,放大一定程度必然会出现锯齿。
    pygame提供了绘制无锯齿线的方法,注意这里的“无锯齿”只是尽可能地减少锯齿的出现,而不可能真的全面消除锯齿的存在。
    blend:不为0时,与线条所在背景颜色混合。

  7. pygame.draw.aalines(surface, color, pointlist, blend=1)
    绘制无锯齿多线。

pygame文字绘制机制

通过使用pygame.freetype来把文字绘制到屏幕上。
无论是中文还是其他语言,文字都是通过点阵图的方式绘制到屏幕上面。
freetype是增强方法,必须要额外进行import pygame.freetype才能使用。

系统字体

对于windows系统,通常把字体存储在C:\windows\fonts目录下。
字体通常是*.ttc或者*.ttf格式的文件。

使用字体

首先需要创建一个字体对象。
pygame.freetype.Font来创建字体对象;
pygame.freetype.render()/render_to()来输出字体。

  1. pygame.freetype.Font(File, size=0)
    File表示字体文件存储的位置,建议使用绝对路径
    size表示的字体的大小。
  2. Font.render_to(surf, dest, text, fgcolor = None, bgcolor = None, rotation, size)
    返回的是一个rect 类型。
    surf:绘制字体的平面
    dest:绘制字体的在屏幕的位置
    text:字体的内容,字符串
    fgcolor:字体颜色
    bgcolor: 背景颜色
    rotation:逆时针旋转的角度
    size:字体的大小,如果不另外设置会使用之前的Font的大小。
import sys, pygame
import pygame.freetype

pygame.init()
size = width, height = (600, 400)
screen = pygame.display.set_mode(size)

f1 = pygame.freetype.Font("C://windows//Fonts//msyh.ttc", 36)
rect = f1.render_to(screen, (200, 160), "世界和平", )
  1. Font.render(text, fgcolor=None, bgcolor=None, rotation, size)
    相比于render_to()它少了前两个参数。
    它会返回一个rect对象与一个surf对象,来表示把文字绘制到一个新的屏幕上。

pygame绘图机制的精髓

  1. surface类
    表示的是绘图平面,绘图层、图层;
    表示的是图形或文字图像最终绘制的位置。
    图层是可以和主图层的并列存在的,但是只有主图层的图像会被显示在屏幕上。
  2. rect类
    表示一个矩形区域,但是它只对应一个主图层上的区域。
    它是表示主图层上某一个区域的位置信息或指针;
    可以指定某个图层绘制在特定区域上。
  3. 主图层
    由pygame.display.set_mode()生成的surface对象就是主图层。
    如果希望把其他图层的东西绘制到主图层上就要使用blit方法,例如:
    screen.blit(ball, ballrect)
    这就是把小球的图像ball的图层将其绘制到ballrect的区域上。

壁球小游戏文字型

需求:把壁球替换为一段文字,可以进行移动;
关键要素:文字的绘制与刷新。

可以使用render_to()方法或者render()方法来绘制文字。

import sys, pygame
import pygame.freetype

pygame.init()
size = width, height = 600, 400
speed = [1, 1]
Black = 0, 0, 0
Gold = 255, 251, 0
pos = [230, 160]

screen = pygame.display.set_mode(size)
pygame.display.set_caption("pygame壁球小游戏文字型")
fps = 300
fclock = pygame.time.Clock()
f1 = pygame.freetype.Font("C://windows//Fonts//msyh.ttc", 36)
f1rect = f1.render_to(screen, pos, "世界和平", fgcolor=Gold, size=50)


while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed[0] = speed[0] - 1 if speed[0] > 0 else 0
            elif event.key == pygame.K_RIGHT:
                speed[0] = speed[0] + 1
            elif event.key == pygame.K_UP:
                speed[1] = speed[1] + 1
            elif event.key == pygame.K_DOWN:
                speed[1] = speed[1] - 1 if speed[1] > 0 else 0

    if pos[0] < 0 or pos[0] + f1rect.width > width:
        speed[0] = -speed[0]
    if pos[1] < 0 or pos[1] + f1rect.height > height:
        speed[1] = -speed[1]
    pos[0] = pos[0] + speed[0]
    pos[1] = pos[1] + speed[1]
    screen.fill(Black)
    f1rect = f1.render_to(screen, pos, "世界和平", fgcolor=Gold, size=50)
    pygame.display.update()
    fclock.tick(fps)

以上内容来自北京理工大学嵩天老师及其团队的《Python游戏开发入门》课程第四周的内容。
非常感谢嵩天老师及其团队给我们带来这样优质的课程。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM