[Monogame && Nez]学习笔记004|tiledMap.Object层:坐标提取,区域检测
本文介绍了在Nez游戏引擎中实现角色出生点设置和区域检测的方法。首先通过在Tiled地图的Object层添加名为"born"的文字物体来指定角色出生位置,代码中通过查找该物体获取坐标。其次展示了如何检测角色是否进入特定区域:在Tiled中添加名为"area"的矩形区域,代码中创建RectangleF对象保存区域数据,当角色进入该区域时,会定时生成Mark实体
·
指定角色的出生点

我在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;
}
}
最后我们就能实现角色进入区域的时候,每隔一段时间就提出一个警告的效果了

更多推荐

所有评论(0)