指定角色的出生点

我在Object层中添加了一个文字物体,把Name改成born,把文字设置为spawn_point

这样nez的tmxMap对象就可以通过Name来获取到这个物体的坐标

            //获取到map对象的Object层
            var objectLayer = map.GetObjectGroup("obj");

            //寻找objectLayer层中第一个名字为born的物体
            var playerStartObject = objectLayer.Objects.FirstOrDefault(obj => obj.Name == "born");
            if (playerStartObject != null)
            {
                //把出生的坐标设置为这个物体的坐标
                spawn_point = new Vector2((int)playerStartObject.X, (int)playerStartObject.Y);
            }

因为之前在player.cs中使用了transform的方法,导致角色摄像机偏差。现在展示场景和角色的所有代码

MyScene.cs

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Nez;
using Nez.Sprites;
using Nez.Tiled;
using Nez.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Vector2 = Microsoft.Xna.Framework.Vector2;

namespace Project1
{
    public class MyScene:Scene
    {
        Entity mouse_ent;
        Entity player;
        public Vector2 spawn_point;
        public override void OnStart()
        {
            base.OnStart();
           
            Core.DebugRenderEnabled = false;

            var mouse_tex = Content.LoadTexture("mouse.png");
            var tex = Content.LoadTexture("Icon.bmp");
            var ent = CreateEntity("ent");
            ent.AddComponent(new SpriteRenderer(tex));

            ent.SetPosition(Screen.Width / 2, Screen.Height / 2);

            
            


            TmxMap map = Content.LoadTiledMap("Map/Scene.tmx");
            var tiledEntity = CreateEntity("tiled-map-entity");
            var com_map=tiledEntity.AddComponent(new TiledMapRenderer(map, "collide"));

            //获取到map对象的Object层
            var objectLayer = map.GetObjectGroup("obj");

            //寻找objectLayer层中第一个名字为born的物体
            var playerStartObject = objectLayer.Objects.FirstOrDefault(obj => obj.Name == "born");
            if (playerStartObject != null)
            {
                //把出生的坐标设置为这个物体的坐标
                spawn_point = new Vector2((int)playerStartObject.X, (int)playerStartObject.Y);
            }


            mouse_ent = CreateEntity("mouse");
            var sprite_mouse = mouse_ent.AddComponent(new SpriteRenderer(mouse_tex));
            sprite_mouse.SetOrigin(new Vector2(5, 0));

            player = AddEntity(new Player());
            player.SetLocalPosition(spawn_point);

        }
        public override void Update()
        {
            base.Update();
            Camera.Position = player.Position;
            Vector2 mouseWorldPos = Camera.ScreenToWorldPoint(Input.MousePosition);
            mouse_ent.SetPosition(mouseWorldPos);
            
        }
    }
}

Player.cs

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Nez;
using Nez.Sprites;
using Nez.Textures;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project1
{
    internal class Player:Entity
    {
        Texture2D spr_sheet;
        
        public SpriteAnimator _animator=new SpriteAnimator();

        public Mover mover = new Mover();

        public override void OnAddedToScene()
        {
            base.OnAddedToScene();

            AddComponent(mover);

            AddComponent(_animator);

            spr_sheet = Core.Content.LoadTexture("player.png");

            var _sprites = Sprite.SpritesFromAtlas(spr_sheet, 64, 64);


            _animator.AddAnimation("idle", _sprites.Take(1).ToArray(), 10);
            _animator.AddAnimation("run", _sprites.Skip(1).Take(7).ToArray(), 10);

            
            _animator.Play("run");

            var collider = AddComponent(new BoxCollider()).SetSize(20, 20).SetLocalOffset(new Vector2(0,20));

            Flags.SetFlagExclusive(ref collider.CollidesWithLayers, 0);
            Flags.SetFlagExclusive(ref collider.PhysicsLayer, 1);
        }

        public override void Update()
        {
            base.Update();
            var dirX =Convert.ToInt32(Input.IsKeyDown(Keys.D))-Convert.ToInt32(Input.IsKeyDown(Keys.A));
            var dirY = Convert.ToInt32(Input.IsKeyDown(Keys.S)) - Convert.ToInt32(Input.IsKeyDown(Keys.W));
            var spd = 1;

            //mover.ApplyMovement(new Vector2(dirX * spd, dirY * spd));
            mover.Move(new Vector2(dirX * spd, dirY * spd), out CollisionResult res);

            if (dirX!=0 || dirY != 0)
            {
                ChangeAnim("run");
                if (dirX < 0) {_animator.FlipX= true; }
                if (dirX > 0) { _animator.FlipX = false; }
            }
            else
            {
                ChangeAnim("idle");
            }
        }

        public void ChangeAnim(string anim_name)
        {
            if (_animator != null && !_animator.IsAnimationActive(anim_name)) {
                _animator.Play(anim_name);
            }
        }
    }
}

运行之后,角色可以出生在指定的物体坐标上

检测角色所在区域

现在让我们检测一下区域的识别

我绘制了一个感叹号,作为角色进入场景的反馈。

mark.png

我们为它单独做一个实体,因为它可以出生和销毁

using Nez;
using Nez.Sprites;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Vector2 = Microsoft.Xna.Framework.Vector2;
namespace Project1
{
    public class Mark:Entity

    {
        public Mover mover=new();
        public int timer=0;
        public override void OnAddedToScene()
        {
            base.OnAddedToScene();
            var tex = Core.Content.LoadTexture("mark.png");
            AddComponent(new SpriteRenderer(tex));
            AddComponent(mover);
        }
        public override void Update()
        {
            base.Update();
            timer += 1;
            if (timer > 50)
            {
                Destroy();
            }
            mover.ApplyMovement(new Vector2(0, -1f));

        }
    }
}

在tiled中的物体层添加一个矩形,name设置为area

来到MyScene.cs中,我们初始化2个变量

        public RectangleF area_rec;

        public int mark_spawn_timer = 0;

一个用来记录区域的数据,另一个用来决定生成mark的频率

接下来检测area并且把数据装进rec中

           var area_object = objectLayer.Objects.FirstOrDefault(obj => obj.Name == "area");
           if (area_object != null)
           {
               
               area_rec.X = area_object.X;
               area_rec.Y = area_object.Y;
               area_rec.Width = area_object.Width;
               area_rec.Height = area_object.Height;

           }

然后检测角色的坐标是否在recF里面,如果是的话,就根据这个timer来生成Mark实体

            if (area_rec.Contains(player.Position))
            {
                mark_spawn_timer += 1;
                if (mark_spawn_timer > 50)
                {
                    AddEntity(new Mark().SetPosition(
                        new Vector2(
                        player.Position.X+20,
                        player.Position.Y-30)
                        ));
                        ;
                    mark_spawn_timer = 0;
                }
            }

最后我们就能实现角色进入区域的时候,每隔一段时间就提出一个警告的效果了

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐