ToohrVyk

Members
  • Content count

    9683
  • Joined

  • Last visited

Community Reputation

1595 Excellent

About ToohrVyk

  • Rank
    GDNet+

Personal Information

  1. [OOP] problem

    You declared functions modify, initialize, show and free in CGameApp, but you never defined them, which could be the cause for your error. Either provide a definition, or declare them as pure virtual using the following syntax : [CODE] virtual void modify() = 0;[/CODE]
  2. AJAX Tiles Game

    Greetings, GameDev-ers. I have a little challenge for you lot. I've written a small browser-based game where two players have to conquer a pristine white board by painting the tiles in either red or blue. [url="http://tiles.nicollet.net/"][b]You can view it here[/b][/url]. The important detail is that you're not expected to play it. The game plays itself by asking the Red and Blue AIs for the moves they wish to make, and you only get to watch two artificial intelligences duke it out on a virtual board. Oh, and you can write your own AIs, upload them to a web server somewhere, and paste their URL in the Red AI or Blue AI boxes, to see how they fare against mine (or others which might be posted in this thread). I've posted a [url="https://github.com/VictorNicollet/AjaxTiles-AI"]GitHub project[/url] that contains the PHP code for my AIs, along with a [url="https://github.com/VictorNicollet/AjaxTiles-AI/blob/master/README"]README[/url] that explains how you can implement it in other languages. And you could also read the [url="http://www.nicollet.net/2011/04/ajax-tiles-game"]relevant blog post[/url] for the game. Looking forward to seeing your Artificial Intelligence masterworks.
  3. Unity [web] web based questions

    The web (as in HTTP + HTML) is just a specific kind of client/server model, with its own benefits and drawbacks, which may or may not apply to the project you are dealing with. For instance, HTTP is a pull-only stateless protocol, which is both a benefit (you can handle more clients per server, and you can spread the load across multiple servers) and a drawback (the server cannot initiate communication with the client, every request must carry all necessary state information). So, it would be a great choice for a game that involves millions of low-bandwidth clients, and a bad choice for games with a handful of high-bandwidth users. The web does have the benefit of being fairly platform-independent and requiring no software download (although you can achieve this with a client/server model using Flash or Java, too), but you will be limited in terms of rendering power. Presenting static dialogs and forms, along with simple 2D graphics and animations, is possible, but anything more complex than that (including, say, playing sounds) is going to require specific software on the client side. To be able to tell more, we would need more information about your project.
  4. Tutorial topic required

    [url="http://en.wikipedia.org/wiki/Vector_field"]Vector fields[/url] and [url="http://en.wikipedia.org/wiki/Screw_theory"]screw theory[/url] would be fairly interesting topics.
  5. Programming FML

    Quote:Original post by shurcool What function would you recommend to use instead? As you might have guessed, the issue here is that GetNextFloat involves a subtle side-effect that is easy to miss - despite being called 'Get', the 'Next' part involves a change in the underlying stream object. The solution is to make this side-effect obvious. In a functional language, you would simulate the side-effect by having GetNextFloat return a pair composed of the float and the remaining data in the stream. This way, you can't get the float without noticing that a stream was also returned. Of course, this requires a proper implementation of streams as immutable lazy linked lists, which is too complex for weak languages like C++ to handle elegantly. The C++ solution follows this idea but gives up on immutability: stream operations return the modified stream, which means that if you need to access the read value, you need to add a variable access and unless you're deep into code obfuscation, you'll use a distinct statement (solving the problem). Still, streams are not immutable, which means that the original stream is also modified (and thus, returned for optimization purposes) which means that stream reading remains vulnerable to exceptions (an exception does not "roll back" the read data back into the stream). In short, that line of code (at least in C++) should have been: float x, y, z; fileStream >> x >> y >> z; // operator precedence constrains order of evaluation vertices[vertl].mLocation = KMath::CVector3(x,y,z); Or possibly even: fileStream >> vertices[vertl];
  6. Programming FML

    I suspect 50% of those, including your example, would be summarized as "Today, I used side-effects where none were needed. FML" The bug is that the GetNextFloat function exists in the first place [wink]
  7. Hi. Quote:Original post by amirabiri - Should I strive for as many game logic updates as possible, i.e Update() between each two frames without H-sync? Or should I aim to call Update() only every specific interval?Depends on the game. Working with fixed-duration update steps is usually easier on the brain cells of the programmer, especially without a sturdy math background. You can also run different subsystems at different frequencies (such as movement 100 times per second, but checking for player/enemy death 10 times per second). Quote:- If I go for intervals in the previous questions, should I try and compensate for the lack of sync between the render frames and the game ticks by rendering "half movement"?No. Try updating faster than you render. If it turns out that there are too many things moving around, 80% of these things will be of the same type (usually particles or similar low-intelligence entities) and you can then implement interpolation specifically for that type. Quote:- Should I have an Actor base class that contains lots of functionality in it and rely on subclassing, or should I have compositions of objects each responsible for different parts of he actor like moving, animation, physics, AI, etc.You shouldn't care about that. How you factor common code out of your program is something that should and will evolve as you work on it, so you should strive to keep it as flexible and easily refactored as possible. However, make sure that the Actor is a base class for code sharing needs, not because it's an interface. If your renderer, or your simulation, or your collision tester, or any part of your system expects "Actors", you're in trouble. A renderer should expect renderables (which may be actors), the simulation should expect updatables (which may be actors), and so on: this lets you decide whether to keep a one actor = one renderable = one updatable correspondence or move away from it. . Quote:- Should I have one big list of Actors and iterate through all of them each game logic cycle calling Update(), or should I try to minimize this big iteration in some way?It's a basic fact of life that a bullet does not behave like a player, and an enemy does not behave like a pick-up. Trying to treat the the same way will result in a warm fuzzy feeling of "design" (yes, with quotes) and daily pains when the program design does not match the game design. Until you absolutely, positively determine that object A behaves exactly like object B, keep them separate in two different lists. If you need to share code between the two, have them implement a common interface for that specific functionality (say, both pick-ups and enemies can collide with the player, so they should both have a collision detection method and a "collided player" event: group these facts in a dedicated interface) and write code that works on objects with that interface. Quote:- Should the game be single threaded or is it advisable to employ multi-threading?Multi-threading is a skill in itself. Using it will make development harder and may detract you from your objective. Unless multi-threading is absolutely critical to what you are trying to achieve or made insanely easy by your libraries or programming language (say, on the level of Erlang), go for it. Otherwise, wait until you feel comfortable with single threaded design.
  8. I sheathe my sword in the reddish light of a bloodied twilight, neither proud nor ashamed of what had to be done. To my left, Tezuma the Ever-Vigilant runs a few unit tests, going through the motions without really expecting any to fail. Sitting on a moss-covered rock nearby, Matsuru treats her wounds—a stray fang from the beast's death throes, envenomed with the bitter ichor of static initialization order, found its way through her statically typed armor. When men first came to the valley of Wu, they were desperate and miserable, for they had no hides to shield them from the cold winters, no wings to escape the maws of nightly beasts and no roots to draw sustenance from the barren soil. Man, a creature of craft and tools, could not function without a complete infrastructure where the miner brought the ore to the smelter, who brought the iron to the smith, who brought the plow to the farmer, who tended the fields and provided pizza and coffee to the programmer, who wrote video games for them all. And so, the ever-pervading Titans of Wu saw the desperation of these men, and pity entered their eternal hearts. Yojimbo, the Wooden Dragon, took upon himself to bring fresh wood to every man in the valley. Mishigo, the Sparkling Flame, brought fire to every hearth, warmth to every home and overclocking to every Pentium. Soon, every Titan found its way into the daily lives of the men of Wu. Today, my blade sought the heart of Asuna, the Physics Engine, and found it. "Who will provide our daily simulation steps, if not Asuna?" had they asked for centuries. Men had grown too dependent on the mighty Titan, scared as they were to do the work themselves. And so, as the small valley grew to a continent-spanning empire, the presence of a single Physics Engine grew increasingly inadequate. For when the wise sages of the east wanted to run a simulation, they had to wait for the clever smiths of the west to finish their own, and such woe came to those who had forgotten their cleanup steps that most of the time was spent in repetitive multi-threading incantations rather than actual simulation. And so the time came to slay our former ally, for only its death could bring change to the World of Men. Like wind among the snow-covered BSP trees, our secret army flowed throughout the code base, spying on Asuna's every tendril with our refactoring tools, silently replacing her all-encompassing embrace with a rogue network of ersatz Physics Engine instances that were passed hand-to-hand to those who needed them. Static type-checking ensured that no man was left behind, and a small unit-testing task force was trained for the occasion. Until that climactic battle. For Asuna noticed, and so great was her anger that countless access violations tore apart the fabric of the empire. Our spies and networks had provided everyone with the instances they needed, and our unit tests could detect the tremors in the Titan's footsteps, but the power of the Mighty Ones was beyond our imagination—for with their fingertips they commanded the powers of Unwritten Assumptions. So concerned had we been with providing every man and woman with their own instance, that we had forgotten to check who expected to share an instance with another: everyone had their own instance now, but everyone expected the others to be using it as well. In the utter collapse of our civilization, we fought to bring together foreigners from distant realms who happened to work with our own people. Who would have expected that two people thousands of miles apart needed to use the exact same instance? But the fight is over now. Dry tears mourn our fallen brothers of the Global Variable Inquisition, and a black wind rises from the east. Orochi, General of the All-Seeing Logging System, has roused from his slumber. When you're writing code, you need to make assumptions or you will never ship anything. Some assumptions are pretty solid — "I will never have my code run on a Sega Genesis console" is as solid as it gets these days — but others are weaker. There's a whole spectrum of them actually, and you need to decide which deserve to be made and which should be avoided. Having all your code share a certain instance is such an assumption. Sometimes, making it is the fastest path you can follow to your objective, and it would be silly to avoid it merely because it "feels" dirty, or someone told you it's a bad thing. What you absolutely need to, however, is prepare a contingency plan. When (not if) that assumption is eventually broken, you will need reinforcements, because the last thing you want to do is backtrack on that assumption with your debugger. In fact, there's an entire scale of how easily you can backtrack on an assumption: Toggle a compiler option or runtime configuration setting. This is as cheap as it gets, so don't fret. Make that assumption and move on. Total time: five minutes. This is where "how much stack memory do I need?" assumptions live. Change a definition in your code or data files and recompile. This increases the possibility of error, and it requires sufficient knowledge of the code base to know that definition was there in the first place, but it's still a cakewalk. Total time: 15 minutes, including coffee. This is where "How much damage does a rocket do?" happens. Use automated refactoring tools. This is where "Do we call them _foo or m_foo?" happens. Total time: 30 minutes, mostly checking that the refactoring was correct. Do some manual refactoring using a simple deterministic set of rules, until the compiler stops complaining. This is what removing a global variable means if you've followed proper global usage patterns (more on this in a bit). Total time (from my experience): about an hour for a 20KLOC project. I do this about once a week (and I don't have unit tests, but I have excellent reasons for doing so). Do some manual refactoring using complex rules, until the unit tests stop complaining. This is what removing a global variable means if you were sloppy with your usage patterns. This might take you a day, possibly more—at this level, things are not predictable anymore. Read the code to reverse engineer the basic principles, write unit tests, rewrite significant portions. Could take up to a week and involve at least one team member flying into a murderous rage. This only really happens if your program is a mess and there's sticky goo floating all around the place. So, what are these usage patterns I've been blubbering about? One pattern is the (observationally equivalent) immutable value. If your global is a constant, or behaves like a constant for all means and purposes, it makes refactoring a lot easier, because it means that two distinct places in your code cannot communicate through that variable. Of course, it's still possible that the two places expect to receive the same constant (such as an array size), but you've eliminated a whole slew of potential issues. In short, if you can use a constant, do it. If data can be changed, but you can make it look like it never does from 99% of your code, do it and document with appropriate language features (const...) Another pattern is the layered architecture. Make every piece of your code part of a layer, and then decide which layers are allowed to do what. MVC is a good example of this: the view cannot change the model data, and the model data cannot interact with the renderer. So, if the renderer was a global, and you needed to un-globalize it, you wouldn't need to worry about the model. As you write your game, you will end up with a lot more layers than just MVC, until it looks like a stack of thin pancakes such as "enemy controllers", "weapon views", "AI models" ... make sure you decide on coherent rules for every such layer as far as global access goes, including rules about when two elements may expect to be using the same instance or not. Yet another pattern is the thousand faces instance—using polymorphism or encapsulation, hide a single instance behind several types that represent different aspects of what it can do. Even though right now a "Physics Simulator" and an "AI Physics Simulator" are the exact same thing (down to the method names and types), you can have one type evolve independently of the other and immediately track down where in your code it was used. Once you need to remove the global aspect, you can do so by applying rules on a per-type basis. Ultimately, when a variable ceases to be global, you need to pass it down to every place that needs it, by making it a member variable of the objects that use it or an argument of the functions that use it (use whichever is appropriate on a case-by-case basis). Don't think that because an instance stops being a global variable, and becomes a member variable of a global variable, it's solved. Global is a different thing from "global variable". If you can access your object without passing it as an argument or creating it yourself, it's global even if it's not a global variable. The bottom line is: are you comfortable with backtracking on your assumption ten days from now? Ten months from now? Do you have a documented contingency plan? If you're scared about it, backtrack now before it's too late.
  9. I'd like to help you, but I'm not going to allow write-access to my Facebook wall to an application I have never heard of and have no reason to trust...
  10. If you don't want to spend too much time thinking about it, don't preallocate at all and let the free store handle it. If you have some time to spend on the subject, create two independent memory pools (one for each object type) and preallocate the total number in both. This will waste twice as much memory, but it's fairly simple to set up and reasonably safe. If you have a lot of time to spend on the subject, create a single memory pool that contains chunks of a size equal to the size of the largest of the two objects. This way, any chunk may be initialized as either type of object. Of course, all of this assumes that you're overloading operator new to use the pooled memory (as opposed to pre-instantiating the objects, which is a lot worse in terms of code safety and maintenance).
  11. Quote:Original post by Gaiiden Fixed. I just pulled the style code out of functions.php and am now handling it in header.php, where it seems to work. Ah yes. I missed the part about functions.php because I was expecting you to be in a typical template file, like header.php. What caused you trouble is that Wordpress sets up a series of global variables representing what is about to draw before starting any rendering (and it does this again for the post/page loop, and again for the comment loop). So, most template-bound functions like is_page or get_post_custom are implicitly dependent on the rendering context...
  12. Saw your message on twitter. I don't have much time right now, so I won't dive into the specifics of your code. Have you considered using custom fields instead? This would allow you to specify an image in every page: <?php $custom_fields = get_post_custom(); if (count($custom_fields['my_post_image']) > 0) define('HEADER_IMAGE', '%s/'.$custom_fields['my_post_image'][0]); else define('HEADER_IMAGE', '%s/images/default.jpg'); ?>
  13. Relational model for games?

    This way of doing things will replace many language constructs you take for granted with a clunky hand-made version. For instance, if you decide to support JOIN and WHERE (and you will, if you need to work with foreign keys) then you also have to handle indexes (otherwise, every foreign key lookup will require a complete table traversal). Deletion of elements is similarly difficult, since it will involve moving elements around to plug the holes while retaining their correct position in the index. Sorting elements by a certain value is also an interesting challenge, since you'll have a choice between temporary indexing (basically a sort on the column right before you read the data), permanent tree indexing (keep a multimap using the field as the key) and permanent array indexing (keep a sorted array of indices) by optimizing for your read/write proportion. Yet, I like your idea. I toyed with it for a while. My strategy was to define the tables using metaprogramming, by stating what fields were present in each table and what indexes were to be used and what queries were to be done. The compiler would then construct the appropriate C++ code for every query. If that query involved doing an operation on the selected lines (as often happens when you UPDATE) that code would be written as C++ and inlined by the compiler directly in the loop that traversed the data. Note that relational databases do support inheritance. For instance, if a "ship" and a "bullet" are both a "physical object", then you would have two lines in table "physical" with ID=25 and ID=26, one line in table "ship" with ID=25, and one line in table "bullet" with ID=26. This means that if your database engine supports UPDATE queries, you can simply run an update query on table "physical" to move all your physical objects!
  14. Hey there. Stumbled by, and thought I would show this topic some love. From a performance standpoint, in your typical PHP+MySQL web application, updating the game state on demand is an extremely bad idea, on par with holding a metal pole in a thunderstorm or bathing in shark-infested waters with a bathing suit made of fresh seal meat. You can try it, and you can make it work (if your server is hideously over-powered for the number of users you have), but it has severe scaling issues. The first problem with on-demand updates has already been mentioned: it might take a while between sessions. The next user to come online has to suffer a huge performance hit to let the game server catch up with the current state. Not because the language is slow or because it's doing a+=1 five times instead of a+=5 once (all of this can be optimized, although not necessarily for free) but because a massively concurrent web application needs to save the data back to the database, and writing data to MySQL is insanely expensive. If your application has to perform even one indexed INSERT per interaction, then a single user catching up on all the interactions for an hour of idle time will have one hell of a wait time. And without one INSERT per interaction, good luck implementing the «here's what happened while you were away» feature on your game. But that's not the worst issue (you can kind-of-solve-it by making sure someone requests an update every X seconds, just like the Original Poster is trying to solve it here). The second problem with on-demand updates is stampeding (or serialization, depending on how you look at it). Stampeding basically happens like this: User A connects to the server, notices that some updates should be done, and starts performing them transactionally. User B connects to the server. Since User A is acting transactionally, User B sees the same needs-to-be-updated game state and starts updating it transactionally. This doubles the performance load of the update. More users connect. Since the performance load increased, the updates take longer, so there's a higher probability of starting an upload that is already being processed. The server load increases until it basically gives up and takes its own life in frustration (yes, MySQL does that). Depending on what your updates look like and how your transaction isolation level is configured, you might experience serialization instead: User A connects and does an update. User B connects and reads the "Todo" table(s) but is locked out because User A is working on it, so User B idles until User A is done. The lock on the "Todo" table(s) means your server can now only serve one user at a time. This is a major performance problem if you intend to serve more than a handful of simultaneous users, because locking problems can not be solved by adding more hardware. The ideal architecture for a web game is to have a single update "thread" (might be a cron job or a script running without a time limit) that polls the database for things to be done and does them, and any number of threads to serve the HTTP requests from the players by reading data from the database and using lock-free, possibly delayed, cluster-indexed INSERTs to tell the update thread what to do. If you have the money, replicate the main database on another server and have all the players read from the slave to lighten the load and read locks on the master (if the server holding the update thread is powerful enough, you can scale your game to infinity). If you don't have that kind of money, and you see the update thread getting locked out too often, you might want to set lower a thread isolation level (READ COMMITTED) to reduce that (at the cost of sometimes displaying some inconsistent data on the user's screens). In practice, it also helps if the game is designed so that most updates cost nothing. This can be done with two techniques: Do not compute or store anything the game logic does not need. If you don't need it to run the game logic, then you can compute it on demand when (and if) the user asks to see it and discard it afterward. For instance, if your units gain ranks based on the number of enemies they kill, then you do need to compute and store the number of kills, but you don't have to find out the name of the current rank until the user needs to see it. Use "do not open until" timestamps. Instead of the user inserting a "Build Space Station" order in an order table, they should instead insert a "Space Station" building in the building table with a timestamp of NOW() + buildtime. This means the act of successfully building the space station does not involve any computation (at the cost of an additional timestamp test when reading from the building table, but that can be easily indexed). These will decrease the load on your server. By the way, the default time limit for a PHP script running in CLI is infinite (and defaults to 30 seconds for CGI and Apache mod_php), so you don't have to configure anything.
  15. Sadly, there are no clean ways to reverse an iterator (aside from using random access iterator arithmetic to construct the reverse iterator from rbegin() again). On the other hand, I would probably re-engineer the algorithm into two different steps: - Whenever you need to remove elements, run through them, determine if they have to be removed, delete them and set them to NULL. - Whenever there's a possibility that elements have been removed, use std::remove_if and erase to eliminate all NULL element. This has the benefit of being conceptually easier on the brain, since you don't have to care about removing elements while iterating.