用Python和Pygame写游戏-从入门到精通(10)

时间:2022-04-02 19:14:10

这节讲了一些之前出现过的键盘操作。

键盘设备

以前第二部分也稍微使用了一下键盘,那时候是用了pygame.event.get()获取所有的事件,当event.type == KEYDOWN的时候,在判断event.key的种类,而各个种类也使用K_aK_b……等判断。这里再介绍一个pygame.key.get_pressed()来获得所有按下的键值,它会返回一个元组。这个元组的索引就是键值,对应的就是是否按下,比如说:

pressed_keys = pygame.key.get_pressed()
    if pressed_keys[K_SPACE]:
        # Space key has been pressed
        fire()pressed_keys = pygame.key.get_pressed()

当然key模块下还有很多函数:

  • key.get_focused —— 返回当前的pygame窗口是否激活
  • key.get_pressed —— 获得所有按下的键值
  • key.get_mods —— 按下的组合键(Alt, Ctrl, Shift)
  • key.set_mods —— 你也可以模拟按下组合键的效果(KMOD_ALT, KMOD_CTRL, KMOD_SHIFT)
  • key.set_repeat —— 无参数调用设置pygame不产生重复按键事件,二参数(delay, interval)调用设置重复事件发生的时间
  • key.name —— 接受键值返回键名

使用键盘控制方向

用Python和Pygame写游戏-从入门到精通(10)

通过向量来控制方向的上下左右,但仅局限于8个方向。

#-*- coding:utf-8 -*-
background_image_filename = './images/sushiplate.jpg'
sprite_image_filename = './images/fugu.png'

import pygame
from pygame.locals import *
from sys import exit
from gameobjects.vector2 import Vector2

pygame.init()

screen = pygame.display.set_mode((640, 480), 0, 32)

background = pygame.image.load(background_image_filename).convert()
sprite = pygame.image.load(sprite_image_filename)

clock = pygame.time.Clock()
#传入坐标被作为向量
sprite_pos = Vector2(200, 150)
#初始速度
sprite_speed = 300.

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
    #获取按下的键值
    pressed_keys = pygame.key.get_pressed()
    #设置按键的向量初值
    key_direction = Vector2(0, 0)
    #若按下左键则像素减一
    if pressed_keys[K_LEFT]:
        key_direction.x = -1
    elif pressed_keys[K_RIGHT]:
        key_direction.x = 1
    if pressed_keys[K_UP]:
        key_direction.y = -1
    elif pressed_keys[K_DOWN]:
        key_direction.y = 1
    #按键向量规格化
    key_direction.normalize()

    screen.blit(background, (0, 0))
    screen.blit(sprite, sprite_pos)

    time_passed = clock.tick(30)
    time_passed_passed = time_passed / 1000.0
    #鱼的新的位置=(按键向量*鱼的运动速度*帧)+ 初始位置(前一个位置)
    sprite_pos += key_direction * sprite_speed * time_passed_passed
    #刷新鱼图片位置
    pygame.display.update()

用上下左右键来控制鱼的移动实例。

下面是一个可以全方位逆时针选择的鱼实例:

#-*- coding:utf-8 -*-

background_image_filename = './images/sushiplate.jpg'
sprite_image_filename = './images/fugu.png'

import pygame
from pygame.locals import *
from sys import exit
from gameobjects.vector2 import Vector2
from math import *

pygame.init()

screen = pygame.display.set_mode((640, 480), 0, 32)

background = pygame.image.load(background_image_filename).convert()
sprite = pygame.image.load(sprite_image_filename).convert_alpha()

clock = pygame.time.Clock()

sprite_pos = Vector2(200, 150)  # 初始位置
sprite_speed = 300.  # 每秒前进的像素数(速度)
sprite_rotation = 0.  # 初始角度
sprite_rotation_speed = 360.  # 每秒转动的角度数(转速)

while True:

    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    pressed_keys = pygame.key.get_pressed()

    rotation_direction = 0.
    movement_direction = 0.

    # 更改角度
    if pressed_keys[K_LEFT]:
        rotation_direction = +1.
    if pressed_keys[K_RIGHT]:
        rotation_direction = -1.
    # 前进、后退
    if pressed_keys[K_UP]:
        movement_direction = -1.
    if pressed_keys[K_DOWN]:
        movement_direction = +1.

    screen.blit(background, (0, 0))

    # 获得一条转向后的鱼,rotate(Surface, angle) -> Surface
    # 未经过滤的逆时针旋转。 角度参数代表度数并可以是任何浮点值。 负角度量将顺时针旋转。
    rotated_sprite = pygame.transform.rotate(sprite, sprite_rotation)
    # 转向后,图片的长宽会变化,因为图片永远是矩形,为了放得下一个转向后的矩形,外接的矩形势必会比较大
    w, h = rotated_sprite.get_size()
    # 获得绘制图片的左上角
    sprite_draw_pos = Vector2(sprite_pos.x - w / 2, sprite_pos.y - h / 2)
    # 将一个平面的一部分或全部图象整块从这个平面复制到另一个平面
    screen.blit(rotated_sprite, sprite_draw_pos)

    time_passed = clock.tick()
    time_passed_seconds = time_passed / 1000.0

    # 图片的转向速度也需要和行进速度一样,通过时间来控制
    sprite_rotation += rotation_direction * sprite_rotation_speed * time_passed_seconds

    # 获得前进(x方向和y方向),这两个需要一点点三角的知识,类似于sin(pi/6)=30
    heading_x = sin(sprite_rotation * pi / 180.)
    heading_y = cos(sprite_rotation * pi / 180.)
    # 转换为单位速度向量
    heading = Vector2(heading_x, heading_y)
    # 转换为速度
    heading *= movement_direction

    sprite_pos += heading * sprite_speed * time_passed_seconds

    pygame.display.update()
我们通过上下控制前进/后退,而左右控制转向。我们通过 pygame.transform.rotate() 来获得了转向后的图片,具体参数可以参考代码。各条语句的作用也可以参考注释