--- Log opened Fri Apr 20 00:00:53 2007 |
00:40 | <@McMartin> | I'm not sure what you mean by "metaprogramming" in your question, so I can't answer it |
01:08 | | Mahal [~Mahal@Nightstar-12512.worldnet.co.nz] has quit [Quit: Leaving] |
01:25 | | ReivSLEP is now known as Reiver |
01:31 | | MyCatEats is now known as MyCatVerbs |
01:31 | < Janus> | Lordy... I need some advice on a wide-wide subject. |
01:32 | < Attilla> | How wide? |
01:33 | < Janus> | Game loops. |
01:33 | <@McMartin> | Advice implies a problem. |
01:33 | < Janus> | There's a problem~ |
01:34 | <@McMartin> | "Game loops" isn't a problem. |
01:34 | <@McMartin> | "My game loopi sn't working" is one, as is "I know nothing about how to organize one", but the latter suggests different kinds of answers |
01:37 | <@gnolam> | So... what /is/ the problem, Janus? |
01:37 | <@gnolam> | (Highlighting for effect!) |
01:37 | <@McMartin> | Lacking a problem, my advice is that only the main thread gets to touch the video. |
01:38 | < Janus> | I guess it's the latter... It's just that... *thinks of a way to explain it effectively.* |
01:41 | <@gnolam> | It looped so fast it produced a positive feedback loop that, thanks to the immense power consumption and the accidentally perfect harmonics, ripped open a hole in space-time that threatens to consume the Earth within 72 hours? |
01:42 | <@gnolam> | If not, I have no idea what to do. |
01:42 | <@gnolam> | ;-) |
01:43 | <@McMartin> | First. Fixed framerate or flexible? |
01:43 | < Janus> | Flexible. *still tinkering with it* |
01:43 | <@McMartin> | OK |
01:43 | <@McMartin> | Your basic loop looks like this: |
01:43 | <@McMartin> | forever { |
01:44 | <@McMartin> | Determine how much time has elapsed since the last frame |
01:44 | <@McMartin> | Read the input |
01:44 | <@McMartin> | Advance the world model the amount necessary for the time given |
01:44 | <@McMartin> | Render the screen |
01:44 | <@McMartin> | { |
01:44 | <@McMartin> | Er, } |
01:45 | | * gnolam preferse fixed logic rates. Less flexibility, but so much less of a hassle. |
01:45 | <@gnolam> | -e |
01:45 | <@McMartin> | You will probably want to make that first one "determine how much time has elapsed, and if it's less than a certain amount, sleep long enough to make it be that amount, then remeasure" |
01:45 | | Mahal [~Mahal@Nightstar-12512.worldnet.co.nz] has joined #Code |
01:45 | | mode/#code [+o Mahal] by ChanServ |
01:45 | <@McMartin> | gnolam: Still leaves open how you handle frameskip. |
01:46 | <@McMartin> | You can livelock yourself with astonishing ease. |
01:46 | <@gnolam> | if (frames_behind > frameskip_amount) { frames_behind = 0; tell_the_user_to_upgrade_seriously_(); } |
01:46 | < Janus> | Alright, I think I got it! My problem is that... I know how to make a loop where the world model follows the same rules consistantly, like an FPS. But I'm a little confused about how to make one where the input, rules, etc. change depending on the situation, like a ... turn-based card game. (grasping for genres there.) |
01:47 | <@McMartin> | You need to make "update the world" not be the same function all the time, either by reassigning a function pointer or having some variable indicatating what mode the game is in. |
01:47 | <@McMartin> | If you're at the main menu, for instance, "the world" is basically "what thing is selected" and the world model is "arry keys or the joystick move the selection" |
01:48 | <@McMartin> | s/arry/arrow/ |
01:48 | <@gnolam> | If you're OOPing, the former is a pretty good application for the strategy pattern. |
01:48 | <@McMartin> | If you aren't, a state machine is the way to go. |
01:48 | <@McMartin> | Arguably, even if you are a state machine is The Win. |
01:49 | <@McMartin> | UQM is Not The Way To Do It. |
01:50 | <@McMartin> | If we ever feel like totally rewriting the entire leeging game logic, we have some plans for State Machine Of Doom, but they're not terribly well-designed ones. |
01:50 | < Janus> | I believe I am. The "world model" is actually where one of the objects has their update() method called. Also, my game loop looks almost exactly like yours, Martin. |
01:50 | <@McMartin> | (UQM uses huge amounts of threading and uses the procedure stack for context. Don't Do This (tm)) |
01:50 | <@gnolam> | Ick. |
01:51 | <@McMartin> | (It's cleaner than it used to be, though!) |
01:51 | <@McMartin> | (There's something to be said for having a state stack, especially for something RPG-like with loads of context menus) |
01:51 | <@McMartin> | (But.) |
01:51 | <@gnolam> | (Why are we whispering?) |
01:52 | <@McMartin> | Janus: Have a class for Game Mode, subclassed for each kind of mode the game can be in. |
01:52 | <@McMartin> | Reassign some global to indicate mode, or have the updateframe method return the mode object that should be used next frame. |
01:52 | <@McMartin> | And have those mode objects be Singletons. |
01:53 | <@McMartin> | In C, I'd do this with an enum used to index an array of function pointers. |
01:53 | < Janus> | Would... having a switch/case thingy work there? |
01:53 | <@McMartin> | Yes, that too would work. |
01:53 | | Mahal [~Mahal@Nightstar-12512.worldnet.co.nz] has quit [Quit: Leaving] |
01:53 | | Mahal [~Mahal@Nightstar-12512.worldnet.co.nz] has joined #Code |
01:53 | | mode/#code [+o Mahal] by ChanServ |
01:53 | <@McMartin> | Though the enum/array of fnpointers is probably more efficient. |
01:53 | <@McMartin> | On the third hand, this code is running, at most, 100 times a second. |
01:53 | <@McMartin> | You can spare the cycles =P |
01:55 | <@McMartin> | If you are in fact doing something turn-based, though, you're probably best off fixing the framerate at 30. |
01:55 | <@gnolam> | I'd put it higher. Fluid animation FTW. |
01:55 | <@McMartin> | That way you don't have to include a time unit argument. |
01:55 | <@McMartin> | ... Film is 18. |
01:55 | <@gnolam> | ... 18? |
01:56 | <@McMartin> | NTSC television is 30 after you take interlacing into account. |
01:56 | <@gnolam> | 24/25, with motion blur. |
01:56 | <@McMartin> | PAL is 25. |
01:56 | <@gnolam> | The latter is important. |
01:56 | < Janus> | I have to draw my own animations, so it'll be as fluid as igneous rock. |
01:56 | < Janus> | Regardless of framerate~ |
01:56 | <@McMartin> | More to the point, if you want fluid animations, you must use variable framerate or your userbase will kill you. |
01:56 | <@McMartin> | And you probably need to do kinematics, etc. |
01:57 | <@McMartin> | 60 is "traditional" |
01:57 | <@McMartin> | But that frame rate was often halved in practice. |
01:57 | <@McMartin> | UQM's varies between 25 and 35 depending on what you're doing. |
01:58 | <@McMartin> | But for any given activity it's fixed. |
01:58 | < Janus> | (... How come framerates are usually around 60 like that, anyway?) |
01:58 | <@gnolam> | Eh, you don't have to go all interpolatey. It's just that 30 is a /low framerate/. |
01:58 | <@gnolam> | Janus: traditional refresh rate. |
01:58 | <@McMartin> | Televisions refresh based on AC power oscillation. |
01:59 | <@McMartin> | Which is 60Hz in North America, and 50Hz in Europe. |
01:59 | <@McMartin> | TVs are also interlaced, so actual frame rate is half that. |
01:59 | <@gnolam> | If you have resolution >= , say, 640x480 and/or fast-moving objects... that low rate will show. |
02:00 | <@McMartin> | And if you require the ability to pixel-render 1024x768 85 times a second, your sysreqs are ridiculously artificially high |
02:00 | <@McMartin> | Which is why dynamic framelength computation becomes mandatory. |
02:02 | <@McMartin> | You also have to worry about clipping through objects at very low framerates, but that's neither here nor there. |
02:02 | < Janus> | Heh, until now, I just plopped a "past_t = t; t = SDL_Tick();" at the beginning of a loop, and try oh so hard to keep it high. |
02:02 | <@McMartin> | For Fixed Frame Rate you want something like SleepThreadUntil. |
02:02 | <@McMartin> | For those kinds of things, UQM is a useful model. |
02:03 | < Janus> | Would something like that free up the CPU? I've noticed that when I run things I've made, they hog up whatevers available ruthlessly. |
02:03 | <@McMartin> | target = past_t + (frame length in ms) - SDL_Tick(); if target >= 0 SDL_Delay(target) |
02:03 | <@McMartin> | Yes. |
02:03 | <@McMartin> | You must yield once a frame. |
02:04 | <@McMartin> | In particular, rendering more often than the refresh rate is utterly pointless |
02:04 | <@McMartin> | After the call to SDL_Delay() you then reassign past_t |
02:04 | | * ToxicFrog upreads |
02:05 | <@ToxicFrog> | Last time I did this, "update the world model" was "traverse the object chain and call the :update method on each object"; the last object in the chain was responsible for redrawing the screen. This meant you could switch between menus, main game, etc just by switching object chains. |
02:06 | <@McMartin> | This implies the existence of an object chain, of course~ |
02:06 | <@McMartin> | Those are also nice because you can save state by serializing all the chains. |
02:08 | < Janus> | It's a very small model, with three objects total. One for the 'world', two for two characters, and perhaps two more as the two characters inherit a PC or a NPC object. (or those inherit them, or some such.) |
02:09 | < Janus> | Those two character objects are also members of the world object. So only one update method needs to be called. |
02:09 | <@McMartin> | It should always be the case that only one update method needs to be called. |
02:09 | <@McMartin> | If not, you're missing a level of abstraction, to wit, a Game Mode object. |
02:10 | <@McMartin> | You basically need multiple worlds; one for the Main Menu, one for the Game, etc. |
02:10 | <@McMartin> | You can select it with a switch/case, or by reassigning a local variable, or by reassigning a global, but the basic concept remains the same. |
02:12 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has quit [Quit: Z?] |
02:12 | < Janus> | What if it's not that divided though..? Like, say, the difference between where the player and NPC enter their commands, and then those said commands are executed. |
02:12 | <@McMartin> | Then you haven't divided your model finely enough. |
02:13 | <@McMartin> | You can change "the world" once per frame, here. |
02:13 | <@McMartin> | "Player is entering commands" and "NPC is simulating commands being entered" are different "worlds" here. |
02:14 | <@McMartin> | Alternately, the "world" is carrying extra state of its own indicating what mode it's in and it does another layer of transforming (ignoring input when the NPC's selection is displayed, etc.) |
02:14 | < Janus> | Okay, I'm starting to see now. |
02:16 | < Janus> | Alright! Thanks for your help then! I'm always forgetting about how useful abstraction is. |
02:17 | <@McMartin> | Spending time in the guts of game code helps too. |
02:17 | | * McMartin found some lovely bit-level evil in Gradius's game loop. |
02:19 | | * Janus shots it in the core. |
02:21 | | Janus is now known as Jan[bathipoo] |
02:44 | | Raif [~corvusign@Nightstar-22484.hsd1.ca.comcast.net] has joined #Code |
02:44 | | mode/#code [+o Raif] by ChanServ |
03:43 | | Jan[bathipoo] is now known as Janus |
04:03 | | Janus [~Cerulean@Nightstar-10302.columbus.res.rr.com] has quit [Quit: So I poured it into my hand to see if it was empty. It is now.] |
04:15 | | MyCatVerbs is now known as MyCatSleeps |
04:20 | | You're now known as TheWatcher |
06:05 | | Vornicus-Latens is now known as Vornicus |
06:34 | | Syloqs-AFH [Syloq@NetAdmin.Nightstar.Net] has quit [Connection reset by peer] |
06:53 | | AD[Laptop] [~farkoff@Nightstar-29204.neoplus.adsl.tpnet.pl] has joined #Code |
06:56 | | AD[Laptop] is now known as AnnoDomini |
07:25 | | AnnoDomini [~farkoff@Nightstar-29204.neoplus.adsl.tpnet.pl] has quit [Quit: AWAY!] |
07:28 | | Reiver is now known as ReivAFK |
08:15 | | You're now known as TheWatcher[afk] |
09:19 | | gnolam [lenin@Nightstar-13557.8.5.253.se.wasadata.net] has joined #Code |
09:19 | | mode/#code [+o gnolam] by ChanServ |
10:07 | | You're now known as TheWatcher[wr0k] |
10:32 | | Chalcedon [Chalceon@Nightstar-6297.dialup.ihug.co.nz] has joined #code |
10:32 | | mode/#code [+o Chalcedon] by ChanServ |
10:36 | | Chalcedon [Chalceon@Nightstar-6297.dialup.ihug.co.nz] has quit [Ping Timeout] |
10:36 | | AD[Laptop] [AnnoDomini@62.108.180.ns-23472] has joined #Code |
10:41 | | AD[Laptop] [AnnoDomini@62.108.180.ns-23472] has quit [Quit: BRB. Plugged the mouse in too late and now the roller is non-functional.] |
10:43 | | AD[Laptop] [AnnoDomini@62.108.180.ns-23472] has joined #Code |
10:53 | | gnolam is now known as gnolam|away |
11:15 | | ReivAFK is now known as Reiver |
12:29 | | gnolam|away is now known as gnolam |
12:43 | | Thaqui [~Thaqui@Nightstar-25849.jetstream.xtra.co.nz] has quit [Connection reset by peer] |
13:20 | | AD[Laptop] [AnnoDomini@62.108.180.ns-23472] has quit [Quit: Going hunting for Snickers bars.] |
13:30 | | Mahal is now known as MahalBEDD |
15:30 | | * ToxicFrog kills both MS Access and MDBTools with a fork |
15:37 | | You're now known as TheWatcher[afk] |
15:43 | | * MyCatSleeps idly follows up by vapourising their corpses with an ion cannon. |
15:44 | | MyCatSleeps is now known as MyCatVerbs |
16:28 | | * ToxicFrog ...s at windows |
16:28 | <@ToxicFrog> | So, drag and drop apparently sets PWD to some random whack-ass value that is usually, but not always, $HOME. |
16:30 | <@Reiver> | ? |
16:31 | <@Vornicus> | by drag and drop I assume you mean dragging a file onto a program |
16:32 | <@ToxicFrog> | Yeah. |
16:33 | <@ToxicFrog> | For example, I drag s:/Source/evarchive/test.csv onto s:/Source/evarchive/evarchive.exe |
16:33 | <@ToxicFrog> | $PWD is c:/Home/ben/ |
16:33 | <@Vornicus> | You get the full paths of the things being thrown around, right? |
16:34 | <@ToxicFrog> | Yeah, which doesn't help when I'm trying to load supporting files from ./ |
16:34 | <@Vornicus> | ah, true |
16:34 | <@Vornicus> | you may wish to issue a chdir |
16:34 | | * ToxicFrog fiddles with getting at argv[0] from lua |
16:39 | | Reiver is now known as ReivZzz |
16:53 | <@Pi> | Have you instead tried loading supporting files from /. ? |
17:07 | | ReivZzz is now known as ReivSLEP |
17:15 | | KarmaBot [~karma.bot@Nightstar-29204.neoplus.adsl.tpnet.pl] has quit [Connection reset by peer] |
17:16 | | KarmaBot [~karma.bot@Nightstar-29204.neoplus.adsl.tpnet.pl] has joined #Code |
17:16 | | You're now known as TheWatcher |
17:49 | | You're now known as TheWatcher[afk] |
17:57 | | AD[Laptop] [~farkoff@Nightstar-29204.neoplus.adsl.tpnet.pl] has joined #Code |
18:00 | | AD[Laptop] is now known as AnnoDomini |
19:00 | | You're now known as TheWatcher |
19:13 | | Syloq [Syloq@NetAdmin.Nightstar.Net] has joined #code |
19:28 | | KBot [~karma.bot@Nightstar-29708.neoplus.adsl.tpnet.pl] has joined #Code |
19:29 | | AnnoDomini [~farkoff@Nightstar-29204.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
19:30 | | KarmaBot [~karma.bot@Nightstar-29204.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
19:30 | | KBot is now known as KarmaBot |
19:36 | | AD[Laptop] [~farkoff@Nightstar-29708.neoplus.adsl.tpnet.pl] has joined #Code |
20:34 | | Syloq is now known as Syloqs-AFH |
20:49 | | MyCatVerbs is now known as MyCatEats |
21:01 | | Janus [~Cerulean@Nightstar-10302.columbus.res.rr.com] has joined #Code |
21:58 | | Chalcedon [Chalceon@Nightstar-6297.dialup.ihug.co.nz] has joined #code |
21:59 | | mode/#code [+o Chalcedon] by ChanServ |
22:24 | | Chalcedon [Chalceon@Nightstar-6297.dialup.ihug.co.nz] has quit [Quit: ] |
22:41 | | You're now known as TheWatcher[T-2] |
22:45 | | You're now known as TheWatcher[zZzZ] |
22:53 | | MyCatEats is now known as MyCatVerbs |
23:26 | | MahalBEDD is now known as Mahal |
23:45 | | Chalcedon [~Chalceon@Nightstar-2104.ue.woosh.co.nz] has joined #code |
23:45 | | mode/#code [+o Chalcedon] by ChanServ |
23:53 | | AD[Laptop] [~farkoff@Nightstar-29708.neoplus.adsl.tpnet.pl] has quit [Quit: OBJECTION!] |
23:59 | < MyCatVerbs> | Whoa, crap on a crutch. |
23:59 | < MyCatVerbs> | GHC produces big executables. |
23:59 | <@Vornicus> | GHC? |
--- Log closed Sat Apr 21 00:00:04 2007 |