Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
shrughes
Oct 11, 2008

(call/cc call/cc)

PDP-1 posted:

The object that G references can't be switched to a different object,

It can be if you use reflection.

Adbot
ADBOT LOVES YOU

brian
Sep 11, 2001
I obtained this title through beard tax.

shrughes posted:

It can be if you use reflection.

WHY?!

Why would you needlessly complicate someone explaining a fairly basic idea with a utility library that they won't use for months if at all? Seriously this is the poo poo that confuses people into doing retarded things like spend 3 months planning the perfect engine for their extensible version of tetris so they could feasibly make it an MMO if they wanted to 20 years from now.

Luminous
May 19, 2004

Girls
Games
Gains
Uh, because knowledge is a good thing? If you're so goddamn stupid that a little extra knowledge outweighs your ability to rationalize a design, you have bigger loving issues that you should deal with.

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.
I've been working on a physics engine for the last few days and it mostly works fine but seems to be 'leaking' energy somewhere. If I put a bunch of 100% elastic objects into a box and let them bounce around for a few minutes they eventually start to settle down the the bottom of the box instead of bouncing forever. I've confirmed this by summing the kinetic + potential energy over all simulation objects at each timestep and the total energy of the system drops steadily over time. Any ideas as to where the missing energy could be going?

ten_twentyfour
Jan 24, 2008

Correct me if I'm wrong, but aren't kinematics algorithms non-conservative with respect to energy because of floating point error or some other reason?

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.

ten_twentyfour posted:

Correct me if I'm wrong, but aren't kinematics algorithms non-conservative with respect to energy because of floating point error or some other reason?

Good guess! I think I just figured it out and it was a numerical error issue. I had expected some degree of long-term error due to limited precision but I was surprised that the system ground down so quickly.

It turns out the culprit was the gravity term - it makes all the object trajectories tend to arc downward so they all have a negative second derivative. I'm using what amounts to trapezoidal integration in time, so since everything has a negative second derivative the errors at each integration step are all biased in the same direction and add up constructively. If I turn gravity off the errors are more randomly distributed, add destructively, and everything bounces around forever.

I guess I'll need to use a higher-order integration setup to reduce the rate that the errors accumulate until it's not as noticeable. Or, I could just require that half the simulation objects be helium balloons that try to float up instead of falling down.

The Cheshire Cat
Jun 10, 2008

Fun Shoe
I remember someone else had a similar problem a while ago. I'm not too familiar with the math involved, but I seem to remember that the solution was to move away from real gravitation equations and instead use a system of potential and kinetic energy, which guarantees conservation of energy since kinetic + potential should always equal the same amount; an amount you can test against and adjust the energy values to compensate if it comes to the wrong answer.

Basically, the point is that because calculation errors are going to screw up your results, you just need to cheat to fix them. The important thing about game physics is that they FEEL real rather than are accurate models of physical processes.

The Cheshire Cat fucked around with this message at 00:54 on May 15, 2011

Mast
Dec 1, 2007

PDP-1 posted:

I've been working on a physics engine for the last few days and it mostly works fine but seems to be 'leaking' energy somewhere. If I put a bunch of 100% elastic objects into a box and let them bounce around for a few minutes they eventually start to settle down the the bottom of the box instead of bouncing forever. I've confirmed this by summing the kinetic + potential energy over all simulation objects at each timestep and the total energy of the system drops steadily over time. Any ideas as to where the missing energy could be going?

Maybe you should ask Multivac.

Princess Kakorin
Nov 4, 2010

A real Japanese Princess
I swear I'm not trying to poo poo up the thread with questions, but I keep coming back.

I'm at a loss again, this time with how removing objects from a list actually works.
From what I can tell, if I am in a for loop and remove something from a list, it forces the loop it is in the exit? But that doesn't seem right, I'm at a loss(and dead tired) so let me show you.

I spawn two character sprites, P1 and P2.
code:
P1



P2
When I press down the spacebar, it let's out two streams of bullets - one belonging to P1 and the other belonging to P2. Let's say these bullets move 5 pixels/frame

code:
1111111111111111111111111111111111111111111
P1




P2
2222222222222222222222222222222222222222222
Now, here's where things get strange. If either P1 or P2 hit a bullet in the stream belonging to the other, it removes the bullet from that stream AND forces the bullets in the top stream to pause, making it seem like it just deleted two bullets when it just deleted one. Below, let's say P1 hit P2's stream 8 bullets from the end. P2 would lose that bullet, and a gap would occur, which is expected.
However, P1's stream of bullets contains the same number of bullets, but at 8 from the end it develops a gap of 5 pixels, the same size as P2's gap.

code:
1111111  111111111111111111111111111111111111
P1




P2
2222222  2222222222222222222222222222222222
The only reason I can think of is that it forces all loops to exit, which doesn't make any sense otherwise my gameloop would end, but it doesn't.
I hope my explanation made sense, I'll upload a video or pics tomorrow if it doesn't.

Here's the code for my collision detection, by the way -

code:
       private void collisionDetection()
        {
            int index = 0;
            for (index = 0; index < Game1.spriteList.Count; index++)
            {
                //If it does not hit a bullet or it's parent 
                if (Game1.spriteList[index].GetType()!=typeof(bullet) && parent!=Game1.spriteList[index])
                {
                    if (bounding.Intersects(Game1.spriteList[index].bounding))
                    {
                        //Do damage
                        //Edit this later, right now it only deletes what it hits and itself
                        Game1.spriteList.RemoveAt(index);
                        Game1.spriteList.Remove(this);

                    }
                }

            }

        }

Screeb
Dec 28, 2004

status: jiggled

Princess Kakorin posted:

snip

When you remove something from a list, all the items from that point forward will be moved down an index. If you're removing items from a list, either decrement your count variable so that the next one doesn't get skipped (because the for loop will increment) eg

code:
Game1.spriteList.RemoveAt(index);
...
--index;
(You could just put that on one line by doing Game1.spriteList.RemoveAt(index--) if you really want, and are careful)

Or, just run the loop backwards, eg

code:
for (index = Game1.spriteList.Count-1; index >= 0; --index)

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe
Princess Kakorin, do you loop through Game1.spriteList to call collisionDetection on everything as well? Because that will cause you even more problems, for the same reasons that Screeb mentioned. The safest solution is to give each sprite a "Kill Me" flag. Instead of removing things from the spriteList, just set that flag in the sprite to true. Then, after doing your main collision detection loop, loop through all the sprites again (backwards) and remove the ones that have that flag set to true. You should then be able to remove whatever you like during your loops without worrying about messing up your lists.

Princess Kakorin
Nov 4, 2010

A real Japanese Princess

Screeb posted:

When you remove something from a list, all the items from that point forward will be moved down an index. If you're removing items from a list, either decrement your count variable so that the next one doesn't get skipped (because the for loop will increment) eg

code:
Game1.spriteList.RemoveAt(index);
...
--index;
(You could just put that on one line by doing Game1.spriteList.RemoveAt(index--) if you really want, and are careful)

Or, just run the loop backwards, eg

code:
for (index = Game1.spriteList.Count-1; index >= 0; --index)

Yeah, I forgot about that and added it in after I had made that post. While it makes things run smoother, I still have the same problem with each bullet stream developing a space when the other loses a bullet. When I set the bullets to not move, and I remove a bullet from the opposite stream no space is developed, either.

Princess Kakorin
Nov 4, 2010

A real Japanese Princess

Gerblyn posted:

Princess Kakorin, do you loop through Game1.spriteList to call collisionDetection on everything as well? Because that will cause you even more problems, for the same reasons that Screeb mentioned. The safest solution is to give each sprite a "Kill Me" flag. Instead of removing things from the spriteList, just set that flag in the sprite to true. Then, after doing your main collision detection loop, loop through all the sprites again (backwards) and remove the ones that have that flag set to true. You should then be able to remove whatever you like during your loops without worrying about messing up your lists.

I don't have everything call collision detection, just the bullets. For now, atleast. I'm going to have to give the same function to the enemy and player units to test to see when they collide with other objects. I'll try setting a kill flag and report back with the results.

EDIT: The problem persists. Here's a runthrough how the bullets are spawning, maybe it will shine some light on it?


code:
//Updates every sprite in the game
for(int i = 0; i<spriteList.count; i++)
{
        spriteList[i].update()
}


//The players update function
update()
{
//Movement, blah blah blah
//Shooting
if(isKeyDown(keys.space))
{
     shootBullet();
}

//ShootBullet
shootBullet()
{
   bullet myBullet = new bullet();
   myBullet.load(content, "bullet", this) //loads the image and sets the parent of the bullet to whatever spawned it
   game1.spriteList.add(myBullet);

}

//bullet update
update()
{
            X+= 5;
            bounding.X = X;
            
            if (X >= GraphicsDeviceManager.DefaultBackBufferWidth) Game1.spriteList.Remove(this);
            collisionDetection();
            if (killSwitch)
            {
                Game1.spriteList.Remove(this);
            }

}

//Bullet collision
        private void collisionDetection()
        {
            int index = 0;
            for (index = Game1.spriteList.Count-1; index >= 0; index--)
            {
                //If it does not hit a bullet or it's parent 
                if (Game1.spriteList[index].GetType()!=typeof(bullet) && parent!=Game1.spriteList[index])
                {
                    if (bounding.Intersects(Game1.spriteList[index].bounding))
                    {
                        //Do damage
                        //Edit this later, right now it only deletes what it hits and itself
                        killSwitch = true;
                      //  Game1.spriteList.RemoveAt(index);
                       // Game1.spriteList.Remove(this);

                    }
                }

            }

        }

So, the way it goes through spawning bullets is; it looks at P1 and sees that space is down, so it spawns 1 bullet. Then, it looks at P2 and spawns 1 bullet. Then it looks at the two bullets, moves them and checks for collisions. Then it repeats, adding another bullet belonging to P1 then another bullet to P2, moves all 4 bullets and checks for collision, etc etc.

Princess Kakorin fucked around with this message at 16:12 on May 15, 2011

Staggy
Mar 20, 2008

Said little bitch, you can't fuck with me if you wanted to
These expensive
These is red bottoms
These is bloody shoes


After the loop where you call update() on each sprite, loop through again from the back. Move the 'if (killswitch) stuff into the second loop, don't have it within the update() function.

code:
for (int I = spriteList. Count - 1; I >=0; I--)
{
if (spriteList[I].killSwitch)
{
Delete spriteList[I];
spriteList.erase( spriteList.begin() + I );
}
}

Princess Kakorin
Nov 4, 2010

A real Japanese Princess

Staggy posted:

After the loop where you call update() on each sprite, loop through again from the back. Move the 'if (killswitch) stuff into the second loop, don't have it within the update() function.

code:
for (int I = spriteList. Count - 1; I >=0; I--)
{
if (spriteList[I].killSwitch)
{
Delete spriteList[I];
spriteList.erase( spriteList.begin() + I );
}
}

Ah, it works! Wonderful.
Okay, so now I need to wrap my brain around it. I see no problem with what I posted earlier(especially since I translated it over from another project I wrote in Basic).
So why does it work that way, and not any other way?

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe
Well, your update loop looks like this:

code:
for(int i = 0; i<spriteList.count; i++)
{
        spriteList[i].update()
}

So:

1) Sprite number I calls update
2) Update removes the sprite from the list, so sprite number I is now gone
3) To fill the gap left at I, the list code automatically moves all the sprites after I, one step back in the list
4) Now sprite number I is the sprite that used to be sprite I+1
5) Your update loop returns, adds 1 to I, and keeps processing.
6) The sprite that was moved into position I in step 4 therefore doesn't get an update call that frame.
7) Assuming your bullets are moving in a straight line, at a constant speed, the bullet that never got an update will now be in the same position as the bullet that was fired immediately after it, so it will seem to disappear.

You can get round this by looping backwards and things, but that will only help you if you're removing the thing being updated. Your original code removed two things from the list at once, which would have meant keeping track of the right index to update fairly irritating. Hence transferring the code that actually removed things to a different loop, so you could remove what you liked, when you liked, without messing things up.

Gerblyn fucked around with this message at 17:28 on May 15, 2011

Force Quilt
Jan 28, 2006

PDP-1 posted:

I was mainly responding to the assertion that you had to inherit from a class before you could access its static members, but yeah using const for actual constants is also a good idea since it prevents you from accidentally modifying the value.

code:
    public static class Globals 
    {
        // value type
        public const float Pi = 3.14159f;   

        // reference type
        public static readonly Vector2 G = new Vector2(0f, -9.8f);
    }
Now Pi is a const that can be accessed from anywhere but never changed.

The object that G references can't be switched to a different object, but values like G.X or G.Y can be modified (I don't know a way around that in C# short of making a get property that fully copies out the referenced object each time).


Out of curiosity, what issues does it cause?

G isn't a reference; it's a value.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?

PDP-1 posted:

Good guess! I think I just figured it out and it was a numerical error issue. I had expected some degree of long-term error due to limited precision but I was surprised that the system ground down so quickly.

It turns out the culprit was the gravity term - it makes all the object trajectories tend to arc downward so they all have a negative second derivative. I'm using what amounts to trapezoidal integration in time, so since everything has a negative second derivative the errors at each integration step are all biased in the same direction and add up constructively. If I turn gravity off the errors are more randomly distributed, add destructively, and everything bounces around forever.

I guess I'll need to use a higher-order integration setup to reduce the rate that the errors accumulate until it's not as noticeable. Or, I could just require that half the simulation objects be helium balloons that try to float up instead of falling down.

I haven't tried this, but I had an idea to counteract this. Keep track of the total kinetic + potential energy. Record the initial value and set it as the "target" value. Whenever the total energy exceeds the target value use .99 as the coefficient of restitution, and whenever the total is less than the target use 1.01. That should keep the energy near the target without having to replace the whole engine..

Zizzyx
Sep 18, 2007

INTERGALACTIC CAN CHAMPION

Can someone take a quick look at my code and let me know if I'm headed in the right direction? Here's what I've done so far:

- Made an action queue that handles all possible events, from character turns, delayed effects, instant effects, timed messages, expiring events, etc.

- Made an interface using curses with partitions for: character list, main arena, options area, message area.

My next hurdle is make the options area interactive. Every time I ask about how to use a library I get a suggestion to use a different one, and I can't figure out the documentation for some such as urwid, so I'd like it if someone could look at what I have and tell me where I can go from here. Right now my project is just two files:

main.py

terminterface.py

If there is any evidence of bad habits in there, please let me know, as well as areas in which my code is doing things the hard way.

e: right now it actually does nothing but display some information on the screen, but all the functions work and you can have characters schedule attack events and etc.

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.

HappyHippo posted:

I haven't tried this, but I had an idea to counteract this. Keep track of the total kinetic + potential energy. Record the initial value and set it as the "target" value. Whenever the total energy exceeds the target value use .99 as the coefficient of restitution, and whenever the total is less than the target use 1.01. That should keep the energy near the target without having to replace the whole engine..

Thanks for the suggestion, I don't think I'll have to cheat it though since I did find something that works.

My first integrator was just an Euler scheme, so velocity and position would update as

v += (forces/mass)*dt;
x += v * dt;

where 'forces' was the vector sum of all forces applied to the object - contacts, constraints, and gravity. This mostly worked, but since gravity causes a constant curvature in the trajectory of the objects and the integrator doesn't take second derivative effects into account there was an accumulating error over time.

The solution turned out to be extending the integrator to include second derivative effects by adding on the next term in the Taylor series:

v += (forces/mass)*dt;
x += v*dt - 0.5f*(forces/mass)*dt*dt;

Where forces/mass is just a re-arranging of F=m*a and 'a' is the second derivative of position. That term is negative because of the way the y-axis is 'up' in the physics simulation vs. 'down' in the screen position.

Now that the second derivative effects are in the system is super stable - right after I fixed it someone called and I ended up being on the phone for half an hour while the simulator ran and it lost less than a 1e-7 fraction of the original system energy.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I spent my home nerd time the past few days learning how to wrap C++ code for the sake of Python. The goal is that I'd like to be able to doodle around in Python and prototype game logic there while the stuff I've chosen to use for graphics and sound and all sits in C/C++ land. I've having a hard time figuring out where to draw the line in what I should do in the interpreter and what to initially manage externally.

At first I thought I'd try to write wrappers for everything and have it all start up in Python, but a few days in and I was still crawling down the rabbit hole just to get something basic all wrapped. So I think I have opted to tie up the rendering engine into my own separate object and pass garbage into it as I see fit.

There was some talk previously about representing game logic objects with some master Entity class. I am wondering how one manages and passes them around. My first thought is to just toss these over to the rendering engine and have it try to figure out what to do with them. So the entities would at some point in their representation would need to have some mesh in it and enough state that the renderer can set it all up at that instant.

So I am assuming the main currency of the different components of the game engine would be these entities. Is that the general idea?

Twernmilt
Nov 11, 2005
No damn cat and no damn cradle.
I'm working on a cooperative multiplayer game for fun over the summer. I'm to the point where I need to start making sure my networking code is sufficient over the Internet rather than just on my LAN. My current plan is to add some attributes to the server that will randomly either delay sending a message(to simulate latency) or fail to send it if it's UDP(to simulate packet loss) with a set probability.

Does anyone have any thoughts on this approach? Is there a better way to simulate Internet traffic on my LAN?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Twernmilt posted:

Does anyone have any thoughts on this approach? Is there a better way to simulate Internet traffic on my LAN?
Seems like you'd only be testing one way (though you could equally ignore a random subset of incoming traffic). I'd suggest rather than modifying your server, making a tiny "in between" server that forwards traffic each way and performs the dropping/lagging. Don't forget to occasionally allow UDP packets to arrive in the wrong order!

devilmouse
Mar 26, 2004

It's just like real life.

Twernmilt posted:

Does anyone have any thoughts on this approach? Is there a better way to simulate Internet traffic on my LAN?

Do you have a linux box (or even a mac!) somewhere you can set up in between your server/client or that you can set up as a router?

iptables, the built-in firewall, can do all of this (dropped packets, lag, etc). There's a slightly nicer version that does the same thing called dummynet (http://info.iet.unipi.it/~luigi/dummynet/) too.

Twernmilt
Nov 11, 2005
No damn cat and no damn cradle.

devilmouse posted:

Do you have a linux box (or even a mac!) somewhere you can set up in between your server/client or that you can set up as a router?

iptables, the built-in firewall, can do all of this (dropped packets, lag, etc). There's a slightly nicer version that does the same thing called dummynet (http://info.iet.unipi.it/~luigi/dummynet/) too.

This is exactly what I'm looking for! Hopefully it works out. I was about to sit down and write a proxy to do this.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
How difficult is it to learn UDK and make simple games in it? By simple, I mean prototyping, etc. I have programming and map making experience but I'm a terrible artist.

Hughlander
May 11, 2005

Twernmilt posted:

I'm working on a cooperative multiplayer game for fun over the summer. I'm to the point where I need to start making sure my networking code is sufficient over the Internet rather than just on my LAN. My current plan is to add some attributes to the server that will randomly either delay sending a message(to simulate latency) or fail to send it if it's UDP(to simulate packet loss) with a set probability.

Does anyone have any thoughts on this approach? Is there a better way to simulate Internet traffic on my LAN?

What I normally do is 3 fold.

1) Introduce Latency to every packet
2) Drop a random % of packets
3) Create a network spike. (Delay a series of packets and then have them all arrive rapidly)

Better answer though, unless you're trying particularly to create a netengine, I'd look at protocol buffers or EFNet or something similar and consider networking a solved problem.

Twernmilt
Nov 11, 2005
No damn cat and no damn cradle.

Hughlander posted:

Better answer though, unless you're trying particularly to create a netengine, I'd look at protocol buffers or EFNet or something similar and consider networking a solved problem.

So far the protocol for sending messages hasn't been particularly difficult to implement. I think what I really need to test is that the amount of messages I'm sending is acceptable and ensure that the way I'm syncing the world between players works in the face of latency and packet loss. I've never used protocol buffer or EFNet but they don't look like they solve that particular problem, unless I'm missing something.

Twernmilt fucked around with this message at 05:13 on May 17, 2011

Princess Kakorin
Nov 4, 2010

A real Japanese Princess

Gerblyn posted:

Explanation


Ah, okay. That makes sense, I wasn't thinking properly.
New question: Any good tutorials on using XML with XNA? I've scoured through google, and the best I could come up with is this, but it still leaves a handful of questions, such as, what do I pass for the contentreader when calling the function for Read(ContentReader input, Sprite existingInstanc)?
No place seems to have the answer lying about.

Princess Kakorin fucked around with this message at 00:55 on May 18, 2011

Long John Power
Sep 11, 2001

I think this may be a bit of a daft question. But looking at a particle system like this...

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=19

In a particle system like this, what would you think the best way would be to have an unspecified number of particle instances to say make up enemies or something.

In my head I am trying to put arrays inside structs and all sorts of impossible and equally horrible things when I am sure there is a really simple answer?

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.

Long John Power posted:

In a particle system like this, what would you think the best way would be to have an unspecified number of particle instances to say make up enemies or something.

I'd look at a List<WhateverClass> in .NET or a std::vector in c++. It'd let you add an arbitrary number of units, remove dead ones, and then iterate through each item to do Update/Draw ticks.

Vietnom nom nom
Oct 24, 2000
Forum Veteran

Orzo posted:

How difficult is it to learn UDK and make simple games in it? By simple, I mean prototyping, etc. I have programming and map making experience but I'm a terrible artist.

UDK isn't as simple as say Unity in my opinion. If you just want to get a basic FPS with a simple level up and running UDK can be dead simple since it's origins are Unreal obviously. But you have to really mess around with it to get it to work in other genres, and that means learning UnrealScript, which is proprietary.

The strength of UDK in my mind is how feature rich it is, plus the tools that surround it (all of which you need to learn to some extent to get the most out of UDK). The power of UDK has translated into complexity in my opinion, which is fine considering how flexible it's required to be.

If I was looking to create a serious project with a small team of guys dedicated to it with the hopes of making a presentation to publishers of the prototype and getting a publishing deal, that's where UDK can really shine in my opinion (see: Hawken).

For small, 1-2 man projects outside of 2D, things like Unity make more sense to me. UDK can be a bit overkill in other words.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

PDP-1 posted:

I'd look at a List<WhateverClass> in .NET or a std::vector in c++. It'd let you add an arbitrary number of units, remove dead ones, and then iterate through each item to do Update/Draw ticks.
If you're dealing with fixed-size allocations, one trick you can do is link allocation blocks (i.e. single particles) to each other. This makes traversal completely skip dead elements and makes deletions have a fixed-cost.

i.e. start with 20 particle slots, all "dead," and each pointing to another particle. You don't even need to indicate that it's dead, just know what the first dead particle is and the first live one. Initialize all of them to have the "next" particle be the one after it, the first one is the first dead particle.

When allocating a particle, delink the first dead particle from the dead list, add it as the head of the live list. When processing particles, start at the first live one, and if the particle dies, delink it from the live list and re-link it to the dead list.

Expanding is linear cost (just add more dead allocation units), collapsing is linear cost (just traverse the live elements and copy to the start of the new array, then add more dead allocation units), allocation and deletion are fixed cost, traversal cost is linear only with the number of traversable elements. Only thing that sucks about it is cache coherency since it fragments after a while.

poemdexter
Feb 18, 2005

Hooray Indie Games!

College Slice
Me and a buddy are working on a multiplayer asteroids game together for fun using XNA. We've really never ever messed with netcode before and are really completely lost as to what best practices are for what data the player should be sending to the server. We plan on having a dedicated server. So far we kinda think the client should send it's new position vector to the server, but we're not sure if we should take it a step further back and just send the server keyboard input. We figure we'll use UDP but we just need some simple documentation/book/blog posts/etc just to get us started.

Our most pressing questions would be:
1. For a very simple asteroids game, what should the client be sending the server?
2. What is ok for the client to handle and what should the server handle?
3. I assume we should be limiting the packet sending somehow in the main game loop so it's not pushing packets out as fast as the game loops.

Another generic XNA question would be does the XNA library handle timing by itself natively? As in, will we need to add some timing functionality so that the clients run at the same speed across all hardware?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

poemdexter posted:

1. For a very simple asteroids game, what should the client be sending the server?
Options!
1. If you send just inputs, and have the client react only to what the server says is happening, everything stays synchronized but things respond horribly sluggishly if you don't have awesome ping. Works okay for an "order submitting" game like an RTS, but would suck for Asteroids.
2. If you send inputs and have the client react immediately to inputs you get better reactions but occasional hideous "resync" issues if the server didn't get a message right away.
3. If you send inputs with timestamps and have the client also react immediately to inputs, and the server and/or clients rewind and replay what's happening when it gets a backdated input, you get good results and responsiveness but it's clearly a pain in the arse to do. (You also have to make sure every input eventually gets through even if you're using UDP, this way, since otherwise the clients think different things are happening.) It's also susceptible to doctored 'backdated' messages if someone really really wants to cheat.
4. If you send positions it's a lot more convenient because the clients can basically synchronize themselves, but you're really relying on the client to be honest. Even with honest clients you can get "A thinks A shot B, but B thinks it didn't" issues as the clients won't be in sync at all times, so you also have to decide on a way to resolve that (if I was doing it this way I'd make it so the victim of a shot is the one believed, but I wouldn't do it this way - I would, however, tentatively recommend it if you're a beginner because it's a much simpler way to get adequate results).

Edit: Also note, when I say "inputs" here I mean things that are relevant to the server - in the case of Asteroids it would be approximately the same as keyboard input, translated to "thrust pressed" and "thrust released" sort of things, but for an RTS you wouldn't send every mouse movement, you'd just send the orders you're giving, that's the relevant part of the input.

quote:

2. What is ok for the client to handle and what should the server handle?
Depends on which of the above you chose, and how much you want to trust the players not to hack. I like to offload as much as possible to the clients, other systems like to make it so the server handles all events and all the clients do is display and take input. (Those systems generally have the client display 'predictive' things based on input that the server hasn't reported back yet, to make it feel more responsive.)

quote:

3. I assume we should be limiting the packet sending somehow in the main game loop so it's not pushing packets out as fast as the game loops.
Probably. That's one of the advantages of sending only input, the amount of data is precisely the amount that's relevant (you don't send "pressing up.. still pressing up.. still pressing up...", you send "pressing up... stopped pressing up.")

quote:

Another generic XNA question would be does the XNA library handle timing by itself natively? As in, will we need to add some timing functionality so that the clients run at the same speed across all hardware?
Generally you want game time to not be related to frames at all. Don't move 2 pixels per frame, move 2 pixels per sixtieth of a second (or whatever). You don't need the clients to run at the same speed then, you can just end up with one running at 400 frames per second and one running at 8 frames per second, but everything still moves at the same speed, just jerkier for the guy with the 486.
Edit: It's generally still a good idea to use fixed time intervals for your 'physics' rather than just going to whatever time the client is at, to avoid small variations arising from different clients calculating at different time intervals - though if you're feeding timestamps into your 'physics' this is moot, they'll match regardless.

roomforthetuna fucked around with this message at 01:09 on May 19, 2011

Vino
Aug 11, 2010

OneEightHundred posted:

If you're dealing with fixed-size allocations, one trick you can do is link allocation blocks (i.e. single particles) to each other. This makes traversal completely skip dead elements and makes deletions have a fixed-cost.

i.e. start with 20 particle slots, all "dead," and each pointing to another particle. You don't even need to indicate that it's dead, just know what the first dead particle is and the first live one. Initialize all of them to have the "next" particle be the one after it, the first one is the first dead particle.

When allocating a particle, delink the first dead particle from the dead list, add it as the head of the live list. When processing particles, start at the first live one, and if the particle dies, delink it from the live list and re-link it to the dead list.

Expanding is linear cost (just add more dead allocation units), collapsing is linear cost (just traverse the live elements and copy to the start of the new array, then add more dead allocation units), allocation and deletion are fixed cost, traversal cost is linear only with the number of traversable elements. Only thing that sucks about it is cache coherency since it fragments after a while.

Not reading the entire discussion here (so busy! no time!) but I usually do something similar but with a vector. The structure has an "active" flag that's off until it's needed, so iterating over the list is a bit faster than with a linked list (just skip teh inactive ones) and adding/removing is simple as flipping that "active" flag.

It's a bit slower to allocate more I suppose if you hit the top limit of a large vector but generally with things like particle systems you'll never get more than a certain number of particles and you can estimate and pre-allocate up front.

Princess Kakorin
Nov 4, 2010

A real Japanese Princess
Anybody know what the deal is when you get this error when _trying_ to use XML?
code:
Error	1	There was an error while deserializing intermediate XML. Cannot find type "Collision_Detection_2.player".	C:\Users\Documents\Visual Studio 2008\Projects\Collision_Detection_2\Collision_Detection_2\Content\player1.xml	4	10	Collision_Detection_2
All the tutorials on XML do something different(from what I've seen), and when people come across this error they're told to make sure that the namespace and class name is spelled right, and that fixes it. But, for me it doesn't work. The class name is player with a lower case p, and the namespace is indeed Collision_Detection_2.
And they said this XML stuff would be easy.

PDP-1
Oct 12, 2004

It's a beautiful day in the neighborhood.

Princess Kakorin posted:

Anybody know what the deal is when you get this error when _trying_ to use XML?

I haven't done XML importing in XNA myself, so this may be a bit of a longshot, but how do you have your solution/project structure set up? Is the player* class in a standalone project along with anything else that will be serialized to/from XML?

Your game project needs to be able to see the player class so that it can be used at runtime. Your XML importer needs to be able to see the player class so that it can be used at buildtime. The player class can't be in either the game or the content importer projects because there is no way for both of them to reference it without generating a circular dependency and still be usable at runtime. So, the solution is to put the player class in its own project and have both the game and content importer reference that third project.

I'm probably not explaining this well but check out Shawn Hargreaves' Blog, particularly the 'Sharing Data Types Between Build And Runtime' section. In the terminology of that blog your player class might be a 'purple' class.


* Class names begin with caps, dammit. Player, not player. :mad:

Princess Kakorin
Nov 4, 2010

A real Japanese Princess

PDP-1 posted:

I haven't done XML importing in XNA myself, so this may be a bit of a longshot, but how do you have your solution/project structure set up? Is the player* class in a standalone project along with anything else that will be serialized to/from XML?

Your game project needs to be able to see the player class so that it can be used at runtime. Your XML importer needs to be able to see the player class so that it can be used at buildtime. The player class can't be in either the game or the content importer projects because there is no way for both of them to reference it without generating a circular dependency and still be usable at runtime. So, the solution is to put the player class in its own project and have both the game and content importer reference that third project.

I'm probably not explaining this well but check out Shawn Hargreaves' Blog, particularly the 'Sharing Data Types Between Build And Runtime' section. In the terminology of that blog your player class might be a 'purple' class.


* Class names begin with caps, dammit. Player, not player. :mad:

It makes sense, I'll throw something together when I get home. If it does work, I wish the blogs/tutorials I've read would have stated that in the begining.

Adbot
ADBOT LOVES YOU

The Saddest Robot
Apr 17, 2007

Long John Power posted:

I think this may be a bit of a daft question. But looking at a particle system like this...

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=19

In a particle system like this, what would you think the best way would be to have an unspecified number of particle instances to say make up enemies or something.

In my head I am trying to put arrays inside structs and all sorts of impossible and equally horrible things when I am sure there is a really simple answer?

How many items are you expecting for the 'unspecified number'?

It's bad in theory to create/destroy lots of objects on demand in the main loop. If you're going to be creating thousands of objects/enemies/particle systems it would be ideal to create them once at the beginning and re-use them when possible. This is especially true with particle systems - you don't want to be creating and destroying particles on demand, that won't scale well at all and will fragment your memory space like swiss cheese.

Depending on your usage you can probably get away with a list or a std::vector to hold all of them and add a bunch of items to the list when needed; like blocks of 500 or something. You can then just brute force through the list and ignore the ones that are marked as inactive.

If we're talking about tens of thousands of items you'll want a more optimized approach.

Particle systems... simple in theory but complex to make work well with the hardware/system.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply