1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import mediaQuery from '@ohos.mediaquery' 17import mediaLibrary from '@ohos.multimedia.mediaLibrary' 18import GameRules from "../model/GameRules" 19import ImageModel from "../model/ImageModel" 20import ImagePicker from '../common/ImagePicker' 21import Logger from '../model/Logger' 22import PictureItem from '../model/PictureItem' 23 24enum gameStatus { 25 running = 1, 26 over = 0 27} 28 29const PERMISSIONS: Array<string> = ['ohos.permission.READ_MEDIA', 'ohos.permission.WRITE_MEDIA','ohos.permission.MEDIA_LOCATION'] 30const IMAGE_SIZE: number = px2vp(640) 31const GAME_TIME: number = 300 // 游戏时长 32const TAG: string = 'Index' 33 34@Entry 35@Component 36struct Index { 37 private listener = mediaQuery.matchMediaSync('screen and (min-aspect-ratio: 1.5) or (orientation: landscape)') 38 private ImageModel: ImageModel = new ImageModel(getContext(this)) 39 private game: GameRules = new GameRules() 40 private timer: number = -1 41 private isRefresh: boolean = false 42 @State numArray: PictureItem[] = [] 43 @State imgDatas: Array<mediaLibrary.FileAsset> = [] 44 @State @Watch("onTimeOver") gameTime: number = GAME_TIME 45 @State @Watch("onImageChange") index: number = 0 46 @State isLand: boolean = false 47 onLand = (mediaQueryResult) => { 48 console.info(`[eTSMediaQuery.Index]onLand: mediaQueryResult.matches=${mediaQueryResult.matches}`) 49 this.isLand = mediaQueryResult.matches 50 } 51 52 async aboutToAppear() { 53 this.listener.on('change', this.onLand) 54 let context = getContext(this) as any 55 await context.requestPermissionsFromUser(PERMISSIONS) 56 this.imgDatas = await this.ImageModel.getAllImg() 57 Logger.info(TAG, `images = ${this.imgDatas.length}`) 58 this.numArray = await this.ImageModel.splitPic(this.index) 59 } 60 61 onTimeOver() { 62 if (this.gameTime == 0) { 63 this.game.gameStatus = 0 64 AlertDialog.show({ message: 'TimeOver' }) 65 clearInterval(this.timer) 66 } 67 } 68 69 async onImageChange() { 70 this.isRefresh = true 71 this.dialogController.close() 72 this.numArray = await this.ImageModel.splitPic(this.index) 73 this.init() 74 this.isRefresh = false 75 } 76 77 init() { 78 this.gameTime = GAME_TIME 79 this.game.gameStatus = 0 80 clearInterval(this.timer) 81 } 82 83 gameOver() { 84 let count = 0 85 for (let i = 0;i < 7; i++) { 86 if (this.numArray[i].index == i) { 87 count++ 88 } else { 89 count = 0 90 break 91 } 92 if (count == 7) { 93 AlertDialog.show({ message: $r('app.string.congratulations') }) 94 this.game.gameStatus = gameStatus.over 95 clearInterval(this.timer) 96 this.gameTime = GAME_TIME 97 } 98 } 99 } 100 101 start() { 102 this.init() 103 this.timer = setInterval(() => { 104 this.gameTime-- 105 }, 1000) 106 } 107 108 dialogController: CustomDialogController = new CustomDialogController({ 109 builder: ImagePicker({ 110 imageDatas: this.imgDatas, 111 index: $index 112 }), 113 autoCancel: true, 114 gridCount: 12 115 }) 116 117 @Builder 118 ImageShow() { 119 Image(this.imgDatas[this.index].uri) 120 .width(IMAGE_SIZE) 121 .height(290) 122 .objectFit(ImageFit.Fill) 123 .onClick(async () => { 124 if (this.isRefresh) { 125 return 126 } 127 this.imgDatas = await this.ImageModel.getAllImg() 128 setTimeout(() => { 129 this.dialogController.open() 130 }, 200) 131 }) 132 } 133 134 @Builder 135 ImageGrid(leftMargin: number, topMargin: number) { 136 Grid() { 137 ForEach(this.numArray, (item, index) => { 138 GridItem() { 139 Image(item.pixelMap) 140 .width('99%') 141 .objectFit(ImageFit.Fill) 142 .height(vp2px(65)) 143 } 144 .backgroundColor(item.pixelMap === undefined ? "#f5f5f5" : "#ffdead") 145 .onClick(() => { 146 if (this.isRefresh) { 147 return 148 } 149 if (this.game.gameStatus === gameStatus.running) { 150 this.isRefresh = true 151 this.numArray = this.game.gameInit(index, this.numArray) 152 this.gameOver() 153 this.isRefresh = false 154 } 155 }) 156 }) 157 } 158 .columnsTemplate('1fr 1fr 1fr') 159 .columnsGap(2) 160 .rowsGap(2) 161 .width(IMAGE_SIZE) 162 .height(290) 163 .margin({ left: leftMargin, top: topMargin }) 164 } 165 166 build() { 167 Column() { 168 Row() { 169 Text(`Time:0${Math.floor(this.gameTime / 60)}:${this.gameTime % 60 < 10 ? '0' + this.gameTime % 60 : this.gameTime % 60}`) 170 .margin({ top: 5, bottom: 5 }) 171 } 172 173 if (this.imgDatas.length > 0) { 174 if (this.isLand) { 175 Row() { 176 this.ImageShow() 177 this.ImageGrid(10, 0) 178 } 179 .margin({ top: 5 }) 180 } else { 181 Column() { 182 this.ImageShow() 183 this.ImageGrid(0, 5) 184 } 185 .margin({ top: 5 }) 186 } 187 } 188 Button($r('app.string.start'), { type: ButtonType.Capsule, stateEffect: true }) 189 .height(50) 190 .width('100%') 191 .fontSize(18) 192 .margin({ top: 5 }) 193 .backgroundColor(this.game.gameStatus === gameStatus.over ? '#0D9FFB' : '#E5E5E5') 194 .enabled(this.game.gameStatus === gameStatus.over) 195 .onClick(() => { 196 this.start() 197 this.numArray = this.game.gameBegin(this.numArray) 198 }) 199 200 Button($r('app.string.restart'), { type: ButtonType.Capsule, stateEffect: true }) 201 .height(50) 202 .width('100%') 203 .fontSize(18) 204 .margin({ top: 5 }) 205 .backgroundColor(this.game.gameStatus === gameStatus.running ? '#0D9FFB' : '#E5E5E5') 206 .enabled(this.game.gameStatus === gameStatus.running) 207 .onClick(() => { 208 this.start() 209 this.numArray = this.game.gameBegin(this.numArray) 210 }) 211 } 212 .width('100%') 213 .height('100%') 214 .padding({ left: '1%', right: '1%' }) 215 } 216}