Ioh
#45 posted by megaman on 2008/03/30 15:24:24
and, upon reading metl's answer a bit more:
you'd also have the main game loop decide when to render a frame and when to update the gamestate (ie. seperate render() and update() methods).
Also...
#46 posted by metlslime on 2008/03/31 01:33:56
like megaman said, some functions (such as physics/movement) will want a "frametime" delta in addition or or instead of the global time. So you should have both be available.
Well,
#47 posted by necros on 2008/03/31 04:46:09
i found out that clock() returns what looks like a simple integer in msec starting at 0 when the game starts, so i'm using that.
but what is this frametime delta you are talking about? like the time between frames? cause i haven't a clue on how to calculate something like that.
i realise though, that i'll eventually need something like that. i changed the movement system to work with velocity vectors but i won't be able to accurately update positions without some way to tell how much time is taking place between frames.
Necros:
#48 posted by metlslime on 2008/03/31 05:48:52
"frametime" i.e. time "delta" i.e. time between frames is easily calculated: just currenttime - previoustime. It is useful for things like physics, for example:
entity.position += entity.velocity * frametime;
entity.velocity += entity.gravity * frametime;
note that the second line above is responsibly for jump height being framerate-dependant!
My Understanding Is That Timing Is Messy Stuff
#49 posted by bear on 2008/03/31 09:13:07
Basically there are a number of ways of getting the time and some of the timers that give you the data aren't that exact.
You should be able to find some good info in the http://www.gamedev.net forums and I think I remember seeing it discussed on the http://www.shmup-dev.com/ forums too in the past.
Thanks :)
#50 posted by necros on 2008/04/01 20:52:51
i think i've got it working, or at least, it seems to be.
every frame:
time_currentFrame = clock();
time_previousFrame = time_currentFrame;
time_frameDelta = (time_currentFrame - time_previousFrame) / 1000;
this gives me the fraction of time per second, and i have one function that does:
nextPosition = currentPosition + (velocity * time_frameDelta)
for all movements.
for actual velocity calculations, i capped that at 10 frames per second (every 100ms) to keep cpu usage down for needlessly precise velocities.
Umm
#51 posted by bambuz on 2008/04/02 02:23:49
you have to reverse the order of the first two lines?
Yeah.
#52 posted by necros on 2008/04/02 04:47:02
:P
Function
#53 posted by necros on 2008/04/04 22:11:32
how do you call a function outside of the class you're in atm? is it even possible?
i know you can do object->doThis() but that requires you to first find the pointer for that object, and then that function usually means you want to perform the function on that object...
i wanted to do the old style C thing where you just have a function you call from anywhere (like how T_Damage and T_RadiusDamage work in quakeC).
i'm kind of shit at this whole OO stuff, so am i going about this the totally wrong way?
Make It A Static Method
#54 posted by czg on 2008/04/04 22:25:30
#55 posted by JneeraZ on 2008/04/04 22:29:47
Or just place the function outside of any class definitions. Functions at the global level work the same as C functions.
How?
#56 posted by necros on 2008/04/05 00:10:17
how exactly do i make it static? or how do i declare the function outside a class definition? do i make a new cpp file or something or..?
Static
#57 posted by bambuz on 2008/04/05 01:02:27
is another modifier, kinda like private or public.
A static thing is something you can not make instances of, kinda.
So you have classes like Moose and you can make moose1, moose2 etc... But there can be a static method in the Moose class that is not particular to any moose1 or moose2 instance.
Like double Moose.mass_of_the_sun() which then returns a static constant that is always the same no matter what you do with the moose instances.
Kinda like that. Damn it's been too long since I've coded.
#58 posted by JneeraZ on 2008/04/05 12:23:49
necros
You're asking some pretty basic questions here in all honesty. Maybe reading a primer on C/C++ would be in order here.
Yeah
#59 posted by BlackDog on 2008/04/05 16:45:03
C++ is a painful and unforgiving language. If you dive right in, you're going to hit something hard and spiky.
I would go so far as suggesting a different language, if that's practical (pygame is pretty sweet). If it isn't, then you really need to read up on the basics.
#60 posted by JneeraZ on 2008/04/05 17:22:05
C++ is fine and gets far more flack than it deserves.
C# is far superior however. FAR superior.
I guess it would help to know what specifically you're trying to code and for what platform.
#61 posted by BlackDog on 2008/04/05 18:10:42
C++ does get treated unfairly - google Erik Naggum's usenet rants sometime for a hilarious example - but I wouldn't call it "fine".
I don't really want to get into a flamewar over C++'s fucked up design: I'm just going to note that there are plenty of better languages to choose from.
#62 posted by necros on 2008/04/05 23:14:37
at the same time, i always learnt best by doing. it's more frustrating, but it sticks better.
i've tried reading some lit on c++ but they annoy the hell out of me. i'd rather they just give me the syntax for it and give me a brief overview of how to put it in the code instead of going into all the long winded crap about stuff i never remember anyway.
otoh, the more i look at this code, the more i feel it needs to be rewritten almost from scratch. there are some things in here which i don't like at all.
ie: instead of treating ships and missiles as inheriting from the same class, they are completely different classes, and neither of them can 'see' the other.
ideally, i would have liked to override the basic 'update' function of a base entity class for specific ones (ie: for missiles and ships) and then be able to call it by just iterating down one big list of entities and calling the same function.
instead, i'm trying to hack my way around it by making a static function in a new class so that i can call it from inside one class that normally can't see the other class.
also, for, apparently no reason, missiles aren't instanciated objects, but are regular structs which is also causing other problems.
i'm going back to school next week, so i'll probably ask these questions to my instructors instead and see what they think...
Heh
#63 posted by necros on 2008/04/05 23:15:07
the title for the above post should have read "that may be true, but"
If This Is Your First C++ Program...
#64 posted by mwh on 2008/04/06 10:45:31
you should entirely expect to have to throw it away and start again.
(Or your 10th or 100th, to be fair: "build one to throw away" is a long standing slogan of software engineering).
#65 posted by JneeraZ on 2008/04/06 11:35:49
The problem is that hardly anyone ever does that. :) That's where horrible feature bloated abominations are born.
Unarmed Ogre
#66 posted by ijed on 2008/06/01 03:03:43
I've been stuggling to make an Ogre variant and I'm having troubles with ai/fight/ogreb.
Basically the fat cunt keeps trying to go to th_missile when he has no grenades (crash). I must be missing something obvious here but I don't know what.
The error returned is on his run sequence (has all his own functions) but if I replace his th_missile linking it to eg.melee then I'm ok, except it takes him ages to close the distance because he's swinging chainsaws about.
NULL function
Basically I don't want him to ever th_missile - but looking over ai and other monsters sheds no light - dogs / knights / fiends all use ai_run without problem.
I'm going in circles, it seems. If anyone can shed any light on this I'd appreciate it.
C++ For C Programmers
#67 posted by inertia on 2008/06/01 09:18:27
http://www.4p8.com/eric.brasseur/cppcen.html
I find that documents called "X For C Programmers" tend to hit the spot. This is mainly for necros.
Ijed
#68 posted by Supa on 2008/06/01 11:14:34
OgreCheckAttack sets their attack state to AS_MISSILE, which leads to ai_run calling ai_run_missile, which leads to self.th_missile.. which leads to the crash.
You'll need to comment out the monster_ogre/OgreCheckAttack lines in CheckAnyAttack (so they'll use CheckAttack instead) and make sure you don't give them a .th_missile, else CheckAttack will convienently call self.th_missile for you. :)
An Ogre By Another Name
#69 posted by Preach on 2008/06/01 11:39:17
Have you tried changing the classname from monster_ogre to, for example, monster_ogre_unarmed? I have a feeling that might make it work.
The reason why is hidden in fight.qc and ai.qc. fight.qc is the place to start, have a look at the two functions CheckAttack and OgreCheckAttack. The former is the generic function for any monster, and it's careful enough to check whether self.th_missile is set or not before deciding to make a missile attack. OgreCheckAttack is more presumptive, it knows that an ogre has a missile attack and so goes straight ahead with setting AS_MISSILE.
This is all quite deceptive, as OgreCheckAttack never explicitly uses th_missile - it just sets AS_MISSILE and lets ai.qc do the th_missile part. ai.qc is also the place to find out how the game chooses between CheckAttack and OgreCheckAttack. The function that decides is called CheckAnyAttack, and as you can see it decides based on the classname. So if you give your melee ogres a different classname then it should use CheckAttack only, which is safe to use without th_missile set.
The downside to this method is that, like with monster_ogre_marksman, your ogres will be able to infight with each other. So you could just make the check in CheckAnyAttack more stringent:
if (self.classname == "monster_ogre" && self.th_missile)
return OgreCheckAttack ();
For neatness of code, this way is probably better, as it means you can have a single spawnfunction for both grenadiers and berserkers. This is good code sharing, as any change you make to an ogre you probably want to make for both of them.
The third solution would be to modify OgreCheckAttack to properly check for th_missile, but I don't think that's the best way to go, it could end up complicated.
|