I wanted to start developing an opengl basic game. After some coding i ran into an error.
I wanted to add a projection matrix and after I created it, the rendered image went white and even the transformation matrix didn't work correctly.
I tested the location IDs with GL.GetUniformLocation(Variable Names) and both of them were -1.
The way I add the projection matrix:
projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)(Math.PI / 180) * FOV, aspectRatio, NEAR_PLANE, FAR_PLANE);
The way I add the transformation matrix:
Matrix4 matrix = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(rx)) * Matrix4.CreateRotationY(MathHelper.DegreesToRadians(ry)) * Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(rz));
Matrix4 translationsMatrix = Matrix4.CreateTranslation(translation);
Matrix4 scaleMatrix = Matrix4.CreateScale(scale);
matrix *= scaleMatrix;
matrix *= translationsMatrix;
This(the transformation matrix) works fine by it's own.
And here is my renderer class:
TexturedModel texturedModel = entity.Model;
RawModel model = texturedModel.Model;
GL.BindVertexArray(model.VaoID);
GL.EnableVertexAttribArray(0);
GL.EnableVertexAttribArray(1);
Matrix4 transformationMatrix = Maths.CreateTransformationMatrix(entity.Position, entity.RotationX, entity.RotationY, entity.RotationZ, entity.Scale);
shader.LoadTransformationMatrix(transformationMatrix);
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, texturedModel.Texture.ID);
GL.DrawElements(PrimitiveType.Triangles, model.VertexCount, DrawElementsType.UnsignedInt, 0);
GL.DisableVertexAttribArray(0);
GL.DisableVertexAttribArray(1);
GL.BindVertexArray(0);
Why does it behave like this and how can I "fix" it?
EDIT
Here are my shader codes. (I have forgotten them previously)
VertexShader:
#version 400 core
in vec3 position;
in vec2 textureCoords;
out vec2 pass_textureCoords;
uniform mat4 transformationMatrix;
unfiorm mat4 projectionMatrix;
void main(void){
gl_Position = projectionMatrix * transformationMatrix * vec4(position, 1.0);
pass_textureCoords = textureCoords;
}
Abstract Shader Class:
abstract class ShaderProgram
{
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
public ShaderProgram(string vertexShaderFile, string fragmentShaderFile)
{
vertexShaderID = LoadShader(vertexShaderFile, ShaderType.VertexShader);
fragmentShaderID = LoadShader(fragmentShaderFile, ShaderType.FragmentShader);
programID = GL.CreateProgram();
GL.AttachShader(programID, vertexShaderID);
GL.AttachShader(programID, fragmentShaderID);
BindAttributes();
GL.LinkProgram(programID);
GL.ValidateProgram(programID);
GetAllUniformLocations();
}
protected abstract void GetAllUniformLocations();
protected int GetUniformLocation(string uniformName)
{
return GL.GetUniformLocation(programID, uniformName);
}
public void Start()
{
GL.UseProgram(programID);
}
public void Stop()
{
GL.UseProgram(0);
}
public void CleanUp()
{
Stop();
GL.DetachShader(programID, vertexShaderID);
GL.DetachShader(programID, fragmentShaderID);
GL.DeleteShader(vertexShaderID);
GL.DeleteShader(fragmentShaderID);
GL.DeleteProgram(programID);
}
protected abstract void BindAttributes();
protected void BindAttribute(int attribute, string variableName)
{
GL.BindAttribLocation(programID, attribute, variableName);
}
protected void LoadFloat(int location, float value)
{
GL.Uniform1(location, value);
}
protected void LoadVector(int location, Vector3 vector)
{
GL.Uniform3(location, vector);
}
protected void LoadBoolean(int location, bool value)
{
GL.Uniform1(location, value ? 1 : 0);
}
protected void LoadMatrix(int location, Matrix4 matrix)
{
GL.UniformMatrix4(location, false, ref matrix);
}
private static int LoadShader(String file, ShaderType type)
{
string shaderSource = File.ReadAllText(file);
int shaderID = GL.CreateShader(type);
GL.ShaderSource(shaderID, shaderSource);
GL.CompileShader(shaderID);
return shaderID;
}
}
Static Shader:
class StaticShader : ShaderProgram
{
private static string vertexFile = "f/shaders/vertexShader.txt";
private static string fragmentFile = "f/shaders/fragmentShader.txt";
private int location_transformationMatrix;
private int location_projectionMatrix;
public StaticShader()
: base(vertexFile, fragmentFile)
{
}
protected override void BindAttributes()
{
base.BindAttribute(0, "position");
base.BindAttribute(1, "textureCoords");
}
protected override void GetAllUniformLocations()
{
location_transformationMatrix = base.GetUniformLocation("transformationMatrix");
location_projectionMatrix = base.GetUniformLocation("projectionMatrix");
}
public void LoadTransformationMatrix(Matrix4 matrix)
{
base.LoadMatrix(location_transformationMatrix, matrix);
}
public void LoadProjectionMatrix(Matrix4 projection)
{
base.LoadMatrix(location_projectionMatrix, projection);
}
}
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'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 want to override a method while it's object initialization, something like this:
Button = new Button(parameter1, parameter2){
public override onClicked(){
//implementation
}
};
This it's what a got:
public class Button:Entity
{
protected Texture2D texture2D;
public Vector2 vector2;
public Button(Texture2D image, Vector2 position
{
this.image = image;
this.position = position;
this.action = action;
}
public abstract void onClicked();
}
abstract class Entity
{
public Vector2 position;
public int radius = 20;
protected Texture2D image;
public virtual void draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(image,position,Color.White);
}
}
I just try to make an implementation like the one I speak before but it does not compile. How one can get this to compile or implement such "per-instance" overrides?
public class Button:Entity
{
//Vector, Radius and texture are already part of Button, since it extend Entity
public EventHandler onClicked;
public Button(Texture2D image, Vector2 position)
{
this.image = image;
this.position = position;
this.action = action;
}
}
abstract class Entity
{
public Vector2 position;
public int radius = 20;
protected Texture2D image;
public virtual void draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(image,position,Color.White);
}
}
And use it this way:
Button = new Button(parameter1, parameter2){
onClicked = new EventHandler(NameOfYourMethod);
};
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
}