开发一个Android休闲小游戏 —— 水果连连看

A. 项目描述

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

fruits

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

  1. 游戏规则和目标:

    • 游戏采用经典的连连看玩法,玩家需要在限定时间内连接相同的水果。
    • 主要目标是在规定时间内尽可能快地消除界面上的水果,获得更高的分数。
  2. 用户界面设计:

    • 主界面包括游戏开始按钮功能入口。
    • 游戏界面应展示游戏区域、剩余时间、帮助提示等元素。
    • 提供美观的水果图标,并在用户成功连接时提供声音和视觉反馈。
  3. 游戏流程:

    • 游戏开始时,随机生成一定数量的水果图标并铺满游戏区域。
    • 玩家可以通过点击两个相同的水果图标,若它们之间存在不超过两个直线拐点的路径,则可以连接消除。
    • 连接成功后,所选水果图标会消失。
    • 若剩余时间归零或无剩余可连接的水果,则游戏结束。
  4. 难度和帮助:

    • 游戏难度应逐渐增加,可以通过减少游戏规定时间的方式实现。
    • 提供游戏帮助提示的功能,帮助用户完成游戏,同时限定使用帮助的次数。

游戏界面

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

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

游戏结束

D. 项目演示

水果连连看,演示视频

下载安装包试玩

E. 项目源码

项目截图

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

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
高清版 Book Description “Wolfenstein 3D”-like and ”Doom”-like game apps are some of the classic Android games presented in the original edition of this book. Since their release, Android has progressed with the debut of Android 4.0, adding better fonts, new User Interface and Experience (UI/UX) APIs, tablet considerations, multi-touch capabilities, multi-tasking, faster performance, and much more to the Android game app development repertoire. Multi-touch code gives these games and their players dynamic input and exchange ability, for a more realistic arcade game experience. Faster and better performance offers game players a more seamless, fun arcade experience like never before on Android. There is also improved native C/C++ integration with Android’s NDK as well, which makes coding, compiling, and converting both productive and efficient with gains in app performance. With actionable real-world source, Advanced Android 4 Games shows you how to build more sophisticated and addictive Android games, harnessing the power of these recent advancements. * Coverage of the new UI, UX, multi-touch and multi-tasking features available with Android 4.0. * Learn other techniques for improving the game playing experience including Wi-Fi tethering, better multi-tasking, new and better streaming Web video using WebM, and more. * By combining the elegant object-oriented features of Java and the raw power of C, there is no limit to the types of games that you can build for the platform, such as the “Quake 3D”-like game app case study in this book. You’ll definitely have fun, and perhaps you’ll even make some money. Enjoy! What you’ll learn * Key advanced Android gaming techniques using the new Android SDK 4 to help you earn more money in the app stores * How to compile native code (C) in Android using the NDK * How to add and integrate multi-touch * How to use Bluetooth controllers (Zeemote) * More gaming tricks and tips, such as hybrid 3D graphics with OpenGL and JNI * How to port and augment a 2D shooter game app similar to “Wolfenstein” for Android * How to port and augment another 2D shooter “Doom”-like game app for Android using OpenGL * How to build a 3D shooter game like “Quake” * How and where to best deploy these game apps Who this book is for This book is for savvy Android app developers who are looking for professional or advanced techniques for porting, augmenting and building 2D and 3D game apps that are complex, fun and lucrative. Table of Contents 1. Welcome to Android Gaming 2. Gaming Tricks: 3. More Gaming Tricks: Hybrid 3D Graphics with OpenGL and JNI 4. 2D Shooters: Wolfenstein-like App for Android 5. 2D Shooters with OpenGL: Doom-like App for Android 6. 3D Shooters Part I: Quake-like App 7. 3D Shooters Part II: Quake II 8. Appendix: Deployment and Compilation Tips
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值