精华内容
下载资源
问答
  • AndroidTV 模拟器的搭建

    千次阅读 2014-01-18 22:35:34
    要求:Eclipse版本3.5以上  ADT版本10.0.1  TCL的SDK(我看了看核心是Android2.2的...下載SDK和TCL的模拟器  2.Eclipse安装ADT(版本一定要符合哦,要不不行)  3.Eclipse挂载SDK  Eclipse环境中设置Window->
    要求:Eclipse版本3.5以上
             ADT版本10.0.1
             TCL的SDK(我看了看核心是Android2.2的API)

    步骤:
          1.下載SDK和TCL的模拟器
          2.Eclipse安装ADT(版本一定要符合哦,要不不行)
          3.Eclipse挂载SDK
             Eclipse环境中设置Window->Preferences,在弹出的对话框中选中第二项Android,在SDK Location中设置解压好的开发包文
             件夹路径
          4.用下载的TCL的模拟器(emulator.exe)把SDK路径/tools文件夹下原来的的emulator.exe覆盖掉
          5.OK,已经可以跑起来了,用AVDManager建立一个TCL720P的模拟器玩玩吧,记住由于屏幕大小原因点击start按钮在  
             launchOption中设置显示比例,在ScreenSize填上10,此时的显示比例大概是0.6吧

    图片:


    付TCL Android TV技术资料:
    1系统概况  

    1.1 硬件环境概况
    存储设备:支持SD卡和U盘.
    CPU主频800M以上,内存512M以上,flash512M以上.
    USB:扩展4个.
    音频输入输出:双通道立体声输入输出.
    HDMI输出,最大分辨率1920*1080.
    网口:1个10M/100M的以太网口.
    支持键盘鼠标输入.
    通过USB口可以扩展其他设备(摄像头,无线网口等).
    支持通过ADB进行调试.

    1.2 软件环境概况
    操作系统版本:android2.2.
    SDK版本: TCL SDK.
    支持OPENGL2.0,硬件加速.
    多媒体解码支持:MVB/TS/MP4/3GP等.

    1.3 操作设备:非触摸屏操作
    红外遥控器.
    按键:Home,Menu,Back,上,下,左,右,ok,左滑轮,右滑轮,3D键.
    2安装说明
    2.1 下载.
    http://developer.tcl.com下载TCL SDK开发包,对应为Windows版本与Ubuntu版本,请下载与当前系统匹配版本.
    2.2 设置开发包路径.
       解压下载好的开发包,Eclipse环境中设置Window->Preferences,在弹出的对话框中选中第二项Android,在SDK Location中设置解压好的开发包文件夹路径.
    2.3设置ADT
        下载ADT-10.0.1.zip,Eclipse环境中设置Help->Install New Software,弹出的对话框中点击Add,再点击Archive,选择ADT-10.0.1.zip,点击Next进行安装.

    2.4 创建模拟器
    开发包根目录下双击SDK Setup.exe 对话框Setting中勾选Misc两项,在Available Packages选项中选择需要安装的组件.在第一项Virtual Devices选项中,点击New,创建新的模拟器.在skin中,请选择TCL800/TCL720P/TCL1080P进行开发.
    TCL800:800x450  TCL720P:1280x720  TCL1080P:1920x1080
    在TV环境上分辨率为720P/1080P.


    2.5 模拟器缩放
    考虑到用户显示器大小因素,在使用TCL1080P/TCL720P两种分辨率进行开发时,需要将模拟器尺寸缩小以满足显示器显示.
    Eclipse中请点击下图所示图标:



    选中模拟器后点击Start,会弹出Launch Options对话框.勾选”Scale”方框.如果当前是1080P/720P,请将Screen Size设置为合适的数值使Scale值小于1并且适合显示器显示,如图2.4,设置为4,缩小比例为0.67.



    3开发设计要求

    3.1 开发环境:
    elclipse,Sdk版本TCL_SDK,模拟器开发.( 主机环境不限)

    3.2  应用程序类型
    与互联网电视功能密切相关的应用,充分利用互联网电视平台特性,能给用户带来新的用户体验.

    3.3 输入要求:
    基于模拟器开发,必须支持键盘输入控制.支持的键盘标准控制键如下:
    上键:焦点向上移动.对应遥控器的上键.
    下键:焦点向下移动.对应遥控器的下键.
    左键:焦点向左移动.对应遥控器的左键.
    右键:焦点向右移动.对应遥控器的右键.
    回车键:进入下级子菜单.对应遥控器的ok键.
    ESC键:返回上级菜单.对应遥控器的back键.
    WIN键:弹出menu选项.对应遥控器的菜单键.
    支持汉字输入.

    3.4 输出要求:
    • 支持1280*720分辨率输出;支持1920*1080分辨率输出.
    • 按照流程SPEC完成应用程序流程设计.
    • 按照UI的设计效果实现最终的交互界面.
    • 应用程序最终以APK包的形式进行提交,并提供使用说明文档.
    • 提供源代码以及附注文档.
    3.5  响应要求:
    • 应用程序的菜单以及功能切换响应时间不能影响用户体验.
    3.6  调试:
    • 模拟器调试同时提供若干开发板以及电视用于应用程序开发调试.
    3.7 安装:
    • 支持使用ADB工具进行安装,同时支持直接集成到系统的安装.


    4开发平台独特性
    4.1  操作设备变化.
    操控设备为红外遥控.对应键值见表4.1.针对PC模拟器开发环境,用键盘代替遥控器按键.

    遥控器按键
    Android标准键值(KeyEvent)
    备注
    Power
    KEYCODE_POWER

    退出
    KEYCODE_BACK


    KEYCODE_DPAD_UP


    KEYCODE_DPAD_DOWN


    KEYCODE_DPAD_LEFT


    KEYCODE_DPAD_RIGHT

    OK
    KEYCODE_ENTER

    菜单
    KEYCODE_MENU

    3D
    KEYCODE_TCL_3D
    自定义
    飞梭左转
    KEYCODE_TCL_LEFT_SCROLL 
    自定义
    飞梭右转
    KEYCODE_TCL_RIGHT_SCROLL 
    自定义
                            

    linux下的sdk开发包:http://cdn.cedock.com/tcl-dev/android-sdk-TCL_linux.tar.gz

    windows下的sdk开发包:http://cdn.cedock.com/tcl-dev/android-sdk-TCL_windows.rar

    eclipse下ADT插件下载:http://cdn.cedock.com/tcl-dev/ADT-10.0.1.zip
    展开全文
  • 搞了个android tv盒子,想修改默认的launcher桌面,网上搜了好几天,没有成功。即使设置了如下默认开机launcher在android tv系统中也不会出来选择开启哪个launcher的选择框,...我的模拟器android 版本是 api level ...

    搞了个android tv盒子,想修改默认的launcher桌面,网上搜了好几天,没有成功。即使设置了如下默认开机launcher在android tv系统中也不会出来选择开启哪个launcher的选择框,可能android tv 系统跟android 系统还不太一样啊。

    于是乎就在网上到处搜方法,还真搜到了一个在模拟器上成功替换默认桌面的方法。

    我的模拟器android 版本是 api level 26 应该是android tv 8.0

    Name: Android_TV_1080p_API_26

    CPU/ABI: Android TV Intel Atom (x86)

    Path: C:\Users\root\.android\avd\Android_TV_1080p_API_26.avd

    Target: android-tv [Android TV] (API level 26)

    呃,要进行替换首先模拟器上要有root权限。但是因为android 7.0之后的模拟器都默认没有root权限了。需要这样再命令行启动模拟器。找到自己的模拟器目录:

    C:\Users\root\AppData\Local\Android\Sdk\emulator>emulator -avd Android_TV_1080p_API_26 -writable-system

    模拟器起来后,执行adb shell,提示符是$,表示没有root权限,然后su,提示符变成#,获取到root权限。

    执行 pm disable-user --user 0 com.google.android.tvlauncher ,禁用google默认的android tv 桌面。执行之前一定要先安装自己的有 android.intent.category.HOME android.intent.category.LAUNCHER android.intent.category.DEFAULT 的app 哦

    C:\Users\root>adb shell

    generic_x86:/ $ su

    generic_x86:/ # pm disable-user --user 0 com.google.android.tvlauncher

    Package com.google.android.tvlauncher new state: disabled-user

    之后冷重新启动模拟器,你就会发现开机后的桌面变成了自己的app啦。

    有空试试我的android tv 机顶盒,看看行不行。

    关于不同android tv 版本禁用 google默认 launcher的命令如下,自己多试试,版本对应不一定对,原帖地址是:Alternate Launcher (No Root) on Marshmallow, Nougat, Oreo, Pie Info,为了方便我把内容转过来:

    Connect your Shield TV via USB to mini USB with PC, For the 2017 Shield Model please look below for connection info.

    Leave the Shield plugged in and turned on as the way u usually use it connected to tv open command prompt (Minimal ADB and Fastboot ) on PC and type adb devices the PC will try to connect with Shield TV via USB. A message will pop up on the tv requesting permission for that device. Confirm that message with the controller or other device you use [mouse](http://i.viglink.com/?key=d2e43d31777d6249cc7d4a64dada8bca&insertId=68ffc0fd4e078f69&type=CD&exp=60%3ACI1C55A%3A5&libId=k4ejna3j01000n4o000DA66a8smwytd8p&loc=https%3A%2F%2Fforum.xda-developers.com%2Fshield-tv%2Fthemes-apps%2Falternate-launcher-root-marshmallow-t3359076&v=1&iid=68ffc0fd4e078f69&opt=true&out=http%3A%2F%2Fwww.ebay.com%2Fsch%2Fi.html%3F_nkw%3Dmouse&title=Alternate%20Launcher%20(No%20Root)%20on%20Marshmallow%2C%E2%80%A6%20%7C%20nVidia%20Shield%20Android%20TV&txt=%3Cspan%3Emouse%3C%2Fspan%3E), remote etc.

    Type in the command prompt

    adb shell

    pm hide com.google.android.leanbacklauncher

    To undo this

    adb shell

    pm unhide com.google.android.leanbacklauncher

    This will make the new launcher the default as it hides the leanback

    (Commands are different for the Nougat build see Update below)

    Also If this is needed because you cannot get into settings on your device afterwards I have attached a copy of the shields setting apk file that I got off the nvidia site just install it as you would any other apk and all is fine access all settings etc.

    This should work fine with any launcher that is setup as a Home Launcher please make sure you have a launcher that works and is what u need/want and that it is indeed set up and set as Home launcher.

    **UPDATE** : For Shields running Nougat build

    This is for Nougat NON Rooted shields, This also works on the 2015 model.

    For Nvidia Shield 2017 Model Please follow the updated instructions After you have set up minimal adb and fast boot on PC.

    First get a Type-A to Type-A USB cable or an [adapter](http://i.viglink.com/?key=d2e43d31777d6249cc7d4a64dada8bca&insertId=b074541887ac4ffb&type=CD&exp=60%3ACI1C55A%3A5&libId=k4ejna3j01000n4o000DA66a8smwytd8p&loc=https%3A%2F%2Fforum.xda-developers.com%2Fshield-tv%2Fthemes-apps%2Falternate-launcher-root-marshmallow-t3359076&v=1&iid=b074541887ac4ffb&opt=true&out=http%3A%2F%2Fwww.ebay.com%2Fsch%2Fi.html%3F_nkw%3Dadapter&title=Alternate%20Launcher%20(No%20Root)%20on%20Marshmallow%2C%E2%80%A6%20%7C%20nVidia%20Shield%20Android%20TV&txt=%3Cspan%3Eadapter%3C%2Fspan%3E) that makes micro usb to Type-A

    Use the Usb port furthest away from the Hdmi Port On The Shield TV

    Select Usb device mode In Settings

    Select Settings--Storage and Reset -- Using Usb (for Mtp)

    Select Settings--About--Build-- Press Build 8 times to enable Developer mode then

    Select Settings--Developer Options--Usb debugging (For adb)

    Then

    Type in the command prompt:

    adb shell

    pm uninstall -k --user 0 com.google.android.leanbacklauncher

    This should work fine with any launcher that is setup as a Home Launcher please make sure you have a launcher that works and is what u need/want and that it is indeed set up and set as Home launcher.

    **UPDATE**: OREO Here are the new commands for the Oreo update

    Type in the command prompt:

    adb shell

    pm uninstall -k --user 0 com.google.android.leanbacklauncher

    and

    pm uninstall -k --user 0 com.google.android.tvlauncher

    This will uninstall the Default launcher on non-rooted shields please make sure you have a functional launcher, set as Home launcher before doing this.

    **UPDATE:** Pie (8-3-2019) To enable adb debugging on Pie go to Settings -- device preferences -- about then scroll down to build select and click it until developer mode is enabled.

    To Disable the New Pie Launcher use this command

    adb shell

    pm disable-user --user 0 com.google.android.tvlauncher

    呃。。。。恢复原有桌面。。。。

    C:\Users\root>adb shell

    generic_x86:/ $ su

    generic_x86:/ # pm enable --user 0 com.google.android.tvlauncher

    Package com.google.android.tvlauncher new state: enabled

    展开全文
  • 资源为个人android TV版本开发学习用,几个TV开发常见问题,Android TV TextView如何实现增加滚动条,TV上屏幕适配总结,Android Studio中模拟器中关于VT-x is disabled in BIOS错误解决方案,Home界面实现原理...
  • 2048大家应该都玩过,今天我们就来实现一个可以在鸿蒙系统上运行2048小游戏,因为没有智慧屏,所以这里是在鸿蒙远程TV模拟器上运行,大概长下面这样:鸿蒙TV模拟器在开始写代码之前,我们来分析下,要实现这个小...

    2048大家应该都玩过,今天我们就来实现一个可以在鸿蒙系统上运行的2048小游戏,因为没有智慧屏,所以这里是在鸿蒙远程TV模拟器上运行的,大概长下面这样:

    b0f81fad45d69fb99ff5a421e9e5548a.png

    鸿蒙TV模拟器

    在开始写代码之前,我们来分析下,要实现这个小游戏大概需要这么几步:

    • 1.自定义数字卡片的样式CardView,包含设置卡片的文本数字,以及卡片的数字的颜色,以及单个卡片的背景。

    • 2.自定义一个游戏视图GameView,所有和游戏相关的逻辑都在这个View处理,当然最重要的还是手势的监听。

    • 3.在主页面引用自定义的GameView,以及添加一些分数,最高分,悔棋,重新开始等按钮,和游戏介绍等。

    1.自定义游戏卡片CardView

    PS:为什么要定一个CardView,你不直接用鸿蒙中的Text控件,给它设置一个背景呢,主要是想把设置数字和数字颜色和背景的相关逻辑单独处理。

    这里要介绍一下两个鸿蒙中的控件,TextStackLayout,用法上相当于Android中的TextViewFramLayout,用来展示文本和包裹子控件的,当然这里也不一定需要用StackLayout,也可以用鸿蒙中的其他ViewGrop来代替,这里就不作过多介绍了,具体可以自行查询官网了解。我们可以分几步来实现自定义的CardView:

    • 1.继承自StackLayout,实现其中3个构造方法。

    • 2.在初始化方法中声明一个Text,设置Text的背景。

    • 3.定义一个方法,用来根据数字设置文本的字体颜色和背景。

        /**
    * 初始化方法
    * 在初始化方法中声明一个Text,设置Text的背景
    */

    void initView() {
    //声明一个Text
    lable = new Text(getContext());
    lable.setTextSize(60);
    lable.setTextAlignment(TextAlignment.CENTER);

    //设置textView的背景
    ShapeElement element = new ShapeElement();
    element.setRgbColor(new RgbColor(198, 187, 183));
    lable.setBackground(element);
    LayoutConfig layoutConfig = new LayoutConfig(-1, -1);
    addComponent(lable, layoutConfig);
    setNum(0);
    }

    /**
    * 设置卡片文字和背景颜色
    * @param num
    */

    void setTextColor(int num){
    ShapeElement element = new ShapeElement();
    switch (num){
    case 0:
    element.setRgbColor(new RgbColor(205, 193, 180));
    break;
    case 2:
    lable.setTextColor(new Color(Color.getIntColor("#645B52")));
    element.setRgbColor(new RgbColor(238,228,218));
    break;
    case 4:
    lable.setTextColor(new Color(Color.getIntColor("#645B52")));
    element.setRgbColor(new RgbColor(237,224,200));
    break;
    case 8:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(242,177,121));
    break;
    case 16:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(245,149,99));
    break;
    case 32:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(246,124,95));
    break;
    case 64:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(246,94,59));
    break;
    case 128:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(237,207,114));
    break;
    case 256:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(237,204,97));
    break;
    case 512:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(153,204,0));
    break;
    case 1024:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(131,175,155));
    break;
    case 2048:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(0,153,204));
    break;
    }
    element.setCornerRadius(10);
    lable.setBackground(element);
    }

    PS:这里要注意下,设置背景颜色的话目前只能通过ShapeElement,调用其中的setRgbColor方法,设置RGB颜色。

    2.自定义游戏视图GameView

    • 1.继承TabLayout,实现其构造方法,其中TabLayout和Android中的很像,只是目前api还没有Android中那么多买单时也可以用来显示表哥布局,这里我们要实现TabLayout来绘制游戏的16宫格视图。

    • 2.定义一个卡片二维数组cardMap,用来保存卡片的位置和数字信息。定义个用来记录滑动自前卡片位置的二维数组retractMap用来实现悔棋。

    • 3.使用setTouchEventListener方法重写onTouchEvent来监听手势的滑动,实现上下左右滑动的监听。

    • 4.实现上下左右滑动监听的逻辑,合并数字卡片以及悔棋相关逻辑。使用SoundPlayer来播放滑动时候的声音。

    • 5.实现游戏结束逻辑,如果有cardMap里面有值为0即还有空格,或者当前格上下左右有相等的数字,则游戏继续,否则游戏结束
      具体逻辑实现可以参考已下代码:

    实现手势滑动监听,区别上下左右代码

            //设置触摸监听事件
    setTouchEventListener(new TouchEventListener() {
    private float starX, starY, offsetX, offsetY;

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
    MmiPoint point = touchEvent.getPointerScreenPosition(0);
    switch (touchEvent.getAction()) {
    case TouchEvent.PRIMARY_POINT_DOWN:
    starX = point.getX(); //记录手指按下的x点坐标
    starY = point.getY(); //记录手指按下的y点坐标
    break;
    case TouchEvent.PRIMARY_POINT_UP:
    offsetX = point.getX() - starX;//横向滑动距离
    offsetY = point.getY() - starY;//纵向滑动距离
    if (Math.abs(offsetX) > Math.abs(offsetY)) {
    if (offsetX < -5) {
    //左滑监听
    System.out.println("左边");
    swipeLeft();
    } else if (offsetX > 5) {
    //右滑监听
    System.out.println("右边");
    swipeRight();
    }
    } else {
    if (offsetY < -5) {
    //上滑监听
    System.out.println("上边");
    swipeUp();
    } else if (offsetY > 5) {
    //下滑监听
    System.out.println("下边");
    swipeDown();
    }
    }

    break;
    }
    return true;
    }
    });

    实现上下左右滑动业务逻辑代码

     private void swipeLeft() {
    retractMap();
    boolean isMerge = false;
    //向左边滑动
    for (int y = 0; y < 4; y++) {
    for (int x = 0; x < 4; x++) {
    for (int x1 = x + 1; x1 < 4; x1++) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x1][y].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    //添加移动动画,目前还有问题
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);

    cardMap[x][y].setNum(cardMap[x1][y].getNum());
    cardMap[x1][y].setNum(0);
    x--;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x1][y])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x1][y].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    private void swipeRight() {
    retractMap();
    //向右滑动
    //是否存在合并或者移动
    boolean isMerge = false;
    for (int y = 0; y < 4; y++) {
    for (int x = 3; x >= 0; x--) {
    for (int x1 = x - 1; x1 >= 0; x1--) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x1][y].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);
    cardMap[x][y].setNum(cardMap[x1][y].getNum());
    cardMap[x1][y].setNum(0);
    x++;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x1][y])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x1][y].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    private void swipeUp() {
    retractMap();
    //是否存在合并或者移动
    boolean isMerge = false;
    //向上滑动
    for (int x = 0; x < 4; x++) {
    for (int y = 0; y < 4; y++) {
    for (int y1 = y + 1; y1 < 4; y1++) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x][y1].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y1].getNum());
    cardMap[x][y1].setNum(0);
    y--;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x][y1])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x][y1].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    private void swipeDown() {
    retractMap();
    //是否存在合并或者移动
    boolean isMerge = false;
    //向下滑动
    for (int x = 0; x < 4; x++) {
    for (int y = 3; y >= 0; y--) {
    for (int y1 = y - 1; y1 >= 0; y1--) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x][y1].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y1].getNum());
    cardMap[x][y1].setNum(0);
    y++;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x][y1])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x][y1].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    游戏结束相关逻辑代码

       /**
    * 游戏结束
    * 如果有cardMap里面有值为0即还有空格,或者当前格上下左右有相等的数字,则游戏继续
    * 否则游戏结束
    */

    private void gameOver() {
    boolean isOver = true; //标示游戏是否结束,默认结束
    ALL:
    for (int y = 0; y < 4; y++) {
    for (int x = 0; x < 4; x++) {
    if (cardMap[x][y].getNum() == 0 ||
    (x > 0 && cardMap[x][y].equals(cardMap[x - 1][y])) ||
    (x < 3 && cardMap[x][y].equals(cardMap[x + 1][y])) ||
    (y > 0 && cardMap[x][y].equals(cardMap[x][y - 1])) ||
    (y < 3 && cardMap[x][y].equals(cardMap[x][y + 1]))) {
    isOver = false;
    break ALL;
    }
    }
    }
    if (isOver) {
    //游戏结束,保存总分
    DatabaseHelper databaseHelper = new DatabaseHelper(mainAbilitySlice); // context入参类型为ohos.app.Context。
    String fileName = "game"; // fileName表示文件名,其取值不能为空,也不能包含路径,默认存储目录可以通过context.getPreferencesDir()获取。
    Preferences preferences = databaseHelper.getPreferences(fileName);
    int totalScore = preferences.getInt("totalScore", 0);//保存的总分
    if (totalScore < mainAbilitySlice.getScore()) {
    //如果保存的总分小于当前总分,那么就保存大当前总分
    preferences.putInt("totalScore", mainAbilitySlice.getScore());
    preferences.flush();
    }

    mainAbilitySlice.gameOver();
    //设置最高分
    mainAbilitySlice.showTotalScore(preferences.getInt("totalScore", 0));
    }

    }

    3.在主页面应用GameView实现游戏相关的介绍,分数,以及重新开始和悔棋按钮的点击事件

    新建一个MainAbilitySlice继承AbilitySlice,AbilitySlice是用来展示应用的页面的,这和Android的Activity还是有点区别的,一个页面可以有多个AbilitySlice,这和Android中的fragment有点像,但是页面在前台时只能展示一个AbilitySlice,所以说它和两者还是有点区别的。

    PS:这里要注意的是由于DevEco Studio中目前xml布局还不支持自定义视图,所以我们这里只能在java代码中实现游戏页面的整体布局,还是比较麻烦的,

    通过这个小项目我们可以了解到鸿蒙开发和Android 还是比较像的,当时开发这个小游戏的时候,好的的api也是不知道,由于有Android项目开发经验,以及对java sdk比较熟悉,很多东西都是慢慢试出来,比如,滑动事件的监听,卡片字体的颜色和背景的等,希望鸿蒙后面会越来越完善。
    具体代码可以在我的github上查看

    展开全文
  • 2048大家应该都玩过,今天我们就来实现一个可以在鸿蒙系统上运行2048小游戏,因为没有智慧屏,所以这里是在鸿蒙远程TV模拟器上运行,大概长下面这样:鸿蒙TV模拟器在开始写代码之前,我们来分析下,要实现这个小...

    2048大家应该都玩过,今天我们就来实现一个可以在鸿蒙系统上运行的2048小游戏,因为没有智慧屏,所以这里是在鸿蒙远程TV模拟器上运行的,大概长下面这样:

    7a07411aeae941832ec287d44b1e5903.png

    鸿蒙TV模拟器

    在开始写代码之前,我们来分析下,要实现这个小游戏大概需要这么几步:

    • 1.自定义数字卡片的样式CardView,包含设置卡片的文本数字,以及卡片的数字的颜色,以及单个卡片的背景。

    • 2.自定义一个游戏视图GameView,所有和游戏相关的逻辑都在这个View处理,当然最重要的还是手势的监听。

    • 3.在主页面引用自定义的GameView,以及添加一些分数,最高分,悔棋,重新开始等按钮,和游戏介绍等。

    1.自定义游戏卡片CardView

    PS:为什么要定一个CardView,你不直接用鸿蒙中的Text控件,给它设置一个背景呢,主要是想把设置数字和数字颜色和背景的相关逻辑单独处理。

    这里要介绍一下两个鸿蒙中的控件,TextStackLayout,用法上相当于Android中的TextViewFramLayout,用来展示文本和包裹子控件的,当然这里也不一定需要用StackLayout,也可以用鸿蒙中的其他ViewGrop来代替,这里就不作过多介绍了,具体可以自行查询官网了解。我们可以分几步来实现自定义的CardView:

    • 1.继承自StackLayout,实现其中3个构造方法。

    • 2.在初始化方法中声明一个Text,设置Text的背景。

    • 3.定义一个方法,用来根据数字设置文本的字体颜色和背景。

        /**
    * 初始化方法
    * 在初始化方法中声明一个Text,设置Text的背景
    */

    void initView() {
    //声明一个Text
    lable = new Text(getContext());
    lable.setTextSize(60);
    lable.setTextAlignment(TextAlignment.CENTER);

    //设置textView的背景
    ShapeElement element = new ShapeElement();
    element.setRgbColor(new RgbColor(198, 187, 183));
    lable.setBackground(element);
    LayoutConfig layoutConfig = new LayoutConfig(-1, -1);
    addComponent(lable, layoutConfig);
    setNum(0);
    }

    /**
    * 设置卡片文字和背景颜色
    * @param num
    */

    void setTextColor(int num){
    ShapeElement element = new ShapeElement();
    switch (num){
    case 0:
    element.setRgbColor(new RgbColor(205, 193, 180));
    break;
    case 2:
    lable.setTextColor(new Color(Color.getIntColor("#645B52")));
    element.setRgbColor(new RgbColor(238,228,218));
    break;
    case 4:
    lable.setTextColor(new Color(Color.getIntColor("#645B52")));
    element.setRgbColor(new RgbColor(237,224,200));
    break;
    case 8:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(242,177,121));
    break;
    case 16:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(245,149,99));
    break;
    case 32:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(246,124,95));
    break;
    case 64:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(246,94,59));
    break;
    case 128:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(237,207,114));
    break;
    case 256:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(237,204,97));
    break;
    case 512:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(153,204,0));
    break;
    case 1024:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(131,175,155));
    break;
    case 2048:
    lable.setTextColor(new Color(Color.getIntColor("#FFFFFF")));
    element.setRgbColor(new RgbColor(0,153,204));
    break;
    }
    element.setCornerRadius(10);
    lable.setBackground(element);
    }

    PS:这里要注意下,设置背景颜色的话目前只能通过ShapeElement,调用其中的setRgbColor方法,设置RGB颜色。

    2.自定义游戏视图GameView

    • 1.继承TabLayout,实现其构造方法,其中TabLayout和Android中的很像,只是目前api还没有Android中那么多买单时也可以用来显示表哥布局,这里我们要实现TabLayout来绘制游戏的16宫格视图。

    • 2.定义一个卡片二维数组cardMap,用来保存卡片的位置和数字信息。定义个用来记录滑动自前卡片位置的二维数组retractMap用来实现悔棋。

    • 3.使用setTouchEventListener方法重写onTouchEvent来监听手势的滑动,实现上下左右滑动的监听。

    • 4.实现上下左右滑动监听的逻辑,合并数字卡片以及悔棋相关逻辑。使用SoundPlayer来播放滑动时候的声音。

    • 5.实现游戏结束逻辑,如果有cardMap里面有值为0即还有空格,或者当前格上下左右有相等的数字,则游戏继续,否则游戏结束
      具体逻辑实现可以参考已下代码:

    实现手势滑动监听,区别上下左右代码

            //设置触摸监听事件
    setTouchEventListener(new TouchEventListener() {
    private float starX, starY, offsetX, offsetY;

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
    MmiPoint point = touchEvent.getPointerScreenPosition(0);
    switch (touchEvent.getAction()) {
    case TouchEvent.PRIMARY_POINT_DOWN:
    starX = point.getX(); //记录手指按下的x点坐标
    starY = point.getY(); //记录手指按下的y点坐标
    break;
    case TouchEvent.PRIMARY_POINT_UP:
    offsetX = point.getX() - starX;//横向滑动距离
    offsetY = point.getY() - starY;//纵向滑动距离
    if (Math.abs(offsetX) > Math.abs(offsetY)) {
    if (offsetX < -5) {
    //左滑监听
    System.out.println("左边");
    swipeLeft();
    } else if (offsetX > 5) {
    //右滑监听
    System.out.println("右边");
    swipeRight();
    }
    } else {
    if (offsetY < -5) {
    //上滑监听
    System.out.println("上边");
    swipeUp();
    } else if (offsetY > 5) {
    //下滑监听
    System.out.println("下边");
    swipeDown();
    }
    }

    break;
    }
    return true;
    }
    });

    实现上下左右滑动业务逻辑代码

     private void swipeLeft() {
    retractMap();
    boolean isMerge = false;
    //向左边滑动
    for (int y = 0; y < 4; y++) {
    for (int x = 0; x < 4; x++) {
    for (int x1 = x + 1; x1 < 4; x1++) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x1][y].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    //添加移动动画,目前还有问题
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);

    cardMap[x][y].setNum(cardMap[x1][y].getNum());
    cardMap[x1][y].setNum(0);
    x--;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x1][y])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x1][y].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    private void swipeRight() {
    retractMap();
    //向右滑动
    //是否存在合并或者移动
    boolean isMerge = false;
    for (int y = 0; y < 4; y++) {
    for (int x = 3; x >= 0; x--) {
    for (int x1 = x - 1; x1 >= 0; x1--) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x1][y].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);
    cardMap[x][y].setNum(cardMap[x1][y].getNum());
    cardMap[x1][y].setNum(0);
    x++;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x1][y])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y], x1, x, y, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x1][y].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    private void swipeUp() {
    retractMap();
    //是否存在合并或者移动
    boolean isMerge = false;
    //向上滑动
    for (int x = 0; x < 4; x++) {
    for (int y = 0; y < 4; y++) {
    for (int y1 = y + 1; y1 < 4; y1++) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x][y1].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y1].getNum());
    cardMap[x][y1].setNum(0);
    y--;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x][y1])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x][y1].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    private void swipeDown() {
    retractMap();
    //是否存在合并或者移动
    boolean isMerge = false;
    //向下滑动
    for (int x = 0; x < 4; x++) {
    for (int y = 3; y >= 0; y--) {
    for (int y1 = y - 1; y1 >= 0; y1--) {
    //如果同一行的右边的点数字大于0
    if (cardMap[x][y1].getNum() > 0) {
    //如果最左边没有数字时,则将右边数字移动到左边
    if (cardMap[x][y].getNum() <= 0) {
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y1].getNum());
    cardMap[x][y1].setNum(0);
    y++;
    isMerge = true;
    } else if (cardMap[x][y].equals(cardMap[x][y1])) {
    //如果有右边的数字和左边的数字相等,则进行合并
    // mainAbilitySlice.getAnimLayer().createMoveAnim(cardMap[x][y1], cardMap[x][y], x, x, y1, y);
    cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);
    cardMap[x][y1].setNum(0);
    isMerge = true;
    mainAbilitySlice.addScore(cardMap[x][y].getNum());
    }
    break;
    }
    }
    }
    }
    //如果存在合并或者移动,则添加一个随机棋子
    if (isMerge) addRoundNum();
    }

    游戏结束相关逻辑代码

       /**
    * 游戏结束
    * 如果有cardMap里面有值为0即还有空格,或者当前格上下左右有相等的数字,则游戏继续
    * 否则游戏结束
    */

    private void gameOver() {
    boolean isOver = true; //标示游戏是否结束,默认结束
    ALL:
    for (int y = 0; y < 4; y++) {
    for (int x = 0; x < 4; x++) {
    if (cardMap[x][y].getNum() == 0 ||
    (x > 0 && cardMap[x][y].equals(cardMap[x - 1][y])) ||
    (x < 3 && cardMap[x][y].equals(cardMap[x + 1][y])) ||
    (y > 0 && cardMap[x][y].equals(cardMap[x][y - 1])) ||
    (y < 3 && cardMap[x][y].equals(cardMap[x][y + 1]))) {
    isOver = false;
    break ALL;
    }
    }
    }
    if (isOver) {
    //游戏结束,保存总分
    DatabaseHelper databaseHelper = new DatabaseHelper(mainAbilitySlice); // context入参类型为ohos.app.Context。
    String fileName = "game"; // fileName表示文件名,其取值不能为空,也不能包含路径,默认存储目录可以通过context.getPreferencesDir()获取。
    Preferences preferences = databaseHelper.getPreferences(fileName);
    int totalScore = preferences.getInt("totalScore", 0);//保存的总分
    if (totalScore < mainAbilitySlice.getScore()) {
    //如果保存的总分小于当前总分,那么就保存大当前总分
    preferences.putInt("totalScore", mainAbilitySlice.getScore());
    preferences.flush();
    }

    mainAbilitySlice.gameOver();
    //设置最高分
    mainAbilitySlice.showTotalScore(preferences.getInt("totalScore", 0));
    }

    }

    3.在主页面应用GameView实现游戏相关的介绍,分数,以及重新开始和悔棋按钮的点击事件

    新建一个MainAbilitySlice继承AbilitySlice,AbilitySlice是用来展示应用的页面的,这和Android的Activity还是有点区别的,一个页面可以有多个AbilitySlice,这和Android中的fragment有点像,但是页面在前台时只能展示一个AbilitySlice,所以说它和两者还是有点区别的。

    PS:这里要注意的是由于DevEco Studio中目前xml布局还不支持自定义视图,所以我们这里只能在java代码中实现游戏页面的整体布局,还是比较麻烦的,

    通过这个小项目我们可以了解到鸿蒙开发和Android 还是比较像的,当时开发这个小游戏的时候,好的的api也是不知道,由于有Android项目开发经验,以及对java sdk比较熟悉,很多东西都是慢慢试出来,比如,滑动事件的监听,卡片字体的颜色和背景的等,希望鸿蒙后面会越来越完善。
    具体代码可以在我的github上查看

    展开全文
  • 让PSP带你回童年FC模拟器联机教程对于...PSP上有一款名为NesterJ的FC模拟器,最近它刚刚推出了1.20alpha版本,该版本的模拟器在保留以往操作简明的优良传统的同时,还新加入了无线联机功能,也就是说你再也不用...
  • 最近接了个与TV开发相关项目,采用AS自动生成项目在模拟器上运行没问题,但是在电视真机上就是安装不上,跑不起来,我这还没有电视测试,测试还要去找朋友借设备,有点郁闷。 AS自动生成manifest文件如下 ...
  • 之前手机版模拟器都没问题,但是不知道为什么,最近新建的Tv版模拟器似乎不能联网,尝试多次发现了以下解决方案: 1.命令行 打开你 sdk 目录中 emulator 文件夹 按住 shift 键同时右击空白处 选择在此处打开...
  • 替换\AndroidSDK\system-images\android-21\android-tv\armeabi-v7a\目录中system.img android-21\android-tv\armeabi-v7a\ 依据使用android API版本 硬件架构 转载于:https://www.cnblogs.com/pok...
  • Android TV 开发笔记一:环境搭建

    千次阅读 2015-04-03 19:11:17
    3、打开SDK Manager,下载需要的开发包和模拟器,如下图展示的,模拟器我只下载了一个,你可以看需求下载其他版本的模拟器。 4、在AVD Manager中创建模拟器 5、模拟器启动的过程是相当的漫长,在模拟器中
  • Xcode是开发者为Apple TV, Apple Watch, iPad, iPhone, 和Mac开发应用完整工具箱。Xcode开发环境捆绑了分析工具(analysis tool),模拟器(Simulator)和tvOS SDKs, watchOS SDKs, iOS SDKs, macOS SDK形式OS组件。...
  • Android Studio 2.0出炉

    2016-04-08 11:45:58
    Android Studio 2.0是打造高品质,高性能Android应用程序开发平台,包括手机和平板电脑,Android Auto,Android Wear和Android TV等。Android Studio包括代码编辑器,代码分析工具,模拟器和更多东西。Android ...
  • 这是一款优秀的应用开发工具,Xcode 12 mac版包含Xcode IDE、Swift和C / C ++ / Objective-C编译器、性能分析工具、模拟器等专业的功能,你可以轻松进行编码、测试和调试工作,有需要Xcode 12 mac版的朋友可以来试试...
  • Android开发常用命令行

    2016-02-29 17:02:43
    android 1.列出当前可用SDK版本: android list target2.列出当前存在avd:android list ...创建avd -n后面带模拟器名字 -t后面带 target id -b后面带ABI(Valid ABIs: android-tv/armeabi-v7a, android-tv/x86,
  • Xcode 10新内容

    千次阅读 2018-06-09 09:21:57
    Xcode是开发者为Apple TV, Apple Watch, iPad, iPhone, 和Mac开发应用完整工具箱。Xcode开发环境捆绑了分析工具(analysis tool),模拟器(Simulator)和tvOS SDKs, watchOS SDKs, iOS SDKs, macOS SDK形式OS组件。...
  • 我发现lakka支持游戏平台特别多,包括国产OrangePI,真是太棒了。我们可以用这个来打造一个全功能模拟器平台。...写这边文章时候最新版本是v2.1 稳定,除了利用win32diskimage写入TF卡外,官方也提...
  • 借助 AVD,您可以定义要在 Android 模拟器中模拟 Android 手机、Wear OS 手表或 Android TV 设备特性。 如果您使用 Android Studio,就无需使用此工具,而是可以从 IDE 中创建和管理 AVD。 avdmanager工具在 ...
  • 对于开发者来说两个最关键的点值得关注:一个是Beta版的开发工具,一个是开源网站。 一、开源网站 在开发者大会上宣布将HarmonyOS源代码捐赠给中国开放原子开源基金会,并在大会上公布了鸿蒙系统的开源路线。 官网...
  • 新版Android开发教程.rar

    千次下载 热门讨论 2010-12-14 15:49:11
    � 基于 QEMU 开发的模拟器调试手段不十分丰富,只支持通话、SMS等,速度慢。 � 暂不具备 Push Mail 和 Office(DataViz 、 QuickOffice 计划近期推出 ) 功能,目前主要面向的是普通消费 者 用户,对商业用户支持...
  • 这是在创建模拟器时需要system image,也就是在创建模拟器时CPU/ABI项需要选择,下载并解压后,将解压出整个文件夹复制或者移动到your sdk 路径/system-images文件夹下即可, 如果没有system-images目录就先...
  • Java局域网通信——飞鸽传书源代码 28个目标文件 内容索引:JAVA源码,媒体网络,飞鸽传书 Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
     Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...

空空如也

空空如也

1 2
收藏数 23
精华内容 9
关键字:

tv版的模拟器