微信小游戏 彩色试管 倒水游戏 逻辑

 最近开始研究微信小游戏,有兴趣的 可以关注一下 公众号, 记录一些心路历程和源代码。

定义一个 Cup类:
主要功能
  1. 初始化水杯:根据传入的颜色信息初始化水杯中的水层。
  2. 倒水:模拟水杯倾斜并倒出水的过程。
  3. 加水:模拟向水杯中加水的过程。
  4. 颜色管理:管理水杯中不同颜色的水层。
  5. 交互:处理水杯的点击事件,触发倒水或加水的操作。
    import { Component, _decorator,Node, UITransform, Color, Tween, Vec2, tween, v3, v2, Vec3, Widget, Layers } from "cc";
    import { AudioEnum, AudioUtil } from "../utils/audio_util";
    import Water, { WaterInfo } from "./water";
    import { WaterFlow } from "./waterFlow";
    import { EDITOR } from "cc/env";const { ccclass, property } = _decorator;export let WaterColors = ["#155DEF","#F2C90F","#004616","#E4584F","#00B38A","#DD2E44","#E5C69A","#65DC8E","#B068F0","#F010BF","#538849",
    ]//*高度乘数因子,满杯水只显示80% */
    const HEIGHT_FACTOR = 0.8;//一杯水,分成四组四个颜色,0表示没有水 */
    export interface _CupInfo{colorIds:Array<number>;//长度为4
    }const SPLIT_COUNT = 4;@ccclass
    export default class Cup extends Component {@property(Water)private water:Water = null;private _flow:WaterFlow = null;public getFlow():WaterFlow{if(this._flow){return this._flow;}let _node = new Node("water_flow");_node.layer = Layers.Enum.UI_2D_node.addComponent(UITransform)this._flow = _node.addComponent(WaterFlow);return this._flow;}private onClick:(c:Cup)=>void = null;onBtn_click(){if(this.isPouring()){return;}if(this.onClick){this.onClick(this);}}public isPouring(){return Math.abs(this.node.angle)>1.0;}//每个试管 初始化 4层颜色initWater(){const info = this.info;let arr = [];for(let i=SPLIT_COUNT-1;i>=0;i--){let colorId = info.colorIds[i];if(colorId==0){continue;}let lastObj = arr[arr.length-1];if(!lastObj||lastObj!=colorId){arr.push({height:1/SPLIT_COUNT,colorId:colorId});}else{lastObj.height += 1/SPLIT_COUNT;}}arr.forEach(function (obj) {let hex = WaterColors[obj.colorId]||"#538849"// log("obj.colorId",obj.colorId,"color",hex)obj.color = new Color().fromHEX(hex);obj.height*=HEIGHT_FACTOR;})this.water.initInfos(arr);}private info:_CupInfo = null;setCupInfo(info:_CupInfo,onClick:(c:Cup)=>void){this.info = info;this.onClick = onClick;this.initWater();this.reset();}update(){if(EDITOR){return;}if(this.water.skewAngle==this.node.angle){return;}this.water.skewAngle = this.node.angle;}private setPourOutCallback(pourStart,pourEnd){//水开始从瓶口流出来const _onStart = function(){if(pourStart){pourStart(this)}}//水倒完了const _onFinish = function(){if(this.tween){this.tween.stop();this.tween = null;}if(pourEnd){pourEnd(this)}}this.water.setPourOutCallback(_onStart.bind(this),_onFinish.bind(this));}private setPourInCallback(onFinish){//水倒完了const _onFinish = function(){let isFinished = this.checkIsFinshed();// log("-----------isFinished",isFinished)if(onFinish){onFinish(this,isFinished)}if(isFinished){AudioUtil.playEffect(AudioEnum.finishOne,0.4)}}this.water.setPourInCallback(_onFinish.bind(this));}/**是否完成了(同颜色填满整个杯子) */checkIsFinshed(){let isFinished = true;let colorIds = this.info.colorIds;let tmpId = null;let empTyNum = 0;for(let i=0;i<SPLIT_COUNT;i++){if(tmpId==null){tmpId = colorIds[i]}if(tmpId!=colorIds[i]){isFinished = false;break;}else if(colorIds[i]==0){empTyNum++;}}if(empTyNum==SPLIT_COUNT){isFinished = true;}return isFinished;}private tween:Tween<Node> = null;moveToPour(dstPt:Vec3,isRight:boolean,onPourStart:(c:Cup)=>void,onPourEnd:(c:Cup)=>void){this.setPourOutCallback(onPourStart,onPourEnd);let startAngle = this.water.getPourStartAngle()let endAngle = this.water.getPourEndAngle()this.water.onStartPour();if(isRight){startAngle*=-1;endAngle*=-1;}let moveDur = 0.5;let pourDur = 0.8;this.tween = tween(this.node).set({angle:0}).to(moveDur,{position:v3(dstPt.x,dstPt.y),angle:startAngle}).to(pourDur,{angle:endAngle}).call(()=>{this.tween = null;}).start();let top = this.getTop();let colorIds = this.info.colorIds;for(let i=0;i<SPLIT_COUNT;i++){let _id = colorIds[i]if(_id==0){continue;}else if(top.topColorId==_id){//顶部相同颜色的水都倒掉了colorIds[i] = 0;}else{break;}}}startAddWater(colorId:number,num:number,onComplete:(cup:Cup,isFInish:boolean)=>void){this.setPourInCallback(onComplete);let acc = 0;for(let i=SPLIT_COUNT-1;i>=0;i--){if(this.info.colorIds[i]!=0){continue;}this.info.colorIds[i] = colorId;if(++acc==num){break;}}let hex = WaterColors[colorId]||"#538849"this.water.addInfo({colorId:colorId,height:num/SPLIT_COUNT *HEIGHT_FACTOR,color:new Color().fromHEX(hex)});AudioUtil.playPourWaterEffect(num/SPLIT_COUNT);}/**加水立刻 */addWaterImmediately(colorId:number,num:number){let acc = 0;for(let i=SPLIT_COUNT-1;i>=0;i--){if(this.info.colorIds[i]!=0){continue;}this.info.colorIds[i] = colorId;if(++acc==num){break;}}this.initWater();}/**将顶部的颜色删除num个 */removeTopWaterImmediately(num:number){let acc = 0;let top = this.getTop();let colorIds = this.info.colorIds;for(let i=0;i<SPLIT_COUNT;i++){let _id = colorIds[i]if(_id==0){continue;}else if(top.topColorId==_id){//顶部相同颜色的水都倒掉了colorIds[i] = 0;if(++acc>=num){break}}else{break;}}this.initWater();return top;}getTop(){let colorIds = this.info.colorIds;let emptyNum = 0;//杯顶的空位有几格let topColorId = 0;//杯顶颜色idlet topColorNum = 0;//杯顶的颜色共有几格for(let i=0;i<SPLIT_COUNT;i++){if(colorIds[i]==0){emptyNum++;continue;}if(topColorId==0||topColorId==colorIds[i]){topColorId = colorIds[i];topColorNum++;}else{break;}}return {emptyNum:emptyNum,topColorId:topColorId,topColorNum:topColorNum,colorHex:WaterColors[topColorId]||"#538849"}}reset(){this.node.angle = 0;this.water.skewAngle = 0}public setPourAnchor(isRight:boolean){let pt = v2(3,2);pt.x = isRight?(this.node.getComponent(UITransform).width-pt.x):pt.x;pt.y = this.node.getComponent(UITransform).height-pt.y;pt.x = pt.x/this.node.getComponent(UITransform).width;pt.y = pt.y/this.node.getComponent(UITransform).height;this.setAnchor(pt) }public setNormalAnchor(){this.setAnchor(v2(0.5,0.5))}private setAnchor(anchor:Vec2){let trans = this.node.getComponent(UITransform)let oldAnchor = trans.anchorPoint.clone()let selfPt = this.node.getPosition();//当前锚点世界坐标trans.setAnchorPoint(anchor);let offsetAnchor = v2(anchor.x-oldAnchor.x,anchor.y-oldAnchor.y)let offsetPt = v2(offsetAnchor.x*trans.width,offsetAnchor.y*trans.height)offsetPt = rotatePt(offsetPt,this.node.angle)selfPt.x += offsetPt.x;selfPt.y += offsetPt.y;this.node.setPosition(selfPt);this.water.getComponent(Widget).updateAlignment()}/**获取当前水面的global y坐标 */getWaterSurfacePosY(needAdjust=false){let top = this.getTop();let y = (SPLIT_COUNT-top.emptyNum)/SPLIT_COUNT;if(y<0.02){y = 0.02}else if(needAdjust){y-=1.0/SPLIT_COUNT*HEIGHT_FACTOR;}y*=HEIGHT_FACTOR;y-=0.5;let pt = v3(0,this.water.node.getComponent(UITransform).height*y);pt = this.water.node.getComponent(UITransform).convertToWorldSpaceAR(pt)return pt.y}
    }//水杯旋转角度控制
    function rotatePt(pt:Vec2,angle:number){let radian = angle2radian(angle);let ret = v2();ret.x = pt.x*Math.cos(radian)-pt.y*Math.sin(radian);ret.y = pt.x*Math.sin(radian)+pt.y*Math.cos(radian);return ret;
    }function angle2radian(angle:number){while(angle>360){angle-=360;}while(angle<-360){angle+=360;}return (angle%360) * Math.PI / 180.0;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/46291.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Prometheus 云原生 - 基于 file_sd、http_sd 实现 Service Discovery

目录 开始 为什么需要服务发现机制 File Service Discovery&#xff08;file_sd&#xff09; 基本概念 配置方式 使用案例 HTTP Service Discovery&#xff08;http_sd&#xff09; 基本概念 配置方式 使用案例 开始 为什么需要服务发现机制 我们知道在 Prometheus …

【链表】算法题(一) ---- 力扣 / 牛客

一、移除链表元素 移除链表中值为val的元素&#xff0c;并返回新的头节点 思路&#xff1a; 题目上这样说&#xff0c;我们就可以创建一个新的链表&#xff0c;将值不为val的节点&#xff0c;尾插到新的链表当中&#xff0c;最后返回新链表的头节点。 typedef struct ListNo…

[安洵杯 2019]easy_web1

知识点&#xff1a; 1.base64加解密 2.md5加解密 3.md5碰撞绕过强类型比较 4.Linux命令绕过 进入页面发现url地址中存在 img参数和一个cmd参数&#xff0c;img参数看上去像是base64编码&#xff0c;可以去尝试一下解码. 进行了两次base64解密得到3535352e706e67看着像16进制那么…

员工聊天记录监控方法大全(五种方法你自己选择)

在现代企业中&#xff0c;为了保障业务安全、防止数据泄露和促进工作效率&#xff0c;很多公司会采用各种方法监控员工的聊天记录。虽然听起来有点“大哥哥在看着你”的感觉&#xff0c;但只要在合法和透明的前提下进行&#xff0c;这其实是为了构建一个更加健康、安全的工作环…

网络流问题-Min-cut

文章目录 1. 网络流问题基础1.1 概述1.2 常规算法1.3 总结 2. Ford-Fulkerson Algorithm2.1 概述2.2 Ford 算法2.3 Ford 算法小结 链接&#xff1a; B站学习视频 1. 网络流问题基础 1.1 概述 最大流问题主要是关于有向图问题。有向图中有m个边&#xff0c; n个节点,其中有一个…

怎么用PPT录制微课?详细步骤解析!

随着信息技术的不断发展&#xff0c;微课作为一种新型的教学形式&#xff0c;因其短小精悍、针对性强等特点&#xff0c;在教育领域得到了广泛的应用。而PPT作为一款常用的演示工具&#xff0c;不仅可以用来制作课件&#xff0c;还可以利用其内置的录屏功能或结合专业的录屏软件…

Dify中的经济索引模式实现过程

当索引模式为经济时&#xff0c;使用离线的向量引擎、关键词索引等方式&#xff0c;降低了准确度但无需花费 Token。 一.提取函数**_extract** 根据不同文档类型进行内容的提取&#xff1a; def _extract(self, index_processor: BaseIndexProcessor, dataset_document: Data…

FastAPI 学习之路(四十三)路径操作的高级配置

在实际开发中&#xff0c;可能我们有些接口不能在接口文档中与其他业务接口一样开放给前端或者其他对接人&#xff0c;那么我们肯定会想着在接口文档中对其进行屏蔽隐藏操作&#xff0c;那么可以实现吗&#xff1f; 接口文档中隐藏接口 当然&#xff0c;还很简单&#xff0c;…

【CSS in Depth 2 精译】2.6 CSS 自定义属性(即 CSS 变量)+ 2.7 本章小结

文章目录 2.6 自定义属性&#xff08;即 CSS 变量&#xff09;2.6.1 动态变更自定义属性 2.7 本章小结 当前内容所在位置 第一章 层叠、优先级与继承第二章 相对单位 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性 …

PGCCC|【PostgreSQL】PCA+PCP+PCM等IT类认证申报个税退税指南

小编特将PostgreSQL证书申报个税退税流程&#xff0c;编辑成文&#xff0c;供大家申报参考哦~ 1.申报专项附加扣除 第一步&#xff1a;打开个人所得税APP&#xff0c;选择“专项附加扣除填报”&#xff1a; 第二步&#xff1a;“扣除年度”选择您要申报的年度&#xff0c;并…

Windows 默认以管理员运行打开CMD

winr 默认以管理员打开运行CMD 需求&#xff1a;在运行页面输入cmd 希望是可以直接通过管理员方式打开的。 winr 打开运行 输入secpol.msc 打开本地安全策略&#xff08;注意家庭版是没有这个的&#xff09; 找到本地策略–安全选项–用户帐户控制: 以管理员批准模式运行所有管…

基于Python thinker GUI界面的股票评论数据及投资者情绪分析设计与实现

1.绪论 1.1背景介绍 Python 的 Tkinter 库提供了创建用户界面的工具&#xff0c;可以用来构建股票评论数据及投资者情绪分析的图形用户界面&#xff08;GUI&#xff09;。通过该界面&#xff0c;用户可以输入股票评论数据&#xff0c;然后通过情感分析等技术对评论进行情绪分析…

JavaScript 中 await 永远不会 resolve 的 Promise 会导致内存泄露吗?

前言 在 JavaScript 中&#xff0c;await 关键字用于等待一个 Promise 完成&#xff0c;它只能在异步函数&#xff08;async function&#xff09;内部使用。当 await 一个永远不会 resolve 的 Promise 时&#xff0c;它确实会阻塞异步函数的进一步执行&#xff0c;但不会直接…

C1W1.Assignment: Logistic Regression

理论课&#xff1a;C1W1.Sentiment Analysis with Logistic Regression 文章目录 前期准备导入包导入数据处理推文文本 Part 1: Logistic regressionPart 1.1: Sigmoid实现 sigmoid 函数Logistic regression: regression and a sigmoid Part 1.2 Cost function and GradientUp…

Python 使用proto 发送socket数据

import socket import binascii import struct from SensingMonitoring_pb2 import Command, CommandNamesif __name__ "__main__":client socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(("192.168.1.100", 22295))# 发送数据comman…

软件模块的初始化

什么是初始化&#xff1f; 软件的初始化&#xff08;Initialization&#xff09;是指软件启动或重新配置时执行的一系列步骤和过程&#xff0c;旨在准备软件运行环境、加载必要的配置信息、检查系统依赖项、分配资源&#xff08;如内存、文件句柄等&#xff09;&#xff0c;以及…

5、Hacker_Kid-v1.0.1

中等难度 目标root权限 先进行一波IP地址发现 netdiscover -i eth0 -r 192.168.1.1/24 发现存在的靶机ip 进行一波端口的探测 发现是一个apache的服务和一个tornado的网站 这里有个细节部分&#xff0c;53端口常见的情况都是走的udp协议做的域名解析&#xff0c;这里查询出来…

【ARM】CCI缓存一致性整理

目录 1.CCI500提供的功能 2.CCI500在SOC系统中所处的位置​编辑 3.CCI500内部结构​编辑 4.功能描述 1.CCI500提供的功能 2.CCI500在SOC系统中所处的位置 3.CCI500内部结构 Transaction Tracker&#xff08;TT&#xff09;是用来解决一致性和ordering问题的&#xff0c;它…

完成SSH连接与端口映射并运行hello_world.py以及创建conda环境

完成SSH连接与端口映射并运行hello_world.py 第一步&#xff1a; 使用vscode打开连接开发机如图 第二步&#xff1a; 端口映射 ssh -p 37367 rootssh.intern-ai.org.cn -CNg -L {本地机器_PORT}:127.0.0.1:{开发机_PORT} -o StrictHostKeyCheckingno 如&#xff1a; ssh -…