PyGame实现打砖块游戏

文章目录

    • 砖块实现
    • 小车
    • 小球
    • 初始化和主循环

打砖块也是一个非常经典的小游戏,玩法大致如下,用一个小车接一个小球,然后反射小球,使之打在砖块上,当小球碰到砖块之后,则砖块被消掉,逻辑十分清晰。

在这里插入图片描述

在设计游戏之前,先设置一些常量,供后续选用。

import pygame
import randomWIDTH, HEIGHT = 640, 400 # 游戏窗口尺寸SIZE = 20   # 砖块尺寸# 颜色定义
C_PADDLE = (120, 120, 120)
C_BRICK = (0, 128, 55)
C_BALL = (233,233,233)
BLACK = (25, 25, 25)
RED = (255, 0, 0)

砖块实现

可玩性比较高的打砖块游戏,其砖块有着不同的属性,有一些砖块打不掉,有些在打碎之后会掉落一些东西,接住之后可以发生裂变反应。考虑到作为一个初学者小游戏,我们先让所有砖块有着相同的特质,但为了日后的扩展,所以用类来实现砖块。

作为一个砖块来说,只有三个属性,坐标 ( x , y ) (x,y) (x,y)以及边长size,又因为砖块不会动,所以这些参数仅作为传入的参数,而无需调用。而砖块唯一的行为,就是与小球发生碰撞,所以需要有一个判定方法。最终,砖块类实现如下

class Brick:def __init__(self, col, row, dy=50, size=SIZE, color=C_BRICK):x = col*sizey = row*size + dyself.color = colorself.rect = pygame.Rect(x, y, size, size)def hitRect(self, rect):return self.rect.colliderect(rect)def draw(self, screen):pygame.draw.rect(screen, self.color, self.rect)

在实际应用中,显然不可能只有一个砖块,所以在Brick中设置一个静态方法,用以生成随机的砖块,其生成逻辑是,随机生成一个数,如果这个数大于0.3,那么就在当前位置生成一个砖块,否则跳过。

@staticmethod
def randBricks(dense=0.3, size=SIZE, xEdge=WIDTH):bricks = []for row in range(5):col = 0while (col+1)* size < xEdge:bricks.append(Brick(col, row))col += 1 if random.random()>dense else 2return bricks

小车

和砖块相比,小车只多了一个左右移动的功能,即点击左箭头,相左移动,点击右箭头,向右移动。而且其移动的范围不能超出x轴的边界,其小车类实现如下。

class Car:def __init__(self, width, height=10, speed = 10, color=C_PADDLE,xEdge=WIDTH, yEdge=HEIGHT):self.width, self.height = width, heightself.xEdge = xEdgeself.color = colorself.x = (xEdge - width) // 2self.y = yEdge - 30self.vx = speed     # 只有x方向的速度def move(self, keys):if keys[pygame.K_LEFT] and self.x > 0:self.x -= self.vxif keys[pygame.K_RIGHT] and self.x < self.xEdge - self.width:self.x += self.vxdef draw(self, screen):pygame.draw.rect(screen, self.color, (self.x, self.y, self.width, self.height))

小球

相比于不动的砖块,只需要左右移动的小车,小球的行为会稍微复杂一点,不仅需要考虑和墙壁以及小车的碰撞,也要考虑和砖块的碰撞。在这个过程中,需要进行诸多边界的判断,所以除了小球的半径和位置之外,设置L,R,U,D四个函数,用于计算其左右上下的边界位置。小球类实现如下。

class Ball:# xEdge, yEdge分别是水平核垂直方向的边缘def __init__(self, radius, speed=5,xEdge=WIDTH, yEdge=HEIGHT, color=C_BALL):self.r = radiusself.xEdge, self.yEdge = xEdge, yEdgeself.color = colorself.x = random.randint(radius, xEdge - radius)self.y = random.randint(yEdge//3, yEdge // 2)self.vx = self.vy = speedL = lambda self : self.x - self.rR = lambda self : self.x + self.rU = lambda self : self.y + self.rD = lambda self : self.y - self.rxy = lambda self : (self.x, self.y)def move(self):self.x += self.vxself.y += self.vydef rect(self):d = self.r * 2return pygame.Rect(self.L(), self.D(), d, d)# 撞击边缘def hitEdge(self):if self.L() < 0 or self.R() > self.xEdge:self.vx *= -1if self.U() < 0:self.vy *= -1elif self.U() > self.yEdge:return Truereturn False# 撞击cardef hitCar(self, car):if self.y + self.r >= car.y and car.x <= self.x <= car.x + car.width:self.vy *= -1def hitBricks(self, bricks):for brick in bricks[:]:if brick.hitRect(self.rect()):self.vy *= -1bricks.remove(brick)return 1return 0def draw(self, screen):pygame.draw.circle(screen, self.color, (self.x, self.y), self.r)

其中,hitBricks的返回值为1时,表示击中了砖块,否则表示未击中。

初始化和主循环

在具体写主循环之前,先设置一个GameOver的显示函数,这个函数的出镜率很高,在之前的实战中也用到过。

def drawGamerOver(screen, font, width=WIDTH, height=HEIGHT):w, h = font.size('GAME OVER')msg = font.render('GAME OVER', True, RED)screen.blit(msg, ((width - w) // 2, (height - h) // 2 - 40))w, h = font.size('点击任意位置,再来一局')msg = font.render('点击任意位置,再来一局', True, RED)screen.blit(msg, ((width - w) // 2, (height - h) // 2 + 40))

然后是初始化,主要包括小球、小车、砖块的初始化,以及PyGame的初始化。

def init():ball = Ball(10)car = Car(100)bricks = Brick.randBricks()return ball, car, bricks# 初始化 Pygame
pygame.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
font = pygame.font.Font(r"SimHei.ttf", 30)
pygame.display.set_caption("打砖块")# 初始化弹球、板、砖块的位置
ball, car, bricks = init()
score, running, gameOver = 0, True, False

其running用于调控主循环,gameOver则表示当前游戏失败,若失败,则跳入游戏失败的窗口。最后,主循环如下

while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()running = Falsebreakif gameOver:ball, car, bricks = init()gameOver, score = False, 0if not running:breakif not gameOver:keys = pygame.key.get_pressed()car.move(keys)      # 移动小车ball.move()         # 移动弹球ball.hitCar(car)if ball.hitEdge():bricks = Brick.randBricks()  # 重新初始化游戏gameOver = True  # 游戏结束score += ball.hitBricks(bricks)# 清空窗口window.fill(BLACK)if not gameOver:car.draw(window)ball.draw(window)for brick in bricks:brick.draw(window)# 显示分数score_text = font.render(f"Score: {score}", True, C_BRICK)window.blit(score_text, (20, 20))else:drawGamerOver(window, font)pygame.display.flip()   # 更新屏幕显示pygame.time.delay(30)   # 控制帧率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/292028.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EDA实验-----直流电机驱动设计(Quartus II )

目录 一、实验目的 二、实验仪器设备 三、实验的重点和难点 四、实验原理 五、实验步骤 六、实验报告 七、实验过程 1.分频器代码 2.方向选择器 3.直流电动机工作原理 4.电路连接图 5.文件烧录 一、实验目的 了解直流电机控制的工作原理和实现的方法。掌握PWM波控…

linux下的进程组与会话的区别

进程组&#xff08;Process Group&#xff09;和会话&#xff08;Session&#xff09;是Unix/Linux操作系统中的两个概念&#xff0c;它们之间有一些关键区别&#xff1a; 定义和范围&#xff1a;一个进程组是一组相关进程的集合&#xff0c;它们具有相同的进程组ID&#xff08…

使用【OpenI启智平台】进行模型训练

前言 启智平台OpenI是一个人工智能开源开放平台&#xff0c;提供免费GPU算力可以进行模型训练。模式是git进行项目管理&#xff0c;可以创建调试任务调试代码以及保存镜像&#xff0c;创建训练任务训练模型&#xff0c;也提供推理和评测&#xff0c;我没用过就不讲述了。后来我…

Day67力扣打卡

打卡记录 美丽塔 II&#xff08;前缀和 单调栈&#xff09; 链接 class Solution:def maximumSumOfHeights(self, maxHeights: List[int]) -> int:n len(maxHeights)stack collections.deque()pre, suf [0] * n, [0] * nfor i in range(n):while stack and maxHeights…

嵌入式中断理解

一、概念 中断&#xff1a; 在主程序运行过程中&#xff0c;出现了特定的中断触发条件&#xff08;中断源&#xff09;&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继续运行。 中断优先级&#x…

微信小程序-textarea组件字数实时更新

一、前言 本文实现的是在小程序中&#xff0c;textarea文本框输入文字后&#xff0c;实时显示文字的字数&#xff0c;获取更好的用户输入体验以及提示。 下图是实现的效果 二、代码实现 2-1、wxml代码 <view style"padding: 30rpx;"><view style"…

vue中监听Form表单值的变化

想要监听From表单中某个值的变化需要用到vue中的 watch watch: {inputForm.isHeating() {this.inputForm.otherHeating}}, isHeating是表单中的某个值&#xff0c;如果他变化就会清空另一个值

Python:正则表达式---贪婪匹配

在正则表达式中&#xff0c;贪婪匹配是指匹配尽可能多的字符&#xff0c;而非贪婪匹配&#xff08;也称为懒惰匹配或最小匹配&#xff09;则是匹配尽可能少的字符。 .* 表示匹配任意数量的任意字符&#xff08;除换行符外&#xff09;。贪婪匹配会将尽可能多的字符都作为匹配结…

以存算一体芯片加速汽车智能化进程,后摩智能带来更优解?

汽车产业的长期价值锚点已悄然变化&#xff0c;催生出新的商业机遇。 过去&#xff0c;在燃油车市场&#xff0c;燃油经济性和品牌认知度等是重要的消费决策因素和资本价值衡量标准&#xff0c;但在新能源时代&#xff0c;产业价值聚焦在两方面&#xff0c;一是电动化&#xf…

使用 Docker 部署企业培训系统 PlayEdu

1&#xff09;PlayEdu 介绍 官网&#xff1a;https://www.playedu.xyz/ GitHub&#xff1a;https://github.com/PlayEdu/PlayEdu PlayEdu 是一款适用于搭建内部培训平台的开源系统&#xff0c;旨在为企业/机构打造自己品牌的内部培训平台。PlayEdu 基于 Java MySQL 开发&…

Java 并发编程 —— 透过源码剖析 ForkJoinPool

目录 一. 前言 二. 工作窃取的实现原理 2.1. WorkQueue&#xff08;工作队列&#xff09; 2.2. 工作窃取流程 三. ForkJoinPool 源码解析 3.1. ForkJoinPool 的字段 3.1.1. 常量 3.1.2. 成员变量 3.1.3. ctl&#xff08;5个部分组成&#xff09; 3.2. 构造函数 3.3.…

百模大战中的AI行业:新趋势与未来发展

文章目录 每日一句正能量前言技术进步应用拓展行业变革人才竞争后记 每日一句正能量 人生最重要的价值是心灵的幸福&#xff0c;而不是任何身外之物。 前言 随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;已经成为引领技术革命的重要驱动力之一。在当前的…