03-接炸弹小游戏(处理事件)

处理事件

  • 用while True:处理事件
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == MOUSEMOTION:
            pass
        elif event.type == MOUSEBUTTONUP:
            pass

键盘事件

  • 响应键盘按键的最佳方式其实是:设置标志变量,让程序进行后续响应。

  • 对于多种事件处理,用事件轮询或者查看key.name属性

  • 如果需要按键连按,必须设置:

     pygame.key.set_repeat(x_ms)
    

鼠标事件

import pygame
from pygame.locals import *

"""对于MOUSEMOTION事件,属性是event.pos,event.rel和event.button"""
for event in pygame.event.get():
    if event.type == MOUSEMOTION:
        mouse_x, mouse_y = event.pos
        move_x, mov_y = event.rel
        
"""对于MOUSEBUTTONDOWN和UP事件,属性是event.pos和event.button"""
for event in pygame.event.get():
    if event.type == MOUSEBUTTONDOWN:
        mouse_down = event.button
        mouse_down_x, mouse_down_y = event.pos
    elif event.type == MOUSEBUTTONUP:
        mouse_up = event.button
        mouse_up_x, mouse_up_y = event.pos

除了查询事件来获得鼠标按键信息外,还可以用以下方法:

	x, y = pygame.mouse.get_pos() # 获得鼠标坐标位置
	b1, b2, b3 = pygame.mouse.get_pressed() # 读取鼠标按钮数组
	r1, r2 = pygame.mouse.get_rel() # 获得鼠标相对位置

设备轮询

pygame.key.get_pressed()返回一个全部键位的布尔值列表。直接通过键位对应的常量进行索引即可获得对应状态位

keys = pygame.key.get_pressed()
if keys[k_ESCAPE]:
	sys.exit()
  • 实际上,所有的常量都有对应的ASCII码值。可以通过chr()函数获得一个ASCII编码数字的字符串表示。

打字速度小游戏


import sys, random, time, pygame
from pygame.locals import *

def print_text(font, x, y, text, color = (255,255,255)):
    imgText = font.render(text, True, color)
    screen.blit(imgText, (x, y))


pygame.init()
screen = pygame.display.set_mode((600, 500))
pygame.display.set_caption("Keyboard Demo")
font1 = pygame.font.Font(None, 24)
font2 = pygame.font.Font(None, 200)
white = 255, 255, 255
yellow = 255, 255, 0
green = 0,255,0

key_flag = False
correct_answer = 97
seconds = 10
score = 0
clock_start = 0
game_over = True
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == KEYDOWN:
            key_flag = True
        elif event.type == KEYUP:
            key_flag = False
    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()
    if keys[K_RETURN]:
        if game_over:
            game_over = False
            score = 0
            seconds = 11
            clock_start = time.clock() # 注意这里,一开始缩进写错了。导致无法倒计时。
    current = time.clock() - clock_start
    speed = score * 6

    if seconds - current < 0:
        game_over = True
    elif current <= 10:
        if keys[correct_answer]:
            correct_answer = random.randint(97, 122)
            score += 1

    # clear the screen
    screen.fill((0, 100, 0))

    print_text(font1, 0, 0, "Let's see how fast you can type!")
    print_text(font1, 0, 20, "Try to keep up for 10 seconds...")

    if key_flag:
        print_text(font1, 500, 0, "<key>")

    if not game_over:
        print_text(font1, 0, 80, "Time: " + str(int(seconds - current)))

    print_text(font1, 0, 100, "Speed: " + str(speed) + " letters/min")

    if game_over:
        print_text(font1, 0, 160, "Press Enter to start...")

    print_text(font2, 0, 240, chr(correct_answer - 32), yellow)

    # update the display
    pygame.display.update()

在这里插入图片描述
鼠标游戏:

import pygame,sys
from pygame.locals import *


def print_text(font, x, y, text, color=(255,255,255)):
    imgText = font.render(text, True, color)
    screen.blit(imgText, (x,y))


pygame.init()
screen = pygame.display.set_mode((600,500))
pygame.display.set_caption("Mouse Demo")
font1 = pygame.font.Font(None, 24)
white = 255,255,255

mouse_x = mouse_y = 0
move_x = move_y = 0
mouse_down = mouse_up = 0
mouse_down_x = mouse_down_y = 0
mouse_up_x = mouse_up_y = 0

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == MOUSEMOTION:
            mouse_x, mouse_y = event.pos
            move_x,move_y = event.rel
        elif event.type == MOUSEBUTTONDOWN:
            mouse_down = event.button
            mouse_down_x, mouse_down_y = event.pos
        elif event.type == MOUSEBUTTONUP:
            mouse_up = event.button
            mouse_up_x, mouse_down_y = event.pos

    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()
    screen.fill((0, 100, 0))

    print_text(font1, 0, 0, "Mouse Events")
    print_text(font1, 0, 20, "Mouse position: " + str(mouse_x) +
               "," + str(mouse_y))
    print_text(font1, 0, 40, "Mouse relative: " + str(move_x) +
               "," + str(move_y))

    print_text(font1, 0, 60, "Mouse button down: " + str(mouse_down) +
               " at " + str(mouse_down_x) + "," + str(mouse_down_y))

    print_text(font1, 0, 80, "Mouse button up: " + str(mouse_up) +
               " at " + str(mouse_up_x) + "," + str(mouse_up_y))

    print_text(font1, 0, 160, "Mouse Polling")

    x, y = pygame.mouse.get_pos()
    print_text(font1, 0, 180, "Mouse position: " + str(x) + "," + str(y))

    b1, b2, b3 = pygame.mouse.get_pressed()
    print_text(font1, 0, 200, "Mouse buttons: " +
               str(b1) + "," + str(b2) + "," + str(b3))
    r1, r2 = pygame.mouse.get_rel()
    print_text(font1, 0, 220, "Mouse rel :"+str(r1)+","+str(r2))

    pygame.display.update()

效果:
在这里插入图片描述

接炸弹游戏

思路

  • 炸弹就是个圆形,每次y坐标初始值都在屏幕外面,x是随机的范围在(0,500)中间。
  • 在循环中,如果game_over标志为假,那么让炸弹y坐标增加一个值,使其下落。
  • 判断逻辑:
    如果炸弹没有接住,也就是它的y坐标超过屏宽最大值,那么将炸弹的x,y坐标重置到屏幕上面。同时让生命值减少,如果到零则让游戏结束;
    如果炸弹接住,也就是判断它的y是否在屏幕底部而且x是否在挡板宽度以内。
  • 更新挡板位置,如果越界则让它的坐标限定在某个区域。
  • 最后就是绘制更新整个屏幕。(一般来说都是先判定逻辑,再更新屏幕)
import sys,random,time,pygame
from pygame.locals import *


def print_text(font, x, y, text, color=(255, 255, 255)):
    imgText = font.render(text, True, color)
    screen.blit(imgText, (x, y))


# main program begins
pygame.init()
screen = pygame.display.set_mode((600, 500))
pygame.display.set_caption("Bomb Catching Game")
font1 = pygame.font.Font(None, 24)

white = 255, 255, 255
red = 220, 50, 50
yellow = 230, 230, 50
black = 0, 0, 0

lives = 3
score = 0
clock_start = 0
game_over = True
mouse_x = mouse_y = 0

pos_x = 300
pos_y = 460

bomb_x = random.randint(0, 500)
bomb_y = -50
vel_y = 0.7

# repeating loop
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == MOUSEMOTION:
            mouse_x, mouse_y = event.pos
            move_x, move_y = event.rel
        elif event.type == MOUSEBUTTONUP:
            if game_over:
                game_over = False
                lives = 3
                score = 0

    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()
    # 清屏
    screen.fill((0, 0, 100))

    if game_over:
        print_text(font1, 220, 250, "<CLICK TO PLAY>")
        pygame.mouse.set_visible(True)
    else:
        pygame.mouse.set_visible(False)
        bomb_y += vel_y

        # 是否没接住炸弹
        if bomb_y > 500:
            bomb_x = random.randint(0,500)
            bomb_y = -50
            lives -= 1
            if lives == 0:
                game_over = True

        # 是否已经接住炸弹
        elif bomb_y > pos_y:
            if bomb_x > pos_x and bomb_x < pos_x + 120:
                # 炸弹是否在挡板的宽度以内,120是挡板的宽
                score += 10
                bomb_x = random.randint(0, 500)
                bomb_y = -50
        # 绘制炸弹
        pygame.draw.circle(screen, black, (bomb_x - 4, int(bomb_y) - 4), 30, 0)
        pygame.draw.circle(screen, yellow, (bomb_x, int(bomb_y)), 30, 0)

        # 更新挡板位置
        pos_x = mouse_x
        if pos_x < 0:
            pos_x = 0
        elif pos_x > 500:
            pos_x = 500

        #绘制挡板
        pygame.draw.rect(screen, black, (pos_x-4,pos_y-4,120,40), 0)
        pygame.draw.rect(screen, red, (pos_x, pos_y, 120, 40), 0)

    # print # of lives
    print_text(font1, 0, 0, "LIVES: " + str(lives))

    # print score
    print_text(font1, 500, 0, "SCORE: " + str(score))

    pygame.display.update()



效果:
在这里插入图片描述个人想法:

  • 加一个等级系统,当分数达到不同的分值时,适当加大难度,炸弹下落速度会越来越快!
  • 可以加上打字爆破:在炸弹上绘制字母,并存到一个变量中。轮询键盘事件,如果对应标志位是1,让炸弹GG

课后挑战:

  1. 炸弹碰撞时候,显示“BOOM!”并且使用延时。
  2. 炸弹下落时候加上一个不停变换颜色的拖尾。
  3. 加入一个水平速度,让炸弹以一定的角度进行下落。

注:pro版本加入了等级机制,分数每增加50,上升一个难度,速度增加。炸弹有角度下落并且有碰撞检测。

import sys,random,time,pygame
from pygame.locals import *


def print_text(font, x, y, text, color=(255, 255, 255)):
    imgText = font.render(text, True, color)
    screen.blit(imgText, (x, y))


# main program begins
pygame.init()
screen = pygame.display.set_mode((600, 500))
pygame.display.set_caption("Bomb Catching Game")
font1 = pygame.font.Font(None, 24)
font2 = pygame.font.Font(None, 30)


white = 255, 255, 255
red = 220, 50, 50
yellow = 230, 230, 50
black = 0, 0, 0

lives = 6
score = 0
clock_start = 0
game_over = True
mouse_x = mouse_y = 0

pos_x = 300
pos_y = 460
# 爆炸字样位置坐标
boom_x = -50
boom_y = -50
boom_flag = False

bomb_x = random.randint(0, 500)
bomb_y = -50
vel_y = 0.5
vel_x = 0.2
level = 0 # 游戏难度
a = 0.05 # 速度递增系数
k = 0
# repeating loop
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            sys.exit()
        elif event.type == MOUSEMOTION:
            mouse_x, mouse_y = event.pos
            move_x, move_y = event.rel
        elif event.type == MOUSEBUTTONUP:
            if game_over:
                game_over = False
                lives = 3
                score = 0
                level = 0

    keys = pygame.key.get_pressed()
    if keys[K_ESCAPE]:
        sys.exit()
    # 清屏
    screen.fill((0, 0, 100))

    if game_over:
        print_text(font1, 220, 250, "<CLICK TO PLAY>")
        pygame.mouse.set_visible(True)
    else:
        pygame.mouse.set_visible(False)
        bomb_y += (vel_y + level*a)
        bomb_x += (vel_x + level*a)
        if bomb_x>500 or bomb_x<0:
            vel_x = -(vel_x + level*a)
        # print(boom_x)
        # 是否没接住炸弹
        if bomb_y > 500:
            bomb_x = random.randint(0,500)
            bomb_y = -50
            lives -= 1

            if lives == 0:
                game_over = True

        # 是否已经接住炸弹
        elif bomb_y > pos_y:
            if bomb_x > pos_x and bomb_x < pos_x + 120:
                # 炸弹是否在挡板的宽度以内,120是挡板的宽
                boom_x = bomb_x
                boom_y = bomb_y

                score += 10
                bomb_x = random.randint(0, 500)
                bomb_y = -50
                if boom_flag:
                    clock_start = time.clock()
        current = time.clock() - clock_start

        # 等级机制
        if score >= 50*k and score <= 50*(k+1):
            level = k
        else:
            k += 1

        # 绘制炸弹
        pygame.draw.circle(screen, black, (int(bomb_x) - 4, int(bomb_y) - 4), 30, 0)
        pygame.draw.circle(screen, yellow, (int(bomb_x), int(bomb_y)), 30, 0)

        # 更新挡板位置
        pos_x = mouse_x
        if pos_x < 0:
            pos_x = 0
        elif pos_x > 500:
            pos_x = 500

        # 绘制挡板
        pygame.draw.rect(screen, black, (pos_x-4,pos_y-4,120,40), 0)
        pygame.draw.rect(screen, red, (pos_x, pos_y, 120, 40), 0)
        # 绘制爆炸字样
        # print(current)
        if current < 0.5:
            print_text(font2, boom_x-2, boom_y-2, "BOOM!",(255,0,0))
            print_text(font2, boom_x, boom_y, "BOOM!", (255,255, 0))
        else:
            boom_flag = True
    # print # of lives
    print_text(font1, 0, 0, "LIVES: " + str(lives))

    # print score
    print_text(font1, 500, 0, "SCORE: " + str(score))

    print_text(font1, 250, 0, "LEVEL: " + str(level))

    pygame.display.update()






效果:
在这里插入图片描述
**后记:**可以通过pyinstaller把游戏打包成exe文件,让大家一起玩吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值