Jump to content

  • Log In with Google      Sign In   
  • Create Account

samoth

Member Since 18 Jan 2008
Offline Last Active Today, 01:21 PM

#5293237 what good are cores?

Posted by samoth on 24 May 2016 - 11:31 AM

In addition to what Hodgman said... any game that renders anything or plays sounds, any such game, uses several cores. Plus, any game that uses asynchronous file I/O.

If you just open a device context, a thread is created. You don't see it, but it's there. It will work off the render commands that you submit or it will mix the sounds that you play.

Especially in processing sound, running stuff asynchronously (preferrably on another core) is very much real life, and very mission critical. Let the sound card's buffer get empty once, and the user will immediately and inevitably hear it. This must never happen.

Process draw calls on the same core, the same thread even? Sure, it's possible. Welcome to 1995. But you're not getting anywhere close to 201x performance.


#5292606 My C++ gotcha of the day

Posted by samoth on 20 May 2016 - 05:17 AM

Your code is invalid, but irrespective of the use of union (and your compiler is apparently broken because it does not notice). Your inline initialization of the color values in Color is equivalent to a default contructor, and members with constructors are not allowed in anonymous aggregates. That is, you are not allowed to write anything like struct { HasConstructor foo; };
 
Your "type punning" use of the union is actually legitimate because the standard (as of C++09 if I am not mistaken, but could as well be C++11) explicitly makes it well-defined as long as there is a common sequence. It is reasonable to assume that an array of identical objects which require no padding has a common sequence with several subsequent objects of the same type. Not sure if it's guaranteed (probably isn't), but the assumption is by all means reasonable.
 

This reminds me of a different topic "Are accessors evil?" from not long ago. You can rewrite your code without the troubles of unions like so:
 

struct QuadCorners2
{
    Vertex vertices[4];

    Vertex& topLeft() { return vertices[0]; }
    Vertex& topRight()  { return vertices[1]; }
    Vertex& bottomRight(){ return vertices[2]; }
    Vertex& bottomLeft() { return vertices[3]; }
};

 
The only downside is that now you have to write somevertex.topLeft() = blah; instead of somevertex.topLeft = blah;

However, on the positive side, you now have a plain normal struct which will default-initialize each element of its member array per §8.5. For arrays of PODs or arrays of types without default constructor, that will still do nothing, but Color has a default constructor, so everything is good.
 
(I left out const accessors in order not to bloat the code snippet up too much, you may want to add those)
 
So, in reply to "Are accessors evil?" one could say: "Accessors just saved my ass".




#5292602 can c++ be used as a scripting language

Posted by samoth on 20 May 2016 - 04:40 AM

It is certainly possible, and being done (I do it myself). There is a nice in-depth description of yet someone else using C++ for scripting on the molecular web site.

 

The obvious problem about using C++ as a scripting language is that it is not a scripting language.

 

Scripting languages suck because they are so slow, blah blah. But they also have some very noticeable advantages (some of these are more obvious, some are less obvious but nonetheless important). For example, a scripting language exposes to the script writer exactly what you want it to expose, and nothing else. It enforces that you do exactly as allowed, nothing else. An invalid script should never result in an application crash or undefined state, either.

 

C++ does not do things like bounds checking, and it allows you to dereference any valid or invalid pointer, reading from or writing to any address. You can in principle call any OS function, including one that modifies files on the harddisk, opens a process handle, or... a network socket.

 

Which means that user-modifiable scripts are always in some way troublesome. A badly written user script may cause a crash (which you can catch in a handler, see the molecular article), but it might also mess up some random state in a non-obvious way without causing a crash. It might deliberately change state, allowing a player to cheat. It might allow someone to publish a "mod" that has a somewhat nicer window layout and uses your game to host a botnet. It might let someone write a ransomware mod on top of your game. Imagine the PR nightmare linked to "your game encrypted my harddisk and demands money". You will never recover from that one.

 

If scripts reside on a user-controlled computer, it is a valid consideration to remove the feature before shipping, and instead compile all scripts to native code right into the application (or into signed binary modules). Of course that approach isn't without problems either. Among other things, it means that what user and developer have in their hands is no longer 100% identical... It is thus unlikely but possible that the user experiences a bug that the developer cannot reproduce.

 

I'm only using C++ as server-side scripting language. User-side, no thank you, I do not like to open Pandora's box. Never know what comes out of it. On a server, however, it gives me fast iteration, the ability to modify behaviour at runtime, and native speed.




#5292111 ABS and handbrake

Posted by samoth on 17 May 2016 - 12:43 PM

Impossible to tell. There used to be a mantra "brake must be strong enough to tame engine at all times" but that's for the main brake.

The hand brake, or parking brake as it is sometimes called, is not really designed for that purpose. It's for preventing the car to roll down a hill, to do a hill start, and to serve as emergency brake if everything else fails. It's not really meant to be able to subdue the engine (although it might). Whether or not the engine stalls depends on your particular car's design.

5,000 RPM in gear 1 is usually pretty close to the maximum possible torque, so it might very well be that the hand brake is unable to stall the engine in this condition.
Also note that the hand brake often (usually, almost always) address the rear wheels while the majority of non-pony cars has front transmission. So, while the brake might be able to stop (or effectively stop) the car, it might still not stall the motor. Front wheels might do a burn-out while rear wheels stand still (or slide very slowly). Burn-out with front wheels would be a funny thing to see though, don't think I've seen that in my life.


#5292067 ABS and handbrake

Posted by samoth on 17 May 2016 - 08:01 AM

On pre-everything-smart cars, hand brakes were implemented with a steel wire that pulled on a balancing lever which distributed the force to the two sides (more or less evenly). The only thing that influenced this "hard-wiring" in some way was a screw that allowed you to shift balance slightly to one or the other side. To properly adjust your brake, you would drive slowly, at 5-10km/h and gently pull the handbrake. Then you would turn the screw to the opposite side to which the car was drifting. Once it wasn't drifting (noticeably) any more, you would let it at that. That's pretty much all "control circuitry" in hand brakes, traditionally.

So... no... no ABS :-)

Of course, modern cars have all kind of electronic shitnick thingies, including electric hand brakes that have a little motor with a worm gear doing the "pulling". Other than the traditional "wire" type, these brakes usually only know the states "on" and "off", which makes their main use -- hill start on manual transmission -- impossible without some very complicated additional electronic trickery that prevents the car from rolling backwards. Their second most important traditional use -- bringing the car to halt in an at least somewhat controlled way in case of hydraulic failure -- also won't work any more because either the super smart computer will not let you engage the brake at all while the car is moving, or it will instantly block the wheels. That, and they freeze in winter...

My old Prius had a steel-wire foot brake that works like a traditional one. But of course they couldn't help being extra smart and added a little motor on top, which will fasten the brake when the vehicle loses power (it has no other functionality!). So if one day you change your starter battery, you will face the big surprise that you can't drive your car afterwards -- for some mysterious reason it won't move. Until you discover that someone had pulled the parking brake. Grrr...


#5290160 how good is rand() ?

Posted by samoth on 04 May 2016 - 05:15 PM

cryptographic-style random guarantees you will need a specialized library for that.

you mean something like rand_s() ?
Careful with that.

Microsoft says "secure", but MS says a lot of bullshit, and they just love to keep everything as obscure as possible. If you read carefully, it says "as specified in..." and there it says things like parameter validation. Further down, it says "secure random number" and parameter validation again. Note the exact wording.

This is not the same as a cryptographically secure pseudorandom number generator. A CSRNG requires that if the state is compromised, then it is impossible to determine earlier values. Microsoft states "does not affect state set by srand", and indeed there does not seem to be any way of setting it, or any non-obscure state. That's just the point of a CSRNG though... you can set the state and reproduce a sequence (forward, not backward).

A CSPRNG further requires an even distribution of subsequent bits (as close to exactly 50% chance as possible). Microsoft says nothing about that.

This leaves two possible conclusions: Either, it is a generator that uses a secret, obscure state. Or, it is a generator that is seeded by real random entropy much like the random device under Linux. You don't know which one it is, but if you need a cryptographically secure pseudorandom generator, then neither one is suitable.


#5290100 how good is rand() ?

Posted by samoth on 04 May 2016 - 12:00 PM

rand is well-known to be notoriously bad (it has a long, long, long history spanning several decades and many architectures). Although I believe that glibc even uses MT under the hood (not 100% sure, but I believe so). Microsoft's implementation, although quite bad, is actually not so bad compared to some other historic implementations (I forgot the name, but there was once an implementation where you could basically only use 4 bits of the output...).
 
I advise against the general trend to just use Mersenne Twister. It is not a bad generator as such, and once upon a time when there was not much around but using rand or using MT, it certainly was the go-to solution, but it is far from being perfect. It goes way overboard for the average programming problem on the one hand side, but fails to deliver on the other end, which is not optimal.

 

Unless you do some really, really hefty scientific simulations, you do not need the properties that MT guarantees.  Most people (me included) just shrug if they hear 623-dimensional equidistribution. It's as if someone offered me an elephant for free. I have no use for an elephant, so that offer doesn't impress me! I'm not bothered if my random generator shows patterns in 622-dimensional or 570-dimensional space. I'm rarely using more than 4 dimensions for anything, and I think I've never used anything in conjunction with pseudorandom numbers that had more than 8 dimensions.

On the other hand, if you do care about that stuff then you would rather use WELL instead of MT anyway.

 

But if you are like almost everybody, you can as well use something simpler and more efficient.

 

There are alternatives which run faster without polluting caches and without using huge state, and which at the same time pass statistical tests slightly better and have way better recovery from bad state (as the classic textbook example, MT fails catastrophically and takes pretty much forever to recover if you should ever be so careless as to initialize it with an all-zero state).

Sebastiano Vignahas a whole collection of very fast very high quality generators that are one or two lines of C code. Most (all?) of them are based on work by Marsaglia, followed by a nonlinear mix step that improves the quality of the generated numbers. For "anything game", these generators are totally suitable, and they use a fraction of the resources.




#5289885 In-game taxation model

Posted by samoth on 03 May 2016 - 06:57 AM

Are you sure tax adds a lot of depth (fun) to the game? Tax is extremely complex and to most people it is super frustrating. Unless your game is something like "Panama Tax Tycoon" or "Gibraltar Letterbox King", or "Liechtenstein Fraud Inc",  i.e. a game about tax evasion, I think it doesn't add a lot to the experience, it's only annoying. If the player is able to gain X, simply let him keep X. If that is too much for game balance, well, simply let the player gain less.

 

Some of your assumptions on tax are wrong, too.

 

For example:

VAT : Quite no brainer.

On the contrary. VAT = massively big pain in the ass. Different rates in different countries, different rules what can be deducted and what can't. Plus, different rates for food and books and for other things. Or, for food, and books, and other things. Or, for other things and cigarettes. Or... something different.

 

Plus, it is painful to figure out what's the actual VAT. Usually, your government just wants a gross 16% or 19% or 21% of everything, but that is strictly incorrect in most cases. If you are being honest.

For example, a farmer grows potatoes and sells them to a french fries factory. Farmer sells 1 unit for 1 currency, factory "adds value" (OK, it's debatable whether deep-frying potatoes really adds value to them) by processing potatoes and re-sells 1 unit for 2 currency to grocer. Grocer re-sells to consumer for 5 currency, adding no value. Government asks 20% VAT, respectively 1 currency. But note that it is "value added tax", and neither the farmer added value (the potatoes grew by themselves, the farmer didn't add anything to them), nor did the grocer. The fries that are sold to the consumer are 100% identical to the ones the grocer bought. Still, government wants VAT on the final amount of currency. But in practice, it is even more complicated than that. All three parties have to pay a part of that VAT, subtracting the previously paid VAT and adding their own, blah blah. So much trouble only to make it more obscure how the government is stealing from you, and to give more opportunity for you to accidentially becoming a criminal.

 

Also note that some countries (think USA) call their VAT Sales Tax rather than VAT or have both. When it's called Sales Tax, you cannot deduct it from your VAT, even if it's exactly the same thing. If VAT is called VAT, you usually (but also, not always) can deduct it. Sometimes you have both Sales Tax and VAT, too. In some countries (e.g. several British Commonwealth tax evasion countries) you pay no VAT whatsoever if the sale goes abroad (and have reduced corporate tax, too), and sometimes if the transaction was practically (whatever that means) abroad or cross-border. In some places, government always wants VAT regardless where you sell to, and they want import tax in addition to VAT (but not from all countries). And in some countries, they simply don't care.

In some countries they do ask some quite hefty tax, but the customs officers can't be bothered anyway (had that happen in Norway, and then again in Germany -- twice within 24 hours -- some 15-20 years ago, simply got "Yeah, what do I care!" as an answer when I was trying to be a good citizen).

 

Income tax : from employee perspective: theoretically no problem

Not necessarily. In some countries, and in some professions (e.g. waiters, barmaids), you get tip as "regular income". In other countries, all prices are "service included", tip is purely optional. Sometimes, all tip is collected and then divided among the team (very common e.g. in France), in other places it goes right into the waiter's pocket. In some countries it is simply assumed that you get so and so much regardless of whether you actually do (so you may pay income tax on incomes that you never had!).

 

In most countries, and in most professions, it is assumed that you have non-money benefits of sorts, and you pay income tax for these. Not rarely, it is outright ridiculous what is regarded as "benefit". As usual, this is a socialist invention, which of course harms the poor the most.

For example, the stereotypical young woman working in the grocer store down the road gets a discount (something like 15-20%) for comestibles in that same store. Which is only fair considering what shitty pay they're giving her for working all day (less than what the average lazy jobless parasite gets from welfare) and considering that it doesn't really cost the store anything, they still make 30% profit when selling 20% cheaper. Worker woman needs to eat, too. Good idea overall, except... well, except the government makes her pay income tax on that benefit.

 

In some, actually most, countries, you pay tax on capital income (sometimes flat, sometimes added to your other revenues, with and without threshold), but you don't pay that tax (legally!) if you traded on a foreign stock exchange and had the dividends collected by a middle-man with whom you split the revenue. You do pay tax if you collect the dividends yourself or trade in the same country.

 

Residence/Property Tax : Quite straightforward, people pay tax for properties they actively use.

Normally, you pay for anything you own, regardless of what you use. In some countries you pay for usable surface in a house (regardless of whether used or not), plus property counts towards the threshold for wealth tax. Wealth tax is applicable to those who have their primary residence, or any residence, or no residence at all but property, depending on what country you're talking about. Property usually counts towards inheritance tax as well, but in some countries a "nominal value" is used for that purpose which is the value as of 1965 or something, so basically only about 10-15% of the actual value.

 

In some countries, you must pay property tax to the commune, in others to the state. In some countries both (in that case, the community tax has a different fancy name).

 

In some countries you pay for total gross surface regardless of whether something is built on top of it or whether you use it, but rates vary greatly (by like +/- 2,000%) both based on whether there's a construct, and based on the exact location. Sometimes, neighbouring communes have grossly differing rates, too. Germany, for example, is just hilarious in that way. I own a 1.3ha piece of land which costs about half as much tax as a 2-room apartment (which obviously only has a very small share of ground, being an apartment) located in a town 12 kilometers away.

 

Used to be you paid a per-window tax in some countries (that's a reason why most French houses that are over a hundred years old have all windows but one bricked up).

 

It may happen that you pay a "ground seal tax" to the commune on top of property tax, depending on data that your commune gathered from Google Earth (that's no joke!). Whatever it is, it's just another way for the communes of stealing from those who own something. And of course, there's a legal loophole for that one as well.




#5289774 Use which kind of generic string?

Posted by samoth on 02 May 2016 - 01:44 PM

UTF8 works fine. Unicode sucks, no matter how you deal with it since it is way over-engineered and has way too many redundancies and special cases (unless you simply choose to ignore all these issues -- then Unicode is a "just works" thing), but UTF8 not only plays nicely with your 40 year old C string functions and is also kinda intuitive otherwise (think sorting), it also has no more quirks than necessary. Using stuff like wchar_t, you may end up discovering that wide characters have different sizes on different systems. Surprise, surprise.

I'm not overly fond of UTF8, as variable character sizes sound like a major annoyance for GUI display.

Well, with the "standard Unicode" strings under Windows, you have the worst of both worlds. You have wide characters, and you still have variable character sizes (since Windows uses UTF-16). Unless you use WinXP or Win2K, in that case you have "broken Unicode" (UCS-16). Insofar, UTF-8 is none worse, only better. Same amount of trouble, but takes only about 50-60% as much storage (for anything non-Chinese). Plus, English text is just plain normal, readable ANSI English text even in your favorite hex editor (no zero bytes in between), and even European languages are 80-90% multibyte-free, plain ordinary ANSI characters.

The only real inconvenience about UTF8 is that -- under Windows -- you have to convert all strings that you are receiving from the OS in some way, and you may have to convert any strings you pass to an API, too. Takes 10 minutes of consideration once when writing your API wrapper. Or you may simply not care and use filenames which work with legacy functions! After all, most of the time, as a game developer, you get to choose the file name. Choose wisely, and forget about it.

All in all, UTF8 is no biggie most of the time. Under Linux, UTF8 is the default anyway, so no troubles at all there.


#5288611 GPL wtf?

Posted by samoth on 25 April 2016 - 10:23 AM

Note: This reads like a rant (and to 90% it is) but there's also a serious question in the last paragraph.

 

So I've just come across an article which claims that Canonical is in violation of the GPL for distributing a binary of the ZFS module. It doesn't seem to be an April's fool joke.

 

Can someone enlighten me what the issue is because I seem to be too stupid to understand it. To me, the facts look like this:

 

Party 1 holds the rights on product ABC. They license it under the ABC-License. Which is kinda-opensource, but not quite.

Party 2 holds the rights on product DEF. They license it under the GPL. Which is... freedom.

 

ABC and DEF do not share a code base, nor are they otherwise affiliated in some way. Some DEF-affiliated developers made an ABC module that can run under DEF. Which is nice because ABC is a great addition to users of DEF.

 

Party 3 distributes ISO files containing -- among other things -- DEF, as well as ready-to-install DVDs, and they maintain a live packet repository with some thousand other stuffs. They also maintain a source repository so they comply with the GPL.

 

Since pretty much forever, the installation DVDs also included some non-free stuff like Flash and some multimedia codecs for the user's convenience. This has -- obviously -- never been a problem. I never bothered, but whoever wanted these could opt-in to install them. Other parties do the same thing, too (Linux Mint comes to mind).

 

Now, presently, Party 3 is also adding a binary of ABC to their DVD. That's a problem. Those bastards, how can they!

 

Party 3 is in violation of Party 2's license for packing Party 1's smelly stuff onto the same DVD. Because, you know, it's not allowable to have two different religions on the same DVD.

 

No really, what the hell? I must be understanding this wrong. This is just too perverse to be true.

 

Steam runs, among other systems, under Linux. Steam sells/distributes games which are not GPL (the vast majority of them is not even remotely open-source). So, since it is against the GPL to combine non-GPL stuff with the Linux kernel, is Valve in violation with the GPL?

 

More importantly: Are you in violation of the GPL if you sell a game via Steam?




#5288355 How do I link my DLLs to Code Blocks?

Posted by samoth on 23 April 2016 - 05:28 PM

This doesn't have much to do with Code::Blocks, but with properly installing the Allegro libraries, which unluckily is, indeed a process of "copying around DLLs". Note that copying headers and import libraries to places where Code::Blocks will find them isn't enough (you probably thought that this is it for "installing" the library, but it is only half the story).

There are mainly two places where the DLLs can be copied, the system32 directory, or the directory the program is in. Actually, putting the DLLs into the system directory is the "correct thing" seeing how they are shared libraries, and there is not much sharing if every program has its own libs in its own directory. However, in practice, one usually does exactly the opposite.

Normally, when you build a library and run something like "make install", this should already place the DLLS in the system directory. Which is both good and bad. Good because you can immediately run any program that uses them (so, not much stalling development), but bad because when you deploy your software, you must remember that this has to be done on the end user's computer, too (having libs in the program's dir, you can just zip everything up and be good).

I'm not very familiar with Allegro, only having used it once ages ago... is there not an option to make a monolithic build? That would mean only one DLL needing to be copied around, less trouble.


#5286463 Bandwidth cost inside the datacenter

Posted by samoth on 12 April 2016 - 06:33 AM

For the general case, one must certainly say: "it depends, read the contract".

However, for every datacenter that I've seen, datacenter-internal traffic (and most of the time inter-datacenter traffic as well, if they have several locations) is free.


#5285767 Should getters and setters be avoided?

Posted by samoth on 08 April 2016 - 05:10 AM

As usual, you should not take everything too seriously.

 

There is a common behavioural pattern of someone doing something, then someone else noticing that it's actually a clever idea and calling it "best practice". Then someone calls it a "pattern", and soon a witch hunt starts against anyone not applying the pattern. A year later, someone says "considered evil" and the word "antipattern" comes up, and the same witch hunt starts in the opposite direction. And then, another year later, someone says "no longer considered evil".

 

Yes, there are people who use getters and setters in a way that makes you facepalm and moan. But there are also legitimate, sensible applications of getters and setters.

 

Just like with every feature/technique/pattern there are people who recommend it, sometimes for good reasons, sometimes for strawman reasons, and sometimes for religious reasons, and an equal number of people who say the exact opposite. And there are people who use it sensibly, when it's applicable. Try to be among the latter group, and you're good.

 

Whenever it comes to "philosophy" or "religion", it is often hard or impossible to tell what's true and what is not. There is usually no absolute either (neither absolute right nor wrong). Consequently, the examples given to justify one's religion may make perfect sense or may be utter bullshit, depending on which angle you're coming from.

 

For example, take the dog example on Yegor's site. You must think of a dog as a living object. You cannot change its weight, and the dog is immutable. OK, alright... but as anyone who has ever had a pet animal knows, an animal is nowhere near immutable. They grow, they grow fat, they get sick, and they die. Surely, the notion of having to euthanize the animal and replace it with a similar looking one whenever it gains weight or whenever it gets ill is not very "natural", is it?

Thinking about the dog as an object, the dog cannot return NULL, and that is a good thing. Why not, exactly? Real dogs do return NULL when they feel like it. Returning NULL, or figuratively telling "I don't want" or "I don't have any" in another way is a legitimate thing to do. Should a dog be allowed to throw exceptions? You tell me.

 

A bank account should be immutable? So each time you WithdrawMoney(), the bank reopens a new, identical account for you, and deducts the amount from only the original account? Well, that looks like a pattern that should be universally applied! Please tell my bank. Also tell them that I should be able to modify my account balance directly, it's so annoying that WithdrawMoney(-100000) fails with an error message. SetBalance(100000000) doesn't seem to work either.

 

Another scenario where getters/setters are legitimate (in the same sense of doing plausability/validity checks) that immediately comes to mind is placing things in a GUI. Let's say a widget or window has the SetSize setter, which will... duh... set its size. How useless! Except... you want things to be visible on screen, and SetSize will make sure that's the case, even if you call it with invalid values.

 

Another thing is, obviously, hiding implementation details. Rather than assigning true to a boolean, you might call SetEnabled or Enable (which is really the same thing). Why SetSize anyway? I can just change that integer after making sure my values are sane, right?

 

SetEnabled might acquire a mutex because... surprise... the implementation is multi-threaded, which you didn't know of course, and just changing the value whenever you feel like it might have desastrous consequences. Maybe you don't need a mutex, but you need an atomic operation to set a pointer to an object in order to avoid having a worker pick up an intermediate garble value. Or something, whatever it is. The Setter makes sure that whatever it is, it's what happens, and you need not know.

 

It also makes sure that if, for whatever reason, you decide to change your internal representation from a 32-bit integer to a 64-bit integer 10 years in the future, the existing accessors remain valid. GetTickCount under Windows (not object oriented, but same thing really) is a real-life example, which is nothing but an "accessor" that used to simply read the 32-bit integer at 0x7FFE0008. It so happens that now there also exists GetTickCount64 which does the same, only with a bigger integer, but software using the old function still works. And it works under 64-bit Windows as well where the address is a different one. Under the hood, pretty much everything has changed, but 15-year old software still works the same and doesn't need to know. And not only is it "doesn't need to know", but indeed "doesn't want to know".

 

SetSize in your vector-like class might just change an integer or might have to reallocate. In your database object, a function with the same name might change a number, or might cause a file's logical size or a mapping to be altered, optionally dealing with OS errors.




#5285575 Input Polling - Low Latency API

Posted by samoth on 07 April 2016 - 07:36 AM

this is the single keyboard input routine i use in all my games:

GetAsyncKeyState(vkey);

 

typically poll at 15 Hz minimum

May I say that I consider this a terribly ill-advised strategy? Polling is, in my opinion, something one can do as a last resort, if nothing else helps. But never as "the one" default solution for all applications.

 

Polling has one very obvious problem (it needlessly burns CPU), but also a not-so-obvious problem: it is unreliable. And what's worst, it is unreliably unreliable -- you cannot even be sure that it doesn't work. Most of the time it "works fine", except when it doesn't. Which can make reproducing an issue a real pain.

 

This being unreliably unreliable comes from the fact that you do not record transitions between states, but you take discrete point samples. If your sampling frequency is high enough, this "works", but you have to go quite high to be on the safe side. Correctness is always subject to probability, and the transition from "works" to "fails" is smooth. You will probably never see a difference for turning the joystick/steering wheel left or right, but you might, and will, for other things.

 

For example, if a young hyperactive user with healthy fingers hits the "fire" button quickly, the "button down" state may very well live for only around 50-60ms. Well, that's great... 50% chance that you sample the key while it's down, and 50% chance that you're too early or too late.

Or you might encounter scheduling jitter, and instead of the intended 66.66ms (=15Hz) your process sleeps 80ms or 90ms. It's as if the user never pressed the button! Or maybe it works 99 out of 100 times and only fails in the most user-upsetting moment in the middle of a boss fight (quite possibly it even always works when you try it because your fingers are older and your computer is faster).

 

No such thing can happen if one processes events. Events are on/off, yes/no, black/white. Polling is... maybe.
 

as i recall getasync is powered by hardware interrupts

More like hardware interrupts generate key up / key down messages which go through the system's low level message queue, and then at some point set/clear a boolean flag per key in some global state table, and you test the flag in that table each time you call GetAsyncKeyState.

 

 

My question to you is what API would you all recommend?

Without really knowing anything about the steam controller (but having looked at the description online), I would still recommend a solution that uses messages (so... virtual keyboard or capturing a "joystick" with old multimedia functions).

 

If I understand what's online correctly, the Steam controller can simulate either a virtual keyboard or a Gamepad (which is basically... a more or less "ordinary" joystick with a few more buttons and FF). Which means you should be able to use the old multimedia functions that place events in your event queue (in gamepad mode), or just handle the generated keyboard events without even knowing that they actually come from a special controller. Even if the old multimedia functions poll internally (I don't know if they do, but might as well), processing messages is still the "correct" approach. It is as correct and as good as you can get on your end.

 

But of course, there's also XInput... which, ironically requires you to poll... :rolleyes:




#5285437 If statements are all you need

Posted by samoth on 06 April 2016 - 10:13 AM

Well, it's a game about a dragon. If you zoom all the way out, out, out, tilt your head to the right, and squint your eyes, you can almost see the dragon.






PARTNERS