用kotlin来实现一个打方块的小游戏

2024-08-24 07:48

本文主要是介绍用kotlin来实现一个打方块的小游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

今天来做个打方块的小游戏,继续熟悉kotlin的语法,看下要实现的效果图

看着效果图好像挺难的样子,但理清思绪后,你会发现特别的简单,还是那句话,学习方法最重要

思路

  • 构造界面 :

    这个部分比较简单,根据控件的比例来画小球、挡板和击打的方块,所有击打的方块存储在一个集合里面,方块里面存储的信息有left、top、right、bottom位置信息和是否被击打过了的标志

  • 挡板的滑动 :

    下面的挡板需要根据手势的左右移动来反弹小球,所以,我们可以重写onTouch来实现

  • 小球的运动 :

    我们在线程里面开启一个white循环,不停的改变小球的位置,然后重绘界面,小球的运动是有规则的,碰到四周的界面要回弹,碰到击打的方块要回弹,碰到挡板也要回弹,那么,如何回弹呢?我们给小球做一个累加值,让小球不停的去加这个值,碰到碰撞物我们就给这个累加值取反,举个例子,现在offsetX是一个正整数,那么ballX+=offsetX,现在小球是往右移动,当碰撞到最右边的时候,我们给offsetX取反,也就是offsetX=offsetX*-1,这时候offsetX变成了一个负数,那么小球ballX+=offset就会越加越少,也就是往左移动,移动到最左边的时候我们又给offsetX=offsetX*-1,这时候offsetX又变回了正数,这时候,来回的反弹就实现了,ballY的移动也是如此

  • 小球击打方块 :

    小球击打到方块有四个方向:左、上、右、下,我们就说说击打下方的判断吧,小球顶部碰撞到方块的区域为方块的left和right区域,并且当小球的顶部刚好突破方块的bottom位置时,算是一次有效的碰撞,然后我们给这次碰撞做一个标记,然后反弹小球,下次做碰撞的时候我们忽略已经碰撞过的地方,并且不绘制碰撞过的区域

  • 游戏结束 :

    在每次循环结束时都去统计集合里碰撞标志数量是否等于集合的size,是的话就结束循环,游戏结束

思路整理清晰后,我们来一一实现

构造界面

首先来绘制一下小球和挡板

    var width: Float = 0fvar height: Float = 0f/*** 移动滑块的宽度*/var boardWdith: Float = 0f/*** 挡板的高度*/var boardHeight: Float = 0f/*** 挡板距离顶部的距离*/var board2Top: Float = 0f/*** 挡板距离左边的距离*/var board2Left: Float = 0f/*** 小球的半径*/var ballRadius: Float = 0foverride fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)width = w.toFloat()height = h.toFloat()//挡板的宽度boardWdith = width / 8//挡板距离顶部的距离board2Top = height / 8 * 7//挡板的left距离左边的距离,目的使挡板居中board2Left = width / 2 - boardWdith / 2//设置小球的半径为挡板的1/4ballRadius = boardWdith / 4//设置小球的x和y坐标ballX = width / 2ballY = board2Top - ballRadius - dip(10).toFloat() / 2ballPaint.style = Paint.Style.FILLballPaint.isAntiAlias = trueballPaint.color = resources.getColor(R.color.colorAccent)boardPaint.style = Paint.Style.STROKEboardPaint.isAntiAlias = trueboardPaint.strokeWidth = dip(10).toFloat()boardPaint.color = resources.getColor(R.color.colorPrimary)}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)setBackgroundColor(resources.getColor(R.color.black))canvas.drawLine(board2Left, board2Top, board2Left + boardWdith, board2Top, boardPaint)canvas.drawCircle(ballX, ballY, ballRadius, ballPaint)}   

ok,挡板和小球已经画好了

然后,我们来画一下被击打的方块,首先定义一个存储方块信息的Bean类

/*** @author wangqi* @since 2017/12/10 17:26*/public class Brick {/*** 存储方块的颜色*/private String color;/*** 存储方块的坐标*/private RectF rectF;/*** 判断是否碰撞到了,默认为false未碰撞*/private boolean isImpact;public String getColor() {return color;}public void setColor(String color) {this.color = color;}public RectF getRectF() {return rectF;}public void setRectF(RectF rectF) {this.rectF = rectF;}public boolean isImpact() {return isImpact;}public void setImpact(boolean impact) {isImpact = impact;}}

然后我们来看看怎么绘制

    /*** 定义一个存储方块的集合*/var brickList: MutableList<Brick> = mutableListOf()/*** 方块的宽度*/var brickWidth = 0f/*** 方块的高度*/var brickHeight = 0f   override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)...//方块的宽度是view的1/5brickWidth = width / 5//方块的高度是宽度的一半brickHeight = brickWidth / 2       /*初始化方块  设置一个三行四列的方块*/for (row in 0..3) {for (col in 0..4) {createBricks(row, col)}}paintLine.strokeWidth = dip(1.0f).toFloat()paintLine.isAntiAlias = truepaintLine.textSize = dip(width / 50).toFloat()paintLine.style = Paint.Style.FILL}   /*** 创建方块*/fun createBricks(row: Int, col: Int) {var brick = Brick()var rectF = RectF()rectF.left = brickWidth * colrectF.top = brickHeight * rowrectF.right = brickWidth * (col + 1)rectF.bottom = brickHeight * (row + 1)brick.rectF = rectFval hex = "#" + Integer.toHexString((-16777216 * Math.random()).toInt())brick.color = hexbrickList.add(brick)}

ok,方块完美的绘制

挡板的滑动

挡板的滑动部分,我们只需要重写onTouch方法,然后再每次move的过程中去改变挡板距离View左边界的距离

override fun onTouchEvent(event: MotionEvent): Boolean {when (event.action) {MotionEvent.ACTION_DOWN -> {}MotionEvent.ACTION_MOVE -> {board2Left = event.x - boardWdith / 2invalidate()}MotionEvent.ACTION_UP -> {}}return true}

小球的运动

小球的运动是这里面最核心的部分了,我们得细细的讲讲

首先,我们需要定义一个线程,在线程里面定义一个while循环,sleep50毫秒去重回界面,所以,我们要在这50毫秒的时间里,去改变小球的运动轨迹、边界值情况、是否碰撞到方块、是否碰撞到挡板和游戏是否结束,我们先把小球给运动起来再说

    /*** 结束循环的标志位*/var isOver: Boolean = false/*** 小球x方向每次移动的偏移量*/var vx: Float = 8f/*** 小球y方向每次移动的偏移量* 默认为负数,因为小球是向上运动   */var vy: Float = -8foverride fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)...//开启线程thread {while (!isOver) {ballX += vxballY += vy/*边界值判定如果小球小于左边界或大于右边界则x方向取反*/if (ballX + ballRadius > width || ballX - ballRadius < 0) {vx *= -1}/*边界值判定如果小球大于底部边界或小于顶部边界则Y方向取反*/if (ballY - ballRadius < 0 || ballY + ballRadius > height) {vy *= -1}Thread.sleep(50)postInvalidate()}}.start()}

小球开始运动了,咦,小球怎么突然不见了,哈哈,因为被方块遮挡住了

小球移动解决了,接下来我们来处理下小球弹到挡板反弹

        //开启线程thread {while (!isOver) {//边界值判断.../*判断小球是否落在滑块上小球x轴的中心大于挡板的left并且小球x轴中心小于挡板的右边并且小球的y轴中心加上半径加上挡板高度的一半*/if (ballX >= board2Left && ballX <= board2Left + boardWdith&& ballY >= board2Top - ballRadius - dip(10).toFloat() / 2) {//改变Y轴的运动方向    vy *= -1}...}        }

挡板的判断知道了,那么小球和方块的碰撞也就自然清晰了

        //开启线程thread {while (!isOver) {//判断小球是否落在滑块上.../** 循环集合的每一个方块,判断小球当前的位置是否碰撞到方块*/for (i in brickList.indices) {//拿到方块val brick = brickList[i]//忽略撞击过的方块if (brick.isImpact) {continue}//获取方块的坐标val rectF = brick.rectF/*判断小球是否撞击到方块的底部小球x轴的中心大于方块的left小球x轴的中心小于方块的right小球y轴中心减去半径,也就是小球的顶部,是否小于等于方块的底部,也就是穿过方块底部的一瞬间*/if (ballX >= rectF.left && ballX <= rectF.right && ballY - ballRadius <= rectF.bottom) {//设置该方块已被撞击brick.isImpact = true//方向取反vy *= -1}}/** 统计被撞击方块的数量是否等于集合,是的话表明游戏结束,设置结束标志位,停止while循环*/if (brickList.count { it.isImpact } == brickList.size) {isOver = true}...}        }override fun onDraw(canvas: Canvas) {super.onDraw(canvas)...if (isOver) {val text = "通关成功"//获取文字的宽度,目的是为了文字居中val textWidth = paintLine.measureText(text)canvas.drawText(text, width / 2 - textWidth / 2, 100, paintLine)}}

最终效果图

通关成功

总结

小球碰撞到底部边界的判断我没有去做,原因是为了能击打到方块,增加趣味性,还有碰撞方块的四个方向,我只做了碰撞到底部的方向,有兴趣的同学可以自己试着补上,查看完整源码

理论和实践相辅相成,理论是规划实践的实施性,实践是为了证明理论

qq群号492386431

关注公众号codelang

这篇关于用kotlin来实现一个打方块的小游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101874

相关文章

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机