经典游戏还原之:松鼠大作战2

版权声明:

  • 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号“优梦创客”(微信号:unitymaker)
  • 您可以自由转载,但必须加入完整的版权声明!

松鼠大作战游戏制作

  1. 游戏介绍 1990年,经迪士尼授权,由日本卡普空(Capcom)电视游戏公司制作的基于任天堂FC主机的电视游戏《松鼠大作战》出版发行。游戏延用迪士尼动画片《松鼠大作战》里的两只可爱花栗鼠Chip and Dale(奇奇和蒂蒂),从寻找小猫咪的委托任务开始,到摆脱肥猫陷阱与其一决高下为故事内容。可单人玩又可双人对战,可互助又可互攻,流畅度,创造力与可玩性均为同类游戏中的领军者。
    1993年,卡普空制作发行了《松鼠大作战2》再一次将经典搬到屏幕。除了制作更加精良外,故事也更加惊险刺激。
  2. 场景搭建 将场景中的图片首尾拼接,在合适的位置设置碰撞器与平台控制器
  3. 主角Chip登场 将主角图片拖入层级面板上,命名为“player”,添加刚体2D组件和合适的碰撞器组件。为player设置子节点hand,添加碰撞器组件设置为触发,用于触碰箱子的判断;设置子节点foot,调整恰当的位置,用于跳跃,以及主角跳跃动画的条件判定;再设置两个节点用于主角投掷物品发射的位置。
  4. 主角Chip动画制作 打开动画控制器,创建主角的Idel动画,在合适的时间轴拖上相应的主角图片,重复操作将主角的动画设置好。
  5. 主角Chip基本动作实现 为player添加脚本组件,命名为PlayerController,主角的移动需要通过输入设备为其提供指令,并进行相应的操作,Unity中Input可以获得这些操作。horizontal与vertical均是浮点数范围为-1至1,方向与卡迪尔坐标相同,isPressjump与isPressFire均为Bool类型。通过射线的方式我们可以判断处人物是否在跳跃状态下。Chip的移动与跳跃我们通过物理运动进行操作,在FixedUpdate()下进行代码操作;
    isJump = !(Physics2D.Linecast(transform.position, foot.position, 1 << LayerMask.NameToLayer("Map")) || Physics2D.Linecast(transform.position, foot.position, 1 << LayerMask.NameToLayer("Box")));
    horizontal = Input.GetAxis("Horizontal");//上下
    vertical = Input.GetAxis("Vertical");//左右
    isPressjump = Input.GetButtonDown("Jump");//跳跃
    isPressFire = Input.GetButtonDown("Fire1");//攻击
    void FixedUpdate()
    {
        if (isControl)
        {
            if (!isDown && isPressjump && !isJump)
            {
                if (rig.velocity.y < 1F)
                {
                    rig.AddForce(Vector3.up * force);
                }
                isJump = true;
            }
            if (isDown)
            {
                rig.velocity = new Vector3(0, rig.velocity.y);
            }
            else
            {
               rig.velocity = new Vector3(speed * horizontal, rig.velocity.y);
            }
        }
    }
  6. 主角Chip攻击实现 与射击游戏的区别,在本作中,CHip是通过搬物品再投掷出去进行攻击的。这里的设想是将场景的箱子与投掷的箱子区别开来,方便判断。player下的节点hand添加脚本,在OnTriggerStay2D下调用MoveBox方法,isHandBox判断手中是否有箱子,isThrow则判断有没有进行投掷操作。这里贴出主要代码:

    public void MoveBox(Collider2D collision)
    {
        //搬箱子
        if (!isDown && collision.tag.StartsWith("Box") && isPressFire && !isHandBox && !isThrow)
        {
            Destroy(collision.gameObject);//场景中的箱子被销毁了,游戏中松鼠头顶上的箱子仅仅是外观的区别
            isHandBox = true;
            animator.SetTrigger("moveBox");
            Instantiate(movebox);
        }
    }
    private void ThrowBox()
    {
        if (isHandBox && isPressFire)
        {
            isHandBox = false;
            isThrow = true;
            GameObject o = Instantiate(throwingbox);//投掷箱子时实例化一个投掷的箱子(与场景的箱子功能不同)
            if (!isDown)
            {
                o.transform.position = transform.Find("fireposition").position;
            }
            else
            {
                o.transform.position = transform.Find("downfireposition").position;
            }
            o.GetComponent<ThrowingBox>().Throw(transform.localScale.x, vertical);
            StartCoroutine(ResetIsThrow());
            animator.SetTrigger("throwbox");
            Instantiate(throwbox);
        }
    }
  7. 主角Chip动画控制器动画控制 给出合适的条件进行动画转换,本作动作丰富,通过多次尝试,本作动作才比较连贯。
  8. 场景箱子的制作 将箱子图片拖进层级面板中,为它设置合适的碰撞器,做成预制体备用。
  9. 投掷箱子的制作 与场景箱子类似,设置触发器,另外需要增加刚体2D组件与脚本,脚本主要用于处理与怪物接触的交互,同样也制成预制体。
  10. 其他道具的制作 其他道具有花(吃了一定的数量可以奖励生命);蜂蜜(蜜蜂怪物攻击的道具,玩家触碰会造成伤害);坚果(若主角受伤,吃到该道具会增加1点Hp值);叉子(投掷小鼠投掷的道具,玩家触碰会造成1点Hp伤害)。
  11. 一些其他的制定 在本场景的末尾添加添加合适的触发器,绑上脚本可以通过下一个场景;在悬崖处也添加一个长条的触发器,用于触发主角死亡判定并重新加载本场景。
  12. 蜜蜂怪物的制作 在层级面板中,拖进一张蜜蜂怪物的图片,添加刚体组件,和合适的碰撞器,设置为触发。为这个对象设置两个动画,一个为停止动画,一个为飞行动画。摄像机还没有看到蜜蜂时,蜜蜂处于静止状态,当蜜蜂被摄像机照到时,蜜蜂处于飞行状态。蜜蜂飞到玩家的X位置时,投掷蜂蜜道具。附上蜜蜂的物理运动时脚本代码:
    public void FixedUpdate()
    {
        if (isHit)
        {
            rig.velocity = new Vector2(masterFlyX, masterFlyY);
        }
        else if (isRest)
        {
            rig.velocity = Vector2.zero;
        }
        else if (!isStop && !isHit)
        {
            rig.velocity = new Vector2(flyspeedx, flyspeedy);
            if (this.transform.position.x < PlayerController.instance.transform.position.x && honeyNum > 0)
            {
                Attack();
                honeyNum--;
                isRest = true;
                StartCoroutine(ResetIsRest());
            }
        }
    }
  13. 投叉小鼠的制作 与蜜蜂怪物类似,添加刚体组件和合适的碰撞器。为这个对象设置四个动画,停止动画,巡逻动画,攻击动画,跳跃动画。给这个对象加一个点进行射线是不是发现玩家,发现时,执行攻击逻辑播放攻击动画。这里附上部分代码:
    public void Update()
    {
        if (state == State.Stop && this.transform.position.x < cam.position.x + xoffset)
        {
            //怪物行为被激活
            state = State.Walk;
            animator.SetTrigger("Walk");
        }
        else if (this.transform.position.x < cam.position.x - xoffset || this.transform.position.y > cam.position.y + yoffset)
        {
            Destroy(this.gameObject);
        }
        Walk();
        Throw();
        Escape();
    }
  14. Boss制作 在层级面包板中拖入Boss的图片,组件与合适的触发器,Boss主要两种状态,添加刚体,走动状态与停下攻击状态。这里附上Boss的代码:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Boss : MonoBehaviour {
    
        public float range;
        public float speed;
        public float stopTime;
        public float walkTime;
        private float dir = 1;//方向正1表示坐标向右
        private float leftrange;
        private float rightrange;
        private Rigidbody2D rig;
        private Animator ani;
        private SpriteRenderer spriterender;
        private State state = State.Stop;
        private float currentTime;
        public GameObject puke;
        public float pukeSpeed;
        public int hp;
        public int totalHp;
        private bool isFlash = false;
        public float flashTime;
        public Color flashColor;
        public Color normalColor;
        public Color dangerColor;
        public float destoryTime;
    
        public GameObject bosspuke;
        public GameObject kill;
    
        public enum State
        {
            Stop,
            Walk,
            Attack,
            Die
        }
        // Use this for initialization
        void Start () {
            rig = this.GetComponent<Rigidbody2D>();
            ani = this.GetComponent<Animator>();
            spriterender = this.GetComponent<SpriteRenderer>();
            leftrange = this.transform.position.x - range;
            rightrange = this.transform.position.x + range;
        }
    
        void Update () {
    
            ChangeColor();
            ani.SetInteger("state", (int)state);
            if (state == State.Stop)
            {
                StartCoroutine(CancelStop());
            }
            else if (state == State.Walk)
            {
                currentTime += Time.deltaTime;
                if (currentTime > walkTime)
                {
                    currentTime = 0f;
                    state = State.Attack;
                }
                else
                {
                    if (this.transform.position.x > rightrange)
                    {
                        transform.localScale = new Vector3(-1F, 1F, 1F);
                        dir = -1F;
                    }
                    if (this.transform.position.x < leftrange)
                    {
                        transform.localScale = new Vector3(1F, 1F, 1F);
                        dir = 1F;
                    }
                }
            }
            else if (state == State.Die)
            {
                ani.enabled = false;
                this.GetComponent<Collider2D>().enabled = false;
                Destroy(this.gameObject, destoryTime);
            }
        }
    
        public void ChangeColor()
        {
            if (isFlash)
                spriterender.color = flashColor;
            else
                spriterender.color = normalColor;
            if (hp <= 1)
            {
                spriterender.color = dangerColor;
                if (hp <= 0)
                {
                    state = State.Die;
                }
            }
        }
    
        public void FixedUpdate()
        {
            if (state == State.Stop || state == State.Attack)
            {
                rig.velocity = Vector2.zero;
            }
            else if (state == State.Walk)
            {
                  rig.velocity = new Vector2(dir * speed, 0);
            }
            else if (state == State.Die)
            {
                rig.velocity = new Vector2(-3F,-1F);
            }
        }
    
        IEnumerator CancelStop()
        {
            yield return new WaitForSeconds(stopTime);
            state = State.Walk;
        }
    
        public void OnTriggerEnter2D(Collider2D collision)
        {
            if (collision.gameObject.tag == "Player" &&
              !PlayerController.instance.isFlash)
            {
                PlayerController.instance.Hurt();
                PlayerInfo.instance.SubHp();
            }
        }
    
        public void ChangeWalkState()
        {
            state = State.Walk;
        }
    
        public void Attack()
        {
            GameObject o = Instantiate(puke);
            Vector2 start = this.transform.Find("firePos").position;
            Vector2 end = GameObject.Find("player").transform.position;
            o.transform.position = start;
            Vector2 dir = end - start;
            dir = dir.normalized;
            o.GetComponent<Rigidbody2D>().velocity = dir*pukeSpeed;
            Instantiate(bosspuke);
        }
    
        public void Hit()
        {
            hp--;
            isFlash = true;
            StartCoroutine(ResetFlash());
            if (hp<=0)
            {
                Instantiate(kill);
            }
        }
    
        IEnumerator ResetFlash()
        {
            yield return new WaitForSeconds(flashTime);
            isFlash = false;
        }
    
    }
  15. 游戏的大体思路就是这样,让我们看看成品的图片





原文地址:https://www.cnblogs.com/raymondking123/p/8380117.html

时间: 2024-11-10 07:19:21

经典游戏还原之:松鼠大作战2的相关文章

经典游戏还原之:贪吃蛇

版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客"(微信号:unitymaker) 您可以自由转载,但必须加入完整的版权声明! 贪吃蛇与方块 主要玩法:贪吃蛇吃食物,吃到食物后根据相应数值增加身体长度,如果贪吃蛇碰到方块后,根据方块的数值逐渐减少贪吃蛇身体长度,如果贪吃蛇长度为0时,游戏结束,场景中会有一下墙壁阻挡贪吃蛇的左右移动. 角色操作:点击鼠标

刺猬大作战(游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4)

游戏特性[编辑] 游戏引擎用Free Pascal写成,GUI用C++写成,使用SDL和Qt4[2]. 0.9.12开始支持实时动态缩放游戏画面. 个性化[编辑] 刺猬大作战有着高度定制性 游戏模式:游戏方式可以发生很大变化,比如棒球模式中,所有刺猬都有保护膜无法损伤,只能击入水中退场 可以制作语音,游戏已经包括如海盗,唱诗风格等五种风格,使用开放的ogg格式 纸娃娃系统,不只可以为每个队员命名,还可以用头饰分辨每个人,已有超过90种头部装饰分辨每个刺猬 支持定制团队背景和离场的动画效果 武器[

cocos2d-x 3.2 之 三消类游戏——万圣大作战

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 首先祝大家万圣节快乐呀~ 紧赶慢赶,第二款cocos2d-x游戏终于出来了. 万圣大作战 三消类的游戏 下面是游戏的一些截图~ 主界面 设置界面: 游戏界面: 结束界面:         和第一款2048相比, 多了 分数的本地存储(未加密) 音乐和音效的 设置

[知了堂学习笔记]_用JS制作《飞机大作战》游戏_第2讲(四大界面之间的跳转与玩家飞机的移动)

一.通过点击按钮事件,实现四大界面之间的跳转: (一)跳转的思路: 1.打开软件,只显示登录界面(隐藏游戏界面.暂停界面.玩家死亡界面) 2.点击微信登录(QQ登录)跳转到游戏界面,隐藏登录界面 3.点击暂停,弹出具有透明度的暂停界面 4.点击暂停界面的开始按钮,隐藏暂停界面,调用开始方法(点击登录跳转的方法): 5.点击暂停界面的退出游戏,只显示登录界面,隐藏其他界面: 6.游戏结束界面,该界面的跳转目前还不能通过游戏实现,可以先建设(根据上一讲的游戏界面图片制作). 7.点击游戏结束界面的开

cocos2d-x 3.2 它 三消游戏——万圣节大作战

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 首先祝大家万圣节快乐呀~ 紧赶慢赶.第二款cocos2d-x游戏最终出来了. 万圣大作战 三消类的游戏 以下是游戏的一些截图~ 主界面 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHR0cmVl/font/5a6L

cocos2d-x 3.2 之 三消类游戏——万圣大作战 (第一篇)

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 废话: 放寒假了,放松了一下下....(有点多) 前几天 办了张健身卡,准备减肥了,健康重要啊,尤其是身为 程序猿. 话说,办完卡做的体测,20多岁的我,现在身体年龄竟然达到了40 ! 然后,拿了一个韩版 三星 Galaxy S 刷汉化,用惯了一键刷机,这些东西

当我阅读完上千行的游戏球球大作战战斗服务器端源码后...

这周服务器主程安排给了我一个任务(其实是我在用Go做完了一些小demo后,向主程请示下一步的安排),让我将他用Lua语言写的球球大作战的服务端代码转成Go语言形式. 于是,我开搞了! 此内容以上传至github,感兴趣的可以看一下github地址 框架主要分以下几个部分 1,sever-client部分 因为要有主入口,所以要新增一个server文件,client文件用来测试服务器端.而服务器又分以下几类: 与客户端的连接 选择进入的房间 进入房间后玩家数据的收发 战斗中的数据变化 2,玩家和A

球球大作战四亿人都在玩?玩家回归没有优越感,新玩家游戏被虐,游戏体验感极差!

球球大作战,这是一款很火的手游,自己曾经玩了3年的游戏,如今已经厌倦了,所以退游了. 当时任然记得猎魔模式,感觉身边都是人,这游戏身边都有人在玩.后面嘛,由于游戏氛围不太好,合作的人太多,一个人单排这种简直没法玩了,自然卸了. 当初为了棒棒糖,可以没日没夜的玩,可以说是'不择手段',好不容易攒够了棒棒糖,买了一个光环,虽然是比较廉价的,当时自己还是很激动,很开心的,也很心满意足的.当时球球大作战这一款游戏还是很良心的,没有像今天这么多的充值活动,现在的球球大作战怎么感觉越来越向腾讯游戏靠拢了?

贪吃蛇大作战的一点感悟

春节过罢,闲来无事,玩了两日贪吃蛇大作战,之前玩过球球大作战,感觉球球大作战玩法比较多,也比较难入门.而贪吃蛇大作战就简单多了,就两个原则:1不断地吃食物,让自己长大.2尽量避免撞到别人身上,以致于死亡.抱着这样的原则,我就开始了自己的贪吃之路. 刚开始的时候是小心翼翼地吃游戏自带的豆豆,也不敢去击杀别人,还经常撞到别人身上,所以更加小心地玩,自己长大了才敢去围追堵截别人,这样不知不觉居然就能玩到9000多长度了.接着再玩下去就有点心急了,一方面是有前边的经验,感觉也不太难嘛,另一方面想更快地打