当前位置: 首页 > news >正文

昌平网站建设河北邯郸区号

昌平网站建设,河北邯郸区号,网站建设误区图,有哪些做兼职的设计网站安卓小游戏#xff1a;贪吃蛇 前言 这个是通过自定义View实现小游戏的第二篇#xff0c;实际上第一篇做起来麻烦点#xff0c;后面的基本就是照葫芦画瓢了#xff0c;只要设计下游戏逻辑就行了#xff0c;技术上不难#xff0c;想法比较重要。 需求 贪吃蛇#xff0…安卓小游戏贪吃蛇 前言 这个是通过自定义View实现小游戏的第二篇实际上第一篇做起来麻烦点后面的基本就是照葫芦画瓢了只要设计下游戏逻辑就行了技术上不难想法比较重要。 需求 贪吃蛇太经典了小时候在诺基亚上玩了不知道多少回游戏也很简单就两个逻辑一个是吃东西变长一个是吃到自己死亡。核心思想如下 1载入配置读取游戏信息及掩图2启动游戏控制逻辑3手势控制切换方向 效果图 这里就稍微演示了一下就这速度要演示到死亡估计得一分钟以上了掩图用的比较low勉强凑合。 代码 import android.annotation.SuppressLint import android.app.AlertDialog import android.content.Context import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.drawable.Drawable import android.os.Handler import android.os.Looper import android.os.Message import android.util.AttributeSet import android.view.MotionEvent import android.view.View import com.silencefly96.module_views.R import java.lang.ref.WeakReference import kotlin.math.abs/*** 贪吃蛇游戏view** author silence* date 2023-02-07*/ class SnarkGameView JvmOverloads constructor(context: Context,attributeSet: AttributeSet? null,defStyleAttr: Int 0 ) : View(context, attributeSet, defStyleAttr) {companion object{// 四个方向const val DIR_UP 0const val DIR_RIGHT 1const val DIR_DOWN 2const val DIR_LEFT 3// 游戏更新间隔一秒5次const val GAME_FLUSH_TIME 200L// 蛇体移动频率const val SNARK_MOVE_TIME 600L// 食物添加间隔时间const val FOOD_ADD_TIME 5000L// 食物存活时间const val FOOD_ALIVE_TIME 10000L// 食物闪烁时间要比存货时间长const val FOOD_BLING_TIME 3000L// 食物闪烁间隔const val FOOD_BLING_FREQ 300L}// 屏幕划分数量及等分长度private val rowNumb: Intprivate var rowDelta: Int 0private val colNumb: Intprivate var colDelta: Int 0// 节点掩图private val mNodeMask: Bitmap?// 头节点private val mHead Snark(0, 0, DIR_DOWN, null)// 尾节点private var mTail mHead// 食物数组private val mFoodList ArrayListFood()// 游戏控制器private val mGameController GameController(this)// 画笔private val mPaint Paint().apply {color Color.LTGRAYstrokeWidth 1fstyle Paint.Style.STROKEflags Paint.ANTI_ALIAS_FLAGtextAlign Paint.Align.CENTERtextSize 30f}// 上一个触摸点X、Y的坐标private var mLastX 0fprivate var mLastY 0finit {// 读取配置val typedArray context.obtainStyledAttributes(attributeSet, R.styleable.SnarkGameView)// 横竖划分rowNumb typedArray.getInteger(R.styleable.SnarkGameView_rowNumb, 30)colNumb typedArray.getInteger(R.styleable.SnarkGameView_colNumb, 20)// 节点掩图val drawable typedArray.getDrawable(R.styleable.SnarkGameView_node)mNodeMask if (drawable ! null) drawableToBitmap(drawable) else nulltypedArray.recycle()}private fun drawableToBitmap(drawable: Drawable): Bitmap? {val w drawable.intrinsicWidthval h drawable.intrinsicHeightval config Bitmap.Config.ARGB_8888val bitmap Bitmap.createBitmap(w, h, config)//注意下面三行代码要用到否则在View或者SurfaceView里的canvas.drawBitmap会看不到图val canvas Canvas(bitmap)drawable.setBounds(0, 0, w, h)drawable.draw(canvas)return bitmap}// 完成测量开始游戏override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {super.onSizeChanged(w, h, oldw, oldh)rowDelta h / rowNumbcolDelta w / colNumb// 开始游戏load()}// 加载private fun load() {mGameController.removeMessages(0)// 设置贪吃蛇的位置mHead.posX colNumb / 2mHead.posY rowNumb / 2mGameController.sendEmptyMessageDelayed(0, GAME_FLUSH_TIME)}// 重新加载private fun reload() {mGameController.removeMessages(0)// 清空界面mFoodList.clear()mHead.posX colNumb / 2mHead.posY rowNumb / 2// 蛇体链表回收让GC通过可达性分析去回收mHead.next nullmGameController.isGameOver falsemGameController.sendEmptyMessageDelayed(0, GAME_FLUSH_TIME)}override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {super.onMeasure(widthMeasureSpec, heightMeasureSpec)setMeasuredDimension(getDefaultSize(0, widthMeasureSpec),getDefaultSize(0, heightMeasureSpec))}override fun onDraw(canvas: Canvas) {super.onDraw(canvas)// 绘制网格for (i in 0..rowNumb) {canvas.drawLine(0f, rowDelta * i.toFloat(),width.toFloat(), rowDelta * i.toFloat(), mPaint)}for (i in 0..colNumb) {canvas.drawLine(colDelta * i.toFloat(), 0f,colDelta * i.toFloat(), height.toFloat(), mPaint)}// 绘制食物for (food in mFoodList) {if (food.show) canvas.drawBitmap(mNodeMask!!,(food.posX 0.5f) * colDelta - mNodeMask.width / 2,(food.posY 0.5f) * rowDelta - mNodeMask.height / 2, mPaint)}// 绘制蛇体var p: Snark? mHeadwhile (p ! null) {canvas.drawBitmap(mNodeMask!!,(p.posX 0.5f) * colDelta - mNodeMask.width / 2,(p.posY 0.5f) * rowDelta - mNodeMask.height / 2, mPaint)p p.next}}SuppressLint(ClickableViewAccessibility)override fun onTouchEvent(event: MotionEvent): Boolean {when(event.action) {MotionEvent.ACTION_DOWN - {mLastX event.xmLastY event.y}MotionEvent.ACTION_MOVE - {}MotionEvent.ACTION_UP - {val lenX event.x - mLastXval lenY event.y - mLastYmHead.dir if (abs(lenX) abs(lenY)) {if (lenX 0) DIR_RIGHT else DIR_LEFT}else {if (lenY 0) DIR_DOWN else DIR_UP}invalidate()}}return true}private fun gameOver() {AlertDialog.Builder(context).setTitle(继续游戏).setMessage(请点击确认继续游戏).setPositiveButton(确认) { _, _ - reload() }.setNegativeButton(取消, null).create().show()}// kotlin自动编译为Java静态类控件引用使用弱引用class GameController(view: SnarkGameView): Handler(Looper.getMainLooper()){// 控件引用private val mRef: WeakReferenceSnarkGameView WeakReference(view)// 蛇体移动控制private var mSnarkCounter 0// 食物闪烁控制private var mFoodCounter 0// 游戏结束标志internal var isGameOver falseoverride fun handleMessage(msg: Message) {mRef.get()?.let { gameView -mSnarkCounterif (mSnarkCounter (SNARK_MOVE_TIME / GAME_FLUSH_TIME).toInt()) {// 移动蛇体var p: Snark? gameView.mHeadvar dir gameView.mHead.dirwhile (p ! null) {// 移动逻辑会穿过屏幕边界when(p.dir) {DIR_UP - {p.posY--if (p.posY 0) {p.posY gameView.rowNumb - 1}}DIR_RIGHT - {p.posXif (p.posX gameView.colNumb) {p.posX 0}}DIR_DOWN - {p.posYif (p.posY gameView.rowNumb) {p.posY 0}}DIR_LEFT - {p.posX--if (p.posX 0) {p.posX gameView.colNumb - 1}}}// 死亡逻辑,蛇头撞到身体了if (p ! gameView.mHead p.posX gameView.mHead.posX p.posY gameView.mHead.posY) {isGameOver true}// 移动修改方向为上一节的方val temp p.dirp.dir dirdir tempp p.next}mSnarkCounter 0}// 食物控制val iterator gameView.mFoodList.iterator()while (iterator.hasNext()) {val food iterator.next()food.counter// 食物消失if (food.counter (FOOD_ALIVE_TIME / GAME_FLUSH_TIME)) {iterator.remove()continue}// 食物闪烁if (food.counter ((FOOD_ALIVE_TIME - FOOD_BLING_TIME) / GAME_FLUSH_TIME)) {food.blingCounterif (food.blingCounter (FOOD_BLING_FREQ / GAME_FLUSH_TIME)) {food.show !food.showfood.blingCounter 0}}// 食物被吃添加一节蛇体到尾部if (food.posX gameView.mHead.posX food.posY gameView.mHead.posY) {var x gameView.mTail.posXvar y gameView.mTail.posY// 在尾部添加when(gameView.mTail.dir) {DIR_UP - yDIR_RIGHT - x--DIR_DOWN - y--DIR_LEFT - x}gameView.mTail.next Snark(x, y, gameView.mTail.dir,null)gameView.mTail gameView.mTail.next!!// 移除被吃食物iterator.remove()}}mFoodCounterif (mFoodCounter (FOOD_ADD_TIME / GAME_FLUSH_TIME).toInt()) {// 生成食物val x (Math.random() * gameView.colNumb).toInt()val y (Math.random() * gameView.rowNumb).toInt()gameView.mFoodList.add(Food(x, y, 0, 0,true))mFoodCounter 0}// 循环发送消息刷新页面gameView.invalidate()if (!isGameOver) {gameView.mGameController.sendEmptyMessageDelayed(0, GAME_FLUSH_TIME)}else {gameView.gameOver()}}}}data class Food(var posX: Int, var posY: Int, var counter: Int, var blingCounter: Int, var show: Boolean)data class Snark(var posX: Int, var posY: Int, var dir: Int, var next: Snark? null) }对应style配置 res - values - snark_game_view_style.xml ?xml version1.0 encodingutf-8? resourcesdeclare-styleable name SnarkGameViewattr namerowNumb formatinteger/attr namecolNumb formatinteger/attr namenode formatreference//declare-styleable /resources蛇体掩图也给一下吧,当然你找点好看的图片代替下会更好 res - drawable - ic_node.xml vector android:height24dp android:tint#6F6A6Aandroid:viewportHeight24 android:viewportWidth24android:width24dp xmlns:androidhttp://schemas.android.com/apk/res/androidpath android:fillColorandroid:color/white android:pathDataM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z/ /vector主要问题 下面简单讲讲吧大部分还是和上一篇的飞机大战类似这里就讲讲不一样的或者做点补充吧。 资源加载 资源加载就是从styleable配置里面读取设置这里贪吃蛇是完全网格化的游戏这里读取了行数和列数后面把屏幕等分获取到了行高和列长转换逻辑得注意下。蛇的掩图逻辑和上一篇博文一致不细说了。 蛇体移动 蛇体的移动实际就要有一个方向这里每一截蛇都是一个节点构成了一个链表每个节点的方向都是移动前上一个节点的方向这样移动起来就有效果了。当然方向的获取也简单在onTouchEvent中监听DOWN和UP事件就行了比较起点和终点看看往哪边滑动的更改蛇头方向就行后面会向后传递。 这里还有个穿墙的问题要更改下从一边出去会从另一边出来这里改下节点的方向和位置就行了。 食物闪烁 食物的控制是通过counter对游戏刷新频率计数实现的超过计数数量就移除食物到达闪烁时间food内部的blingCounter进行计数在我的设置里是0.5秒反转一下show这样就出来了闪烁效果。 位置摆放问题 这里用的坐标都是中心坐标所以和掩图的宽高有关在生成位置的时候按中心位置去生成在onDraw按掩图的宽高来摆放让掩图中心放在位置上最后出来的效果就比较好看了。
http://www.dnsts.com.cn/news/58780.html

相关文章:

  • 做网站别人输账号代码wordpress 主题 love
  • 开网站做淘宝客自己做微商想做个网站
  • 创建网站的步骤是装饰网站建设公司
  • 江门做公司网站移动网站建设
  • 重庆建设教育协会网站河北邯郸做移动网站
  • 网站的外链情况咸阳网站建设哪家专业
  • 上海app开发技术公司百度爱采购优化软件
  • 重庆营销型网站建设价格专业网站开发建设
  • 学网站建设学校龙岗微信网站制作
  • 贵州省和城乡建设厅官方网站后期网站
  • 太原网站建设维护做网站如何导入信用卡付款
  • 《小城镇建设》》杂志社网站东方市住房和城乡建设局网站
  • 网站建设国际标准网站域名的用处
  • 专业网站建设找哪家好网页前端设计用什么软件
  • 网站开发工具 比较wordpress+标签消失
  • 建设网站公司是什么企业网页是什么
  • 衣柜东莞网站建设技术支持wordpress 进不去后台
  • 医疗网站前置审批医院网站如何建立
  • h5响应式音乐网站模板俄文网站策划
  • 嘉兴网站定制柳州专业网站推广公司
  • 网站被墙怎么办重庆建设厅官网
  • 网站制作网络推广关键词排名公众号怎么制作左右滑动图片
  • 毕业设计做网站 服务器怎么弄默认网站预览能能显示建设中
  • 国外优秀ui设计网站商丘网站建设运营公司
  • 十大高端网站定制设计师网站免费高清素材软件
  • icann官方网站广州企业网站设计公司
  • 什么牛网站建设廊坊网络公司网站
  • 网站建设策划基本流程建站网络公司
  • 网站内容注意事项溜冰鞋 东莞网站建设
  • 网站设置为信任站点网络规划设计师教程 下载