Original Post
Hello, I'm attempting to create a 2D multiplayer game using XNA with C#.
I'm encountering a possible design flaw, so I'm posting a *very* stripped down over simplified version of my code, which I will reference when talking about my concerns.
Ok so here is the first issue.
This line: players.add(new Player(sName)) will give an error because the ArrayList players is not declared as static.
I can easily fix that be making it static, but is this ok? It just seems like I might be going about my framework wrong if whenever I want to update variables in the main code, my network thread forces me to first make them all static before I can access them within the thread. Just wondering if this is ok, or I am doing some kind of amateur mistake / design flaw. Would it make more sense to pass the Game object itself to the thread, so I could just call Game.players.add(new Player(sName)) instead? (Not even sure if that would work) Am I just being paranoid and this isn't really an issue?
My other question is also a design / code related one.
Say I have a custom sprite class called Player, which draws and updates a stick figure on the screen that represents a player.
Now in the games protected override void LoadContent() I instantiate the Player object, and pass a texture into the objects constructor using Content.Load(@"Images/player")
This is fine so far.
But whenever a player joins the server, my network reading thread receives a packet about the new player, and needs to create another instance of the Player class to represent the new connected peer.
For one thing, I can't call Content.Load because the networking thread has no reference to the Game object. I know I can pass the Game object into the thread, and that would allow me to call Game.Content.Load, but like how I mentioned that in the first question, it may not be ideal. Secondly, I don't want to perform Content.Load() after protected override void LoadContent() was already called, as I would assume all loading should only be done there, and not sporadically in the middle of gameplay at random whenever a new player joins. So what is the best way to go about that?
The only thing I can think of.. is perhaps instead of the networking thread doing so much work, perhaps I can just make it raise a flag and temporarily store the data it retrieved into some temporary static vars, and the main Game's Update() loop can check for that flag, and do all the nessesary work with that data before resetting the flag. This prospect frightens me, because if someone joins immediately after someone else joined, the Update() loop might screw up, reading data that is being overwritten before the Update() loop is finished reading/using it. I know I can use locks to protect against that, but wouldn't locks add a lot of overhead, and make my networking thread wait for a lock to open, potentially making the networking thread miss a new incoming message? (Or do networking messages wait in a queue or some kind until they are read?)
I apologize for all these questions, I'm reading 2 books on XNA and C#, and they don't always give an answer to every situation that might occur.
It's one thing to understand the individual concepts, and a whole nother to combine them all together correctly to make a game.
Thank you so much for any advice!
I'm encountering a possible design flaw, so I'm posting a *very* stripped down over simplified version of my code, which I will reference when talking about my concerns.
public class Game1 : Microsoft.Xna.Framework.Game
{
// varaibles here
ArrayList players; // array of player sprites
public Game1()
{
// constructor stuff here
players = new ArrayList();
players.Add(new Player("Player 1"));
}
public Update()
{
// Moves the player depending on keyboard input
// Broadcasts new position to all connected players
}
public Draw()
{
// over simplified code showing that this method draws all player objects in the array
draw(players);
}
// This is a seperate thread, that is continually reading network data
static void readNetworkData()
{
if (PlayerJoined)
{
players.add(new Player(sName)) // Adds a new player sprite to the game to keep track of
}
else if (PlayerSendingPositionUpdateInfo)
{
// updates x and y position of whatever players info is read
}
}
}
Ok so here is the first issue.
This line: players.add(new Player(sName)) will give an error because the ArrayList players is not declared as static.
I can easily fix that be making it static, but is this ok? It just seems like I might be going about my framework wrong if whenever I want to update variables in the main code, my network thread forces me to first make them all static before I can access them within the thread. Just wondering if this is ok, or I am doing some kind of amateur mistake / design flaw. Would it make more sense to pass the Game object itself to the thread, so I could just call Game.players.add(new Player(sName)) instead? (Not even sure if that would work) Am I just being paranoid and this isn't really an issue?
My other question is also a design / code related one.
Say I have a custom sprite class called Player, which draws and updates a stick figure on the screen that represents a player.
Now in the games protected override void LoadContent() I instantiate the Player object, and pass a texture into the objects constructor using Content.Load
This is fine so far.
But whenever a player joins the server, my network reading thread receives a packet about the new player, and needs to create another instance of the Player class to represent the new connected peer.
For one thing, I can't call Content.Load because the networking thread has no reference to the Game object. I know I can pass the Game object into the thread, and that would allow me to call Game.Content.Load, but like how I mentioned that in the first question, it may not be ideal. Secondly, I don't want to perform Content.Load
The only thing I can think of.. is perhaps instead of the networking thread doing so much work, perhaps I can just make it raise a flag and temporarily store the data it retrieved into some temporary static vars, and the main Game's Update() loop can check for that flag, and do all the nessesary work with that data before resetting the flag. This prospect frightens me, because if someone joins immediately after someone else joined, the Update() loop might screw up, reading data that is being overwritten before the Update() loop is finished reading/using it. I know I can use locks to protect against that, but wouldn't locks add a lot of overhead, and make my networking thread wait for a lock to open, potentially making the networking thread miss a new incoming message? (Or do networking messages wait in a queue or some kind until they are read?)
I apologize for all these questions, I'm reading 2 books on XNA and C#, and they don't always give an answer to every situation that might occur.
It's one thing to understand the individual concepts, and a whole nother to combine them all together correctly to make a game.
Thank you so much for any advice!