Jump to content

  • Log In with Google      Sign In   
  • Create Account

Servant of the Lord

Member Since 24 Sep 2005
Offline Last Active Today, 09:47 AM

#5298264 Is using one the switch statement better then using multiple if statements?

Posted by Servant of the Lord on 27 June 2016 - 11:56 AM

 

I cannot spot when and how switch can have outperformed proper conditionals in any way on any platform- and by my logic I conclude it cannot.

The reason has already been covered in this very thread: switches are easy to convert to lookup tables in machine code. Conditional statements are less easy. So in a common case you will get better machine code generated for a switch than a if/else ladder. Some compilers are better at this than others.

And the reason why it is easier for compilers to optimize it is because it gives more information for the compiler to work with, so they can detect common patterns of behavior easier that the compiler is familiar with and knows optimization tricks for.

For the same reason, in C++, these two do the same logic:

for(size_t i = 0; i < array.size(); ++i) //Regular 'for' statement
{
   Element &element = array[i];
   Meow(element);
}

for(Element &element : array) //Range-for statement
{
   Meow(element);
}

...but beside them doing the same logic, the second version is easier for the compiler to optimize, because the structure of the code itself communicates information to the compiler. The second version guarantees to the compiler that every element will only be visited once, and that the elements will be traversed in a specific order, and that all the elements are known in advance - the first version guarantees none of those things.

 

In simple cases, the compiler will likely optimize them both the same, but in more complex cases, the compiler may not be able to figure out the optimization of first example, and so may use slightly lesser optimizations instead. This may result in super teeny-tiny gains or losses in performance, which 99.999% of the time don't matter.

 

Basically, the structure of our code becomes contracts to the compiler making guarantees that help the compiler guide the optimizations. Different code structures make different guarantees.

 

else-if() chains make different guarantees than a switch() does, and the extra information switch() communicates can help the compiler more easily recognize certain types of optimizations that else-if() chains might, in some cases, be more harder for the compiler to detect.

 

But if the OP is asking "Which one should I use?", then the usual criteria applies: Use whatever is cleaner/clearer to whoever has to read and expand and maintain the code, and don't optimize prematurely. When it comes time to optimize, profile first to find out what is slow, then focus on the critical parts, and after realizing that architectural macro-optimizations benefit way more than function-level micro-optimizations, and finally-finally-finally, micro-optimize only the areas that require it.

 

In my own code, I tend to find else-if() chains more visually appealing in some cases, and switch()'s cleaner in other cases, and so have plenty of each.

And every one of switch statements used in my code, 100% of the time they were chosen because it makes the code clearer, not for any optimization purposes.

 

If you are using switch() statements for micro-optimizations, there are other tricks to be aware of also; putting your more-frequently used branches closer to the top of the switch() supposedly helps, though I've never tried it. When you get to that level of micro-optimizing though, that's when something like profile-guided-optimizations provide the compiler with even better information about the real-world usage your code would be put through.




#5298158 PowerUp stuck

Posted by Servant of the Lord on 26 June 2016 - 05:06 PM

What about storing the "end time" (which only is changed when you pick up a powerup) instead of storing the "amount of time left" (which has to be updated every frame).

 

Then, store it in a map.

 

Something like this: (psuedocode)

PowerUpType { LargerPaddle, SmallerPaddle, FasterPaddleMovement, SlowerBalls}

Map<PowerUpTime, Time> powerUpActivationMap;

void Game::PickUpPowerUp(PowerUpType type, Time powerUpDuration)
{
    powerUpActivationMap[type] = (currentTime() + powerUpDuration);
}

bool Game::PowerUpIsActive(PowerUpType type)
{
    return (powerUpActivationMap[type] > currentTime());
}

int Game::GetBallSpeed()
{
     if(PowerUpIsActive(SlowerBalls))
          return BallSpeed_Slower;
     
     return BallSpeed_Regular;
}

int Game::GetPaddleSize()
{
     bool largerPaddle = PowerUpIsActive(LargerPaddle);
     bool smallerPaddle = PowerUpIsActive(SmallerPaddle));
     
     if(largerPaddle AND smallerPaddle) return PaddleSize_Regular;
     if(largerPaddle)  return PaddleSize_Larger;
     if(smallerPaddle) return PaddleSize_Smaller;

     return PaddleSize_Regular;
}



#5298023 Including from the Standard C++ Library

Posted by Servant of the Lord on 25 June 2016 - 02:07 PM

When we include libraries from the standard library (like cmath or cstring), what are we actually including?


First, understand that using different brackets in #include "header" and #include <header> only affects the order that the compiler looks through different directories when searching for the files.
Second, understand that you can use different file extensions (in your own headers) and everything will still work fine (as long as the file actually exists with that extension): myHeader, myHeader.h, myHeader.hpp, myHeader.pch, myHeader.meow, whatever - they are just filenames. Occasionally I've even had to #include a .cpp file from one .cpp to another. They're just text files.

Finally, what *actually* happens vary from compiler to compiler, because C++ only enforces behavior not implementation details. Also, the standard library is (mostly) separate from the compiler, even though it is shipped with compilers. For example, Visual Studio and GCC use *different* standard library implementations even though they behave the same and have the same interface. (GCC defaults to using it's own opensource libstdc++ library, Clang defaults to usibng its own opensource libc++ library, and Visual Studio defaults to using a custom-modified version of the third-party proprietary Dinkumware one. There are also other implementations of the standard library available).

The header files actually exist (usually), and (on Windows) they are usually located where you installed your compiler, unless you manually installed the libraries somewhere else.

In my QtCreator install of MinGW, on Win10, I find <cmath> located in:
C:\Qt\Qt5.5.0\Tools\mingw492_32\i686-w64-mingw32\include\c++

At that location, I find a text file named 'cmath' with no extension (I also find 'cstring' and 'iostream' and 'vector' and so on - text files without filename extensions).
It #includes "math.h", undefines some math.h defines (like cos(), tan(), etc...), reimplements them as real functions (instead of macroes), and puts them inside of the std namespace.

 

Depending on the compiler and header, the compiler can also just pretend behind the scenes that the header file really exists, but really do something else instead as long as the behavior is the same. For example, why recompile the standard library headers over and over again? Maybe the compiler just holds them pre-compiled, if it can detect that you aren't doing something that'd require it to recompile the header (like #defining certain macroes).
 

I'm assuming they aren't header files since there is no ".h" extension. Also, how can we just include files and be able to access functions from that library? Are the function definitions inside the included file? I thought it was good practice to separate declaration from definition?

 

First, a huge amount of the standard library classes and functions are templates. Templates in C++ have to be in headers, declaration-and-definition together. It's an unfortunate consequence of how templates work. So for those classes, whether standard library or 3rd party library or your own code, the header is plenty enough, no .cpp needed.

 

Second, for the functions that aren't templated, and have concrete definitions, they basically fall into several categories: If they are inline, or if the compiler wants to inline them for performance reasons, the compiler will generate the code inside your project's .exe - often those kinds of functions are only a few lines of code, so the performance gains outweigh the minor costs. This is common with compiler intrinsic functions.

For other functions, they can be handled just like regular static libraries (compiled into your code, but not inline), or dynamic libraries.

 

If they are linked to as dynamic libraries, then you have to make sure that .DLL actually is available for your project to find, when you run your executable. For Microsoft, the standard library DLLs are just shipped with Windows as part of the OS or as part of the Visual Studio runtimes.

 

For me, using GCC/MinGW, I have to include the standard library DLLs with my .exe. GCC's is named libstdc++-6.dll, which in-turn calls functions from some of Microsoft's libraries, since it has to function on Windows and some code has to run through the OS (like loading files).

 

You can also tell your compiler to statically include the standard library inside your .exe, but that isn't without tradeoffs.




#5297921 Converting a desktop game into mobile game- Illegal?

Posted by Servant of the Lord on 24 June 2016 - 03:39 PM

Basically, you can make similar types of games, but you can't copy the artwork, name, code, audio, levels, or even the same sequence and nature of upgrades and unlocks.
 
Ideas aren't copyrightable, but implementations of ideas are. You can use the same ideas, but not the implementations (numbers, patterns, visuals, text, etc...). The closer you get to copying someone else's implementation, the more likely you are infringing.
 

I think it also depends on what you want to do afterwards, if it's just practice and not selling, there's no issue at all

 
It's not an issue of selling or not, it's an issue of making it public.
 
If you do it for practice and never release it publicly, that's fine (as long as you aren't violating the DMCA), but if you release it - even for free - you are violating copyright law.




#5297591 Game Object Update Order

Posted by Servant of the Lord on 22 June 2016 - 10:10 AM

Thank you all for your responses. I wanted to know why those of you who have stated that a bucketed approach would be better than a dependency graph? It seems that it has a lot negatives to it. Like, what if you have two logical components where one relies on the other. or two logical components where one has to run before a renderable component, and then the second one has to run after the render component. You then have to have two logic bucket groups that will only be used by one-two components. I could understand wanting to just take the easy way and not worry about all of the dependencies in the engine, but could anyone mind telling me the negatives of using dependency graphs?

 

There are a thousand different ways to program "a game". But we eliminate many of those ways as unnecessary complexity or unnecessarily slow, when we start talking about a specific game. It doesn't make too much sense to argue about which way is better for "games in general".

 

Until you know the specifics of your game, trying to code for every "maybe" that exists adds complexity and unnecessary abstraction. Abstraction, when built up layer by layer, has reasoning costs (it becomes slightly harder to reason about the entire project, and slightly harder for others to learn the engine, and those costs can add up project-wide). It has benefits but also costs - even if those costs are small, it's wasted cost if you don't actually benefit from it (rather than theoretical future benefit).

 

Bah, this makes it sound like I'm saying "don't code for the future", but I'm not. You definitely do want to code for the future by coding cleanly and simply, so it is easy to rapidly modify, debug, and expand for this specific game and any future games you later re-purpose the code for. You also want to code for the future of the known needs of the specific project you are really working on.

What I'm advocating against is pre-emptively building more complex architectures before you actually know whether you even need them - more classes and functions and lines of code to write, reason about, maintain, document, and for others to learn. If it seems likely you'll actually need it for *this* project, by all means plan for it! But if seems theoretically that it might be needed for some vague future project, then you can easily tweak or rewrite part of the architecture for that project, when you are actually making that project (your code is modular and cleanly written, right?).

 

Unless your game requires motorcyles on trains, it is better for your code to decide, "you can't have motorcylces on trains".

Engines that can "do anything" also mean that they do nothing well, and they have to have yet more code written to actually make the abstract fluff do something concrete.

 

Who cares if a bucket group is only used by one entity? It has minimal code complexity and minimal performance costs, while fitting into an established paradigm already used in your architecture. It is very easy (development-cost wise), very simple (comprehension-wise), very fast (execution-wise), and very clean (for code legibility and future changes), to create buckets that run before and after rendering. Or before and after physics. Or before and after... whatever.

 

I'm not against dependency graphs. For some projects or sub-portions of projects it makes sense. I'm not pushing buckets over dependency graphs, I'm pushing for comprehending the requirements of a concrete project, and not being too enamored by (the understandable programmer appeal of) intricate fits-every-situation solutions. I'm pushing for firmly deciding "my engine doesn't do X" as a way to make cleaner, faster, more streamlined engines that are actually usable. With the understanding that, if you eventually find out that you really do need X for a later project, you can add it in or rewrite the isolated module of your architecture that prevented it.




#5297531 Game Object Update Order

Posted by Servant of the Lord on 21 June 2016 - 10:37 PM

Well the reason I don't want to do a hard coded version like
for( auto* MovementComponent ..){ }
for( auto* SkinnedMeshComponent){ }
is that in some cases, a skinned mesh component isn't being modified by a movementcomponent. Or there are hundreds of different scenarios, like maybe update this CrowdComponent, then update this movement component.. then do a post update of componentY and X.


If SkinnedMeshComponents can sometimes be modified by a MovementComponent, and MovementComponents are never modified by a SkinnedMeshComponent, then what is the harm in processing them in the KISS way?
 

Well off of my the top of my head I can think of two dependencies that might be in an engine.

Why are you worrying about stuff that might be needed? If you know it's going to be needed, add it. If you're not sure, then adding "support" for it means trading development time for something you might not use. That's like paying money for a tailor-made suit on the offchance you get invited to a wedding next year - you might attend zero weddings, making it a wasted investment, and even if you do need to attend one, by the time you do need a suit, the one you originally had made might not fit your actual requirements.
 
If you're making an engine "that'll support many different types of games", your engine likely will be used for zero finished games, unfortunately.  :(
(unless you've already made several engines used for several completed and complex games)
 

So I don't want a hardcoded scenario of spaghetti code and am leading more towards a generic approach

 
Hardcoded isn't spaghetti code by default. You can even more easily have generic spaghetti.
 
There's a balance between concrete and generic, and there's a cost to making something generic. You should code cleanly, and make things generic to the extent that is actually useful, IMO.
The amount of genericity that I personally find useful depends on what layer of the architecture I'm working on. I find at lower levels (like utility functions, containers, algorithms, and so on), more genericity is useful, but at higher levels, I want to go increasingly concrete.
 
For me, it's easy to make something generic. It's too easy to make something over-generic. And if I make something over-generic, I basically have to throw it away and redesign from scratch. But if I write something concretely, it can be easily made more generic (if it was coded cleanly), and in a more knowledgeable way (since the concrete version helps you understand the realities of the actual requirements).
 

[example A] The movement components job is to update the SkinnedMeshComponents transform prior to animation evaluation. Because of this, the MovementComponent should run prior to the SkinnedMeshComponent.
[example B] Another dependency is based on children. If one component, lets say a player, is on a vehicle.. the vehicle should update first.

 
You have to decide what is actually needed for the actual game you are actually making. Once you know your requirements, design decisions are very straightforward. If you later on decide you want to use the same code-base for another game, it's easy to fork the codebase, and customize it or generalize it as (actually) needed, where it makes sense.
 
For example, I can think of at least three valid ways of solving the problem you just mentioned. The "best" way depends on the actual nature of the actual game being actually made.
 
Make it order-independent until a post-update step is done
 
Update the entities (player and vehicle) in any order.
 
After all the entities have updated their relative positions, run through the list a final time to calculate their absolute positions. Since you already ran through the list once, you could create an array of pointers to every child entity, and just update that list rather than every entity.
 
Sort based on dependencies
 
In ExampleA, this means just process all the MovementComponents first.
In ExampleB, this means make sure parents occur earlier in the list of elements than their children.
 
Separate into buckets of generations
 
Update all entities that have zero parents. (Probably 95% of your entitieS)
Update all entities that only have one parent. (Almost everything else)
Update all entities that are two parents deep. (What, like three entities?)
 
This is what Uncharted 2 did (Slide 74 in the powerpoint, but the slide itself is labeled '38'), and only needed to go to a depth of four (Gun held by Player standing on Box located on Train).
And rather than worry about parent depths, they just used 'buckets' and crammed different types of entities into different buckets.
 
In their game, they knew (as a requirement) that a vehicle will never be riding another vehicle (while it's possible in reality for motorcycles to be driven on trains, their game didn't need that). Nor do people ride other people (while piggy-back rides are possible in real-life, by saying 'not in this game', it simplified and solidified their engine architecture).
 
So they did four buckets:
Vehicle (e.g. train), Object (e.g. box), Character (e.g. player or NPC), and Prop (e.g. weapon)
 
Then they just updated Vehicle bucket first, then Object bucket, and so on. Because they knew their requirements (and weren't making vague "any situation" engines that are useful for no concrete game), the solution actually became really simple without having to manage complex dependencies.




#5297500 When you realize how dumb a bug is...

Posted by Servant of the Lord on 21 June 2016 - 04:34 PM

Qt uses a custom CSS-inspired DSL to theme its widgets.

 

For a long time (a couple years - it was very low-priority on my TODO list) Qt has been emitting warning after warning saying, Unknown property margins

But a few days ago I finally decided to hunt down the problem.

 

The warning seems pretty self-explanatory: Unknown property margins

So I figured out what widgets were emitting the warning, and made sure all their margins were set properly...

 

The warnings were still getting emitted. Finally (after debugging and glancing through Qt's sourcecode), I realized that what it was really saying was, 'margins' is an unknown property. The Qt stylesheet property is 'margin' without the 's'.  :lol:

 

All they had to do was add commas to variable error messages.... Unknown property 'margins' with quotes makes it so much clearer.




#5297406 Free game analytics

Posted by Servant of the Lord on 20 June 2016 - 09:34 PM

Worse comes to worst, I can just have the game store the data in a file on the player's computer and then have them email it to me.

 

Or just have your game auto-email it to you.

 

Here's what one GameDevver did. Another, IIRC, used Google Analytics and pretended that his smartphone app was a webpage.




#5297405 Should all gameobjects be stored in the same data structure?

Posted by Servant of the Lord on 20 June 2016 - 09:24 PM

Only if the objects are similar in data and go through similar logic paths in the code. The less similar they are (in data and usage), the less likely you want them in the same structure.

 

So basically, it'd vary from game to game.  :wink:

 

Care to post the structs/classes for the three kinds of objects? Do they share a base class? Do they share some variables in common (e.g. collision rects)? Do they share some code in common (e.g. collision testing)?

 

How much do they have in common? Sometimes you want:

ProccessCollisions(&player, allGameObjects);

Othertimes this is better:

ProccessCollisions(&player, allEnemies, &Enemy::collisionRect,    [](Enemy &enemyCollidedWith) { ... });
ProccessCollisions(&player, allWalls,   &Wall::collisionRect,     [](Wall &wallCollidedWith)   { ... });
ProccessCollisions(&player, allItems,   &Item::collisionRect,     [](Item &itemCollidedWith)   { ... });
^ templated func              pointer-to-member-var ^                 ^ lambda callback

Depending on how much varies or is similar, affects whether you should parameterize your data and logic, or treat them as identical.




#5297142 Generating Provinces From A Map

Posted by Servant of the Lord on 18 June 2016 - 03:33 PM

If you have heightmap data for mountains, and know where your lakes and rivers are, elevation changes and rivers help define national boundaries in real life.

 

Further, civilization tends to grow most around waterways because bodies of water are natural "highways" of commerce, and provide easy access to food (fish) and fertile soil, while also helping make the surrounding climate slightly less extreme (cooling off overly-heated areas, and warming up overly cold areas). This is important when placing your more-developed cities.




#5297096 Problem on referencing a vector of derived class

Posted by Servant of the Lord on 17 June 2016 - 11:31 PM

I guess... be generic when you can and it promotes code re-use, and be specific if it feels like you're trying to cram something into a pattern that doesn't fit - or rethink your design.


To me, it's easy to make things generic. So easy, that I often over-abstract. I notice this in some 3rd party libraries and engines too, like there's no concrete goal. Claiming "reusable code" can be a siren song for over-engineering - I'd rather have clean but concrete code that I can easily abstract as necessary.
So I now tend to be more concrete and abstract only as I see a pressing reason to (depending on what layer of code I'm working on - utility and helper stuff tends to be more abstract, for practical reasons), because it's always easy for me to make something more abstract, and harder to make an abstract thing concrete without rewriting it from scratch.

This smells heavily of unneeded abstraction, so in my own code, I'd need to justify it to myself before adding abstractions. I'm just not convinced of the value of it.
However, you obviously don't need to justify your code to me:) 

Since it was suggested to the OP, and since he seems eager to adopt it, I still question whether it's a good thing or if it's over-engineering. He seems to want to treat them all identically, but I don't see a need (or even a valuable enough benefit that outweighs the cons of over-abstracting) to treat them all identically, and by default, I feel they shouldn't be treated identically, because they aren't actually related.
Each component type is processed by a different system and each system does different work, the only thing they have in common - as far as I can see - is the name of the design pattern we are applying. And a shared design pattern isn't enough motivation for me to use inheritance: functions are a design pattern, but we don't put unrelated functions into a map together. Typically, only functions that are genuinely interchangeable do we typically treat as interchangeable. There are exceptions, ofcourse, but by default I question it as a big-picture engineering code smell.
Flyweights are also a design pattern, but unrelated flyweights shouldn't be put in a map together without a compelling reason - though I see people often doing this in their "asset managers", and I occasionally fall in the trap of doing it myself before I realize it doesn't make sense. 
 

I guess what I'm getting at, is that treating things in an abstract way clearly has benefits [...]

And detriments. Programming is always about tradeoffs. Things can be too concrete, and they can be too abstract. Since it's easier (at least for me) to make concrete things abstract than to make abstract things concrete, by starting concrete and getting more abstract as needed, I save myself work.
There's definitely a balance to it; especially with game engines, where the internet is a vast graveyard of people writing engines in so generic ways that not a single completed game ever gets created with them.
 
I find abstractions easy to write and easy to over-engineer, so after doing abstract-anything-that-can-be-abstracted style of coding, I realized I wasn't benefiting much from it, so now I tone it back and ask myself, "What abstractions actually are worth the added code complexity?". Because they seem to promise more benefits than they actually deliver, I'm extra wary about them - despite them being pleasantly easy to write and appealing to me as a programmer; I want my mind to set up warning bells when I see abstractions without significant reason. (Abstractions at lower levels of code make sense for me - helper functions and algorithms and containers and so on, but when I start getting to the glue that holds everything together, I want to hone it and have something solid that targets an actual game).
 
It might just come down to different engineering styles and the different lens we are viewing our respective projects through.
I do like your idea of separating the component data ownership away from the systems, and will have to give that some thought.

 

Thanks for discussing this! It's an enjoyable topic for me, and large-scale system engineering is an area I still have alot of room for growth in; sorry for being a tad pushy and too argumentative.  :)




#5297056 Finding the "Fun Factor" in a tycoon game

Posted by Servant of the Lord on 17 June 2016 - 07:17 PM

Off the top of my head, here's some real-life choices of business significance that I recall, involving hardware and (a little) software:

 

  • Apple uses high quality pieces in some situations, and low quality pieces in other situations, depending on its targeted market.
  • Microsoft and IBM went with making hardware a commodity - Microsoft won, and IBM lost, and Intel road that wave to incredible heights.
  • Netscape was trying to make web browsers a commodity (to sell server hardware) until they got confused, lacked cohesive plans, and got kicked in the butt by Microsoft's bundling.
  • AOL wanted to make services cheap to sell monthly internet subscriptions, faced revolt from indie game developers, wisely ignored the revolt, merged with Time Warner, didn't know what the heck they were doing, and were then trying to make make services cheap and sell services, and make internet subscriptions cheap and sell internet subscriptions, lacking clear goals.
  • Cray Supercomputers crashed and burned when they flipped and flopped in whether to use commodity pieces and embrace microprocessing, or whether to double-down on custom super-computer designs, taking one of computing's best minds with it when it went down.
  • A decade later, Apple made the same mistake, investing huge sums of money into the Lisa computer which was over-featured for the hardware of that day, and thus overpriced, and was also competing against its cheaper and better products (Like the Mac) that rival teams within its own company made.
  • Microsoft and Sony pushed different competing disc mediums using their console install base. Sony was more gutsy, and pulled off a major victory - Microsoft now pays about $3 bucks per Xbone sold to the Bluray committee. But due to uncontrollable consumer trends, Sony hasn't benefited from it as much as they had hoped. It was a brilliant tactic, but almost a pyrrhic victory due to the winds of chance or the wims of consumers.
  • And Microsoft's not too annoyed about Bluray licensing fees, because Microsoft makes more money off of 3rd party Android phones then it does off of its own Windows Phones - billions of dollars from patents. This is despite Microsoft being the best placed company to take advantage of mobile and IoTs, but because of internal fiefdom fighting among Microsoft's royalty executives, Microsoft kills its ideas with greatest potential purely because the manager lost a politics war with another manager.
  • At the same time, Microsoft's greatest successes have come because of tiny groups that fought internal Microsoft-wars and forced their visions into reality, such as the Beastie Boys of Microsoft, who forced DirectX into existence by lying to Bill Gates, caused major public-relations problems for Disney, and laid the foundation for the Xbox, but also accidentally contributed to Microsoft's anti-trust lawsuit by trying to strong-arm Apple executives?
  • Oh, and did I mention those Beastie Boys directly contributed to id Software's Doom, and indirectly helped kickstart Valve Software? Or that one of the Beastie Boys tried to manipulate the stock market using insider Microsoft knowledge (and lost buttloads of money but was never caught), and that same guy created Google Maps and sold it to Google, using secret undocumented Internet Explorer features that he implemented in Internet Explorer before leaving Microsoft?
  • And the Xbox itself was spearheaded by an unpopular game designer who's previous game product for another company was a well-publicized disaster?
  • Apple switched from PowerPC to x86 because PowerPC failed to grow in processing power as fast as Apple (and IBM and Samsung, iirc) had hoped.
  • Intel failed to take into account smartphone and tablet success, and now is playing second-fiddle to ARM in that market, failed to bring 64 bit computing in time, and was forced to adopt their rival's, AMD's, designs after it gained more market share?
  • And who created their major rival AMD anyway? Wasn't it Intel themselves that chose that tiny AMD company to win a contract with IBM, and then watched in horror as AMD grew faster and larger than Intel had planned, cutting deals to manufacture Intel's processors for companies that Intel would've got the contracts for?
  • Dell pioneered the made-to-order PC customization market, and rode that to success... but then failed to adapt quickly enough to economy of sales, so was undercut in prices on the consumer end, and failed in the customer-service department towards big businesses and so was one-up'd by HP in that market. Now Dell has taken itself back to being privately owned, in the hope of being able to more reflexively respond to future trends (having also missed the mobile game, due to their).
  • IBM successfully transitioned from hardware to consulting and researching, and reaped big. Hewlett-Pacqard (HP) recently tried to do the same, but lacked the guts to go all-in when their stockholders questioned them on it.

 

And this is to say nothing of Siemens, Oracle, AT&T, Texas Instruments, DEC, Pixar (did you know they made and sold computers? And were ran by Steve Jobs who incrementally took the entire company over, piece by piece) and dozens of other companies, with rich histories, and amazing choices that sent them from the gutter to the peaks to the gutters again.

 

A hundred business choices (or failing to realize a choice was even required) toss dozens of multi-billion dollar businesses up and down in this nearly trillion-dollar industry (software + hardware combined). To quote a famous Intel founder and CEO, "Only the paranoid survive". History is stranger, and sometimes more entertaining, than fiction, and there is so much interesting history here, but if you don't know the history, you are hobbling your own creativity and constraining your vision. If you want to pursue a tycoon game with this theme, I'd recommend doing serious reading on the more exciting and enjoyable stories of the computer industry.




#5297050 Problem on referencing a vector of derived class

Posted by Servant of the Lord on 17 June 2016 - 06:23 PM

Fair enough - I get the benefit of generic code, but there's always a balance between concrete and generic, and I don't want to go too generic unless there is a real reason to.

It makes more sense if you have many different component types, I guess.

 

For Update(), I mentioned earlier why I wouldn't want a uniform interface.

For file or network Serialize()ing, I don't want to serialize every component type - some are likely run-time only. I suppose they could have stub virtual functions.

 

Even Clone(), while a good example, likely has some variables you don't want to clone perfectly, though there's no harm in Clone()ing and then editing the result.

 

Basically, how many times do you need to treat every group of components identically? If three or more, then it's worth having a generic interface to me. But I can't think of any that I'd actually use in my code. Clone() is a good example, and gets a 'maybe'. Perhaps my mind is just pulling a blank here.

 

Can you think of any other convincing cases that require genericity?




#5297028 Finding the "Fun Factor" in a tycoon game

Posted by Servant of the Lord on 17 June 2016 - 03:40 PM

^^^ ...and also, there's a creative output factor to it. In many tycoon games, you have some freedom in how you lay out and design your area. Pretty much the only computer game my mom has ever played was Roller Coaster Tycoon - and she did it more for laying out gardens, paths, decor, and so on. I personally enjoyed Rollercoaster Tycoon, Sim City 3000, and Minecraft (which isn't a tycoon game), for the creativity aspect. In RT and SC3000, there was also the "be financially successful" aspect, and in Minecraft it was instead paired with the "survive the dangers and explore" aspects.

 

So, adding SunAndShadow's observations in, we have the following gameplay aspects:

 

 - Freedom to experiment

 - Freedom of exploration.

 - Freedom to create (artistically shaping and decorating your environment).

 

 - The challenge of reaching financial stability / avoiding bankrupcy.

 - The challenge of survival.

 - The challenge of accomplishing explicit goals.

 - Reflex-based action challenges.

 

 - The pleasure of saving up for an upgrade you want and then buying it.

 - The pleasure of seeing progress (towards goals or your upgrade/equipment progress or your city growth).

 - The pleasure of humor (can be risky, because humor that's not enjoyable can turn you off a game, and appreciation of different types of humor can be somewhat subjective unless it's very high quality).

 

Freedom (within reason) is pleasurable and overcoming challenges is pleasurable. Being able to notice difference between before and after progress occurs also is satisfying.

 

In both Sim City (financial stability) and Minecraft (survival), once I reached the point where I was "established" and the challenge became a formality instead of a real challenge, the game became boring so I destroyed and reset the world to start again.




#5297006 Problem on referencing a vector of derived class

Posted by Servant of the Lord on 17 June 2016 - 01:35 PM

Then when you need to retrieve them:

std::vector<Transform> &transforms = theWorld.GetComponents<Transform>();
// Add some transforms:
transforms.push_back({ 1.0f, 2.0f, 3.0f });
transforms.push_back({ 1.0f, 2.0f, 3.0f });

 
Why is that better than:

std::vector<Transform> &transforms = theWorld.transforms;
// Add some transforms:
transforms.push_back({ 1.0f, 2.0f, 3.0f });
transforms.push_back({ 1.0f, 2.0f, 3.0f });

.

So far in my reading about ECS architectures, I haven't heard a good reason why the systems should share a common base-class; and on the other hand, there's some good reasons why systems shouldn't have a common base. The cons seem to outweigh the pros here.

 

[Edit:] Ah, you're talking about separating the components out of the systems. That's an interesting idea. I still don't get the benefit of the component mapper rather than just "theWorld.transformComponents", or "world.components.transforms" though. How does it benefit me, as a programmer?






PARTNERS