|
|
@@ -0,0 +1,204 @@
|
|
|
+import { observationalModel } from "../model/AnimationModel";
|
|
|
+
|
|
|
+@ComponentV2
|
|
|
+export struct observationalComp {
|
|
|
+ // 训练开始与否
|
|
|
+ @Param trainStarted: number = 0
|
|
|
+ @Event gameOver: () => void
|
|
|
+
|
|
|
+
|
|
|
+ @Local iconArray: Array<observationalModel> = []
|
|
|
+
|
|
|
+ // 匹配对数
|
|
|
+ @Local matchCount: number = 0
|
|
|
+ // 尝试次数
|
|
|
+ @Local tryCount: number = 0
|
|
|
+ // 是否可以翻转
|
|
|
+ @Local canFlip: boolean = false
|
|
|
+
|
|
|
+ // 点击的 icon
|
|
|
+ clickIcon: Array<number> = []
|
|
|
+
|
|
|
+ timer: number = -1
|
|
|
+
|
|
|
+ lastTime: number = 0
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 随机打乱iconArray数组中的元素顺序 - 开始游戏
|
|
|
+ */
|
|
|
+ shuffleIconArray(): void {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.flipAll(false)
|
|
|
+
|
|
|
+ const array = this.iconArray;
|
|
|
+ for (let i = array.length - 1; i > 0; i--) {
|
|
|
+ const j = Math.floor(Math.random() * (i + 1));
|
|
|
+ let temp = array[i]
|
|
|
+ array[i] = array[j]
|
|
|
+ array[j] = temp
|
|
|
+ }
|
|
|
+
|
|
|
+ if(this.timer != -1) clearTimeout(this.timer)
|
|
|
+ this.timer = setTimeout(() => {
|
|
|
+ this.flipAll(true)
|
|
|
+ this.timer = -1
|
|
|
+ this.canFlip = true
|
|
|
+ }, 2000)
|
|
|
+ }, 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 翻牌 - 翻开 - 单张
|
|
|
+ flipCard(i: observationalModel, index: number): void {
|
|
|
+ let now = Date.now()
|
|
|
+ if(now - this.lastTime < 200) return
|
|
|
+ this.lastTime = now
|
|
|
+
|
|
|
+ if(!this.canFlip || !i.flip || this.trainStarted != 1) return
|
|
|
+ this.getUIContext().animateTo({duration: 500}, () => {
|
|
|
+ i.flip = false
|
|
|
+ })
|
|
|
+
|
|
|
+ this.clickIcon.push(index)
|
|
|
+ if(this.clickIcon.length == 2){
|
|
|
+ this.tryCount += 1
|
|
|
+ if(this.iconArray[this.clickIcon[0]].type == this.iconArray[this.clickIcon[1]].type) {
|
|
|
+ this.matchCount += 1
|
|
|
+ if(this.matchCount == 4) {
|
|
|
+ this.gameOver()
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.canFlip = false
|
|
|
+ let i1 = this.clickIcon[0]
|
|
|
+ let i2 = this.clickIcon[1]
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getUIContext().animateTo({duration: 500}, () => {
|
|
|
+ this.iconArray[i1].flip = true
|
|
|
+ this.iconArray[i2].flip = true
|
|
|
+ this.canFlip = true
|
|
|
+ })
|
|
|
+ }, 500)
|
|
|
+ }
|
|
|
+ this.clickIcon = []
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 翻牌 - 所有的牌
|
|
|
+ flipAll(flip: boolean = false) {
|
|
|
+ this.getUIContext().animateTo({duration: 500}, () => {
|
|
|
+ this.iconArray.forEach(item => {
|
|
|
+ item.flip = flip
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ @Monitor('trainStarted')
|
|
|
+ trainStartedChange(){
|
|
|
+ if(this.trainStarted == 1) {
|
|
|
+ this.canFlip = false
|
|
|
+ this.matchCount = 0
|
|
|
+ this.tryCount = 0
|
|
|
+ this.shuffleIconArray()
|
|
|
+ } else if(this.trainStarted == 0) {
|
|
|
+ if(this.timer != -1) {
|
|
|
+ clearTimeout(this.timer)
|
|
|
+ this.timer = -1
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.flipAll(false)
|
|
|
+ }, 0)
|
|
|
+ this.matchCount = 0
|
|
|
+ this.tryCount = 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ aboutToAppear(): void {
|
|
|
+ new Array(8).fill('').forEach((_: string, index) => {
|
|
|
+ // 需确保 文件名 没有被更改 icon_observational_%{num}
|
|
|
+ let tag = (index+1)%5 || 4
|
|
|
+ this.iconArray.push(new observationalModel($r(`app.media.icon_observational_${tag}`), false, tag))
|
|
|
+ })
|
|
|
+
|
|
|
+ console.log(`this.iconArray = ${JSON.stringify(this.iconArray)}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ build() {
|
|
|
+ Column() {
|
|
|
+ Grid(){
|
|
|
+ Repeat(this.iconArray)
|
|
|
+ .each(item => {
|
|
|
+ GridItem(){
|
|
|
+ Stack(){
|
|
|
+ Row(){
|
|
|
+ Text(`装备${item.index+1}`)
|
|
|
+ .fontSize(14)
|
|
|
+ .fontWeight(400)
|
|
|
+ .fontColor('#FFA4A4A4')
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .aspectRatio(1)
|
|
|
+ .borderRadius(5)
|
|
|
+ .backgroundColor('#FF555555')
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ .alignItems(VerticalAlign.Center)
|
|
|
+ .zIndex(item.item.flip ? 1 : -1)
|
|
|
+
|
|
|
+ Row(){
|
|
|
+ Image(item.item.src)
|
|
|
+ .width("60%")
|
|
|
+ .aspectRatio(1)
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .aspectRatio(1)
|
|
|
+ .borderRadius(5)
|
|
|
+ .backgroundColor('#FF555555')
|
|
|
+ .alignItems(VerticalAlign.Center)
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .aspectRatio(1)
|
|
|
+ .rotate({ y: 2, angle: item.item.flip ? 0 : 180, perspective: 200 }) // 设置组件旋转轴向量坐标和旋转角度
|
|
|
+ .onClick(() => { this.flipCard(item.item, item.index) })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .key(item => item.id.toString())
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .rowsGap(25)
|
|
|
+ .columnsGap(20)
|
|
|
+ .layoutWeight(1)
|
|
|
+ .columnsTemplate('repeat(3, 1fr)')
|
|
|
+
|
|
|
+ Row({space: 73}){
|
|
|
+ ForEach(['匹配对数', '尝试次数'], (item: string, index) => {
|
|
|
+ Column({space: 13}){
|
|
|
+ Text(item)
|
|
|
+ .fontSize(14)
|
|
|
+ .fontWeight(400)
|
|
|
+ .fontColor('#FFFFFFFF')
|
|
|
+
|
|
|
+ Text() {
|
|
|
+ if(index == 0) {
|
|
|
+ Span(`${this.matchCount}/4`)
|
|
|
+ } else {
|
|
|
+ Span(this.tryCount.toString())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .fontSize(14)
|
|
|
+ .fontWeight(400)
|
|
|
+ .fontColor('#FFFFFFFF')
|
|
|
+ }
|
|
|
+ .alignItems(HorizontalAlign.Center)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
+ }
|
|
|
+ .width("100%")
|
|
|
+ .height("100%")
|
|
|
+ .borderRadius(10)
|
|
|
+ .backgroundColor('#454545')
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
+ .padding({top: 23, left: 18, right: 18, bottom: 30})
|
|
|
+ }
|
|
|
+}
|