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

加强网站建设百度搜索怎么优化

加强网站建设,百度搜索怎么优化,国外外包网站,医院设计安卓小游戏:贪吃蛇 前言 这个是通过自定义View实现小游戏的第二篇,实际上第一篇做起来麻烦点,后面的基本就是照葫芦画瓢了,只要设计下游戏逻辑就行了,技术上不难,想法比较重要。 需求 贪吃蛇&#xff0…

安卓小游戏:贪吃蛇

前言

这个是通过自定义View实现小游戏的第二篇,实际上第一篇做起来麻烦点,后面的基本就是照葫芦画瓢了,只要设计下游戏逻辑就行了,技术上不难,想法比较重要。

需求

贪吃蛇,太经典了,小时候在诺基亚上玩了不知道多少回,游戏也很简单,就两个逻辑,一个是吃东西变长,一个是吃到自己死亡。核心思想如下:

  • 1,载入配置,读取游戏信息及掩图
  • 2,启动游戏控制逻辑
  • 3,手势控制切换方向

效果图

这里就稍微演示了一下,就这速度,要演示到死亡估计得一分钟以上了,掩图用的比较low,勉强凑合。

snark

代码

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 = ArrayList<Food>()// 游戏控制器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: WeakReference<SnarkGameView> = WeakReference(view)// 蛇体移动控制private var mSnarkCounter = 0// 食物闪烁控制private var mFoodCounter = 0// 游戏结束标志internal var isGameOver = falseoverride fun handleMessage(msg: Message) {mRef.get()?.let { gameView ->mSnarkCounter++if (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.posX++if (p.posX >= gameView.colNumb) {p.posX = 0}}DIR_DOWN -> {p.posY++if (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.blingCounter++if (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 -> y++DIR_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()}}mFoodCounter++if (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 version="1.0" encoding="utf-8"?>
<resources><declare-styleable name ="SnarkGameView"><attr name="rowNumb" format="integer"/><attr name="colNumb" format="integer"/><attr name="node" format="reference"/></declare-styleable>
</resources>

蛇体掩图也给一下吧,当然你找点好看的图片代替下会更好!

res -> drawable -> ic_node.xml

<vector android:height="24dp" android:tint="#6F6A6A"android:viewportHeight="24" android:viewportWidth="24"android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"><path android:fillColor="@android:color/white" android:pathData="M12,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.hengruixuexiao.com/news/11276.html

相关文章:

  • 平面设计做名片都去那个网站整合营销策划方案
  • 网站优化包括整站优化吗seo运营做什么
  • 快站建站怎么收费的今日全国最新疫情通报
  • 北京建立网站关键词推广技巧
  • 企业名录黄页大全百度seo关键词工具
  • 在工商局网站怎么做清算t和p在一起怎么做网站
  • 巢湖网站建设如何自己做网站
  • 聊城集团网站建设加盟自媒体发布软件app
  • 做网站维护要什么专业职业技能培训班
  • jsp 网站建设百度应用商店下载安装
  • 网站建设属于什么职位类别seo入门到精通
  • 昭通市建设局网站热点新闻事件及观点
  • 小企业做网站怎么做北京网站优化策略
  • 学院网站建设服务宗旨适合seo的网站
  • 福田欧曼配件大全百度seo搜索引擎优化方案
  • 上饶做网站b2b网站大全免费推广
  • 网络服务类型及协议宁波seo外包推广软件
  • 沈阳网站建设工作室2345网址导航官网官方电脑版
  • wordpress注册 邮件百度搜索关键词优化
  • 利用切片做网站背景图片聚合搜索引擎
  • 怎么做网站的ico软件测试培训费用大概多少
  • 婚纱摄影图片福建seo顾问
  • 四川淘宝网站建设方案百度app最新版本
  • 电影购买网站怎么设计谷歌seo服务公司
  • 电子商务网站建设asp sql 源码下载竞价推广培训课程
  • wordpress 二次验证失败seo基础入门
  • avada如何做中英文网站网络推广外包注意哪些
  • 西安长安网站建设制作湘潭网站制作
  • 色情网站是否需要备案十大广告公司
  • 在龙港网站哪里做网站系统开发