as the titel say's I'm trying to make a game in Monogame, a Bomberman clone, but atm when I try to spawn more then one bomb the animation just moves to the new location. The game object stays where it is supposed to, but it does not have the animation. I think the problem is that it loads the same animation which has been loaded but I just cant seem to figure out how to get it to spawn a new animation everytime a bomb spawns.
I use Content.Load to get the sorite animation, and spawn the bomb with a clone() function with the animation.
var bombAni = new Dictionary<string, Animation>() {
{"Bomb", new Animation(Content.Load<Texture2D>("Obstacle/Bomb"), 3) },
};
_sprites = new List<Sprite>() {
new Player(animations) {
_bomb = new Bomb(bombAni),
Position = new Vector2(32, 32),
Input = new Input() {
Up = Keys.W,
Down = Keys.S,
Left = Keys.A,
Right = Keys.D,
Space = Keys.Space,
}
}
};
public void Play(Animation animation) {
if (animation == _animation) {
return;
}
_animation = animation;
_animation.CurFrame = 0;
_timer = 0;
}
private void AddBomb(List<Sprite> sprites) {
var bomb = _bomb.Clone() as Bomb;
switch (_direction) {
case "Up":
bomb.Position = _position + new Vector2(0, -32);
break;
case "Down":
bomb.Position = _position + new Vector2(0, 32);
break;
case "Left":
bomb.Position = _position + new Vector2(-32, 0);
break;
case "Right":
bomb.Position = _position + new Vector2(32, 0);
break;
}
bomb.lifeSpan = 3f;
bomb.Parent = this;
bombCount++;
sprites.Add(bomb);
}
public Sprite(Dictionary<string, Animation> animations) {
_animations = animations;
_animationManager = new AnimationManager(_animations.First().Value);
}
namespace CompetenceWeek.scripts {
public class Bomb : Sprite {
public float lifeSpan;
private float _timer;
public Bomb(Dictionary<string, Animation> animations) : base(animations) {
}
public Bomb(Texture2D texture) : base(texture) {
}
public override void Update(GameTime gameTime, List<Sprite> sprites) {
_timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
SetAnimations();
_animationManager.Update(gameTime);
if (_timer > lifeSpan) {
isDead = true;
}
}
}
}
namespace CompetenceWeek.scripts {
public class Sprite : ICloneable {
protected AnimationManager _animationManager;
protected Dictionary<string, Animation> _animations;
protected Vector2 _position;
protected Texture2D _texture;
public bool Walkable { get; set; } = false;
public bool isDead = false;
public Player Parent { get; set; }
public Input Input;
public Vector2 Position {
get { return _position; }
set {
_position = value;
if(_animationManager != null) {
_animationManager.Posistion = _position;
}
}
}
public float Speed = 2.5f;
public Vector2 Velocity;
public virtual void Draw(SpriteBatch spriteBatch) {
if(_texture != null) {
spriteBatch.Draw(_texture, Position, Color.White);
} else if (_animationManager != null) {
_animationManager.Draw(spriteBatch);
} else {
throw new Exception("somthings not right");
}
}
public Sprite(Dictionary<string, Animation> animations) {
_animations = animations;
_animationManager = new AnimationManager(_animations.First().Value);
}
public Sprite(Texture2D texture) {
_texture = texture;
}
public virtual void Update(GameTime gameTime, List<Sprite> sprites) {
SetAnimations();
_animationManager.Update(gameTime);
Position += Velocity;
Velocity = Vector2.Zero;
}
protected virtual void SetAnimations() {
if (Velocity.X > 0) {
_animationManager.Play(_animations["PlayerRight"]);
} else if (Velocity.X < 0) {
_animationManager.Play(_animations["PlayerLeft"]);
} else if (Velocity.Y > 0) {
_animationManager.Play(_animations["PlayerDown"]);
} else if (Velocity.Y < 0) {
_animationManager.Play(_animations["PlayerUp"]);
}
}
public object Clone() {
return this.MemberwiseClone();
}
}
}
The problem is with this segment:
protected Dictionary<string, Animation> _animations;
public object Clone() {
return this.MemberwiseClone();
}
When you perform a memberwise clone, it creates a shallow copy, reusing existing references to reference-type objects. This means that the Clone will share the same animation state with the original object.
The solution to this, is to instantiate a new copy of all of the Animations every time you want to clone Bomb.
Something like this:
public object Clone() {
var bomb = (Bomb)this.MemberwiseClone();
bomb.InitAnimations(new Dictionary<string, Animation>() {
{"Bomb", new Animation(Content.Load<Texture2D>("Obstacle/Bomb"), 3) },
};
return bomb;
}
Related
I am working on a 2D, topdown, roguelike game but i got stuck when i tried to make a shooting system.
when i run it and press the arrow keys, the bullet spawns and points in the right direction. It juste doesn't move in any way.
This is my code and i hope someone can figure it out. Btw, everything is connected. The player and the bullet prefab.
using System.Collections;
using System.Linq;
using UnityEngine;
namespace Assets.Scripts
{
[RequireComponent(typeof(Player))]
public class PlayerShootController : ShootControllerBase
{
[SerializeField]
private int _numberOfBombs;
public int NumberofBombs
{
get { return _numberOfBombs; }
set { _numberOfBombs = value; }
}
[SerializeField]
private PlayerHeadController _headObject;
public PlayerHeadController HeadObject
{
get { return _headObject; }
set { _headObject = value; }
}
[SerializeField]
private Bomb _bombPrefab;
public Bomb BombPrefab
{
get { return _bombPrefab; }
set { _bombPrefab = value; }
}
public bool IsShooting { get; private set; }
private KeyCode _shootKey;
private Vector2 _shootDirection;
private Player _player;
public override void Start()
{
base.Start();
_player = GetComponent<Player>();
}
public override void Update()
{
base.Update();
if (IsShooting)
{
SetHeadDirection(_shootKey);
return;
}
if (InputHelpers.IsAnyKey(KeyCode.UpArrow, KeyCode.DownArrow, KeyCode.LeftArrow, KeyCode.RightArrow))
{
if (Input.GetKey(KeyCode.UpArrow))
{
_shootDirection = new Vector2(0, BulletSpeed);
_shootKey = KeyCode.UpArrow;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
_shootDirection = new Vector2(0, -BulletSpeed);
_shootKey = KeyCode.DownArrow;
}
else if (Input.GetKey(KeyCode.LeftArrow))
{
_shootDirection = new Vector2(-BulletSpeed, 0);
_shootKey = KeyCode.LeftArrow;
}
else if (Input.GetKey(KeyCode.RightArrow))
{
_shootDirection = new Vector2(BulletSpeed, 0);
_shootKey = KeyCode.RightArrow;
}
StartCoroutine(Shoot());
}
if (NumberofBombs > 0 && InputHelpers.IsAnyKeyDown(KeyCode.LeftShift, KeyCode.RightShift, KeyCode.E))
{
var bomb = (Bomb) Instantiate(BombPrefab);
bomb.transform.position = transform.position;
NumberofBombs--;
}
}
IEnumerator Shoot()
{
IsShooting = true;
while (Input.GetKey(_shootKey))
{
var bullet = (Rigidbody2D)Instantiate(BulletPrefab);
bullet.GetComponent<BulletScript>().Shooter = transform.gameObject;
bullet.transform.position = transform.position;
if (_shootDirection.y > 0)
{
bullet.transform.Rotate(0, 0, -90);
}
else if (_shootDirection.y < 0)
{
bullet.transform.Rotate(0, 0, 90);
}
else if (_shootDirection.x > 0)
{
TransformHelpers.FlipX(bullet.gameObject);
}
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
if (ShootClips.Any())
{
var clipToPlay = ShootClips[Random.Range(0, ShootClips.Count)];
clipToPlay.pitch = Random.Range(MinShootPitch, MaxShootPitch);
clipToPlay.Play();
}
yield return new WaitForSeconds(ShootingSpeed);
}
IsShooting = false;
//Reset head flipping
if (_headObject.transform.localScale.x < 0)
{
TransformHelpers.FlipX(_headObject.gameObject);
}
}
private void SetHeadDirection(KeyCode shootKey)
{
switch (shootKey)
{
case KeyCode.UpArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Up);
break;
case KeyCode.DownArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Down);
break;
case KeyCode.LeftArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Left);
break;
case KeyCode.RightArrow:
_headObject.SetHeadDirection(PlayerHeadController.HeadDirection.Right);
break;
}
}
}
}
try this:
bullet.AddForce(_shootDirection*moveSpeed*Time.deltaTime);
instead of this:
bullet.AddForce(_shootDirection);
bullet.AddForce(_player.GetComponent<Rigidbody2D>().GetPointVelocity(_player.transform.position) * 0.02f);
tweak the speed for desired result, and if you want the bullet to follow the player you will need to update the shoot direction every certain time with a couroutine
I'm developing a game with Unity and I´'m using Photon's PUN 2 To manage the game's online mode, before, the online connect and list the rooms of the lobby very well, but, I don't know why it isn't working now. Now I can't joina room by seraching it with JoinRoom(RoomName) or JoinRandomRoom(), it just searches a room, then, marks the current state to "Joining" and goes back to the lobby. Also, need to tell that the rooms in lobby aren´t listing, even waiting 5 miutes or more in a room.
Here's my code, thanks:
private Button B;
private Text T;
private AudioSource Audio;
public AudioClip OK, Fail;
void Start ()
{
GameObject.Find("StartPanel").GetComponent<Animator>().SetBool("Show", true);
Audio = GetComponent<AudioSource>();
B = GetComponent<Button>();
T = GameObject.Find("ConnecText").GetComponent<Text>();
B.onClick.AddListener(Clicker);
}
void Clicker()
{
B.interactable = false;
Retrying();
T.text = "Connecting...";
PhotonNetwork.ConnectUsingSettings();
}
public override void OnDisconnected(DisconnectCause cause)
{
Failed();
}
public override void OnConnectedToMaster()
{
StartCoroutine(Connected());
}
IEnumerator Connected()
{
T.text = "Connected!";
Audio.clip = OK;
Audio.Play();
yield return new WaitForSeconds(1);
GameObject.Find("MenuPanel").SetActive(true);
GameObject.Find("MenuPanel").GetComponent<Animator>().SetBool("Show", true);
B.interactable = true;
}
void Retrying()
{
GameObject.Find("FailText").GetComponent<Text>().color = new Color(0, 0, 0, 0);
GameObject.Find("IFail").GetComponent<Image>().color = new Color(0, 0, 0, 0);
}
void Failed()
{
Color myRed = new Color();
ColorUtility.TryParseHtmlString("#DB9191FF", out myRed);
GameObject.Find("FailText").GetComponent<Text>().color = myRed;
GameObject.Find("IFail").GetComponent<Image>().color = Color.white;
T.text = "Retry";
Audio.clip = Fail;
Audio.Play();
B.interactable = true;
}
The list rooms code:
public GameObject roomPrefab;
public Sprite Four, Two, Three;
private string RoomName;
private int PlayerAmount;
private int MaxPlayers;
private Image I;
private Vector2 RoomVector;
private bool Lock = false;
public GameObject Content;
private List<RoomInfo> RoomList;
private bool IsntNull = false;
private Dictionary<string, RoomInfo> cachedRoomList;
private Dictionary<string, GameObject> roomListEntries;
private Dictionary<int, GameObject> playerListEntries;
private GameObject Handle;
public RooManager instance;
private void Awake()
{
if (instance != null)
{
DestroyImmediate(gameObject);
return;
}
DontDestroyOnLoad(gameObject);
instance = this;
cachedRoomList = new Dictionary<string, RoomInfo>();
roomListEntries = new Dictionary<string, GameObject>();
}
void Start()
{
//Content = GameObject.Find("Content").GetComponent<GameObject>();
RoomVector = new Vector2(450 /*370 */, this.transform.position.y);
}
private void ClearRoomListView()
{
foreach (GameObject entry in roomListEntries.Values)
{
Destroy(entry.gameObject);
}
roomListEntries.Clear();
}
public override void OnJoinedRoom()
{
if (playerListEntries == null)
{
playerListEntries = new Dictionary<int, GameObject>();
}
foreach (Player p in PhotonNetwork.PlayerList)
{
GameObject entry = Instantiate(roomPrefab);
playerListEntries.Add(p.ActorNumber, entry);
}
}
public override void OnLeftRoom()
{
foreach (GameObject entry in playerListEntries.Values)
{
Destroy(entry.gameObject);
}
playerListEntries.Clear();
playerListEntries = null;
}
public override void OnLeftLobby()
{
cachedRoomList.Clear();
ClearRoomListView();
}
private void Update()
{
print(PhotonNetwork.NetworkClientState);
}
private void UpdateRoomListView()
{
foreach (RoomInfo Item in cachedRoomList.Values)
{
RoomName = Item.Name;
PlayerAmount = Item.PlayerCount;
MaxPlayers = Item.MaxPlayers;
RoomVector.y -= 100;
GameObject RoomPrefab = Instantiate(roomPrefab, RoomVector, transform.rotation) as GameObject;
if (Item.PlayerCount == 0)
{
Destroy(RoomPrefab);
}
print(PhotonNetwork.CurrentLobby.Name);
RoomPrefab.transform.Find("RoomName").GetComponent<Text>().text = RoomName;
if (Item.Name.Length == 10)
{
Vector2 AddFive = new Vector2(RoomPrefab.transform.Find("RoomName").transform.position.x + 10, RoomPrefab.transform.Find("RoomName").transform.position.y);
RoomPrefab.transform.Find("RoomName").transform.position = AddFive;
}
if (Item.Name.Length >= 10)
{
Vector2 AddTen = new Vector2(RoomPrefab.transform.Find("RoomName").transform.position.x + 40, RoomPrefab.transform.Find("RoomName").transform.position.y + 20);
RoomPrefab.transform.Find("RoomName").transform.position = AddTen;
RoomPrefab.transform.Find("PlayerInt").GetComponent<Text>().fontSize = 47;
}
RoomPrefab.transform.Find("PlayerInt").GetComponent<Text>().text = PlayerAmount.ToString();
if (Item.MaxPlayers == 4)
{
RoomPrefab.transform.Find("IPlayerA").GetComponent<Image>().sprite = Four;
}
else if (Item.MaxPlayers == 2)
{
RoomPrefab.transform.Find("IPlayerA").GetComponent<Image>().sprite = Two;
}
else if (Item.MaxPlayers == 3)
{
RoomPrefab.transform.Find("IPlayerA").GetComponent<Image>().sprite = Three;
}
RoomPrefab.transform.SetParent(Content.transform);
}
}
public override void OnRoomListUpdate(List<RoomInfo> roomList)
{
ClearRoomListView();
UpdateCachedRoomList(roomList);
UpdateRoomListView();
print("Updated");
}
private void UpdateCachedRoomList(List<RoomInfo> roomList)
{
foreach (RoomInfo info in roomList)
{
// Remove room from cached room list if it got closed, became invisible or was marked as removed
if (!info.IsOpen || !info.IsVisible || info.RemovedFromList)
{
if (cachedRoomList.ContainsKey(info.Name))
{
cachedRoomList.Remove(info.Name);
}
continue;
}
// Update cached room info
if (cachedRoomList.ContainsKey(info.Name))
{
cachedRoomList[info.Name] = info;
}
// Add new room info to cache
else
{
cachedRoomList.Add(info.Name, info);
}
}
}
}
Need to say that in the list rooms code, the "Update" message yes prints, and theres no errors or warnings in the console.
OnPhotonCreateRoomFailed
OnPhotonJoinRoomFailed
you may want debug through override more callback
you can find all photon callbacks here
so for my first project with MonoGame I decided to make a tetris clone but I have an issue which I don't know how to solve.
Currently my code is generating a block and moves it downwards until it reach a specific y position. The block need to stay at this position and a new block spawns. I'm doing this with a List which contains object of the block class and then just draw all the blocks in this list.
I took out parts which I believe are not involved in the problem:
public class PlayField : DrawableGameComponent
{
private Game1 gameRef;
private Texture2D fieldTexture;
private BlockGenerator blockGenerator;
private Texture2D[] allBlocks;
private Block currentBlock;
public bool[,] fieldFilled;
private int down_Blocks = 22;
private int side_Blocks = 10;
public List<Block> placedBlocks;
public PlayField(Game game) : base(game)
{
placedBlocks = new List<Block>();
allBlocks = new Texture2D[4];
blockGenerator = new BlockGenerator(allBlocks,gameRef);
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
try
{
if (currentBlock.isMoving == false)
{
placedBlocks.Add(currentBlock);
currentBlock = null;
currentBlock = blockGenerator.GenerateBlock();
}
else
{
currentBlock.UpdatePosition(gameTime);
if (InputManager.CheckForKeyBoardRelease(Keys.A))
{
currentBlock.MoveLeft();
}
if (InputManager.CheckForKeyBoardRelease(Keys.D))
{
currentBlock.MoveRight();
}
}
}
catch(NullReferenceException e)
{
currentBlock = blockGenerator.GenerateBlock();
}
}
public override void Draw(GameTime gameTime)
{
gameRef.SpriteBatch.Begin();
if(currentBlock != null)
{
currentBlock.DrawBlocks();
}
foreach(Block b in placedBlocks)
{
b.DrawBlocks();
}
gameRef.SpriteBatch.End();
base.Draw(gameTime);
}
The method "GenerateBlock" returns a object of type "Block"
public class Block : DrawableGameComponent
{
Game1 gameRef;
public Texture2D blockTexture;
public Vector2[] blockPositions;
TimeSpan lastMove;
TimeSpan blockMove = TimeSpan.FromMilliseconds(500);
public bool isMoving;
public Block(Game game, Texture2D _blockTexture, Vector2[] _blockPositions) : base(game)
{
gameRef = (Game1)game;
blockTexture = _blockTexture;
blockPositions = _blockPositions;
isMoving = true;
}
public void UpdatePosition(GameTime gameTime)
{
Vector2 bottomBlockPositon = FindBottomBlock();
if(bottomBlockPositon.Y < 550)
{
if (WaitTillMove(gameTime))
{
for (int i = 0; i < blockPositions.Length; i++)
{
blockPositions[i] = new Vector2(blockPositions[i].X, blockPositions[i].Y + 25);
}
}
}
else
{
isMoving = false;
Console.WriteLine("X: " +blockPositions[0].X + " Y:" + blockPositions[0].Y);
}
}
public Vector2 FindBottomBlock()
{
Vector2 result = new Vector2(0, 0);
for(int i = 0; i < blockPositions.Length; i++)
{
if(blockPositions[i].Y > result.Y)
{
result = blockPositions[i];
}
}
return result;
}
public bool WaitTillMove(GameTime gameTime)
{
if (lastMove + blockMove < gameTime.TotalGameTime)
{
lastMove = gameTime.TotalGameTime;
return true;
}
return false;
}
public void DrawBlocks()
{
gameRef.SpriteBatch.Draw(blockTexture, blockPositions[0], Color.White);
gameRef.SpriteBatch.Draw(blockTexture, blockPositions[1], Color.White);
gameRef.SpriteBatch.Draw(blockTexture, blockPositions[2], Color.White);
gameRef.SpriteBatch.Draw(blockTexture, blockPositions[3], Color.White);
}
}
Debugging says that my List contains an Element even though it has the wrong positions. But this shouldn't matter because I still only "see" one Block at the same time.
Hopefully someone can toss me into the right direction.
Edit:
public class BlockGenerator
{
Random random;
Texture2D[] allBlocks;
Vector2[] blockPositions;
Texture2D currentBlock;
BlockEnums currentBlockEnum;
Game1 gameRef;
public BlockGenerator(Texture2D[] blocks, Game1 game)
{
gameRef = (Game1)game;
allBlocks = blocks;
currentBlock = allBlocks[1];
blockPositions = new Vector2[4];
random = new Random();
}
public Block GenerateBlock()
{
int colorValue = random.Next(0, 4); //0 = blue, 1 = green, 2 = red, 3 = yellow
currentBlock = allBlocks[colorValue];
currentBlockEnum = BlockEnums.Line;
blockPositions[0] = new Vector2(100, 0);
blockPositions[1] = new Vector2(125, 0);
blockPositions[2] = new Vector2(150, 0);
blockPositions[3] = new Vector2(175, 0);
Block generatedBlock = new Block(gameRef,currentBlock, blockPositions);
return generatedBlock;
}
public class BlockGenerator
{
Random random;
Texture2D[] allBlocks;
Vector2[] blockPositions; // delete this
Then move the initialization code from the constructor into GenerateBlock (add var).
var blockPositions = new Vector2[4];
Then it should work. You were creating new vectors each time you created a block but re-using the same instance of blockPositions each time, so both blocks do exist but will always have the exact same positions.
I haven't had time to test but I think it's right...let me know :)
edit: I'd also suggest moving blockPositions entirely into the Block class. I see no value (in the code you have posted, maybe you have plans for later) in having that logic outside of the class that really owns it...and if it was contained within the class to begin with you would have avoided this problem. Just a suggestion :)
i already make the player character to move to it is destination (animate the character to move to that destination), i wanted to disable the GUI button when the player character is moving, but i can't get it and work it out. Could you guys help me?
Here is the code:
public class UserPlayer : Player
{
public override void TurnUpdate()
{
//Moving animation
if (positionQueue.Count > 0)
{
GUI.enabled = false; // This is the one that i want when the character still moving (animation still moving), disabled the GUI. But i can't get it
transform.position += (positionQueue[0] - transform.position).normalized * moveSpeed * Time.deltaTime;
if (Vector3.Distance(positionQueue[0], transform.position) <= 0.1f)
{
transform.position = positionQueue[0];
positionQueue.RemoveAt(0);
if (positionQueue.Count == 0)
{
actionPoints--;
}
}
}
base.TurnUpdate();
}
public override void TurnOnGUI()
{
base.TurnOnGUI();
}
}
public class Player : MonoBehaviour
{
//for movement animation
public List<Vector3> positionQueue = new List<Vector3>();
public virtual void TurnUpdate()
{
if (actionPoints <= 0)
{
actionPoints = 2;
magicAttacking = false;
moving = false;
attacking = false;
GameManager.instance.NextTurn();
}
}
public virtual void TurnOnGUI()
{
if (GameManager.instance.currentPlayerIndex == 0 || GameManager.instance.currentPlayerIndex == 2)
{
//ToolTip Text
move = GUI.Button(buttonRect, new GUIContent("Move", "Move the Player"));
GUI.Label(tooltipRect, GUI.tooltip, label1);
GUI.tooltip = null;
//Move Button
if (move)
{
if (!moving)
{
GameManager.instance.RemoveTileHighlights();
moving = true;
attacking = false;
GameManager.instance.HighlightTilesAt(gridPosition, Color.blue, movementPerActionPoint);
}
else
{
moving = false;
attacking = false;
GameManager.instance.RemoveTileHighlights();
}
}
}
Your question has been already made, take a look here.
Adapt your code in this way:
public virtual void TurnOnGUI() {
if (GameManager.instance.currentPlayerIndex == 0 || GameManager.instance.currentPlayerIndex == 2) {
...
if(!moving) {
move = GUI.Button(buttonRect, new GUIContent("Move", "Move the Player"));
GUI.Label(tooltipRect, GUI.tooltip, label1);
}
...
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I am right now trying to display a vector holding an X and Y value, for a sprite, from one class Game Object.cs to Game1.cs. I move a protected value (protected Vector2 velocity;) to a public Vector2 velocity when I move it over the draw method (so that it will show how fast the sprite on screen is moving) it comes up with Error 1 An object reference is required for the non-static field, method, or property. So I add static, now it's public static Vector2 velocitys, and play the game. When I look at the X and Y value, they'er there but will not change when I move. I have had this problem on anything with a static.
Is there a way to get rid of the static, or fix this so I can see the X and Y update while I am playing? I have the velocitys Vector take velocity's X and Y in the update in GameObject.cs so that it will constantly take from velocity.
Why does it need a static? Can I change that? Can I update it on the screen?
This is the code:
GameObject.cs:
(Holdes the Vectors velocitys and velocity)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Tile_Engine;
namespace **
{
public class GameObject
{
#region Declarations
protected Vector2 worldLocation;
protected Vector2 velocity;
protected int frameWidth;
protected int frameHeight;
protected bool enabled;
protected bool flipped = false;
protected bool onGround;
protected Rectangle collisionRectangle;
protected int collideWidth;
protected int collideHeight;
protected bool codeBasedBlocks = true;
protected float drawDepth = 0.85f;
protected Dictionary<string, AnimationStrip> animations =
new Dictionary<string, AnimationStrip>();
protected string currentAnimation;
public Vector2 velocitys;
#endregion
#region Properties
public bool Enabled
{
get { return enabled; }
set { enabled = value; }
}
public Vector2 WorldLocation
{
get { return worldLocation; }
set { worldLocation = value; }
}
public Vector2 WorldCenter
{
get
{
return new Vector2(
(int)worldLocation.X + (int)(frameWidth / 2),
(int)worldLocation.Y + (int)(frameHeight / 2));
}
}
public Rectangle WorldRectangle
{
get
{
return new Rectangle(
(int)worldLocation.X,
(int)worldLocation.Y,
frameWidth,
frameHeight);
}
}
public Rectangle CollisionRectangle
{
get
{
return new Rectangle(
(int)worldLocation.X + collisionRectangle.X,
(int)worldLocation.Y + collisionRectangle.Y,
collisionRectangle.Width,
collisionRectangle.Height);
}
set { collisionRectangle = value; }
}
#endregion
#region Helper Methods
private void updateAnimation(GameTime gameTime)
{
if (animations.ContainsKey(currentAnimation))
{
if (animations[currentAnimation].FinishedPlaying)
{
PlayAnimation(animations[currentAnimation].NextAnimation);
}
else
{
animations[currentAnimation].Update(gameTime);
}
}
}
#endregion
#region Public Methods
public void PlayAnimation(string name)
{
if (!(name == null) && animations.ContainsKey(name))
{
currentAnimation = name;
animations[name].Play();
}
}
public virtual void Update(GameTime gameTime)
{
if (!enabled)
return;
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
updateAnimation(gameTime);
if (velocity.Y != 0)
{
velocitys = velocity;
onGround = false;
}
Vector2 moveAmount = velocity * elapsed;
moveAmount = horizontalCollisionTest(moveAmount);
moveAmount = verticalCollisionTest(moveAmount);
Vector2 newPosition = worldLocation + moveAmount;
newPosition = new Vector2(
MathHelper.Clamp(newPosition.X, 0,
Camera.WorldRectangle.Width - frameWidth),
MathHelper.Clamp(newPosition.Y, 2 * (-TileMap.TileHeight),
Camera.WorldRectangle.Height - frameHeight));
worldLocation = newPosition;
}
public virtual void Draw(SpriteBatch spriteBatch)
{
if (!enabled)
return;
if (animations.ContainsKey(currentAnimation))
{
SpriteEffects effect = SpriteEffects.None;
if (flipped)
{
effect = SpriteEffects.FlipHorizontally;
}
spriteBatch.Draw(
animations[currentAnimation].Texture,
Camera.WorldToScreen(WorldRectangle),
animations[currentAnimation].FrameRectangle,
Color.White, 0.0f, Vector2.Zero, effect, drawDepth);
}
}
#endregion
#region Map-Based Collision Detecting Methods
private Vector2 horizontalCollisionTest(Vector2 moveAmount)
{
if (moveAmount.X == 0)
return moveAmount;
Rectangle afterMoveRect = CollisionRectangle;
afterMoveRect.Offset((int)moveAmount.X, 0);
Vector2 corner1, corner2;
if (moveAmount.X < 0)
{
corner1 = new Vector2(afterMoveRect.Left,
afterMoveRect.Top + 1);
corner2 = new Vector2(afterMoveRect.Left,
afterMoveRect.Bottom - 1);
}
else
{
corner1 = new Vector2(afterMoveRect.Right,
afterMoveRect.Top + 1);
corner2 = new Vector2(afterMoveRect.Right,
afterMoveRect.Bottom - 1);
}
Vector2 mapCell1 = TileMap.GetCellByPixel(corner1);
Vector2 mapCell2 = TileMap.GetCellByPixel(corner2);
if (!TileMap.CellIsPassable(mapCell1) ||
!TileMap.CellIsPassable(mapCell2))
{
moveAmount.X = 0;
velocity.X = 0;
}
if (codeBasedBlocks)
{
if (TileMap.CellCodeValue(mapCell1) == "BLOCK" ||
TileMap.CellCodeValue(mapCell2) == "BLOCK")
{
moveAmount.X = 0;
velocity.X = 0;
}
}
return moveAmount;
}
private Vector2 verticalCollisionTest(Vector2 moveAmount)
{
if (moveAmount.Y == 0)
return moveAmount;
Rectangle afterMoveRect = CollisionRectangle;
afterMoveRect.Offset((int)moveAmount.X, (int)moveAmount.Y);
Vector2 corner1, corner2;
if (moveAmount.Y < 0)
{
corner1 = new Vector2(afterMoveRect.Left + 1,
afterMoveRect.Top);
corner2 = new Vector2(afterMoveRect.Right - 1,
afterMoveRect.Top);
}
else
{
corner1 = new Vector2(afterMoveRect.Left + 1,
afterMoveRect.Bottom);
corner2 = new Vector2(afterMoveRect.Right - 1,
afterMoveRect.Bottom);
}
Vector2 mapCell1 = TileMap.GetCellByPixel(corner1);
Vector2 mapCell2 = TileMap.GetCellByPixel(corner2);
if (!TileMap.CellIsPassable(mapCell1) ||
!TileMap.CellIsPassable(mapCell2))
{
if (moveAmount.Y > 0)
onGround = true;
moveAmount.Y = 0;
velocity.Y = 0;
}
if (codeBasedBlocks)
{
if (TileMap.CellCodeValue(mapCell1) == "BLOCK" ||
TileMap.CellCodeValue(mapCell2) == "BLOCK")
{
if (moveAmount.Y > 0)
onGround = true;
moveAmount.Y = 0;
velocity.Y = 0;
}
}
return moveAmount;
}
#endregion
}
}
Game1.cs:
(Draws the Vector2 velocity)
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Tile_Engine;
namespace **
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Player player;
SpriteFont pericles8;
Vector2 scorePosition = new Vector2(20, 580);
enum GameState { TitleScreen, Playing, PlayerDead, GameOver };
GameState gameState = GameState.TitleScreen;
Vector2 gameOverPosition = new Vector2(350, 300);
Vector2 livesPosition = new Vector2(600, 580);
Vector2 Velocitys = new Vector2(100, 580);
Texture2D titleScreen;
float deathTimer = 0.0f;
float deathDelay = 5.0f;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
this.graphics.PreferredBackBufferWidth = 800;
this.graphics.PreferredBackBufferHeight = 600;
this.graphics.ApplyChanges();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
TileMap.Initialize(
Content.Load<Texture2D>(#"Textures\PlatformTiles"));
TileMap.spriteFont =
Content.Load<SpriteFont>(#"Fonts\Pericles8");
pericles8 = Content.Load<SpriteFont>(#"Fonts\Pericles8");
titleScreen = Content.Load<Texture2D>(#"Textures\TitleScreen");
Camera.WorldRectangle = new Rectangle(0, 0, 160 * 48, 12 * 48);
Camera.Position = Vector2.Zero;
Camera.ViewPortWidth = 800;
Camera.ViewPortHeight = 600;
player = new Player(Content);
LevelManager.Initialize(Content, player);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
KeyboardState keyState = Keyboard.GetState();
GamePadState gamepadState = GamePad.GetState(PlayerIndex.One);
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
if (gameState == GameState.TitleScreen)
{
if (keyState.IsKeyDown(Keys.Space) ||
gamepadState.Buttons.A == ButtonState.Pressed)
{
StartNewGame();
gameState = GameState.Playing;
}
}
if (gameState == GameState.Playing)
{
player.Update(gameTime);
LevelManager.Update(gameTime);
if (player.Dead)
{
if (player.LivesRemaining > 0)
{
gameState = GameState.PlayerDead;
deathTimer = 0.0f;
}
else{
gameState = GameState.GameOver;
deathTimer = 0.0f;
}
}
}
if (gameState == GameState.PlayerDead)
{
player.Update(gameTime);
LevelManager.Update(gameTime);
deathTimer = elapsed;
if (deathTimer > deathDelay)
{
player.WorldLocation = Vector2.Zero;
LevelManager.ReloadLevel();
player.Revive();
gameState = GameState.Playing;
}
}
if (gameState == GameState.GameOver)
{
deathTimer += elapsed;
if (deathTimer > deathDelay)
{
gameState = GameState.TitleScreen;
}
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
// TODO: Add your drawing code here
spriteBatch.Begin(
SpriteSortMode.BackToFront,
BlendState.AlphaBlend);
if (gameState == GameState.TitleScreen)
{
spriteBatch.Draw(titleScreen, Vector2.Zero, Color.White);
}
if ((gameState == GameState.Playing) ||
(gameState == GameState.PlayerDead) ||
(gameState == GameState.GameOver))
{
TileMap.Draw(spriteBatch);
player.Draw(spriteBatch);
LevelManager.Draw(spriteBatch);
spriteBatch.DrawString(
pericles8,
"Score: " + player.Score.ToString(),
scorePosition,
Color.White);
spriteBatch.DrawString(
pericles8,
"Lives Remaining: " + player.LivesRemaining.ToString(),
livesPosition,
Color.White);
spriteBatch.DrawString(
pericles8,
"Velocity: " + GameObject.velocitys.ToString(),
Velocitys,
Color.White);
}
if (gameState == GameState.PlayerDead)
{
}
if (gameState == GameState.GameOver)
{
spriteBatch.DrawString(
pericles8,
"G A M E O V E R !",
gameOverPosition,
Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
private void StartNewGame()
{
player.Revive();
player.LivesRemaining = 3;
player.WorldLocation = Vector2.Zero;
LevelManager.LoadLevel(0);
}
}
}
Player.cs:
(A part of the velocity)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Tile_Engine;
namespace **
{
public class Player : GameObject
{
#region Declarations
private Vector2 fallSpeed = new Vector2(0, 20);
private float moveScale = 180.0f;
private bool dead = false;
public int score = 0;
private int livesRemaining = 3;
#endregion
public bool Dead
{
get { return dead; }
}
public int Score
{
get { return score; }
set { score = value; }
}
public int LivesRemaining
{
get { return livesRemaining; }
set { livesRemaining = value; }
}
public void Kill()
{
PlayAnimation("die");
LivesRemaining--;
velocity.X = 0;
dead = true;
}
public void Revive()
{
PlayAnimation("idle");
dead = false;
}
#region Constructor
public Player(ContentManager content)
{
animations.Add("idle",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Idle"),
48,
"idle"));
animations["idle"].LoopAnimation = true;
animations.Add("run",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Run"),
48,
"run"));
animations["run"].LoopAnimation = true;
animations.Add("jump",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Jump"),
48,
"jump"));
animations["jump"].LoopAnimation = false;
animations["jump"].FrameLength = 0.08f;
animations["jump"].NextAnimation = "idle";
animations.Add("die",
new AnimationStrip(
content.Load<Texture2D>(#"Textures\Sprites\Player\Die"),
48,
"die"));
animations["die"].LoopAnimation = false;
frameWidth = 48;
frameHeight = 48;
CollisionRectangle = new Rectangle(9, 1, 30, 46);
drawDepth = 0.825f;
enabled = true;
codeBasedBlocks = false;
PlayAnimation("idle");
}
#endregion
#region Public Methods
public override void Update(GameTime gameTime)
{
if (!Dead)
{
string newAnimation = "idle";
velocity = new Vector2(0, velocity.Y);
GamePadState gamePad = GamePad.GetState(PlayerIndex.One);
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.Left) ||
(gamePad.ThumbSticks.Left.X < -0.3f))
{
flipped = false;
newAnimation = "run";
velocity = new Vector2(-moveScale, velocity.Y);
}
if (keyState.IsKeyDown(Keys.Right) ||
(gamePad.ThumbSticks.Left.X > 0.3f))
{
flipped = true;
newAnimation = "run";
velocity = new Vector2(moveScale, velocity.Y);
}
if (newAnimation != currentAnimation)
{
PlayAnimation(newAnimation);
}
if (keyState.IsKeyDown(Keys.Space) ||
(gamePad.Buttons.A == ButtonState.Pressed))
{
if (onGround)
{
Jump();
newAnimation = "jump";
}
}
if (currentAnimation == "jump")
newAnimation = "jump";
if (keyState.IsKeyDown(Keys.Up) ||
gamePad.ThumbSticks.Left.Y > 0.3f)
{
checkLevelTransition();
}
}
velocity += fallSpeed;
repositionCamera();
base.Update(gameTime);
}
public void Jump()
{
velocity.Y = -500;
}
#endregion
#region Helper Methods
private void repositionCamera()
{
int screenLocX = (int)Camera.WorldToScreen(worldLocation).X;
if (screenLocX > 500)
{
Camera.Move(new Vector2(screenLocX - 500, 0));
}
if (screenLocX < 200)
{
Camera.Move(new Vector2(screenLocX - 200, 0));
}
}
private void checkLevelTransition()
{
Vector2 centerCell = TileMap.GetCellByPixel(WorldCenter);
if (TileMap.CellCodeValue(centerCell).StartsWith("T_"))
{
string[] code = TileMap.CellCodeValue(centerCell).Split('_');
if (code.Length != 4)
return;
LevelManager.LoadLevel(int.Parse(code[1]));
WorldLocation = new Vector2(
int.Parse(code[2]) * TileMap.TileWidth,
int.Parse(code[3]) * TileMap.TileHeight);
LevelManager.RespawnLocation = WorldLocation;
velocity = Vector2.Zero;
}
}
#endregion
}
}
I have figured out for my self, I mostly wanted a quick answer. Just making a public vector does not help, I needed a method to transfer over the Vector:
public Vector2 Velocitys
{
get { return velocity; }
set { velocity = value; }
}
Then just like the public int Score method I draw it:
spriteBatch.DrawString(
pericles8,
"Velocity: " + player.Velocitys.ToString(),
Velocitys,
Color.White);
It works like a charm.
(Its pretty Ironic that the one thing that I asked why I would use it (get and set) would be the answer)