`
Fis
  • 浏览: 87530 次
  • 性别: Icon_minigender_1
  • 来自: 龙城
社区版块
存档分类
最新评论

[原创] 使用代码控制人物动作

    博客分类:
  • AS
阅读更多
原创首发www.eb163.com,转载请保留出处 作者:iiacm(着火骷髅)
  
  游戏里,人物的换装、走动、打斗等等行为都会用动画或者图片来表现、构造,如果使用3D进行建模,自然能水到渠成。但最终还是要输出成图像,如果人物的动作设定很多,那么就有可能需要制作大量的动画来支撑。那有没有可能不通过设计大量的图片或动画就能使人物有丰富的动作呢?本帖子仅是我的个人思考和试验,或许并不能从根本解决问题,不过试验本身都是有趣的,所以我们不妨来看看这样一种方案:使用脚本解析人物动作,包括挥舞肢体和更换外观(样貌与五官,乃至服饰)。这个例子只适用于2D的游戏人物,并且如果需要更强大的动作,则对各组件也必须设计得更加精巧,基本上应该算是个2D的人物骨骼了。顺带提一提,这个试验是我在网上看到一个使用as 2.0脚本控制火柴骨骼挥动的例子时,使我想起曾经也做过类似的东西,其中有共通的地方,于是就拿出来和大家一起探讨探讨,脚本控制火柴骨骼帖子 地址:http://www.eb163.com/club/thread-11196-1-1.html
  效果展示地址:http://www.eb163.com/club/thread-11197-1-1.html
(由于动作间隔太短,可以刷新浏览器后观察,点击人物可以时木偶部件更换颜色)
  首先,需要有个可以控制的角色,这个角色有点像是个可以重复使用的木偶人,让我想起了素还真……
  为了简便,只制作了一个比较Q的东西,二头身,缩短开发时间,当然,如果愿意,我想可以制作一个更加精密的“木偶”,精密程度关系到木偶可以做出的行为复杂度,连带的,他们的服装和五官、发型等都将要愈加的精致。和直接设计所有人物行为动作不同的是,这种木偶式的设计,可以筹划、设计一次,使用多次。不过问题还是有的,就是它不可能适应所有的情况,只能是种在适合的情况下的一种可选方案。
  木偶的制作过程需要比较细致的规划,要点是肢体的划分,为了能更细致的控制躯体,即便是二头身的人偶,我也精确到了膝盖和小臂关节,好使他们能“运动自如”(仅仅是比较的自如)。

木偶关节


  在关节处,也就是肢体围绕作旋转运动的地方定位,在代码中保留引用,可以在初始化身体的时候进行位置校对。所有肢体元件和后面提到的木偶部件都会被分类存放,并且设置链接标识,和Sprite类作好关联,在代码中会被用到。

木偶全身


木偶部件分类


  大致符合想要的人物比例即可。如果有需要可以多做几种体格的人偶来满足开发需求。接下来要做好脸蛋的轮廓,因为是二头身,所以这个脸蛋就…… 这里值得说明的是,我只做了男性和女性的脸蛋轮廓,实际上可以多做几种,比如老人、奸贼、忠诚、反贼…… - -# 无论脸蛋轮廓有多少种,其颈脖位置也要做准确的定位,并在代码中给出引用,并且要熟悉不同元件坐标的转换。这个工作是木偶的关键。





  然后就可以开始设计木偶身上的部件了:发型、眼睛、鼻子、嘴巴、眉毛、修饰(伤疤、各种皱纹、刺青、独眼龙眼罩等)。





  接着就到代码部分了。由于代码比较多,这里只贴出部分主要的代码片段,对整个控制过程进行基本的描述(不过做的过程中未对代码进行全程注释- -!):

import kw.game.charactorBuilder.Knight;
import kw.game.charactorBuilder.CharactorData;
import kw.game.charactorBuilder.head.FaceData;
import kw.game.charactorDataParser.BodyRotation;
import flash.geom.ColorTransform;
import flash.geom.Transform;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.utils.getTimer;
//新增 6 个人物
var aC1:Knight=new Knight();
var aC2:Knight=new Knight();
var aC3:Knight=new Knight();
var aC4:Knight=new Knight();
var aC5:Knight=new Knight();
var aC6:Knight=new Knight();
var cArr:Array=new Array();
/*设置各个人物的外貌,FaceData类负责存储样貌信息,传递给 Knight 中的 knight 属性的setFace() 方法进行设置样貌,其顺序非别标识:性别、发型、眉毛、眼睛、鼻子*/
aC1.knight.setFace(new FaceData(0,1,4,1,1));
aC2.knight.setFace(new FaceData(1,2,1,2,0));
aC3.knight.setFace(new FaceData(0,3,2,4,1));
aC4.knight.setFace(new FaceData(1,1,2,1,0));
aC5.knight.setFace(new FaceData(0,4,3,3,2));
aC6.knight.setFace(new FaceData(0,6,4,0,2));
//放入数组
cArr.push(aC1,aC2,aC3,aC4,aC5,aC6);
//对所有人物进行操作
for (var i:int=0; i<cArr.length; i++) {
        cArr[i].name="f"+i;
     /*这里调用人物的肢体控制函数 knightPosture 我称它为 “摆pose函数”,传入的字符串包含了我制定的规则,使用"|" 符号区分动作序列,有点类似动画帧,":"符号区分同肢体上不同作用的参数,","号为发挥同一作用的一组参数集,这组字符串会让 kw.game.charactorDataParser.CharactorDataParser 类处理,这个类专门解析这组字符串,并生成一个动作序列,然后发给 Charactor 类,也就是人物角色类,让人物角色类执行动作序列,以达到人物动起来的目的。*/
        cArr[i].knightPosture("100:1,0,0:5,0,15,120,25,90,35,0,0,0,0:0:0:0|100:1,0,0:5,0,0,20,25,45,-35,5,0,5,0:6:0:0|100:1,0,0:5,0,0,15,12,45,60,0,15,0,10:6:0:0|100:1,0,0:5,0,15,120,25,90,35,0,0,0,0:0:0:0|100:1,0,0:5,0,0,20,25,45,-35,5,0,5,0:6:0:0|100:1,0,0:5,0,0,15,12,45,60,0,15,0,10:6:0:0");
        addChild(cArr[i]);
        cArr[i].x=70*i;
        cArr[i].y=120;
        cArr[i].addEventListener(MouseEvent.MOUSE_UP,onFUp);
        function onFUp(e) {
                var red:uint=0;
                var blue:uint=0;
                var green:uint=0;
                red=225*Math.random();
                green=225*Math.random();
                blue=225*Math.random();
                var colorTr:ColorTransform=new ColorTransform(1,1,1,1,red,green,blue,0);
                e.target.transform.colorTransform=colorTr;
                trace(e.target.name);
        }
}


package kw.game.charactorDataParser
{
        import flash.geom.Point;
        import kw.game.charactorBuilder.CharactorData;
        
        /**
         * ...
         * @author ...
         */
        public class CharactorDataParser
        {
                public static var ACTIVE_GROUP_FLAG:String = "|";
                public static var CHARACTOR_GROUP_FLAG:String = ":";
                public static var BASE_FLAG:String = ",";
                public function CharactorDataParser() {
                        
                }
                //时间:水平距离,垂直距离,高度:头部角,身体角,腰部角,右手上臂角,右手下臂角,左手上臂角,左手下臂角,右脚大腿角,右脚小腿角,左脚大腿角,左脚小腿角:短武器角:特效编号:特效发生部位|...
                public function parseData(dataStr:String):Array {
                        var retArr:Array=new Array();
                        var activeArr:Array = dataStr.split(ACTIVE_GROUP_FLAG);
                        for (var i:int = 0; i < activeArr.length;i++ ) {
                                var bodyParseData:BodyParseData=new BodyParseData();
                                var str:String = activeArr[i];
                                var groupArr:Array = str.split(CHARACTOR_GROUP_FLAG);
                                var moveArr:Array = new Array();
                                var rotationArr:Array = new Array();
                                var rotationData:BodyRotation=new BodyRotation();
                                bodyParseData.time = groupArr[0];
                                moveArr = groupArr[1].split(BASE_FLAG);
                                bodyParseData.movePoint = new Point(moveArr[0], moveArr[1]);
                                bodyParseData.hight = moveArr[2];
                                rotationArr = groupArr[2].split(BASE_FLAG);
                                for (var j:int = 0; j < rotationArr.length;j++ ) {
                                        rotationData[BodyRotation.propertyList[j]]=rotationArr[j];
                                }
                                bodyParseData.bodyRotation = rotationData;
                                bodyParseData.weaponRotation = groupArr[3];
                                bodyParseData.effectsIndex = groupArr[4];
                                bodyParseData.effectsBodyPos = groupArr[5];
                                retArr.push(bodyParseData);
                        }
                        return retArr;
                }
        }
        
}


package kw.game.charactorBuilder{
        import flash.display.Sprite;
        import flash.events.TimerEvent;
        import flash.net.URLLoader;
        import flash.net.URLRequest;
        import flash.geom.Point;
        import flash.utils.Timer;
        import kw.game.charactorBuilder.head.FaceData;
        import kw.game.charactorDataParser.BodyParseData;
        import kw.game.charactorBuilder.body.*;
        import kw.game.charactorBuilder.CharactorData;
        import kw.game.charactorBuilder.handLeg.HandLeg;
        import kw.game.charactorBuilder.head.Head;
        import kw.game.charactorDataParser.BodyRotation;
        /**
         * ...
         * @author ...
         */
        public class Charactor extends Sprite {
                //-------相貌剪辑名称数组
                protected var faceMcNameArr:Array = ["face_mc", "blow_mc", "eye_mc", "nose_mc", "hair_mc"];
                //-------相貌类构造函数索引
                protected var faceList:Array = ["blowArr", "eyeArr", "noseArr", "hairArr"];
                //-------FaceData类属性清单
                protected var faceDataList:Array = ["blow", "eye", "nose", "hair"];
                //-------相貌类构造函数各性别清单
                protected var faceArr:Array = [CharactorData.MAIL_FACE_C, CharactorData.FEMAIL_FACE_C];
           //-------
                protected var MhairArr:Array = [CharactorData.MHAIR_0, CharactorData.MHAIR_1, CharactorData.MHAIR_2, CharactorData.MHAIR_3, CharactorData.MHAIR_4, CharactorData.MHAIR_5, CharactorData.MHAIR_6, CharactorData.MHAIR_7, CharactorData.MHAIR_8, CharactorData.MHAIR_9, CharactorData.MHAIR_10, CharactorData.MHAIR_11, CharactorData.MHAIR_12];
                protected var FhairArr:Array = [CharactorData.FHAIR_0, CharactorData.FHAIR_1, CharactorData.FHAIR_2, CharactorData.FHAIR_3, CharactorData.FHAIR_4, CharactorData.FHAIR_5];
                protected var MblowArr:Array = [CharactorData.MBLOW_0, CharactorData.MBLOW_1, CharactorData.MBLOW_2, CharactorData.MBLOW_3, CharactorData.MBLOW_4, CharactorData.MBLOW_5, CharactorData.MFBLOW_0];
                protected var FblowArr:Array = [CharactorData.FBLOW_0, CharactorData.FBLOW_1, CharactorData.FBLOW_2];//, CharactorData.MBLOW_3, CharactorData.MBLOW_4, CharactorData.MBLOW_5
                protected var MeyeArr:Array = [CharactorData.MEYE_0, CharactorData.MEYE_1, CharactorData.MEYE_2, CharactorData.MEYE_3, CharactorData.MEYE_4];
                protected var FeyeArr:Array = [CharactorData.FEYE_0, CharactorData.FEYE_1, CharactorData.FEYE_2];
                protected var MnoseArr:Array = [CharactorData.MNOSE_0, CharactorData.MNOSE_1, CharactorData.MNOSE_2];
                protected var FnoseArr:Array = [CharactorData.FNOSE_0];
                //protected var FblowArr:Array = [CharactorData.MBLOW_1];
                //-------------
                public var face_mc:Sprite;
                public var hair_mc:Sprite;
                //------------------
                public static var COLOR_HAIR:Array;//[{red:157, green:26, blue:2},{}]
                //--------------------
                public static var HEAD:String="head_mc";
                public static var RIGHT_HAND:String="rightHand_mc";
                public static var RIGHT_HAND_2:String="rightHand2_mc";
                public static var LEFT_HAND:String="leftHand_mc";
                public static var LEFT_HAND_2:String="leftHand2_mc";
                public static var BODY:String="body_mc";
                public static var BODY_2:String="body2_mc";
                public static var RIGHT_LEG:String="rightLeg_mc";
                public static var RIGHT_LEG_2:String="rightLeg2_mc";
                public static var LEFT_LEG:String="leftLeg_mc";
                public static var LEFT_LEG_2:String = "leftLeg2_mc";
                public static var WEAPON:String = "weapon_mc";
                //---------------------------
                protected var _head:Head;
                protected var _rightHand:HandLeg;
                protected var _rightHand2:HandLeg;
                protected var _leftHand:HandLeg;
                protected var _leftHand2:HandLeg;
                protected var _body:BodyPart;
                protected var _body2:BodyPart;
                protected var _rightLeg:HandLeg;
                protected var _rightLeg2:HandLeg;
                protected var _leftLeg:HandLeg;
                protected var _leftLeg2:HandLeg;
                //----------
                protected var bodyPartMcArr:Array;
                //--------
                protected var postureArr:Array;
                protected var postureIndex:int = 0;
                protected var postureTimer:Timer;
                //-------------
                protected var charactorFaceData:FaceData;
                public function Charactor() {
                        init();
                }
                public function refreshBody(tuneData:BodyParseData){
                        this.x += tuneData.movePoint.x;
                        this.y += tuneData.movePoint.y;
                        _head.rotation=tuneData.bodyRotation.headR;
                        _body.rotation=tuneData.bodyRotation.bodyR;
                        _body2.rotation=tuneData.bodyRotation.body2R;
                        _rightHand.rotation=tuneData.bodyRotation.rightHandR;
                        _rightHand2.rotation=tuneData.bodyRotation.rightHand2R;
                        _leftHand.rotation=tuneData.bodyRotation.leftHandR;
                        _leftHand2.rotation=tuneData.bodyRotation.leftHand2R;
                        _rightLeg.rotation=tuneData.bodyRotation.rightLegR;
                        _rightLeg2.rotation=tuneData.bodyRotation.rightLeg2R;
                        _leftLeg.rotation=tuneData.bodyRotation.leftLegR;
                        _leftLeg2.rotation = tuneData.bodyRotation.leftLeg2R;
                        //--------
                        for(var i:int=1;i<bodyPartMcArr.length;i++){
                                bodyPartMcArr[i].refreshBodyPart();
                        }
                }
                public function tuneBody(arr:Array) {
                        var tuneData:BodyParseData;
                        if (postureIndex == 0) {
                                postureArr = arr;
                                tuneData = arr[postureIndex];
                                postureTimer = new Timer(tuneData.time, 1);
                                postureTimer.addEventListener(TimerEvent.TIMER, onPostureTime);
                                postureTimer.start();
                        }else{
                                tuneData = arr[postureIndex];
                                postureTimer = new Timer(tuneData.time, 1);
                                postureTimer.addEventListener(TimerEvent.TIMER, onPostureTime);
                                postureTimer.start();
                        }
                        function onPostureTime(e:TimerEvent) {
                                postureIndex++;
                                refreshBody(tuneData);
                                if (postureIndex < arr.length) {
                                        postureTimer.removeEventListener(TimerEvent.TIMER, onPostureTime);
                                        tuneBody(arr);
                                }else {
                                        postureTimer.removeEventListener(TimerEvent.TIMER, onPostureTime);
                                }
                        }
                }
                public function setFace(faceData:FaceData) {//sex, hair, brow, eye, nose, mounth, furrow, other
                        charactorFaceData = faceData;
                        var consFunc;
                        consFunc = faceArr[faceData.sex];
                        face_mc = new consFunc;
                        face_mc.name = faceMcNameArr[0];
                        while (_head.numChildren!=0) {
                                _head.removeChildAt(numChildren - 1);
                        }
                        _head.addChild(face_mc);
                        for (var i:int = 1; i < faceMcNameArr.length; i++ ) {
                                var sprite:*;
                                if (faceData.sex == 0) {
                                        consFunc = this["M" + this.faceList[i - 1]][faceData[faceDataList[i - 1]]];
                                        sprite = new consFunc;
                                        sprite.name = faceMcNameArr[i];
                                        _head.addChild(sprite);
                                }else {
                                        consFunc = this["F" + this.faceList[i - 1]][faceData[faceDataList[i - 1]]];
                                        sprite = new consFunc;
                                        sprite.name = faceMcNameArr[i];
                                        _head.addChild(sprite);
                                }
                        }
                        /*//====
                        if(sex==0){
                                consFunc = MhairArr[faceData.hair];
                                hair_mc = new consFunc;
                                hair_mc.name = "hair_mc";
                                if (_head.getChildByName("hair_mc") == null)_head.addChild(hair_mc);
                                //----
                                consFunc = MhairArr[faceData.hair];
                                hair_mc = new consFunc;
                                hair_mc.name = "hair_mc";
                                if (_head.getChildByName("hair_mc") == null)_head.addChild(hair_mc);
                        }else {
                                consFunc = FhairArr[faceData.hair];
                                hair_mc = new consFunc;
                                hair_mc.name = "hair_mc";
                                if (_head.getChildByName("hair_mc") == null)_head.addChild(hair_mc);
                        }*/
                }
                //-----------------------------------------
                protected function init() {
                        initBodyXY();
                        initPartMc();
                        initBodyPartNode();
                }
                protected function initPartMc(){
                        _body=this[BODY];
                        _head=_body[HEAD];
                        _body2=_body[BODY_2];
                        _rightHand=_body[RIGHT_HAND];
                        _leftHand=_body[LEFT_HAND];
                        _rightLeg=_body2[RIGHT_LEG];
                        _leftLeg=_body2[LEFT_LEG];
                        _rightHand2=_rightHand[RIGHT_HAND_2];
                        _leftHand2=_leftHand[LEFT_HAND_2];
                        _rightLeg2=_rightLeg[RIGHT_LEG_2];
                        _leftLeg2=_leftLeg[LEFT_LEG_2];
                        bodyPartMcArr = new Array(_body, _head, _rightHand, _rightHand2, _leftHand, _leftHand2, _rightLeg, _rightLeg2, _leftLeg, _leftLeg2, _body2);
                        for (var i:int = 0; i < bodyPartMcArr.length;i++ ) {
                                bodyPartMcArr[i].bodyContent = this;
                        }
                }
                protected function initBodyXY(){
                        this[BODY].x = CharactorData.BODY_X;
                        this[BODY].y = CharactorData.BODY_Y;
                }
                protected function initBodyPartNode(){
                        _body.controlled = null;
                        for (var i:int = 1; i < bodyPartMcArr.length;i++ ) {
                                _body.addControlsUnit(bodyPartMcArr[i]);
                        }
                        _head.controlled=_body.getBodyPartMc(Body.UP_NODE_MC);
                        _body2.controlled=_body.getBodyPartMc(Body.DOWN_NODE_MC);
                        _rightHand.controlled=_body.getBodyPartMc(Body.RIGHT_NODE_MC);
                        _leftHand.controlled=_body.getBodyPartMc(Body.LEFT_NODE_MC);
                        _rightLeg.controlled=_body2.getBodyPartMc(Body2.RIGHT_NODE_MC);
                        _leftLeg.controlled=_body2.getBodyPartMc(Body2.LEFT_NODE_MC);
                        _rightHand2.controlled=_rightHand.getBodyPartMc(HandLeg.NODE_MC);
                        _leftHand2.controlled=_leftHand.getBodyPartMc(HandLeg.NODE_MC);
                        _rightLeg2.controlled=_rightLeg.getBodyPartMc(HandLeg.NODE_MC);
                        _leftLeg2.controlled=_leftLeg.getBodyPartMc(HandLeg.NODE_MC);
                }
        }
        
}


关于木偶的执行效率
  整个木偶主要消耗资源的地方在字符串命令解析的地方,试验以前,我对as解析字符串,也就是查找字符串中命令的效果进行了测试,我用的字符串是从一个类似游戏数值的电子表格中取出来的,里面存放了金庸先生的14部武侠小说的所有武功秘籍和武器装备的游戏资料,当然是我自己填的,但是数据量相当庞大`` 如此巨大的文本,解析时间用了256毫秒… 看来as还是挺住了。不过也许这样的情况并不够极端,并不足以说明字符串解析的可行性。或许也可以考虑考虑使用正则表达式来做解析这部分的功能。不过无论如何,这个仅仅是种游戏角色的实现方案探讨性的试验,其可行性可能并不高,那么大家就权当是种小小的娱乐吧``

  • 大小: 4 KB
  • 大小: 7.2 KB
  • 大小: 7.8 KB
  • 大小: 5.1 KB
  • 大小: 4.9 KB
  • 大小: 11.4 KB
  • 大小: 10.8 KB
  • 大小: 10.1 KB
  • 大小: 9.5 KB
  • 大小: 9 KB
分享到:
评论

相关推荐

    Hoshi人物模型 包括人物动作

    动画师会使用关键帧动画或者蒙皮权重来控制模型的运动,例如走路、跑步、跳跃、表情变化等,使角色看起来更加生动自然。 4. **引擎兼容性**:描述中提到在2018.3版本上运行,这可能指的是特定的游戏引擎或渲染平台...

    原创像素角色Rotor动作素材

    标题"原创像素角色Rotor动作素材"暗示了这是一系列专门为游戏角色 rotor 设计的像素艺术动画。"原创"一词强调这些动作是设计师独立创作的,具有独特性和创新性,而非复制品或修改自其他来源。像素角色的设计对于那些...

    原创歌曲分享平台代码 java原创歌曲分享平台代码

    原创歌曲分享平台代码 java原创歌曲分享平台代码 基于springboot的原创歌曲分享平台代码 1、原创歌曲分享平台的技术栈、环境、工具、软件: ① 系统环境:Windows/Mac ② 开发语言:Java ③ 框架:SpringBoot ④ ...

    原创歌曲分享-原创歌曲分享平台-原创歌曲分享平台源码-原创歌曲分享平台java代码-基于springboot的原创歌曲分享平台

    原创歌曲分享-原创歌曲分享平台-原创歌曲分享平台源码-原创歌曲分享平台java代码-原创歌曲分享平台设计与实现-基于springboot的原创歌曲分享平台-基于Web的原创歌曲分享平台设计与实现-原创歌曲分享网站-原创歌曲...

    原创歌曲分享-原创歌曲分享平台-原创歌曲分享平台源码-原创歌曲分享平台java代码-基于Web的原创歌曲分享平台设计与实现-代码

    原创歌曲分享-原创歌曲分享平台-原创歌曲分享平台源码-原创歌曲分享平台java代码-原创歌曲分享平台设计与实现-基于springboot的原创歌曲分享平台-基于Web的原创歌曲分享平台设计与实现-原创歌曲分享网站-原创歌曲...

    大连东软信息学院原创卡通人物

    大连东软信息学院原创卡通人物1

    齐鲁软件flash原创动画设计源代码

    通过查看和分析这些源文件,学习者可以了解动画的制作流程,如时间轴控制、图层管理、动作脚本编写(ActionScript)以及交互逻辑实现等。 综上所述,这份压缩包中的知识点主要涵盖以下几个方面: 1. **Flash动画...

    spring 整合JDBC 原创代码

    可以使用PlatformTransactionManager接口来控制事务的开始、提交、回滚。通过`@Transactional`注解,可以在方法级别声明事务边界。 5. **参数绑定** Spring JDBC提供两种方式绑定参数:占位符(例如`?`)和命名...

    单片机C语言实例--397-原创VB上位机控制数码管.zip

    这表明该实例的开发者可能使用了版本控制工具来管理他们的代码。 6. **下位机程序**:压缩包中的“下位机程序”很可能包含了单片机的固件代码,可能为C语言编写的源代码或者已经编译好的二进制文件。这部分代码实现...

    迷你MiniCYBook(原创 源代码)

    迷你MiniCYBook是一款基于原创源代码的成语词典软件,旨在为用户提供丰富的成语查询和学习功能。这款软件的核心特点是提供了完整的源代码,使得用户不仅可以使用它进行成语查询,还可以深入研究其内部工作原理,对...

    自己原创的易语言代码.rar

    3.为什么要使用易语言实现伪原创? 使用易语言实现伪原创有以下几个优点: (1)易语言代码简单易懂,即使是初学者也能快速上手。 (2)易语言可以方便地读写文本文件,适合进行伪原创操作。 (3)易语言可以...

    j2me动作类手机游戏源代码(本人原创)

    在源代码中,我们可以看到如何使用J2ME的图形库来绘制游戏场景,创建动态的角色和物体,以及实现基本的物理运动模拟。 1. 角色控制:玩家通过键盘或触摸屏控制主角移动,源码中会包含对按键事件的监听和响应机制。...

    旅游小程序-前端代码-原创素材

    旅游小程序-前端代码_原创素材旅游小程序-前端代码_原创素材旅游小程序-前端代码_原创素材旅游小程序-前端代码_原创素材旅游小程序-前端代码_原创素材旅游小程序-前端代码_原创素材旅游小程序-前端代码_原创素材旅游...

    伪原创自动检测zip 网页代码

    标题中的“伪原创自动检测zip 网页代码”指的是一个专门用于检测文章伪原创性的网页源码工具。这个工具不包含自动收集文章或者自动生成伪原创内容的功能,它的核心作用是比对和校正文章,确保内容的原创性。 在...

Global site tag (gtag.js) - Google Analytics