【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(7) 原创 精华

木棉花_小蓝
发布于 2022-10-16 22:08
浏览
4收藏

前言

   上期内容中,我们成功实现游戏处于关卡选择页面时进入不同关卡页面跳转逻辑。在本期的内容中,我们会为此游戏添加计时功能,同时接入数据库保存通关记录。完成这些后,数独游戏项目便也竣工了。


正文

创建退出按钮与秒表


首先,我们需要在项目内导入图片:打开:entry\src\main\resources\base\media,将如

下图片放置在media目录下(可以以复制粘贴的方式放置):


【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(7)-鸿蒙开发者社区


放置完成后,我们打开GameAbilitySlice,并在onstart()函数的合适位置放置如下代码:

        //退出的弹窗
        CommonDialog Dialog_exit=new CommonDialog(getContext());
        Dialog_exit.setSize(800,400);
        Dialog_exit.setTitleText("  提示");
        Dialog_exit.setContentText("          游戏未完成,确认退出?");
        Dialog_exit.setButton(IDialog.BUTTON1,"确定",(iDialog, i) ->Dialog_exit.destroy() );
        Dialog_exit.setButton(IDialog.BUTTON2,"取消",(iDialog, i) ->Dialog_exit.hide() );
        Dialog_exit.setDestroyedListener(new CommonDialog.DestroyedListener() {
            @Override
            public void onDestroy() {  //组件销毁监听器
                terminate();  //当弹窗被销毁后,GameAbilitySlice也会被销毁,以实现页面退出的功能
            }
        });

//创建Image对象,并设置点击监听器
        Image exit=new Image(this);
        exit.setPixelMap(ResourceTable.Media_exit);
        exit.setScaleMode(Image.ScaleMode.CLIP_CENTER);
        exit.setComponentSize(130,130);
        exit.setPosition(50,25);
        exit.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                    Dialog_exit.show();  //点击Image组件后,Dialog_exit会弹出
            }
        });
        layout1.addComponent(exit);

这里我们是先创建Dialog对象,再创建Image对象的,原因是:只有Dialog对象先生成,Image的点击监听器内才能调用已创建的Dialog对象的方法


此时我们打开模拟机并随机进入一个关卡,可以看到,页面的左上角多了一个可点击图标:


【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(7)-鸿蒙开发者社区

图标被点击后,系统会弹出一个提示弹窗:

【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(7)-鸿蒙开发者社区


计时器

成功加入退出的功能后,接下来要做的就是在游戏界面加入一个计时器。

首先,我们在合适的位置编写一个run()函数:

  import ......


public class GameAbilitySlice extends AbilitySlice {

  ......

//同步计时器,用于输出时间
    private  Timer timer;
    int sec,min;
    public void running(){
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                getUITaskDispatcher().asyncDispatch(()->{
                    sec++;
                    if (sec >= 60) {
                        min++;
                        sec = sec % 60;
                        if (min >= 60) {
                            min = min % 60;
                        }
                    }
                });
            }
        },0,1000);
    }
  
  ......
    
      @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        ......
    
    

加入计时器的功能:

      @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        
        ......

       //计时器
        Text time=new Text(this);
        time.setText("用时:");
        time.setTextSize(75);
        time.setTextColor(Color.RED);
        time.setPosition(260+360,40);
        layout1.addComponent(time);


        TickTimer ticktimer=new TickTimer(this);
        ticktimer.start();
        running();
        ticktimer.setTextSize(75);
        ticktimer.setTextColor(Color.BLACK);
        ticktimer.setPosition(465+360,40);
        layout1.addComponent(ticktimer);

数据库

首先实现页面设计。

在graphic目录下,创建一个背景元素文件,并命名为background_ability_record.xml,之后加入如下代码:

<?xml version="1.0" encoding="UTF-8" ?>
<shape
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:shape="rectangle">

    <solid
        ohos:color="#FFFFFF"/>
</shape>

在layout目录下,创建一个xml文件,并命名为background_ability.xml,之后加入如下代码:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:alignment="center"
    ohos:orientation="vertical">


    <Text
        ohos:id="$+id:text_record1"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_record"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="30vp"
        ohos:margin="10vp"
        />


    <Text
        ohos:id="$+id:text_record2"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_record"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="30vp"
        ohos:margin="10vp"
        />

    <Text
        ohos:id="$+id:text_record3"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$graphic:background_ability_record"
        ohos:layout_alignment="horizontal_center"
        ohos:text_size="30vp"
        ohos:margin="10vp"
        />

    <Text
        ohos:background_element="$graphic:select_text_exit"
        ohos:id="$+id:back_of_record"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:text="返回"
        ohos:top_margin="90vp"
        ohos:text_alignment="horizontal_center"
        ohos:text_size="30vp"
        ohos:text_font="sans-serif"/>

</DirectionalLayout>

打开RecordAbilitySlice,制作基本的AbilitySlice框架:

import ...

public class RecordAbilitySlice extends AbilitySlice {        //继承

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_record); //与xmi文件绑定

    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }




    }

然后,在合适的位置定义一个数据库:

public class RecondAbilitySlice extends AbilitySlice {  

    private Context context; //

    //定义数据库
    private Preferences center(){
        DatabaseHelper databaseHelper=new DatabaseHelper(this);
        Preferences  preferences=databaseHelper.getPreferences("DBM");
        return preferences;

    }

    @Override
    public void onStart(Intent intent) {
        ......

接着,设计UI界面:

     ......

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_record); //与xmi文件绑定    

        Preferences preferences=center();

        int Min1=preferences.getInt("MIN_1",999);
        int Sec1=preferences.getInt("SEC_1",999);

        int Min2=preferences.getInt("MIN_2",999);
        int Sec2=preferences.getInt("SEC_2",999);

        int Min3=preferences.getInt("MIN_3",999);
        int Sec3=preferences.getInt("SEC_3",999);


            Text text1 = (Text) findComponentById(ResourceTable.Id_text_record1);
            if (Min1==999){
                text1.setText("初级" + "    " + "无记录");
            }else {
                text1.setText("初级" + "    " + String.valueOf(Min1) + "分" + String.valueOf(Sec1) + "秒");
            }


            Text text2 = (Text) findComponentById(ResourceTable.Id_text_record2);
            if (Min2==999){
                text2.setText("中级" + "    " + "无记录");
            }else {
                text2.setText("中级" + "    " + String.valueOf(Min2) + "分" + String.valueOf(Sec2) + "秒");
            }

            Text text3 = (Text) findComponentById(ResourceTable.Id_text_record3);
            if (Min3==999){
                text3.setText("高级" + "    " + "无记录");
            }else {
                text3.setText("高级" + "    " + String.valueOf(Min3) + "分" + String.valueOf(Sec3) + "秒");
            }

            Text text4=(Text) findComponentById(ResourceTable.Id_back_of_record);
            text4.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    terminate();
                }
            });
         
         
     }

    ......

最后打开MainAbilitySlice,实现“游戏记录”按钮的页面导航的逻辑:

 @Override
    public void onActive() {
        super.onActive();

        ......

        Button button2=(Button)findComponentById(ResourceTable.Id_record);
        button2.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                present(new RecordAbilitySlice(),new Intent());
            }
        });

    }


打开模拟器,在主界面点击“游戏记录”,可查看UI效果:

【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(7)-鸿蒙开发者社区



打开GameAbilitySlice,先定义一些对象:

public class GameAbilitySlice extends AbilitySlice {

  ......
    
   private Context context;//
   private DatabaseHelper databaseHelper;//
   private Preferences preferences;//
  
  ....
    
   
    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
    ......

之后,创建一个轻量级数据库:

       ......

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);

        //数据库
        context=getContext();
        databaseHelper=new DatabaseHelper(context);
        preferences=databaseHelper.getPreferences("DBM");
           
           ......

制作一个返回布尔值的比较函数compare():

    int Min_record;
    int Sec_record;
    private int strsec;
    private int strmin;
    private String timing;

    //比较函数
    private boolean compare(){

        int nowtime=strmin+strsec*60;
        int mintime= Min_record +Sec_record*60;

        if(nowtime<mintime){
            return true;
        }

        return false;
    }

找到button_pr,完成记录时间的逻辑:

        Button button_pr=new Button(this);
        ......
        button_pr.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {

  
                if (Gamesuccess()){
                    ticktimer.stop();    //让计时器停止
                    timing=ticktimer.getText();//获得通关时间
                    strsec=sec;
                    strmin=min;
                    Dialog_win.setContentText("                      用时:"+timing);//让通过时间在弹窗中显示

                    Dialog_win.show();

                }else {
                    ticktimer.stop();  //让计时器停止

                    Dialog_fail.setContentText("           游戏未完成或答案不正确" );
                    Dialog_fail.show();
                }

            }
        });
     ......

找到对话框,加入指令:

 //对话框
        CommonDialog Dialog_win=new CommonDialog(getContext());
        Dialog_win.setSize(800,400);
        Dialog_win.setTitleText(" 游戏解答成功!");
        Dialog_win.setButton(IDialog.BUTTON1,"返回主菜单",(iDialog, i) -> Dialog_win.destroy());
        Dialog_win.setDestroyedListener(new CommonDialog.DestroyedListener() {
            @Override
            public void onDestroy() {
//销毁监听器内加入指令
                if(L==1){
                    Min_record=preferences.getInt("MIN_1",60);
                    Sec_record=preferences.getInt("SEC_1",60);

                    if (compare()) {
                        preferences.putInt("MIN_1", strmin);
                        preferences.putInt("SEC_1",strsec);
                        preferences.flush();//清除缓冲区的缓存

                    }
                }
                if(L==2||L==3){
                    Min_record=preferences.getInt("MIN_2",60);
                    Sec_record=preferences.getInt("SEC_2",60);
                    if (compare()) {
                        preferences.putInt("MIN_2", strmin);
                        preferences.putInt("SEC_2",strsec);
                        preferences.flush();  //清除缓冲区的缓存


                    }
                }
                if(L==4){
                    Min_record=preferences.getInt("MIN_3",60);
                    Sec_record=preferences.getInt("SEC_3",60);
                    if (compare()) {

                        preferences.putInt("MIN_3", strmin);
                        preferences.putInt("SEC_3",strsec);
                        preferences.flush();
                        
                    }
                }

                terminate();
            }
        });

完成上述操作后,打开模拟器试玩游戏:


【木棉花】#打卡不停更#HarmonyOS小游戏项目——数独Sudoku(7)-鸿蒙开发者社区


结语

恭喜你,你已经成功在IDE制作了一个小游戏项目。


©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
标签
已于2022-10-17 10:15:53修改
3
收藏 4
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

完结撒花,感谢楼主一路的讲解。

回复
2022-10-17 10:30:05
回复
    相关推荐