利用kotlin实现一个打方块的小游戏实例教程

前言

今天来做个打方块的小游戏,继续熟悉kotlin的语法,更多关于kotlin的语法大家可以参考这篇文章://www.jb51.net/article/114069.htm

看下要实现的效果图:

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

思路

1、构造界面 :

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

2、挡板的滑动 :

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

3、小球的运动 :

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

4、小球击打方块 :

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

5、游戏结束 :

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

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

构造界面

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

 var width: Float = 0f
 var height: Float = 0f
 /**
 * 移动滑块的宽度
 */
 var boardWdith: Float = 0f
 /**
 * 挡板的高度
 */
 var boardHeight: Float = 0f
 /**
 * 挡板距离顶部的距离
 */
 var board2Top: Float = 0f
 /**
 * 挡板距离左边的距离
 */
 var board2Left: Float = 0f
 /**
 * 小球的半径
 */
 var ballRadius: Float = 0f
 override 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/4
 ballRadius = boardWdith / 4
 //设置小球的x和y坐标
 ballX = width / 2
 ballY = board2Top - ballRadius - dip(10).toFloat() / 2
 ballPaint.style = Paint.Style.FILL
 ballPaint.isAntiAlias = true
 ballPaint.color = resources.getColor(R.color.colorAccent)
 boardPaint.style = Paint.Style.STROKE
 boardPaint.isAntiAlias = true
 boardPaint.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/5
  brickWidth = 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 = true
 paintLine.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 * col
 rectF.top = brickHeight * row
 rectF.right = brickWidth * (col + 1)
 rectF.bottom = brickHeight * (row + 1)

 brick.rectF = rectF
 val hex = "#" + Integer.toHexString((-16777216 * Math.random()).toInt())
 brick.color = hex
 brickList.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 / 2
  invalidate()
  }
  MotionEvent.ACTION_UP -> {
  }
 }
 return true
 }

小球的运动

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

 /**
 * 结束循环的标志位
 */
 var isOver: Boolean = false
 /**
 * 小球x方向每次移动的偏移量
 */
 var vx: Float = 8f
 /**
 * 小球y方向每次移动的偏移量
 * 默认为负数,因为小球是向上运动
 */
 var vy: Float = -8f
 override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
 super.onSizeChanged(w, h, oldw, oldh)
 ...
 //开启线程
 thread {
  while (!isOver) {
  ballX += vx
  ballY += 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)
  }
 }

最终效果图

通关成功

总结

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

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

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Kotlin 基础教程之数组容器

    Kotlin 基础教程之数组容器 Arrays Kotlin 标准库提供了arrayOf()创建数组, **ArrayOf创建特定类型数组 val array = arrayOf(1, 2, 3) val countries = arrayOf("UK", "Germany", "Italy") val numbers = intArrayOf(10, 20, 30) val array1 = Array(10, { k -> k * k

  • 使用Kotlin开发Android应用的初体验

    昨晚,最近一届的谷歌IO大会正式将Kotlin确定为了官方开发语言,作为一名Android开发鸟,怎么能不及时尝尝鲜呢? Kotlin的简要介绍 在开发之前,很多同学一定有很多疑问,Kotlin到底有啥好处,怎么和现有的项目共存呢?Java那么些特性Kotlin都有吗?嗯,让我们一一来看. Kotlin 非常适合开发 Android 应用程序,将现代语言的所有优势带入 Android 平台而不会引入任何新的限制: 兼容性:Kotlin 与 JDK 6 完全兼容,保障了 Kotlin 应用程序可以

  • Android Kotlin的使用及简单实例

    Android Kotlin的使用及简单实例 写在前面的话,作为一个不熬夜的人,一觉醒来发现Kotlin成为了Android的官方语言,可谓是大喜过望.为了趁热打铁,我决定提前三天放出原定本周日Release的文章.希望能及时让大家了解一下Kotlin. 相信很多开发人员,尤其是Android开发者都会或多或少听说过Kotlin,当然如果没有听过或者不熟悉也没有关系.因为本篇文章以及博客后期的内容会涉及到很多关于Kotlin的知识分享. 在写这篇文章前的一个多月,Flipboard中国的Andr

  • Kotlin 开发环境详解及简单实例

    Hello Kotlin 在前段时间举办的Google I/O 2017上,Google宣布Kotlin成为Android官方的开发语言,这个最初发布于2011年的语言在短短的时间内就吸引了大量的开发者,而Google使得它进入了更多人的视线. Kotlin是一种开源的基于JVM的变成语言,由JetBeans公司开发(大概除了使用VS的.net开发者意外,都会或多或少听说或使用过IDEA吧),名字取自圣彼得堡附近的一个小岛(Koltin island). Kotlin是一种简单的语言,其主要目标

  • Kotlin 的注解类详解及实例

    Kotlin 的注解类详解及实例 注解声明 注解是将元数据附加到代码的方法.要声明注解,请将 annotation 修饰符放在类的前面: annotation class Fancy 注解的附加属性可以通过用元注解标注注解类来指定: @Target 指定可以用 该注解标注的元素的可能的类型(类.函数.属性.表达式等): @Retention 指定该注解是否 存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true): @Repeatable 允许 在单个元素上多次

  • 利用kotlin实现一个打方块的小游戏实例教程

    前言 今天来做个打方块的小游戏,继续熟悉kotlin的语法,更多关于kotlin的语法大家可以参考这篇文章://www.jb51.net/article/114069.htm 看下要实现的效果图: 看着效果图好像挺难的样子,但理清思绪后,你会发现特别的简单,还是那句话,学习方法最重要 思路 1.构造界面 : 这个部分比较简单,根据控件的比例来画小球.挡板和击打的方块,所有击打的方块存储在一个集合里面,方块里面存储的信息有left.top.right.bottom位置信息和是否被击打过了的标志 2

  • 利用Python写了一个水果忍者小游戏

    目录 前言: 一.需要导入的包 二.窗口界面设置 三.随机生成水果位置 四.绘制字体 五.玩家生命的提示 六.游戏开始与结束的画面 七.游戏主循环 最后 前言: 水果忍者到家都玩过吧,但是Python写的水果忍者你肯定没有玩过.今天就给你表演一个新的,用Python写一个水果忍者.水果忍者的玩法很简单,尽可能的切开抛出的水果就行. 今天就用python简单的模拟一下这个游戏.在这个简单的项目中,我们用鼠标选择水果来切割,同时炸弹也会隐藏在水果中,如果切开了三次炸弹,玩家就会失败. 一.需要导入的

  • 利用Python编写简易版德州扑克小游戏

    目录 德州扑克简要介绍 什么是德州扑克 游戏规则简要介绍 德州扑克游戏的python实现过程 游戏初始化 评选赢家 游戏主题函数 游戏体验与展示 模块不足与后续改进 德州扑克简要介绍 什么是德州扑克 德州扑克不知道大家是否玩过,它是起源于美国的得克萨斯州的一种博弈类卡牌游戏,英文名叫做Texas Hold’em Poker.玩法上又分为常规桌(Cash, 现金局),单桌赛(SNG)和多桌锦标赛(MTT).虽然扑克种类繁多,但基本的扑克规则通常保持一致.它是一种考验心态与谋略的游戏. 游戏规则简要

  • 利用原生JS实现欢乐水果机小游戏

    简介: 玩家点击某个押注物品则在该物品上下注.点击开始则游戏开始,如果没有下注则不能开始游戏. 游戏中的物品有八中,分别为:苹果.西瓜.柠檬.橙子.铃铛.77.双星.BAR. 在放行游戏区左右方为押注区,每种物品下方有加减号按钮,每次点 击加号增加一个筹码注金,反之减号就减少一个筹码注金 开始: 开始键 奖励:GOOD LUCK 由于这个时低配版的,我就没有按照原版的写进去,就是中了GOOD LUCK直接获得15分. 出于好耍,本人想起了小时候玩过的水果机,js也学了一会儿了,就想用它写一个简单

  • Java多线程实现方块赛跑小游戏

    本文实例为大家分享了Java实现方块赛跑小游戏的具体代码,供大家参考,具体内容如下 在一个图形界面上构造两个位于同一起跑线方块,起跑线位于界面靠左位置, A 方块先开始运动,向右移动 50 像素后停止,B 方块开始运动,向右移动 100 像素后停 止,A 方块继续向右运动 100 像素后停止,B 方块开始运动,如此循环接替执行,直至 某一个方块到达终点,界面显示该方块胜利信息. 1)  自定义一个threadA,ThreadB, ThreadFrame类(均继承自Thread). 2)  定义全

  • C++ 实战开发一个猜单词的小游戏

    目录 前言 效果展示 一.函数接口 二.重要函数接口详解 1.菜单内容 2.退出程序 3.打开单词文件 4.开始游戏 5.查看玩家排名 6.清空玩家排名 7.玩家排名 全部代码展示 前言 程序内的单词全部保存于word.txt的文本文档中,玩家排名保存在rand.txt文本文档中.运行程序时,会自动读取文本中的内容. 游戏规则:①先请用户输入猜的单词数量,可以有一个默认值.②随机抽取单词,对每个单词,系统根据谜底单词长度在屏幕上显示相应个数'#',假设谜底单词为"hello",则在屏幕

  • 利用Java实现简单的猜数字小游戏

    目录 实现思路 代码实现 实现思路 由计算机随机产生1~100的整数.用户猜测计算机产生的数字,并输入数字,当输入的数字与计算机产生的数字相同时输出恭喜你,猜对了.当输入的数字小于计算机产生的数字输出太小了,当输入的数字大于计算机产生的数字输出太大了 可以用for循环设定游戏猜的次数,增加代码的可玩性 代码实现 import java.util.Random; import java.util.Scanner; public class User { public static void mai

  • 利用pixi.js制作简单的跑酷小游戏

    目录 前言 项目地址 demo地址 初始化项目 主要逻辑 useParkour useScene useHurdle Player 前言 此项目使用pixi.js和vue实现,部分素材来自爱给网,本项目仅作用于 pixi.js 学习用途,侵权立删. 项目地址 shellingfordly/pixi-games demo地址 pixi-games 初始化项目 使用vite初始化项目 pnpm create vite my-vue-app 安装pixi.js和pixi-tweener pixi-tw

  • 利用Java编写个"不贪吃蛇"小游戏

    目录 前言 代码 蛇.药丸的抽象 游戏界面 启动类 游戏演示 最后 前言 我写的这个”贪吃蛇“和小时候玩的”贪吃蛇“有点不一样,以往的”贪吃蛇“吃了食物蛇身就会变长,而我写的这个吃了“食物”蛇身会变短,并且胜利条件就是“把蛇变没”,嘻嘻~ 这里的“食物”其实是“药丸”,初始时,蛇身很长,你要通过食用“药丸”,来让自己的身体变短,直到自己消失不见,你就获胜了. “药丸”共有三种,分别为“红色药丸.蓝色药丸.绿色药丸”,对应分值“5分.2分.1分”,蛇吃了“药丸”会减掉对应分值数量的身体,并累计分值

  • 使用vue编写一个点击数字计时小游戏

    使用vue编写一个点击数字计时小游戏,列入你在文本框中输入3,点击开始会生成一个3行3列的表格,表格数据为1-9随机排列,这时候从1开始点击,按顺序点到9,当按正确顺序点击完毕,会提示所用的时间,如果顺序没有按对,会提示游戏结束. 1.首先下载vue源码,下载地址http://cn.vuejs.org 2.jquery是在面向dom操作,而vue是面向数据操作的,所以使用vue最好不要去操作dom,尽量发挥出vue的独到之处,(如果使用过angularjs可能更容易理解) 3.建立一个普通的ht

随机推荐