Interesting... time to go off and read some more about data structures :)
What bits of source code should I look up to take a peek at the game loop? Interested in how it sorts through objects and knows what to do with each object :E
Explorer
#621 posted by Preach on 2011/10/05 10:26:30
I'd say SV_Physics() in sv_phys.c is the main loop to start with. It runs once per frame, looping through all the entities, running physics and QC functions on them. It doesn't give you everything the server does in a frame, stuff like creating the updates to be sent out to the network and parsing the input from the client is elsewhere. But it is the heart of the matter.
One thing that I've found extremely helpful in tackling the quake source code is loading it into a proper IDE like Visual Studio. Being able to right click a function name or typedef and select "go to definition" allows you to focus on figuring out what the functions do, rather than having to switch your train of thought to hunting down the function manually. The history buttons are likewise important so that you can return to the original function just as easily.
Finally "Find All References" allows you to step outwards, for instance to go from Sv_Physics back out to the rest of the server code, and see where it fits in.
So On The Subject
#622 posted by Preach on 2011/10/12 01:37:21
of looking far too closely at the engine physics source, is this a mistake?
trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
{
��trace_t���trace;
��vec3_t����offset;
��vec3_t����start_l, end_l;
��hull_t����*hull;
// fill in a default trace
��memset (&trace, 0, sizeof(trace_t));
��trace.fraction = 1;
��trace.allsolid = true;
��VectorCopy (end, trace.endpos);
// get the clipping hull
��hull = SV_HullForEntity (ent, mins, maxs, offset);
��VectorSubtract (start, offset, start_l);
��VectorSubtract (end, offset, end_l);
// trace a line through the apropriate clipping hull
��SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
// fix trace up by the offset
��if (trace.fraction != 1)
����VectorAdd (trace.endpos, offset, trace.endpos);
// did we clip the move?
��if (trace.fraction < 1 || trace.startsolid )
����trace.ent = ent;
��return trace;
}
Quoting from fitzquake source but I think it's unaltered. I've bolded the references to offset, because as far as I can see it never gets initialised. It doesn't actually matter in the call to SV_HullForEntity because that function never reads the offset parameter, just uses it as a local variable for internal calculations!
Still, since it's not passed by reference there presumably the same junk sitting there from the uninitialised starting state. Is it just by fortunate placement on the stack that it always gets zero initialised or something? It looks like it should at least mess up trace_endpos if it really contained garbage, or worse the whole SV_RecursiveHullCheck call...
It's Actually Passed By Reference!
#623 posted by ericw on 2011/10/12 05:04:30
It's only evident when you check the definition of vec3_t in q_stdinc.h:
typedef float vec_t;
typedef vec_t vec3_t[3];
vec3_t is an array type, so it is always passed by reference in a function call. In this case, it looks like SV_HullForEntity always writes to the offset variable, so there's no problem.
That is really confusing, though - at first I though vec3_t was a type that is passed by value, like struct { float x; float y; float z}.
Ah...
#624 posted by metlslime on 2011/10/12 05:24:09
that's what i suspected too, looking at that code.
Preach
#625 posted by inertia on 2011/10/12 06:18:32
Do you write about code elsewhere?
Other Writing
#626 posted by Preach on 2011/10/12 09:57:34
inertia: No, this is basically my one coding outlet! I've got a little article coming up on names in qc which lead me to look up this function and get confused.
ercw: Thanks! Been away from c coding too long I missed that vector thing. And I really should have seen it given the way that the VectorAdd function works, clearly taking a pass by reference in order to mutate the third parameter. Ah well...
In C++
#627 posted by RickyT33 on 2011/10/13 20:22:16
how does a for loop initialise an integer automatically?
int a;
for (a=1; a<150; a++){cout << a;}
Works, buuuut:
int a; cout << a;
throws a compiler error with
"Run-Time Check Failure #3 - The variable 'a' is being used without being initialized."
Now obviously i could start with:
int a=0;
But what gives the for loop the right to initialise the variable before it begins testing it?
#628 posted by metlslime on 2011/10/13 21:02:56
for (a=1; ...
The a=1 is the part that initializes the variable
#629 posted by RickyT33 on 2011/10/13 22:08:50
Hmmmmm. I kinda suspected that. I guess I'm mis-understanding the for part. I can't help but think of it as an if.
The excercise which has gotten me confused is the following:
int i, j;
bool isprime;
for(i=1; i<100; i++){
isprime = true;
// see if the number is evenly divisible
for(j=2; j<= i/2; j++)
// if it is then it is not prime
if ((i%j) == 0) isprime = false;
if (isprime) cout << i << " is prime. \n";
It's the modulus test part, and my understanding of prime numbers which has gotten me confused.
I inserted this after the second last 'if':
cout << "i=" << i << ", j=" << j << " ";
This way it shows me what the two variables are. I don't understand why the test works.
#630 posted by necros on 2011/10/13 22:48:09
cout << "i=" << i << ", j=" << j << " ";
looks suspiciously like some of the stuff i've been learning about linux and input redirection...
#631 posted by Spirit on 2011/10/13 23:01:58
What exactly don't you understand?
The if (isprime)? If you test a variable without explictly writing eg isprime == 42 it will test if the variable is true (or not false or something like that).
#632 posted by RickyT33 on 2011/10/13 23:16:39
%
% is what i dont understand lol.
Why is 2%3 equal to 2 ?
Why is 45%89 equal to 45 ?
#633 posted by Spirit on 2011/10/13 23:20:01
Yeah - I Just Read That, Incidentally.
#634 posted by RickyT33 on 2011/10/13 23:36:20
The most useful bit of information I could find on that page was:
^ ISO/IEC 14882:2003 : Programming languages -- C++. 5.6.4: ISO, IEC. 2003. "the binary % operator yields the remainder from the division of the first expression by the second. .... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined".
The word "nonnegative" scares me a bit TBH.
#635 posted by necros on 2011/10/13 23:36:43
modulus is basically the remainder. like you do long division and stop before going into decimals.
so 2%3 is 2 because 2 can't fit into 3 at all, so you have 2 as the remained.
same with 45%89.
otoh, if you had 3%2, it's 1, because 2 fits into 3 once, and you have 1 left over.
Necros
I'm sure you meant to say: 3 can't fit into 2 at all, that's why 2 % 3 = 2. Look at this, Ricky:
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
etc.
Just try a few examples and you'll get a feel for what the modulo operator does.
Thanks Necros & SleepwalkR
#637 posted by RickyT33 on 2011/10/14 10:36:27
I also figured he meant a three, but I was pretty cross-eyed already ;)
I think I'm starting to understand it. C++ is weird though, because sometimes you get a negative short. Which is weird. BUT I'm beginning to get my head round it. Which means I'm learning :D
Sleep
#638 posted by necros on 2011/10/14 22:22:36
haha, apparently math doesn't fit at all into my head. :P
Ricky
You're probably messing up the types (using signed short instead of unsigned or something).
Shoutouts To Awesome Lines Of QC Code #1
#640 posted by Preach on 2011/12/13 16:31:43
A real gem from the walkmonster_start_go code I've never noticed before today:
self.ideal_yaw = self.angles * '0 1 0';
Why not just use self.angles_y? Because that wouldn't be vectorised and involve lots of awesome multiplication!
Why Not Just Use Self.angles_y?
#641 posted by mh on 2011/12/15 02:33:01
...because then self.ideal_yaw_x and self.ideal_yaw_z may not be set to 0.
#642 posted by necros on 2011/12/15 02:40:51
ideal_yaw is a float though
Yeah
#643 posted by Preach on 2011/12/15 09:57:08
It's the dot product, so it returns the sum of all three components once you do the componentwise multiplication. Very handy some of the time, but a bit of a waste here.
Rocket Trails
#644 posted by Mike Woodham on 2011/12/25 09:40:59
What is it that gives rocket (and grenades) their flight trails?
|