首页 > 其他分享 >水果连连看,Android 小游戏开发

水果连连看,Android 小游戏开发

时间:2023-11-06 18:34:24浏览次数:38  
标签:p2 map p1 连连看 游戏 Point 小游戏 path Android

A. 项目描述

"水果连连看"是一款经典的休闲益智小游戏。游戏的目标是通过连接相同的水果图标来消除它们,最终清空整个游戏界面。它以其简单易懂的规则和有趣的玩法而受到许多玩家的喜爱。

让我们来梳理一下这款小游戏的功能需求。

  1. 游戏规则和目标:
  • 游戏采用经典的连连看玩法,玩家需要在限定时间内连接相同的水果。
  • 主要目标是在规定时间内尽可能快地消除界面上的水果,获得更高的分数。
  1. 用户界面设计:
  • 主界面包括游戏开始按钮功能入口。
  • 游戏界面应展示游戏区域、剩余时间、帮助提示等元素。
  • 提供美观的水果图标,并在用户成功连接时提供声音和视觉反馈。
  1. 游戏流程:
  • 游戏开始时,随机生成一定数量的水果图标并铺满游戏区域。
  • 玩家可以通过点击两个相同的水果图标,若它们之间存在不超过两个直线拐点的路径,则可以连接消除。
  • 连接成功后,所选水果图标会消失。
  • 若剩余时间归零或无剩余可连接的水果,则游戏结束。
  1. 难度和帮助:
  • 游戏难度应逐渐增加,可以通过减少游戏规定时间的方式实现。
  • 提供游戏帮助提示的功能,帮助用户完成游戏,同时限定使用帮助的次数。

水果连连看,Android 小游戏开发_连连看

小结: 以上是"水果连连看"小游戏的功能需求。作为开发者,需要根据这些需求设计游戏逻辑、实现连连消除算法、开发用户界面和交互等相关功能。同时,确保游戏流畅运行、界面美观、易于上手。

B. 开发工具

  • Android Studio Dolphin | 2021.3.1 Patch 1
  • Java , JDK 11.0.13
  • Gradle , gradle-7.4

C. 代码设计

1. 游戏区域

1.1 游戏区域基类

BoardView 是游戏的自定义视图的基类,继承自 View 类,实现了游戏区域的若干通用功能:

  • 常量 xCountyCount 分别表示 x、y轴方向的图标数+2,这个多出来的2用来表示游戏界面与屏幕边缘的间距;
  • BoardView 类包含了各种成员变量,包括用于表示游戏棋盘的数组、所有的水果图片、选中的水果图片以及可以连通点的路径 ;
  • BoardView 构造函数初始化示图,计算每个水果图标的长宽、初始化所有的水果图片资源;
  • onDraw方法:绘制可以连通的路径,然后将路径以及两个图标清除;绘制棋盘的所有图标;绘制选中图标,当选中时图标放大显示;
@Override
protected void onDraw(Canvas canvas) {

        /*
         * 绘制连通路径,然后将路径以及两个图标清除
         */
        if (path != null && path.length >= 2) {
            final float halfIconSize = (float) iconSize / 2;
            for (int i = 0; i < path.length - 1; i++) {
                Paint paint = new Paint();
                paint.setColor(Color.YELLOW); // Color.CYAN
                paint.setStyle(Paint.Style.FILL); // STROKE
                paint.setStrokeWidth(4);
                Point p1 = indextoScreen(path[i].x, path[i].y);
                Point p2 = indextoScreen(path[i + 1].x, path[i + 1].y);
                // iconSize / 2
                canvas.drawLine(p1.x + halfIconSize, p1.y + halfIconSize,
                        p2.x + halfIconSize, p2.y + halfIconSize, paint);
            }
            Point p = path[0];
            map[p.x][p.y] = 0;
            p = path[path.length - 1];
            map[p.x][p.y] = 0;
            selected.clear();
            path = null;
        }
        /*
         * 绘制棋盘的所有图标 当这个坐标内的值大于0时绘制
         */
        for (int x = 0; x < map.length; x += 1) {
            for (int y = 0; y < map[x].length; y += 1) {
                if (map[x][y] > 0) {
                    Point p = indextoScreen(x, y);
                    canvas.drawBitmap(icons[map[x][y]], p.x, p.y, null);
                }
            }
        }

        /*
         * 绘制选中图标,当选中时图标放大显示
         */
        for (Point position : selected) {
            Point p = indextoScreen(position.x, position.y);
            if (map[position.x][position.y] >= 1) {
                canvas.drawBitmap(icons[map[position.x][position.y]],
                        null,
                        new Rect(p.x - 5, p.y - 5, p.x + iconSize + 5, p.y + iconSize + 5), null);
            }
        }
    }
  • 创建了工具函数 indextoScreenscreenToindex,分别用于将图片数组中的索引转换成屏幕上的坐标、将图标在屏幕中的坐标转成在数组上的索引。

总体而言,BoardView 类提供了游戏的最基础的同时也是通用的功能,它绘制了游戏区域内的所有水果图片、绘制了可以联通的路径以及清除图标、点击图片放大显示,以及一些通用的工具函数。

1.2 游戏区域实现

GameView 是游戏示图的实现,继承了 BoardView 类,实现了游戏的点击操作逻辑、关卡控制以及倒计时等功能。

  • GameView 类使用常量MAX_TIME设定了游戏的最大时间,使用变量totalTime表示每一局游戏的总时间,在函数 startNextPlay中通过每一局减少10秒的方式缩短游戏时间来实现提高游戏难度的目的;
  • GameView 用到了接口 OnTimerListenerOnStateListenerOnToolsChangeListener,分别用于游戏时间、游戏状态以及使用帮助提示的监听回调;
  • GameView使用内部类 RefreshHandler 继承自 Handler,用来定时刷新界面,并判断是否结束;使用内部类 RefreshTime继承自Thread,实现了游戏倒计时的逻辑;
  • startPlay方法表示开启新一局游戏,初始化包括游戏界面排布、使用帮助提示次数限制、剩余时间、重启倒计时等状态;
  • reStartPlay方法用来继续之前的游戏,之前的游戏状态保持不变;
  • startNextPlay方法用来开启下一关游戏,提高游戏难度;
  • onTouchEvent函数用来处理用户的点击操作,用户点击了水果图片时,判断是否可以消除,以及点击效果的实现;
  • win 方法用于判断游戏是否获胜;
  • die 方法判断游戏是否无法继续;
// 判断游戏是否无法继续
    private boolean die() {
        for (int y = 1; y < yCount - 1; y++) {
            for (int x = 1; x < xCount - 1; x++) {
                if (map[x][y] != 0) {
                    for (int j = y; j < yCount - 1; j++) {
                        if (j == y) {
                            for (int i = x + 1; i < xCount - 1; i++) {
                                if (map[i][j] == map[x][y]
                                        && link(new Point(x, y),
                                        new Point(i, j))) {
                                    return false;
                                }
                            }
                        } else {
                            for (int i = 1; i < xCount - 1; i++) {
                                if (map[i][j] == map[x][y]
                                        && link(new Point(x, y),
                                        new Point(i, j))) {
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
        }
        return true;
    }
  • link方法用于判断两个点是否可以连线
// 判断两个点是否可以连线
    private boolean link(Point p1, Point p2) {
        if (p1.equals(p2)) {
            return false;
        }
        path.clear();
        if (map[p1.x][p1.y] == map[p2.x][p2.y]) {
            if (linkD(p1, p2)) { //	判断两个点是否可以连线
                path.add(p1);
                path.add(p2);
                return true;
            }

            Point p = new Point(p1.x, p2.y);
            if (map[p.x][p.y] == 0) {
                if (linkD(p1, p) && linkD(p, p2)) { //	判断两个点是否可以连线
                    path.add(p1);
                    path.add(p);
                    path.add(p2);
                    return true;
                }
            }
            p = new Point(p2.x, p1.y);
            if (map[p.x][p.y] == 0) {
                if (linkD(p1, p) && linkD(p, p2)) {
                    path.add(p1);
                    path.add(p);
                    path.add(p2);
                    return true;
                }
            }
            expandX(p1, p1E); // 左右扫描X轴
            expandX(p2, p2E); // 左右扫描X轴

            for (Point pt1 : p1E) {
                for (Point pt2 : p2E) {
                    if (pt1.x == pt2.x) {
                        if (linkD(pt1, pt2)) {
                            path.add(p1);
                            path.add(pt1);
                            path.add(pt2);
                            path.add(p2);
                            return true;
                        }
                    }
                }
            }

            expandY(p1, p1E); // 上下扫描Y轴
            expandY(p2, p2E); // 上下扫描Y轴
            for (Point pt1 : p1E) {
                for (Point pt2 : p2E) {
                    if (pt1.y == pt2.y) {
                        if (linkD(pt1, pt2)) {
                            path.add(p1);
                            path.add(pt1);
                            path.add(pt2);
                            path.add(p2);
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        return false;
    }
  • change方法用于重新排布水果图片,使用Random随机生成位置索引;
  • getScore方法实现了用户得分的计算,剩余时间越多、关卡越高、使用帮助的次数越少,得分越高;

3. 游戏结果

游戏结果使用 MyDialog 自定义弹窗提示,呈现游戏胜利/失败的结果、得分,并且给用户选择退出游戏、重新开始以及玩下一关。

水果连连看,Android 小游戏开发_ico_02

D. 项目演示

视频演示

<iframe src="//player.bilibili.com/player.html?aid=747353677&bvid=BV1JC4y1V7HY&cid=1302140141&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>

E. 项目源码

水果连连看,Android 小游戏开发_使用帮助_03

获取源码:关注公众号《数字森林》,后台发送 连连看

水果连连看,Android 小游戏开发_使用帮助_04

标签:p2,map,p1,连连看,游戏,Point,小游戏,path,Android
From: https://blog.51cto.com/u_16307842/8215542

相关文章

  • android 系统修改签名:以android13为例
    android系统修改签名:以android13为例修改签名方式修改签名文件使用签名工具(development/tools/)修改签名文件development/tools/make_keyplatform'/C=CN/ST=ShenZhen/L=NanShan/O=Tripod/OU=WCD/CN=demo/[email protected]'  注意:以上两张图片表......
  • Android Studio 下载Gradle 超时解决方案
    错误提示1、卡在Gradle:Downloadhttps://services.gradle.org/distributions/gradle-3.2-all.zip不动。2、提示Error:Connectiontimedout:connect。  解决方案:1、手动下载gradle.zip文件打开项目里gradle\wrapper\gradle-wrapper.properties这个文件,找到类似于下面的这一......
  • Cocos Creator 3.x 之Android Studio打包
    一,前言1,CocosCreator5.3.22,AndroidStudioDolphin|2021.3.1Patch13,SDK和NDK3.1,SDK3.1,NDK二,使用CocosCreator构建Android工程1,点击“构建”按钮。(注意:不用点击“生成”,我们使用AndroidStudio生成APK)2,生成的Android工程注意:在Cocos项目下生成了native文件夹,如下三,手......
  • android studio 编译Telegram源码经验总结(2023-11-05)
    前言Telegram是一款强大的端到端加密IM,专注于安全性和速度,支持Android/IOS/Windows/macOS等平台,功能丰富,运行流畅,免费开源,代码具有学习和研究意义。一、androidtelegram源码下载地址:github:https://github.com/DrKLO/Telegram.git二、编译环境的选择:Windows版本:1064位;Andro......
  • 2023年最强大厂Android面试题库来了,不接受反驳!
    前言上周和部门BP聊天,她说最近在boss上放出一个初级Android岗位,平均每天都能收到300多份简历。Android市场越来越卷,跳槽前做好技术进阶突击,才能稳拿offer。相信有过中、大厂面试经验的小伙伴都知道,中、大厂面试提问都不会是点到为止那么简单,很多面试官会就一个比较基础的问题,一......
  • Android系统中进程的优先级
    进程与线程进程是操作系统中正在运行的程序的实例。每个进程都有自己的内存空间和系统资源,并且可以独立地执行指令。进程可以包含一个或多个线程,线程是进程中的执行单元,负责执行具体的任务。在操作系统中,进程是资源分配的基本单位。操作系统通过调度算法来管理和控制进程的执行顺序......
  • 记一个 Android 14 适配引发的Android 存储权限问题
    一、bug背景项目中有下面这样一段代码,在AndroidT版本运行正常,现在适配到AndroidU上之后,运行时crash了。。。。...values.put(MediaStore.Images.Media.DATA,file.absolutePath)values.put(MediaStore.Images.Media.DISPLAY_NAME,file.name)...resolver.update(ur......
  • 基于Python+Pygame实现一个滑雪小游戏
    目录项目介绍Pygame介绍项目文件夹介绍演示视频代码免费领取一、项目介绍使用介绍:运行main.py文件后,通过左右按键可以控制小人的移动,如果经过旗杆那么+10分,如果碰到树木那么减50分。二、Pygame介绍Pygame是一个用于游戏开发和多媒体应用的Python库。它是基于SDL(Simple......
  • 亲测可行,Android Studio 查看源码出现 Source for ‘Android API xxx Platform’ not
    亲测可行,AndroidStudio查看源码出现Sourcefor‘AndroidAPIxxxPlatform’notfound的解决方法如标题中的问题,产生的原因就是SDK源码目录下找不到对应版本的源码文件。解决方案一般就是下载对应版本的源码文件即可。这里主要是另一种情况,每次Google发布Android新......
  • python_猜数字小游戏
    #需求:根据用户输入的数字进行猜数字游戏,要求:数字的范围(1,100),且最多有7次机会fromrandomimportrandintanswer=randint(0,100)foriinrange(7):you_answer=input("请输入一个整数:")ifyou_answer.isdigit():you_answer=int(you_answer)......