|
|
@@ -18,8 +18,16 @@
|
|
|
<script lang="ts" setup>
|
|
|
import { MiniRender } from '@/components/canvas/MiniRender';
|
|
|
import { UniWeappRender } from '@/components/canvas/UniWeappRender';
|
|
|
+import { RandomUtils } from '@imengyu/imengyu-utils';
|
|
|
import { getCurrentInstance, onBeforeUnmount, onMounted } from 'vue';
|
|
|
|
|
|
+let currentText : MiniRender.Text | null = null;
|
|
|
+const todoTreeText = '现在没有树的动画,树是静态的。';
|
|
|
+
|
|
|
+const emit = defineEmits<{
|
|
|
+ (e: 'fruitPick'): void;
|
|
|
+}>();
|
|
|
+
|
|
|
const HEIGHT = 260;
|
|
|
const instance = getCurrentInstance();
|
|
|
const systemInfo = uni.getWindowInfo();
|
|
|
@@ -38,79 +46,118 @@ const render = new MiniRender.Scene(
|
|
|
bg.width = systemInfo.windowWidth;
|
|
|
bg.height = HEIGHT;
|
|
|
|
|
|
-
|
|
|
- const text = new MiniRender.Text('动画问题解决啦,就等设计师出图了!', {
|
|
|
+ const text = new MiniRender.Text(todoTreeText, {
|
|
|
fontSize: 20,
|
|
|
color: '#000',
|
|
|
align: 'left',
|
|
|
wrap: 'wrap',
|
|
|
- maxWidth: 200,
|
|
|
+ maxWidth: 300,
|
|
|
});
|
|
|
text.x = 70;
|
|
|
text.y = 50;
|
|
|
+ currentText = text;
|
|
|
|
|
|
- const robot = new MiniRender.AnimateSprite({
|
|
|
- framerate: 7,
|
|
|
- images: ['https://docs.imengyu.top/assets/character_robot_sheet.png'],
|
|
|
- frames: [
|
|
|
- // 来自 character_robot_sheet.xml(96x128)
|
|
|
- // walk0..walk7
|
|
|
- [0, 512, 96, 128],
|
|
|
- [96, 512, 96, 128],
|
|
|
- [192, 512, 96, 128],
|
|
|
- [288, 512, 96, 128],
|
|
|
- [384, 512, 96, 128],
|
|
|
- [480, 512, 96, 128],
|
|
|
- [576, 512, 96, 128],
|
|
|
- [672, 512, 96, 128],
|
|
|
- // run0..run2
|
|
|
- [576, 256, 96, 128],
|
|
|
- [672, 256, 96, 128],
|
|
|
- [768, 256, 96, 128],
|
|
|
- // attack0..attack2
|
|
|
- [0, 384, 96, 128],
|
|
|
- [96, 384, 96, 128],
|
|
|
- [192, 384, 96, 128],
|
|
|
- ],
|
|
|
- animations: {
|
|
|
- walk: { frames: [0, 1, 2, 3, 4, 5, 6, 7] },
|
|
|
- run: { frames: [8, 9, 10] },
|
|
|
- attack: { frames: [11, 12, 13], loop: false },
|
|
|
- },
|
|
|
- playOnce: false,
|
|
|
- currentAnimation: 'walk',
|
|
|
- });
|
|
|
- robot.x = 30;
|
|
|
- robot.y = 105;
|
|
|
- robot.play();
|
|
|
-
|
|
|
- const flag = new MiniRender.Sprite();
|
|
|
- flag.src = 'https://xy.wenlvti.net/app_static/images/village/TreeTestFlag.png';
|
|
|
- flag.x = 125;
|
|
|
- flag.y = 144;
|
|
|
- flag.width = 80;
|
|
|
- flag.height = 100;
|
|
|
- flag.interactive = true;
|
|
|
- flag.on('click', () => {
|
|
|
- uni.showToast({
|
|
|
- title: 'flag clicked',
|
|
|
- icon: 'success',
|
|
|
- });
|
|
|
- });
|
|
|
+ const treeMain = new MiniRender.Sprite();
|
|
|
+ treeMain.src = 'https://xy.wenlvti.net/app_static/images/home/tree/Level4.png';
|
|
|
+ treeMain.x = 135;
|
|
|
+ treeMain.y = 55;
|
|
|
+ treeMain.width = 180;
|
|
|
+ treeMain.height = 200;
|
|
|
+ treeMain.interactive = true;
|
|
|
|
|
|
render.root
|
|
|
.add(bg)
|
|
|
.add(text)
|
|
|
- .add(flag)
|
|
|
- .add(robot);
|
|
|
+ .add(treeMain)
|
|
|
},
|
|
|
(dtMs: number) => {
|
|
|
|
|
|
}
|
|
|
);
|
|
|
|
|
|
+function createFruit() {
|
|
|
+ const fruit = new MiniRender.AnimateSprite({
|
|
|
+ framerate: 7,
|
|
|
+ images: ['https://xy.wenlvti.net/app_static/images/home/tree/AnimFruit.png'],
|
|
|
+ frames: [
|
|
|
+ [0, 0, 30, 30],
|
|
|
+ [30, 0, 30, 30],
|
|
|
+ [60, 0, 30, 30],
|
|
|
+ [90, 0, 30, 30],
|
|
|
+ [120, 0, 30, 30],
|
|
|
+ [150, 0, 30, 30],
|
|
|
+ ],
|
|
|
+ animations: {
|
|
|
+ default: { frames: [0, 1, 2, 3, 4, 5] },
|
|
|
+ },
|
|
|
+ playOnce: false,
|
|
|
+ currentAnimation: 'walk',
|
|
|
+ });
|
|
|
+ fruit.play();
|
|
|
+ fruit.x = RandomUtils.genRandom(120, 260);
|
|
|
+ fruit.y = RandomUtils.genRandom(90, 120);
|
|
|
+ fruit.width = 30;
|
|
|
+ fruit.height = 30;
|
|
|
+ fruit.interactive = true;
|
|
|
+ fruit.data = {
|
|
|
+ type: 'fruit',
|
|
|
+ };
|
|
|
+ fruit.on('click', () => {
|
|
|
+ emit('fruitPick');
|
|
|
+ });
|
|
|
+ render.root.add(fruit);
|
|
|
+}
|
|
|
+
|
|
|
+function createFruits(count: number) {
|
|
|
+ //创建或者删除水果,使得数量等于count
|
|
|
+ const fruitNodes = render.root.children.filter((child) => child.data?.type === 'fruit');
|
|
|
+ const fruits = fruitNodes.length;
|
|
|
+ if (fruits === count) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (fruits > count) {
|
|
|
+ fruitNodes.slice(0, fruits - count).forEach((fruit) => {
|
|
|
+ render.root.remove(fruit);
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (let i = 0; i < count - fruits; i++) {
|
|
|
+ createFruit();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function removeAllFruit() {
|
|
|
+ const fruits = render.root.children.filter(child => child.data?.type === 'fruit');
|
|
|
+ fruits.forEach(fruit => {
|
|
|
+ render.root.remove(fruit);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
function playStateAnimation(state: 'collect' | 'water' | 'fertilize' | 'task' | 'bless' | 'exchange') {
|
|
|
//TODO: 播放动画
|
|
|
+ if (currentText) {
|
|
|
+ switch (state) {
|
|
|
+ case 'collect':
|
|
|
+ currentText.text = '拾果状态' + todoTreeText;
|
|
|
+ removeAllFruit();
|
|
|
+ break;
|
|
|
+ case 'water':
|
|
|
+ currentText.text = '浇水状态' + todoTreeText;
|
|
|
+ break;
|
|
|
+ case 'fertilize':
|
|
|
+ currentText.text = '施肥状态' + todoTreeText;
|
|
|
+ break;
|
|
|
+ case 'task':
|
|
|
+ currentText.text = '任务状态' + todoTreeText;
|
|
|
+ break;
|
|
|
+ case 'bless':
|
|
|
+ currentText.text = '赐福状态' + todoTreeText;
|
|
|
+ break;
|
|
|
+ case 'exchange':
|
|
|
+ currentText.text = '兑换状态' + todoTreeText;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
defineExpose({
|
|
|
@@ -118,6 +165,7 @@ defineExpose({
|
|
|
render.root.removeAll();
|
|
|
render.init();
|
|
|
},
|
|
|
+ createFruits,
|
|
|
playStateAnimation,
|
|
|
});
|
|
|
|