Stage.4 —— 打马

游戏开发对话录
一场关于游戏开发的对话,讨论了游戏设计、工厂模式的应用及射击游戏的实现细节,包括飞碟和子弹的管理、用户交互及镜头控制等内容。

13:所以说这样很有意思吗
k :嗯,我觉得挺有趣的,打马,就跟打码同音哦
13:这种时候自己解释不会很尴尬吗
k :但是总是要说一下的吗,虽然像这样自己觉得很有意思,但是别人不知道什么意思的时候,硬着头皮解释也是挺尴尬的。。
13:所以说就不要用这样的标题啊,简单的UFO游戏就不行吗?
k :但是内容上感觉就不太一样吧
13:也是
k :是吧
13:(总觉得哪里不对。。。)啊!所以说一开始就别做成这样啊!!!
k :你看,你又激动了,这种时候就越应该冷静下来对吧,彼此就不能好好说话吗?
13:唯独不想要你这么说。。。

—– 一小时前 —–
k :果然说到游戏的时候
13:说到游戏的时候?
k :那肯定就要是射击类游戏吧
13:是啊,当年最初发展起来的就是射击类游戏呢。。。
k :等下
13:嗯?
k :https://www.wikipedia.org/
13:额。。。突然怎么了
k :由于不想听长篇。。呃亨。。百科知识,k向你抛出了一个维基百科
13:长篇大论对吧,你刚刚想说长篇大论对吧!
k :赶紧开始做游戏吧,不然要ddl咯
13:别在这个时候说ddl的事情啊。。(距离ddl还有12小时)
k :那就开始吧,所以最重要的果然是。。。
13:(完全不听。。。)唉,嘛,要说的话,重点肯定就是工厂模式的实现了吧,虽然也不是什么新东西就是了
k :唔。。。
13:怎么
k :不对吧,重要的果然要是游戏的趣味性吧
13:小孩子啊你,我们现在可已经是设计者了哦?
k :哼,就是这样,一个个都变成了愚蠢的大人了呢
13:额。。。
k :所以说你们这些。。。
13:我一直都不说,你该不会就是因为不知道什么是工厂模式所以就避开不说了吧
k :。。。
13:。。。
k :我知道啊
13:迟疑了很久呢
k :唉,所谓的这些模式什么的,上次就是什么动作分离什么的,还有什么MVC什么的,网上又查不到,然后这次又是什么什么模式,阿森纳?所以又不知道是什么鬼,所以就说我们的老。。。。
13:喂!!!
k :怎,怎么了,吓死我了
13:你才吓死我了啊。。。差点就翻车了
k :你怎么老这么激动啊
13:所以说是谁的错。。。
k :哎,你就不能控制一下情绪吗,就是那种看着手下的NPC们开心聊天的时候想起以前工会的朋友们一起聊天的快乐时光就会突然 呼!的一下冷静下来那种
13:完全不知道你在说什么
k :所以赶紧开始吧,工厂模式就交给你了
13:所以果然要我来啊。。。嘛,其实工厂模式说起来,最主要的就是生产和回收这两个行为了,简单来讲就是,我们可以将工厂看成一个飞碟的集合,然后里面分为两类,一类就是已经发射的飞碟,另一类就是存储在工厂内的飞碟了
k :工厂不是应该要生产东西的吗,怎么。。。
13:说的没错(有点欣慰),所以另外一个重要的问题就是,我们要什么时候生产,也就是是实例化一个飞碟预制体的问题了。其实也很简单呢,我们只需要在发射的时候简单判断,我们是不是有库存的飞碟啊?没有的话那就要赶紧做出来啊。。。这样子
k :哇,你这种说话方式很恶心欸, 从来没有人和你说过吗
13:恶心,你还真敢说啊,有种再说一次
k :不要呢~你恶心的时候才不想和你说话呢~
13:你才恶心啊。。。不要随便就从哪里就把台词搬过来啊。。唉,所以,额,就是大概代码这么实现吧:

//未发射的飞碟
List<ClayPigeon> free;
//发射的飞碟
List<ClayPigeon> used;
//下次发射的时间
public float next_fire;
//发射时间差
public float fire_rate;

void Update () {
    //如果数组大小大于0,就遍历used
    if (used.ToArray ().Length > 0) {
        foreach (ClayPigeon pigeon in used) {
            if (pigeon.isFree || scene_controller.isGameOver) {
                //如果已经空闲,或者游戏已经结束,就回收
                recollectClayPigeon (pigeon);
            } else
                //否则,更新状态  P.S.这种方式果然还是和动作管理有点像。。
                pigeon.Update ();
        }
    }
    //判断是否已经到达下次发射时间(不要用等于,很简单不解释)
    if(Time.time > next_fire && !scene_controller.isGameOver){
        //让发射器朝向发射方向
        this.transform.LookAt (new Vector3(7, Random.Range(1, 10), Random.Range(6, 15)));
        //将发射的飞碟从free中移除
        this.free.Remove(fireClayPigeon (RoundController.Instance));
        //更新下次发射的时间,记得在重新开始游戏时要把时间更新到当前时间
        //next_fire = Time.time + fire_rate * Time.deltaTime;
        next_fire += fire_rate * Time.deltaTime;
    }
}

public ClayPigeon fireClayPigeon(RoundController current_round){
    ClayPigeon clay_pigeon;
    //判断是否还有剩下的飞碟,没有的话就要生产了
    if (free.ToArray().Length == 0) {
        clay_pigeon = new ClayPigeon ();
        clay_pigeon.setGameObject(Instantiate (Resources.Load ("clay pigeon")) as GameObject);
        this.free.Add (clay_pigeon);
    }
    //
    next_fire += fire_rate * Time.deltaTime;
    int round = current_round.current_round;
    clay_pigeon = this.free[0];
    clay_pigeon.setClayPigeon (10 + round / 10, round / 10, round > 10 ? Random.Range (1, 2) : 0, this.transform);
    used.Add (clay_pigeon);
    current_round.rest--;
    return clay_pigeon;
}
public void recollectClayPigeon(ClayPigeon clay_pigeon){
    this.used.Remove (clay_pigeon);
    this.free.Add (clay_pigeon);
    clay_pigeon.beCollect ();
}

k :你这样把很多重要的东西都放在注释里面说
13:干嘛啊
k :怠惰
13:所以说不要这样随便就把台词搬过来啊
k :我只是说实话啊,明明发射这件事情也很重要啊
13:额。。。这种事情我知道啊,但是。。。
k :但是?
13:我操作系统实验还没写,明天要ddl了。。。(距离ddl还有24小时)
k :哇,你自己不也在说这种事情
13:发射这种事情随便弄一下就好了啊,所以都解释说用lookat了,这样让发射器面向发射的目标,就可以直接让子弹往forward方向飞去了,也不用考虑太多角度问题了嘛,代码拿着

//刚体速度,方向为物体朝向,物体朝向用发射器的Transform初始化
this . bullet . GetComponent<Rigidbody> () . velocity = this . bullet . transform . TransformDirection (Vector3 .forward * speed);

放在update里面咯,因为不是继承Monobehaviour,让工厂来调用就行了
k :真怠惰
13:我不管了,怠惰就怠惰吧,让我去烧掉这个世界吧,哈哈哈。。。我要去写操作系统实验了
k :就算是我也没有跟你这样入戏。。。不过真的这样就好吗
13:嗯?
k :唉,这样很没意思呢
13:怎么就没意思了,我们只要再加上用户点击就行了啊,然后再简单的在发生collision的地方生成一个particle的预制体就可以实现,点击破坏飞碟的效果了
k :是啊,然后我们再在射线检测里面将碰撞体的对象,就是发生碰撞的飞碟回收就好了呢
13:是啊,那这样就。。。
k :但是我拒绝!
13:所以说不要随便把台词搬过来啊。。。这样怎么就不行了?
k :哼,我最喜欢的就是在对方以为。。。
13:我去写实验了
k :哇,等一下啊啊啊
13:唉。。。所以你还想干嘛
k :说到射击游戏
13:说到射击游戏?(有种既视感)
k :果然要有子弹吧
13:呃。。。你为什么每次都要来增加工作量呢。。。
k :一个没有子弹的射击游戏,你说,作为一个游戏设计者,这么恶心的游戏你能接受吗!
13:额,也不是不行啊,这种点击消除的在移动端玩起来游戏体验也不差啊,不如说这样的游戏本来就是一种移动端的游戏
k :所!以!说!我们这是一个射击游戏啊!不要每次都要把一个远程的游戏玩成近战可以吗?
13:不知道你在说什么。。
k : 所以,来做子弹吧
13:。。。唉,好吧。。。其实,也不难吧。。。
k :出现了,一直懒得做,然后开始做的时候就说”啊这个,其实也不难“的台词的人出现了
13:别把我说的跟什么都不做的人一样啊,你才是什么都不做吧!我只是说出一个事实而已啊,玩家也是一个工厂嘛,就是一个子弹的工厂而已啊,实现的逻辑可以说完全一样,代码把变量类型改一下完全就可以复制过去了。不一样的其实就是发射了,就是射击的触发方式不一样了。前面我们用的是时间触发的方式,现在自然就是用户的点击事件来触发了,很简单嘛

//Player 脚本中
//这里虽然也有个next_fire,不过这里是用来对用户的射速进行限制的
if (Input. GetMouseButtonDown (0) && Time . time > next_fire && scene_controller .status ) {
    this. clip_free.Remove (shoot ());
    next_fire += fire_rate * Time.deltaTime;
}

而我们自然是把Player的脚本放在Main Camera上了,这样就可以往画面前方发射子弹了

然后我们还可以简单的加个准星之类的东西,粗糙的如下。。。

//好吧,就是用GUI.Label。。。 -> +
if (!scene_controller.isGameOver) {
            GUI.Label (new Rect (Screen . width / 2 + 18, Screen . height / 2 - 15, 30, 20), "—");
            GUI.Label (new Rect (Screen . width / 2 - 32, Screen . height / 2 - 15, 30, 20), "—");
            GUI.Label (new Rect (Screen . width / 2 - 2, Screen . height / 2 + 10, 5, 30), "|");
            GUI.Label (new Rect (Screen . width / 2 - 2, Screen . height / 2 - 40, 5, 30), "|");
        }

然后,自然接下来就是要镜头移动了,我们自然希望镜头随鼠标的移动而移动,然后我们希望发射的子弹是从镜头中间发射的,那么我们自然需要把主表固定在镜头中间,然后,我们不希望看到鼠标,所以我们要让他隐身了

//当游戏进行时,我们可以移动镜头
if (!scene_controller.isGameOver) {
            //获取旋转量
            float translationX = Input.GetAxis ("Mouse X") * speedX;
            float translationY = Input.GetAxis ("Mouse Y") * speedY;
            translationX *= Time.deltaTime;
            translationY *= Time.deltaTime;
            X += translationX;
            Y += translationY;
            this.transform.rotation = Quaternion.identity;
            //要先饶X轴旋转,这样不会对Y轴旋转造成影响,可以自己去试一下,两者体验还是有挺大差距的
            this.transform . RotateAround (this.transform.position, Vector3.right, -Y);
            this.transform. RotateAround (this.transform. position, Vector3. up, X);
}
if (isGameOver) {
            //如果游戏结束了,就取消鼠标的锁定和隐藏
            Cursor.lockState = CursorLockMode . None;
            Cursor.visible = true;
            if (explosion != null) {
                //这是作为伤害判定的墙摧毁的效果
                explosion = Instantiate (Resources.Load ("explosion"), wall. transform. position, Quaternion. identity) as GameObject;
                explosion.GetComponent<Explosion> () . decrement = -10;
            }
            //摧毁墙
            if(wall != null)
                Destroy (wall);
        //反之锁定鼠标,不可见
        } else {
            Cursor.lockState = CursorLockMode . Locked;
            Cursor.visible = false;
        }
}

都是要放在Update里面的哦!

k :所以说你这样很恶心啊。。。
13:那你就不要和我说话,倒不如说你不要在说话了,不管你在怎么说我。。。
k :最后,最后了,我保证
13:。。。。你还要干嘛

—— 现在 ——
13:所以你最后还是要用这只马来做飞碟的预制体吗。。。
k :就决定是你了!
13:就算你转了一下帽檐也一定都不帅啊。。。

– 完

这里写图片描述

内容概要:本文详细介绍了一个基于Python实现的锂电池剩余寿命(RUL)预测项目,采用Transformer-LSTM混合深度学习模型,结合GUI界面实现智能化预测与可视化分析。项目涵盖从数据生成、特征工程、模型构建(Transformer自注意力机制与LSTM时序建模融合)、训练优化、性能评估到实际部署的全流程。通过滑动窗口采样、数据归一化、多维度评估指标(MSE、MAE、R²、RMSE、MAPE)及残差分析,确保模型高精度与鲁棒性。同时集成注意力权重与LSTM隐状态可视化功能,提升模型可解释性,并设计了完整的GUI交互系统,支持数据加载、模型热插拔推理与预测结果动态展示。; 适合人群:具备一定Python编程基础和深度学习知识,熟悉PyTorch框架的数据科学从业者、研究生及从事新能源、智能制造、电池管理系统开发的工程师。; 使用场景及目标:①应用于新能源汽车、储能电站、消费电子等领域的电池健康管理;②实现锂电池剩余寿命的高精度动态预测,支持智能运维与故障预警;③为科研人员提供可复现、可扩展的深度学习时序建模实例,推动电池寿命预测技术的工程化落地。; 阅读建议:建议读者结合代码与文档逐步实践,重点关注数据预处理、模型结构设计与GUI集成部分,尝试在本地环境中运行并调试程序,深入理解Transformer与LSTM协同工作机制,同时可扩展多模态输入或轻量化部署以适应更多应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值