AS3函数复用问询:如何为不同作物田复用同一函数仅修改变量
当然可以!用函数复用搞定多块作物田的逻辑
刚接触AS3就能想到复用代码,这思路超棒!完全不用为每块作物田写重复逻辑,我们只需要把作物田的共性逻辑抽成通用函数,再用配置参数来区分不同作物的特性就行,下面给你一步步拆解实现方案:
一、先整理作物的配置参数
首先,把每块作物田的差异点(比如作物名称、生长帧范围、生长时长这些)做成配置对象,这样后续要加新作物或者修改参数,直接改配置就行,不用动逻辑代码:
// 定义所有作物田的配置数组,每一项对应一块田的参数 var cropConfigs:Array = [ { cropName: "草莓", startFrame: 1, // 生长起始帧 matureFrame: 5, // 成熟帧 totalGrowSteps: 5, // 总生长阶段数(对应帧数差) growInterval: 1000 // 每阶段生长间隔(毫秒) }, { cropName: "胡萝卜", startFrame: 6, matureFrame: 10, totalGrowSteps: 5, growInterval: 1200 }, // 剩下4块田的配置按这个格式依次添加就行 ];
二、编写通用的作物田初始化函数
接下来写一个能处理所有作物田的通用函数,把作物田实例和对应的配置作为参数传入,函数里统一处理生长、点击采摘等逻辑:
function setupCropField(field:MovieClip, config:Object):void { // 给作物田绑定配置,方便后续事件里获取 field["cropConfig"] = config; // 初始化到生长起始帧 field.gotoAndStop(config.startFrame); // 添加点击采摘事件 field.addEventListener(MouseEvent.CLICK, onCropFieldClick); // 创建生长定时器,模拟作物生长 var growTimer:Timer = new Timer(config.growInterval, config.totalGrowSteps); // 把作物田绑定到定时器上,方便定时器回调里获取 growTimer.owner = field; growTimer.addEventListener(TimerEvent.TIMER, onCropGrow); // 绑定定时器到作物田,方便后续控制(比如暂停/重启) field["growTimer"] = growTimer; // 启动生长(如果是需要用户种植后再生长,把这行移到种植逻辑里就行) growTimer.start(); } // 独立的点击处理函数,避免闭包陷阱 function onCropFieldClick(e:MouseEvent):void { var targetField:MovieClip = e.currentTarget as MovieClip; var config:Object = targetField["cropConfig"]; if (targetField.currentFrame == config.matureFrame) { trace("成功采摘" + config.cropName + "!"); // 采摘后重置到初始生长帧,重新开始生长 targetField.gotoAndStop(config.startFrame); targetField["growTimer"].reset(); targetField["growTimer"].start(); } else { var currentStage:int = targetField.currentFrame - config.startFrame + 1; trace(config.cropName + "还没成熟哦,当前是第" + currentStage + "生长阶段"); } } // 独立的生长定时器回调函数 function onCropGrow(e:TimerEvent):void { var growTimer:Timer = e.currentTarget as Timer; var targetField:MovieClip = growTimer.owner as MovieClip; var config:Object = targetField["cropConfig"]; if (targetField.currentFrame < config.matureFrame) { targetField.nextFrame(); } else { // 成熟后停止定时器 growTimer.stop(); trace(config.cropName + "已经成熟啦,快来采摘!"); } }
三、批量初始化所有作物田
最后,把你的6块作物田实例放到数组里,循环调用通用函数完成初始化:
// 假设你的6块作物田实例名为field1到field6,把它们放进数组 var allFields:Array = [field1, field2, field3, field4, field5, field6]; // 循环初始化每块田 for (var i:int = 0; i < allFields.length; i++) { // 对应数组里的配置(注意顺序要和作物田对应哦) setupCropField(allFields[i], cropConfigs[i]); }
额外优化建议
- 如果想让代码更规范,可以把配置做成自定义类,比如
CropConfig,比用Object更清晰,避免拼写错误:
class CropConfig { public var cropName:String; public var startFrame:int; public var matureFrame:int; public var totalGrowSteps:int; public var growInterval:int; public function CropConfig(name:String, start:int, mature:int, steps:int, interval:int) { cropName = name; startFrame = start; matureFrame = mature; totalGrowSteps = steps; growInterval = interval; } } // 创建配置的时候就可以用类实例 var cropConfigs:Array = [ new CropConfig("草莓", 1, 5, 5, 1000), new CropConfig("胡萝卜", 6, 10, 5, 1200) ];
- 如果需要实现“种植”操作(比如初始是空田,用户点击后才开始种植),可以把定时器启动的逻辑移到点击事件的分支里,比如点击空田时切换到生长起始帧并启动定时器。
这样一来,你只需要维护配置数组和通用函数,不管加多少块作物田都不用重复写逻辑,后续修改生长速度、成熟帧这些参数也超级方便,完美适配你的学习需求~
内容的提问来源于stack exchange,提问作者CatNip
相关产品推荐
相关产品推荐

