Qt QML实现弹球消砖块小游戏

前言

弹球消砖块游戏想必大家都玩过,很简单的小游戏,通过移动挡板反弹下落的小球,然后撞击砖块将其消除。本文使用QML来简单实现这个小游戏。
效果图:

在这里插入图片描述
在这里插入图片描述

正文

代码目录结构如下:
在这里插入图片描述
首先是小球部分,逻辑比较麻烦一点,需要检查与砖块的碰撞以及与挡板的碰撞,还要更新小球的轨迹位置,代码如下:
Ball.qml

import QtQuick 2.12Rectangle {id: ballwidth: 15height: 15radius: width / 2color: "#FFFFFF"border.color: "#DDDDDD"border.width: 1// 引用游戏区域和挡板property var gameAreaproperty var paddle// 球的速度和方向property real speedX: 0property real speedY: 0property real baseSpeed: 3// 信号:球丢失signal ballLost()// 重置球的位置和状态function reset() {x = gameArea.width / 2 - width / 2;y = gameArea.height / 2;speedX = 0;speedY = 0;}// 开始移动球function start() {if (speedX === 0 && speedY === 0) {// 随机初始方向,但确保向下var angle = (Math.random() * Math.PI / 2) + Math.PI / 4; // 45-135度之间speedX = Math.cos(angle) * baseSpeed;speedY = Math.sin(angle) * baseSpeed;}}// 检查与砖块的碰撞function checkBrickCollision() {for (var i = 0; i < gameArea.bricksRepeater.count; i++) {var brick = gameArea.bricksRepeater.itemAt(i);if (brick && !brick.destroyed) {var brickPos = brick.mapToItem(gameArea, 0, 0);if (x + width > brickPos.x && x < brickPos.x + brick.width &&y + height > brickPos.y && y < brickPos.y + brick.height) {// 确定碰撞方向并反弹var centerX = x + width / 2;var centerY = y + height / 2;var brickCenterX = brickPos.x + brick.width / 2;var brickCenterY = brickPos.y + brick.height / 2;var dx = centerX - brickCenterX;var dy = centerY - brickCenterY;if (Math.abs(dx / brick.width) > Math.abs(dy / brick.height)) {// 水平碰撞speedX = -speedX;} else {// 垂直碰撞speedY = -speedY;}// 击中砖块,立即消除当前碰撞的砖块brick.hit();return true;}}}return false;}// 检查与挡板的碰撞function checkPaddleCollision() {if (y + height >= paddle.y && y <= paddle.y + paddle.height &&x + width >= paddle.x && x <= paddle.x + paddle.width) {// 根据击中挡板的位置调整反弹角度var paddleCenter = paddle.x + paddle.width / 2;var ballCenter = x + width / 2;var relativePosition = (ballCenter - paddleCenter) / (paddle.width / 2);// 计算新的速度向量var angle = relativePosition * (Math.PI / 3); // 最大±60度var speed = Math.sqrt(speedX * speedX + speedY * speedY);speedX = Math.sin(angle) * speed;speedY = -Math.abs(Math.cos(angle) * speed); // 确保向上反弹// 稍微增加速度speedX *= 1.05;speedY *= 1.05;return true;}return false;}// 更新球的位置Timer {interval: 16 // 约60fpsrunning: gameArea.gameRunningrepeat: trueonTriggered: {// 移动球x += speedX;y += speedY;// 检查墙壁碰撞if (x <= 0 || x + width >= gameArea.width) {speedX = -speedX;x = Math.max(0, Math.min(x, gameArea.width - width));}if (y <= 0) {speedY = -speedY;y = 0;}// 检查是否掉落if (y + height >= gameArea.height - 20 && !checkPaddleCollision()) {ballLost();return;}// 检查砖块碰撞checkBrickCollision();// 检查挡板碰撞checkPaddleCollision();}}
}

其次是砖块 Brick.qml

import QtQuick 2.12Rectangle {id: brickradius: 3// 砖块状态property bool destroyed: falseproperty int colorIndex: 0// 砖块颜色数组readonly property var colors: ["#FF5252", // 红色"#FFAB40", // 橙色"#FFEB3B", // 黄色"#66BB6A", // 绿色"#42A5F5"  // 蓝色]// 砖块被销毁的信号signal brickDestroyed()// 设置砖块颜色color: colors[colorIndex % colors.length]border.color: Qt.darker(color, 1.2)border.width: 1visible: !destroyed// 砖块被击中function hit() {if (!destroyed) {destroyed = true;visible = false;brickDestroyed();}}
}

砖块击中后要销毁。

接着是挡板 Paddle.qml, 挡板可以通过键盘左右键进行移动,也可以直接使用鼠标进行左右拖动,代码如下:

import QtQuick 2.12Rectangle {id: paddlewidth: 120height: 20radius: 10color: "#2196F3"border.color: "#1976D2"border.width: 1Component.onCompleted: {// 初始化时设置挡板居中x = (gameArea.width - width) / 2}// 引用游戏区域property var gameArea// 移动速度property int speed: 15property bool movingLeft: falseproperty bool movingRight: false// 处理键盘按下事件function handleKeyPress(key) {if (key === Qt.Key_Left) {movingLeft = true;} else if (key === Qt.Key_Right) {movingRight = true;}}// 处理键盘释放事件function handleKeyRelease(key) {if (key === Qt.Key_Left) {movingLeft = false;} else if (key === Qt.Key_Right) {movingRight = false;}}// 鼠标控制MouseArea {anchors.fill: parentdrag.target: parentdrag.axis: Drag.XAxisdrag.minimumX: 0drag.maximumX: gameArea.width - parent.width}// 定时器更新挡板位置Timer {interval: 16 // 约60fpsrunning: (movingLeft || movingRight) && gameArea.gameRunningrepeat: trueonTriggered: {if (movingLeft) {paddle.x = Math.max(0, paddle.x - speed);}if (movingRight) {paddle.x = Math.min(gameArea.width - paddle.width, paddle.x + speed);}}}
}

以上是核心控件的完整代码。


本文Demo下载

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

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

相关文章

04_Linux驱动_05_pinctrl子系统

以下代码都在pinctrl相关的驱动函数和设备树中 pinctrl-rockchip.c驱动&#xff0c;对应的是那个&#xff08;那些&#xff09;设备树呢&#xff1f; 答案&#xff1a;通过.compatible "rockchip,rk3568-pinctrl"连接到rk3568.dtsi根节点下的pinctrl节点 一&#…

Python的那些事第四十五篇:继承自Nose的测试框架Nose2

Nose2:继承自Nose的测试框架 摘要 本文深入探讨了Nose2这一继承自Nose的测试框架。在软件开发过程中,测试是确保代码质量和稳定性的重要环节,而测试框架为测试工作的开展提供了有力支持。Nose2作为Nose的继承者,在保留Nose优势的基础上进行了诸多改进和扩展,为Python测试…

如何通过 Airbyte 将数据摄取到 Elasticsearch

作者&#xff1a;来自 Elastic Andre Luiz Airbyte 是一个数据集成工具&#xff0c;可自动化并可扩展地将信息从各种来源传输到不同的目的地。它使你能够从 API、数据库和其他系统提取数据&#xff0c;并将其加载到 Elasticsearch 等平台&#xff0c;以实现高级搜索和高效分析。…

RBAC 模型的简单实现

RBAC 模型基本介绍 RBAC&#xff08;Role-Based Access Control&#xff0c;基于角色的访问控制&#xff09;是一种广泛应用的权限管理模型。它的核心思想是通过角色来管理权限&#xff0c;而不是直接分配权限给用户。用户被赋予一个或多个角色&#xff0c;而每个角色拥有不同…

数据结构---堆栈和列

一、堆栈 1.栈堆&#xff1a;具有一定操作约束的线性表&#xff1b;&#xff08;只在一端做插入删除&#xff09; 2.栈的顺序存储结构&#xff1a; 由一个一维数组和一个记录栈顶元素位置的变量组成。定义方式如下&#xff1a; 3.入栈操作&#xff1a; 注意&#xff1a;&…

2023 年全国职业院校技能大赛(中职组)移动应用与开发赛项 赛题第十套

2023 年全国职业院校技能大赛&#xff08;中职组&#xff09;移动应用与开发赛项 赛题第十套&#xff09; 移动应用与开发赛项竞赛模块 A&#xff1a;移动应用界面设计任务 1 环保中心界面设计&#xff08;7.5 分&#xff09;任务 2&#xff1a;首页界面设计&#xff08;7.5 分…

FPGA为何要尽量减少组合逻辑的使用

在FPGA设计中&#xff0c;组合逻辑的使用确实需要谨慎&#xff0c;尤其是要尽量减少它的复杂性。这并不是因为组合逻辑本身不好&#xff0c;而是因为它在实际应用中容易引发一系列问题&#xff0c;而这些问题往往与FPGA的设计哲学和硬件特性相冲突。让我从几个关键点来和你聊聊…

c语言笔记 字符串函数---strcmp,strncmp,strchr,strrchr

目录 函数strcmp与strncmp 以下是错误的示范&#xff1a;两个指针字符型的指针不能直接进行比较 函数strchr与函数strrchr 函数strchr与函数strrchr与strstr函数三者对比 背景&#xff1a;如果说我们要比较两个字符串是否相等&#xff0c;使用strcmp或者strncmp函数。在c语言中…

合React宝宝体质的自定义节流hook

本文为开发开源项目的真实开发经历&#xff0c;感兴趣的可以来给我的项目点个star&#xff0c;谢谢啦~ 具体博文介绍&#xff1a; 开源&#xff5c;Documind协同文档&#xff08;接入deepseek-r1、支持实时聊天&#xff09;Documind &#x1f680; 一个支持实时聊天和接入 - 掘…

【RTSP】客户端(五)H264 265处理逻辑

H264处理逻辑 整体逻辑分析 实现逻辑 解析 RTP 包头&#xff1a;首先检查 RTP 头部的有效负载类型&#xff08;payloadType&#xff09;是否匹配处理扩展头&#xff1a;如果 RTP 包包含扩展头&#xff0c;跳过扩展头部分&#xff0c;获取有效负载处理分片数据&#xff1a;H264…

IDEA集成git,项目的克隆,远程仓库中文件的添加删除

目录 一、克隆项目 二、使用IDEA完成文件的上传和删除 1.配置git 2.上传 3.删除&#xff08;通过git bash&#xff09; 一、克隆项目 点击克隆&#xff0c;复制url &#xff0c;如下 打开你想要克隆到哪里&#xff0c;右击&#xff0c;选择 open Git Bash here 这一步之后…

神经网络:定义与核心原理

神经网络&#xff08;Artificial Neural Network, ANN&#xff09;是一种受生物神经系统启发的计算模型&#xff0c;旨在通过模拟神经元之间的连接与信息传递机制&#xff0c;实现复杂的数据处理和模式识别功能。其本质是由大量简单处理单元&#xff08;神经元&#xff09;构成…

将pdf或者word转换成base64格式

废话不多说直接上代码&#xff1a; function fileToBase64(file) {return new Promise((resolve, reject) > {const reader new FileReader();reader.readAsDataURL(file);reader.onload function (event) {const base64Data event.target.result.split(,)[1];resolve(b…

Spring @Bean注解使用场景二

bean:最近在写一篇让Successfactors顾问都能搞明白的sso的逻辑的文章&#xff0c;所以一致在研究IAS的saml2.0的协议&#xff0c;希望用代码去解释SP、idp的一些概念&#xff0c;让顾问了解SSO与saml的关系&#xff0c;在github找代码的时候发现一些代码的调用关系很难理解&…

ubuntu22.04 关于挂在设备为nfts文件格式无法创建软连接的问题

最近遇到情况&#xff0c;解压工程报错&#xff0c;无法创建软连接 但是盘内还有130G空间&#xff0c;明显不是空间问题&#xff0c;查找之后发现是移动硬盘的文件格式是NTFS&#xff0c;在ubuntu上不好兼容&#xff0c;于是报错。 开贴记录解决方案。 1.确定文件格式 使用命…

docker后台运行,便于后期用命令行进入它的终端

在 docker compose up --build -d 命令中&#xff0c;​**-d​&#xff08;或 --detach&#xff09;参数的作用是让容器以后台模式&#xff08;detached mode&#xff09;​**运行。以下是详细解释&#xff1a; ​**-d 参数的作用** ​后台运行容器&#xff1a; 默认情况下&a…

网页制作14-Javascipt时间特效の显示动态日期

<!doctype html> <html> <head> <meta charset"utf-8"> <title>动态日期</title> </head><script>var today new Date();//获取时间var ytoday.getFullYear();//截取年var mtoday.getMonth();//截取月份,返回0~11v…

【BP神经网络】实战

1.参考Python实战&#xff1a;BP神经网络_bp神经网络实战python-CSDN博客 2.实践 &#xff08;1&#xff09;运行环境 anocanda Powershell Prompt&#xff08;anocanda3&#xff09; &#xff08;2&#xff09;创建虚拟环境&#xff0c;解决安装包的版本问题 *打开终端&a…

深度学习多模态人脸情绪识别:从理论到实践

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。https://www.captainbed.cn/north 文章目录 1. 引言2. 技术框架与流程图3. 核心算法解析3.1 视觉特征提取&#xff08;CNN&#xff09;3.2…