I am trying to call a 'shoot laser' function, which is in my ProjectileManager Class, from my Player class controls.
Thing is, when I call the exact same function from either my ProjectileManager or the Game1 (main game) class - it works. otherwise I am getting a null on the sprite.
I am doing a content.load on the sprite in projectilemanager class, which works fine when i call the shoot laser function from either the projectilemanager itself or the main game - but not the player class?
note: ive cut out alot of pointless additional functions within these classes for readability
Game1 Class
public class Game1 : Microsoft.Xna.Framework.Game
{
// CLASSES
Player myPlayer;
ProjectileManager projectileManager = new ProjectileManager();
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
projectileManager.ContentLoad(Content);
}
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.V)) //SHOOT LASER TEST - WORKS
{
projectileManager.ShootLaser(new Vector2(5, 5), 5, 1, new Vector2(0, 0), 0, 0);
}
myPlayer.Update();
projectileManager.Update();
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
GraphicsDevice.SamplerStates[0] = noFilter;
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, null, null);
myPlayer.Draw(spriteBatch);
projectileManager.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
Player Class
class Player
{
// Inherent classes
ProjectileManager projectileManager = new ProjectileManager();
Texture2D sprite;
public Vector2 direction;
float speed;
float health;
int spriteType;
public void Update()
{
UpdateControls();
}
void UpdateControls()
{
if (Keyboard.GetState().IsKeyDown(Keys.Space)) //SHOOT LASER - DOESNT WORK
{
projectileManager.ShootLaser(new Vector2(5, 5), 5, 1, new Vector2(0, 0), 0, 0);
}
}
}
Projectile Manager Class
class ProjectileManager
{
//Lists
List<Projectile> projectiles = new List<Projectile>();
//Sprites
Texture2D sprite;
Texture2D spriteLaser;
//Attributes
Vector2 position;
Vector2 dimensions;
int attackPower;
int moveType; //0 = direction based, 1 = homing on player, 3 = hybrid of both (like a missile that fires straight then turns towards target
int team; //the team that the laser is on for collision
Vector2 direction;
float speed;
public ProjectileManager(){}
public void Update()
{
if (Keyboard.GetState().IsKeyDown(Keys.E))
{
ShootLaser(new Vector2(5,5), 5, 1, new Vector2(0,0), 0, 0);
}
foreach (Projectile each in projectiles)
{
each.Update();
}
}
public void ContentLoad(ContentManager content)
{
spriteLaser = content.Load<Texture2D>("playerLaser");
}
public void Draw(SpriteBatch spritebatch)
{
foreach (Projectile each in projectiles)
{
each.Draw(spritebatch);
}
}
public void ShootLaser (Vector2 a_position, int a_attackPower, float a_speed, Vector2 a_direction, int a_moveType, int a_team)
{
position = a_position;
attackPower = a_attackPower;
speed = a_speed;
direction = a_direction;
moveType = a_moveType;
team = a_team;
projectiles.Add(new Projectile(spriteLaser, position, 5, 2, new Vector2(0,1), 0, 0));
}
}
projectile class
class Projectile
{
Vector2 position;
int attackPower;
int moveType; //0 = direction based, 1 = homing on player, 3 = hybrid of both (like a missile that fires straight then turns towards target
int team; //the team that the laser is on for collision
Texture2D sprite;
Vector2 direction;
float speed;
public Projectile(Texture2D a_sprite, Vector2 a_position, int a_attackPower, float a_speed, Vector2 a_direction, int a_moveType, int a_team) //possibly add another variable for hitting other projetiles / cancelling them out
{
sprite = a_sprite;
position = a_position;
attackPower = a_attackPower;
speed = a_speed;
direction = a_direction;
moveType = a_moveType;
team = a_team;
}
public void Update()
{
//movement
// if movetype = 1
if (moveType == 0) // straight line
{
position.Y++;
//position += direction * speed;
}
}
//public Rectangle GetRectangle()
//{
// return new Rectangle((int)m_position.X, (int)m_position.Y, (int)m_dimensions.X, (int)m_dimensions.Y);
//}
// We pass-in a 'SpriteBatch' object so this function
// can call the 'Draw' function on it.
public void Draw(SpriteBatch spritebatch)
{
spritebatch.Draw(sprite, position, Color.White);
}
}
Ive just started learning C#, I cant find any reference to why in the game and projectile manager classes the shootlaser function works, but calling from the player yields no results.
ive tried to debug using breakpoints and from what I can gather the projectile Texture2D sprite is returning a null when the function is called through the player class..
Thoughts?
Thanks
Add a ContentLoad method to your Player class and call the projectileManager.ContentLoad there then call myPlayer.ContentLoad in Game1.LoadContent Method
public class Game1 : Microsoft.Xna.Framework.Game
{
// CLASSES
Player myPlayer;
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
myPlayer.ContentLoad(CoolContent);
}
player class:
class Player
{
// Inherent classes
ProjectileManager projectileManager = new ProjectileManager();
Texture2D sprite;
public Vector2 direction;
float speed;
float health;
int spriteType;
public void LoadContent(CoolContentType coolContent)
{
projectileManager.LoadContent(coolContent);
}
public void Update()
{
UpdateControls();
}
in addition to linking your ContentLoad Method calls. you should get rid of the Texture2D in the Projectile class because it is redundant.
all you need is the values from the Projectiles in your Draw calls while ProjectileManager stores the texture.
class ProjectileManager
{
//Lists
List<Projectile> projectiles = new List<Projectile>();
//Sprites
Texture2D sprite;
Texture2D spriteLaser;
//Attributes
Vector2 position;
Vector2 dimensions;
int attackPower;
int moveType; //0 = direction based, 1 = homing on player, 3 = hybrid of both (like a missile that fires straight then turns towards target
int team; //the team that the laser is on for collision
Vector2 direction;
float speed;
public ProjectileManager(){}
public void Update()
{
if (Keyboard.GetState().IsKeyDown(Keys.E))
{
ShootLaser(new Vector2(5,5), 5, 1, new Vector2(0,0), 0, 0);
}
foreach (Projectile each in projectiles)
{
each.Update();
}
}
public void ContentLoad(ContentManager content)
{
spriteLaser = content.Load<Texture2D>("playerLaser");
}
public void Draw(SpriteBatch spritebatch)
{
spritebatch.Begin();
foreach (Projectile p in projectiles)
{
spritebatch.draw(spriteLaser, p.position,Color.CoolColor);//see how I use the projectile info (p.position). it doesn't need it's own texture :)
}
spritebatch.End();
}
Related
I want to change between 2 materials, depending on the platforms (gameobject) rotation.
Here is what I've done so far:
public class PlatformSpawner : MonoBehaviour
{
public GameObject platform;
public Material[] platformMaterial;
Material currentMaterial;
Renderer _renderer;
}
void Start()
{
_renderer = this.GetComponent<Renderer>();
}
I also wrote this, but I don't want to change materials by buttons:
public void LeftTurn()
{
_renderer.material = platformMaterial[0];
currentMaterial = _renderer.material;
}
public void RightTurn()
{
_renderer.material = platformMaterial[1];
currentMaterial = _renderer.material;
}
}
And this is where the platform rotates randomly 90 degrees to the left or to the right:
public struct SpawnPoint
{
public Vector3 position;
public Quaternion orientation;
public void Step(float distance)
{
if (Random.value < 0.5)
{
position.x += distance;
orientation = Quaternion.Euler(0, 90, 0); //change to one of the materials
}
else
{
position.z += distance;
orientation = Quaternion.Euler(0, 0, 0); //change to the other of the materials.
//This is where I want to material to switch.
//When the objects position changes, the material changes too.
}
}
}
There is a picture of the gameplay. I want to change the material of all the corner platforms to have a nice curve line view.
Can anyone help me what and how to do in this case? I am a bit lost there.
Every help is highly appreciated!
EDIT: new code looks like that. The only issue is that Unity gives me 15 errors (see on the picture below), even if Visual Studio says no issue has been found. The errors refer to the switch.
public class PlatformSpawner : MonoBehaviour
{
public GameObject platform;
public Transform lastPlatform;
SpawnPoint _spawn;
bool stop;
public Material straightMaterial;
public Material turnLeftMaterial;
public Material turnRightMaterial;
public Renderer roadPrefab;
[System.Serializable]
public struct SpawnPoint
{
public Vector3 position;
public Quaternion orientation;
public RoadType type;
public enum RoadType
{
Straight,
LeftTurn,
RightTurn
}
private enum Direction
{
Z,
X,
}
private Direction lastDirection;
public void Step(float distance)
{
type = RoadType.Straight;
if (Random.value < 0.5f)
{
position.x += distance;
orientation = Quaternion.Euler(0, 90, 0);
if (lastDirection == Direction.Z)
{
type = RoadType.RightTurn;
}
}
else
{
position.z += distance;
orientation = Quaternion.Euler(0, 0, 0);
if (lastDirection == Direction.X)
{
type = RoadType.LeftTurn;
}
lastDirection = Direction.Z;
}
}
}
void Start()
{
_spawn.position = lastPlatform.position;
_spawn.orientation = transform.rotation;
StartCoroutine(SpawnPlatforms());
}
IEnumerator SpawnPlatforms()
{
while (!stop)
{
var _spawn = new SpawnPoint();
for (var i = 0; i < 20; i++)
{
var newPlatform = Instantiate(roadPrefab, _spawn.position, _spawn.orientation);
_spawn.Step(1.5f);
var roadMaterial = _spawn.type switch
{
SpawnPoint.RoadType.LeftTurn => turnLeftMaterial,
SpawnPoint.RoadType.RightTurn => turnRightMaterial,
_ => straightMaterial
};
newPlatform.GetComponent<Renderer>().material = roadMaterial;
yield return new WaitForSeconds(0.1f);
}
}
}
}
So it sounds like you basically have a working system for switching the materials and spawning you road parts and materials already look correctly according to your rotations - now you only need to identify the curves.
Actually this is pretty simple:
is the current part in X direction and the next will be in Z -> Left Turn
is the current part in Z direction and the next will be in X -> RightTurn
any other case is straight
So you could probably do something like
public struct SpawnPoint
{
public Vector3 position;
public Quaternion orientation;
public RoadType type;
public enum RoadType
{
Straight,
LeftTurn,
RightTurn
}
private enum Direction
{
// since your orientation by default equals the Z direction use that as default value for the first tile
Z,
X,
}
private Direction lastDirection;
public void Step(float distance)
{
type = RoadType.Straight;
if (Random.value < 0.5f)
{
position.x += distance;
orientation = Quaternion.Euler(0, 90, 0);
if(lastDirection == Direction.Z)
{
type = RoadType.RightTurn;
}
lastDirection = Direction.X;
}
else
{
position.z += distance;
orientation = Quaternion.Euler(0, 0, 0);
if(lastDirection == Direction.X)
{
type = RoadType.LeftTurn;
}
lastDirection = Direction.Z;
}
}
}
And you didn't show your spawn code but I would assume something like
public class Example : MonoBehaviour
{
public Material straightMaterial;
public Material turnLeftMaterial;
public Material turnRightMaterial;
public Renderer roadPrefab;
private void Awake()
{
var spawnPoint = new SpawnPoint();
for(var i = 0; i < 20; i++)
{
var roadTile = Instantiate(roadPrefab, spawnPoint.position, spawnPoint.orientation);
// do the Step after spawning the current tile but before assigning the material
// -> we want/need to know already where the next tile is going to be
spawnPoint.Step(1f);
var roadMaterial = spawnPoint.type switch
{
SpawnPoint.RoadType.LeftTurn => turnLeftMaterial,
SpawnPoint.RoadType.RightTurn => turnRightMaterial,
_ => straightMaterial
};
roadTile.GetComponent<Renderer>().material = roadMaterial;
}
}
}
Behold my Paint skills ;)
This will get you started using Quaternion.Dot.
using UnityEngine;
[RequireComponent(typeof(Renderer))]
public class NewBehaviourScript : MonoBehaviour
{
public Material Material1;
public Material Material2;
public Vector3 Euler = new(90, 0, 0);
private Renderer _renderer;
private void Start()
{
_renderer = GetComponent<Renderer>();
_renderer.material = Material1;
}
private void Update()
{
var dot = Quaternion.Dot(transform.rotation, Quaternion.Euler(Euler));
if (Mathf.Approximately(dot, 1.0f))
{
_renderer.material = Material2;
}
else
{
_renderer.material = Material1;
}
}
}
Using different materials for N, E, S, W corners:
using UnityEngine;
[RequireComponent(typeof(Renderer))]
public class NewBehaviourScript : MonoBehaviour
{
public Material Material1;
public Material Material2;
public Material Material3;
public Material Material4;
public Vector3 Euler1 = new(0, 0, 0);
public Vector3 Euler2 = new(0, 90, 0);
public Vector3 Euler3 = new(0, 180, 0);
public Vector3 Euler4 = new(0, 270, 0);
private Renderer _renderer;
private void Start()
{
_renderer = GetComponent<Renderer>();
_renderer.material = Material1;
}
private void Update()
{
if (Mathf.Approximately(Quaternion.Dot(transform.rotation, Quaternion.Euler(Euler1)), 1.0f))
{
_renderer.material = Material1;
}
if (Mathf.Approximately(Quaternion.Dot(transform.rotation, Quaternion.Euler(Euler2)), 1.0f))
{
_renderer.material = Material2;
}
if (Mathf.Approximately(Quaternion.Dot(transform.rotation, Quaternion.Euler(Euler3)), 1.0f))
{
_renderer.material = Material3;
}
if (Mathf.Approximately(Quaternion.Dot(transform.rotation, Quaternion.Euler(Euler4)), 1.0f))
{
_renderer.material = Material4;
}
}
}
Make sure to wrap the rotation past 360 degrees, else it'll always look yellow (4th material).
I am trying to create level prograss bar, here is the script to fill the Slider along with ball when its moving towards finish line , here finish line is prefab clone which is randomly instantiated at different position. but as expected finishTransform using position(0, 0, 0) from prefab not from the clone. how can i retrieve the clone into the script when it is instantiated? here is the Progressbar Script :
[SerializeField] Transform ballTransform;
[SerializeField] Transform finishTransform;
[SerializeField] Slider slider;
float maxDistance;
void Start()
{
maxDistance = getDistance();
}
void Update()
{
if (ballTransform.position.z <= maxDistance && ballTransform.position.z <= finishTransform.position.z)
{
float distance = 1 - (getDistance() / maxDistance);
setProgress(distance);
}
}
float getDistance()
{
return Vector3.Distance(ballTransform.position, finishTransform.position);
}
void setProgress(float p)
{
slider.value = p;
}
Here is the Platform script where i instantiated the finish line
GameObject finalPlatformInstance = Instantiate(finalPlatform, transform);
finalPlatformInstance.transform.localPosition = new Vector3(0, 0, spawnPosZ);
This can be a solution.
public class PlatformSpawner : MonoBehaviour
{
public GameObject finalPlatform; // This get injected in the editor
public GameObject finalPlatformInstance;
void Awake()
{
finalPlatformInstance = Instantiate(finalPlatform, transform);
finalPlatformInstance.transform.localPosition = new Vector3(0, 0, z);
// TODO: add other logic...
}
}
public class ProgressBar : MonoBehaviour
{
private Platform platform;
void Start()
{
platform = FindObjectOfType<PlatformSpawner>();
}
void Update()
{
// TODO: access it via "platform.finalPlatformInstance"
}
}
I'm currently creating a 2D game engine in C#. At the moment, I'm implementing an entity component system.
My structure is as follows:
Entity Class: Contains a list of IGameComponent's, you can add, remove and delete any component by class type. (ie; entity.RemoveComponent(typeof(Transform));. It also contains a parent Entity, and a list child entities.
IGameComponent Interface: For now, is just an empty interface. (Note that: Components only contain data, and not functionality)
Entity Pool: Contains a list of all the active objects in the game, it's also used to create and destroy entities.
Everything so far is great.
However, I'm faced with a problem. Since components only contain data I need a way to initialize, update and render the components and I'd rather not just add a bunch of virtual methods to a GameComponent class, however I don't know of any other way to resolve it.
What are my options?
EDIT:
I've seen that Unity uses methods like 'SendMessage' which I can only assume uses reflection to call methods. Should I implement something similar?
I don't know if you still need it, but I have made something similar a few years ago and it might help you. It's written in C# built on top of MonoGame/XNA
You GameObject class can look like this
public class GameObject
{
List<GameObjectComponent> _goComponent = new List<GameObjectComponent();
public T GetComponent<T>() where T : GameObjectComponent
{
foreach (GameObjectComponent goc in _goComponent)
if (goc.GetType().Equals(typeof(T)))
return (T)goc;
return null;
}
public void AddComponent(GameObjectComponent gameObjectComponent)
{
_goComponent.Add(gameObjectComponent);
gameObjectComponent.gameObject = this;
gameObjectComponent.Init();
}
public virtual void Update(GameTime gameTime)
{
foreach (GameObjectComponent _goc in _goComponent)
_goc.Update(gameTime);
}
public static void Instantiate(GameObject gameObject)
{
Scene._AddedGO.Add(gameObject);
}
public static void Destroy(GameObject gameObject)
{
Scene._RemoveGO.Add(gameObject);
}
}
GameObjectComponent is similar to MonoBehaivior from Unity3D
public class GameObjectComponent
{
public GameObject gameObject;
public GameObjectComponent()
{
}
public virtual void Init()
{
}
public virtual void Update(GameTime gameTime)
{
}
}
and then you Inherit other classes like so:
public class Sprite : GameObjectComponent
{
public Texture2D texture;
public Vector2 origin = Vector2.Zero;
public Rectangle rect;
public Rectangle sourceRect;
public Color color = Color.White;
public float rotation = 0f;
private float layerDepth = 0f;
public int scale = 1;
public Sprite()
{
}
public void Load(string path)
{
texture = Setup.ContentDevice.Load<Texture2D>(path);
}
}
now you can finally create you Player GameObject
class Player : GameObjectComponent
{
float speed = 150f;
KeyboardState keyState;
float pos_X;
float pos_Y;
int rect_X;
int rect_Y;
public Player(float x, float y, int rx, int ry)
{
pos_X = x;
pos_Y = y;
rect_X = rx;
rect_Y = ry;
}
public override void Init()
{
Sprite sprite = new Sprite();
gameObject.AddComponent(sprite);
gameObject.GetComponent<Sprite>().Load("Sprites/MainGuySpriteSheet_0");
gameObject.GetComponent<Sprite>().scale = 1;
gameObject.GetComponent<Sprite>().rect = new Rectangle(46, 0, 32, 36);
Transform transform = new Transform();
gameObject.AddComponent(transform);
// gameObject.GetComponent<Transform>().position = new Vector2(Screen.width / 2 - gameObject.GetComponent<Sprite>().rect.Width, Screen.height / 2 - gameObject.GetComponent<Sprite>().rect.Height);
gameObject.GetComponent<Transform>().position = new Vector2(pos_X, pos_Y - 32 * (gameObject.GetComponent<Sprite>().scale - 1));
RectCollider collider = new RectCollider();
gameObject.AddComponent(collider);
gameObject.GetComponent<RectCollider>().Set(gameObject.GetComponent<Sprite>(), gameObject.GetComponent<Transform>());
SpriteRenderer render = new SpriteRenderer();
gameObject.AddComponent(render);
gameObject.GetComponent<SpriteRenderer>().layer = 1;
gameObject.GetComponent<SpriteRenderer>().Set(gameObject.GetComponent<Sprite>());
}
public override void Update(GameTime gameTime)
{
//movex = transform.position.X -= 25 * gameTime.DeltaTime();
if (Keyboard.GetState().IsKeyDown(Keys.Left))
gameObject.GetComponent<Transform>().Move(-speed * gameTime.DeltaTime(), 0);
else if (Keyboard.GetState().IsKeyDown(Keys.Right))
gameObject.GetComponent<Transform>().Move(speed * gameTime.DeltaTime(), 0);
else if (Keyboard.GetState().IsKeyDown(Keys.Down))
gameObject.GetComponent<Transform>().Move(0, speed * gameTime.DeltaTime());
else if (Keyboard.GetState().IsKeyDown(Keys.Up))
gameObject.GetComponent<Transform>().Move(0, -speed * gameTime.DeltaTime());
if (Keyboard.GetState().IsKeyDown(Keys.Space) && !keyState.IsKeyDown(Keys.Space))
{
GameObject tomato = new GameObject();
tomato.AddComponent(new Tomato());
tomato.GetComponent<Transform>().position = gameObject.GetComponent<Transform>().position;
GameObject.Instantiate(tomato);
}
if (Keyboard.GetState().IsKeyDown(Keys.Q) && !keyState.IsKeyDown(Keys.Q))
{
SceneManager.LoadScene(new AnotherOne());
}
keyState = Keyboard.GetState();
gameObject.GetComponent<Transform>().position.Y = MathHelper.Clamp(gameObject.GetComponent<Transform>().position.Y, 0, Screen.bounds.Height - gameObject.GetComponent<Sprite>().rect.Height * gameObject.GetComponent<Sprite>().scale);
gameObject.GetComponent<Transform>().position.X = MathHelper.Clamp(gameObject.GetComponent<Transform>().position.X, 0, Screen.bounds.Width - gameObject.GetComponent<Sprite>().rect.Width * gameObject.GetComponent<Sprite>().scale);
}
}
I hope it's not too confusing and helps you a little bit.
To make it clearer I leave a link to the git here: https://github.com/Memorix101/MonoGame_ComponentSystem
Cheers, Memorix101 :)
I'm using XNA to create a Space Invaders copy. So I'm animating many sprites with the same logic placed in their own class, but using different values for most vars. Here is my way of animating from spritesheets:
Texture2D playerTex;
Vector2 playerPos = new Vector2(x, y), playerOrigin;
Rectangle playerHitBox;
float animationTimer = 0f, animationInterval = 100f;
int currentFrame = 1, frameWidth = example number, frameHeight = example number 2;
public void LoadContent(ContentManager Content)
{
playerTex = Content.Load<Texture2D>("ship");
}
public void Update(GameTime gameTime)
{
playerHitBox = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
playerOrigin = new Vector2(playerHitBox.X / 2, playerHitBox.Y / 2);
animationTimer += (float)gameTime.ElapsedGameTime.Milliseconds;
if (animationTimer > animationInterval)
{
currentFrame++;
animationTimer = 0f;
}
if (currentFrame == 2)
{
currentFrame = 0;
}
playerHitBox = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
playerOrigin = new Vector2(playerHitBox.Width / 2, playerHitBox.Height / 2);
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(playerTex, playerPos, playerHitBox, Color.White, 0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
}
Instead of using this logic for every animating object within its own class I'm looking for a way to create a sprite class anduse inheritance to Update()/Draw() the sprite. Could something like this be a good approach for the Draw() method?
public void Draw(Texture2D spriteTex, Vector2 spritePos, Nullable<Rectangle> spriteSourceRect, Color spriteColor, Single spriteRotation, Vector2 spriteOrigin, Vector2 spriteScale, SpriteEffects spriteEffects, Single spriteLayerDepth, SpriteBatch spriteBatch)
{
if (spriteTex != null)
{
spriteBatch.Draw(spriteTex, spritePos, spriteSourceRect, spriteColor, spriteRotation, spriteOrigin, spriteScale, spriteEffects, spriteLayerDepth);
}
}
You can:
Create Sprite class to keep common animation properties like texture, duration and current index.
Create Invider class for custom data like position, health and other.
Create a collection to store custom data for each object in game class.
For example:
class Sprite
{
public Texture2D texture;
public Rectangle Frame;
private frameIndex;
private frameCount;
private frameDuration;
private frameInterval;
public Sprite(Texture pTexture, ...)
{
// init sprite data
}
public Update(GameTime pGameTime)
{
// update sprite data
}
}
class Invider
{
private Sprite Sprite;
public Vector2 Porision;
public int Health;
public Invider(Sprite pSprite, Vector2 pPosition)
{
this.Sprite = pSprite;
this.Position = pPosition;
}
public void Update(GameTime pGameTime)
{
// update invider data
}
public void Draw(SpriteBatch pSpriteBatch)
{
pSpriteBatch.Draw(this.Sprite.Texture, this.Sprite.Frame, this.Position, Color.White);
}
}
public class Game1 : Game
{
private SpriteBatch spriteBatch;
private Dictionary<int, Invider> invidersByID;
private Sprite inviderSprite;
public override Initialize()
{
// fill inviderByID collection
}
public override LoadData()
{
// create inviderSprite
}
public static UpdateStatic(GameTime pGameTime)
{
// update static data like frame index
}
public override void Update(GameTime pGameTime)
{
this.inviderSprite.Update(pGameTime);
foreach(Invider invider in invidersByID.Values){
{
invider.Update(pGameTime);
}
}
public override Draw(SpriteBatch pSpriteBatch)
{
this.spriteBatch.Begin();
foreach(Invider invider in invidersByID.Values){
{
invider.Update(pGameTime);
}
this.spriteBatch.End();
}
}
I have 3 classes:
- Game1 (main class)
- Entity (base entity class)
- Player (player class, extends Entity class)
I draw the player class, but after that I can't seem to change the position of the player object.
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//Create a list with all the entities
List<Entity> entityList = new List<Entity>();
//Player
Player player;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
//Create player
Texture2D playertexture = Content.Load<Texture2D>("player/player");
Rectangle playerrectangle = new Rectangle(10, 10, playertexture.Width, playertexture.Height);
player = new Player(playertexture, playerrectangle);
entityList.Add(player);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
//Update players and entities
player.Update(graphics.GraphicsDevice);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
//Draw player
player.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
class Entity
{
//Standard variables
int health;
int armor;
float speed;
float friction;
//Get graphic and bounding box
Texture2D texture;
Rectangle rectangle;
public Entity(Texture2D newTexture, Rectangle newRectangle){
texture = newTexture;
rectangle = newRectangle;
}
public void Update(GraphicsDevice graphics) {
}
public void Draw(SpriteBatch spriteBatch) {
}
/*
* Modifiers for the variables
*/
public void modifyHealth(int amount) { health = health + amount; }
public void modifyArmor(int amount){ armor = armor + amount; }
public void modifySpeed(float amount) { speed = speed + amount; }
/*
* Getters for variables
*/
public int getHealth() { return health; }
public int getArmor() { return armor; }
public float getSpeed() { return speed; }
public float getFriction() { return friction; }
/*
* Setters for variables
*/
public void setHealth(int amount) { health = amount; }
public void setArmor(int amount) { armor = amount; }
public void setSpeed(float amount) { speed = amount; }
public void setFriction(float amount) { friction = amount; }
/*
* Functions
*/
public void damage(int damage) {
/*
* Calculate health
*
* Armor takes half the damage, if possible
*/
if (damage / 2 >= armor) {
damage = damage / 2;
armor -= damage;
} else if (armor > 0) {
damage -= armor;
armor = 0;
}
health -= damage;
if(health <= 0){
health = 0;
//TODO Death
}
}
}
class Player : Entity
{
//Create player
Entity player;
//Position and velocity
Vector2 position;
Vector2 velocity;
//Texture and rectangle
Texture2D texture;
Rectangle rectangle;
public Player(Texture2D newtexture, Rectangle newrectangle) : base(newtexture, newrectangle) {
texture = newtexture;
rectangle = newrectangle;
//Set basic variables
this.setHealth(100);
this.setArmor(0);
this.setSpeed(10);
this.setFriction(1);
}
public void Update() {
//Movement
if(Keyboard.GetState().IsKeyDown(Keys.Right)){
rectangle.X += 1;
}
rectangle.Y += 4;
}
public void Draw(SpriteBatch spriteBatch) {
spriteBatch.Draw(texture, rectangle, Color.White);
}
}
If there are also general mistakes I make, do point them out, I want to make everything as good as I can now that I'm still learning. Thanks in advance!
Your calling public void Update(GraphicsDevice graphics)
but the movement code is in public void Update()
What I suggest you do is this, use the virtual and override keywords.
In your entity class it should look like this:
public virtual void Update(GraphicsDevice graphics) {
}
And in your player class
public override void Update(GraphicsDevice graphics) {
//ADD MOVEMENT CODE HERE
}