Reputation: 97
I know this question is very specific to those familiar with both tiled and monogame, so I'll try to be a thorough as possible. I've been working on this issue for 15+ hours and am desperate.
I'm trying to draw sprites to the screen using Tiled's object layer. I've created a new object layer, drew some rectangles to it, and added a custom property which I reference in my LoadContent method.
Here is my LoadContent Method:
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
mymap = Content.Load<TiledMap>("Misc/newmap");
enemyShip = Content.Load<Texture2D>("Enemies/enemyship");
//TiledMapObject[] islands = mymap.GetLayer<TiledMapObjectLayer>("Islands").Objects;
ship_sprite = Content.Load<Texture2D>("character/wooden_ship");
Texture2D texture = Content.Load<Texture2D>("character/anima2");
animatedSprite = new AnimatedSprite(texture, 1, 2);
font = Content.Load<SpriteFont>("Misc/londrinasolid");
Song song = Content.Load<Song>("Music/Chad_Crouch_-_Stellars_Jay");
MediaPlayer.Volume = 0.7F;
MediaPlayer.Play(song);
TiledMapObject[] littleBoats = mymap.GetLayer<TiledMapObjectLayer>("SmallBoats").Objects;
foreach (var en in littleBoats)
{
string type;
en.Properties.TryGetValue("type", out type);
if (type == "smallboat")
{
Enemy.enemies.Add(new SmallBoat(en.Position));
}
}
// TODO: use this.Content to load your game content here
}
I've created a TiledMapObject Array which takes the items from the tiledmap object layer. It also checks the custom property name. If it it's "type", which you can see labeled in the bottom lefthand corner of the tiledmap picture, it takes that object and adds it to the array at the position on the tiledmap (at least it's supposed to).
In the draw method, I create a temporary Texture2D variable which references the aforementioned enemy list (which is now filled with two elements from the tiled map). If type Smallboat, it then draws the sprite I want to draw, which it does, just at the wrong position. Here is the relevant draw method:
foreach (Enemy en in Enemy.enemies)
{
Texture2D spritetoDraw;
int rad;
if (en.GetType() == typeof(SmallBoat))
{
rad = 16;
spritetoDraw = enemyShip;
}
else
{
rad = 30;
spritetoDraw = ship_sprite;
}
spriteBatch.Draw(spritetoDraw, new Vector2(en.Position.X - rad, en.Position.Y - rad), Color.White);
}
And here is the starting position of the enemy boat once I run, it's slightly offset from the origin 0,0 because in the draw method I subtract the radius:
Here is my Enemy class, with the SmallBoat child class at the bottom. I've created a new list which should contain the objects from the tiled layer once they are added in the LoadContent method in my main file. I've checked that the objects are being added by using Enemy.Remove(), and they are, so I know that at least the program recognizes the objects in the tiled file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace my_first_game
{
class Enemy
{
private Vector2 position;
protected int radius;
float circle = MathHelper.Pi * 2;
public float rotationAngle;
protected int health;
public static List<Enemy> enemies = new List<Enemy>();
public int Radius { get { return radius; } }
public Vector2 Position { get { return position; }}
public int Health { get { return health; } set { value = health; } }
public Enemy(Vector2 newpos)
{
newpos = position;
}
public void Update(GameTime gametime, Vector2 playerPos)
{
rotationAngle = circle % 2;
double dt = gametime.ElapsedGameTime.TotalSeconds;
Vector2 direction = new Vector2((float)Math.Cos(rotationAngle), (float)Math.Sin(rotationAngle));
Vector2 movedir = Position - playerPos;
movedir.Normalize();
position -= movedir;
}
}
class SmallBoat : Enemy
{
public SmallBoat(Vector2 newpos) : base(newpos)
{
//radius = 50;
}
}
}
What I've tried:
1). commented out all update methods and ran, nothing changes except the ship's don't move.
2). Drawn new rectangles, erased old ones, deleted and created object layers.
3). if I remove a rectangle from the object layer, there are less boats drawn to the screen once the game is running. Therefore I know that the enemies are being drawn to the screen, just not at the right position.
4). Changed the coordinates to a hardcoded fixed number in the draw method instead of en.position.X and en.position.Y. This changes the starting position to the desired location, but it's hardcoded and doesn't solve the problem.
5). Rearranged elements in the loadcontent method and draw method, to no avail.
It seems that the list is being properly referenced and that the issue is that for some reason the coordinates on the tiled map aren't transfering over. Much of my code is based off of a Udemy Monogame tutorial, and the loadcontent method and draw method are basically the same.
Any and all help is warmly welcomed. Please let me know if there's any other information I can provide.
Edit: Here is the entire draw method.
protected override void Draw(GameTime gameTime)
{
controller.controller_update(gameTime);
spriteBatch.Begin();
if (controller.ingame == false)
{
spriteBatch.DrawString(font, "Welcome to Thallasaphobia. \n press Enter to Begin", new Vector2(100, 100), Color.White);
}
spriteBatch.End();
if (controller.ingame == true)
{
GraphicsDevice.Clear(Color.Black);
mapRenderer.Draw(mymap, cam.GetViewMatrix());
spriteBatch.Begin(transformMatrix: cam.GetViewMatrix());
animatedSprite.Draw(spriteBatch, new Vector2(480, 350));
//create a new rectangle around the ship_sprite
Rectangle ship_rectangle = new Rectangle(0, 0, ship_sprite.Width, ship_sprite.Height);
Vector2 origin = new Vector2(ship_sprite.Width / 2, ship_sprite.Height + 15);
foreach (Enemy en in Enemy.enemies)
{
Texture2D spritetoDraw;
int rad;
if (en.GetType() == typeof(SmallBoat))
{
rad = 16;
spritetoDraw = enemyShip;
}
else
{
rad = 30;
spritetoDraw = ship_sprite;
}
spriteBatch.Draw(spritetoDraw, new Vector2(en.Position.X - rad, en.Position.Y - rad), Color.White);
}
spriteBatch.Draw(ship_sprite, ship.Position, ship_rectangle, Color.White, ship.rotationAngle + MathHelper.Pi/2, origin, 1.0f, SpriteEffects.None, 1);
}
spriteBatch.End();
base.Draw(gameTime);
}
Upvotes: 1
Views: 500
Reputation: 76
Although I don't really have a means of testing this, I believe the problem is in your constructor. You currently have this code:
public Enemy(Vector2 newpos)
{
newpos = position;
}
You should actually have:
public Enemy(Vector2 newpos)
{
position = newpos;
}
Since "position" is the property of the Enemy class, THAT is the value we want updated, not newpos, which is just a parameter. So that would explain why your enemy is starting at the origin, because its position is never being initially set.
Upvotes: 6