jolid

Members
  • Content count

    34
  • Joined

  • Last visited

Community Reputation

143 Neutral

About jolid

  • Rank
    Member
  1. Damned new design, wrote a nicer post and hit the wrong button... So here's my main points: touch_the_sky hit it pretty well, but don't update statuses like that. Player hits 'Create Building', create a DB entry with 'building_complete_time', and use that. You don't have to touch the entry again for maintenance purposes: queries like 'GET player_X_buildings WHERE completed_time > NOW' gets you incompletes, queries like 'GET player_Y_buildings WHERE completed_time < NOW' gets you all active/complete buildings. Calculate remaining time with completed_time - NOW. No issues here with long no login times, no extra DB queries/updates, almost no time/date functions (or, hell, math! just addition/subtraction) if you use *nix timestamps. CygnusX has a point on realtime gold/energy/people/etc from buildings. Buildings producing goods is a simple compounding interest problem you can best solve by putting in a once-a-day/login/whatever time for those benefits to be gained (or cron, if you're so inclined, especially if you need to run other external maintenance/cleanup that way). If you HAVE to have those gains in realtime, your best bet is probably a separate process/DB to maintain everything separate from the game load, but that's still going to be slightly off and hard to maintain. You're basically running/writing banking software and/or stock markets at that point, and while it's not impossibly hard, it's probably more of a headache than you really want (unless you're that kind of math geek! :-P) Just think in terms of data for now. Many large games (even running in realtime almost identically to what's described above) end up using regularly scheduled cronjobs and such but it's often a byproduct of load balancing or maintenance (meaning account security, checking for h4ckz, pruning old data, etc). Since those tasks end up getting optimized to hell and back and have to touch every account anyway, some things can be put in there to get a net gain (slower scheduled task, faster per user) in performance. None of that should matter at 1000 (or even 10000, sometimes even 100000 depending on DB size and host) users, though. Splitting any turn-based game (meaning you do X tasks over Y time) into chunks crunchable by an optimized cronjob is typically preferable, though, as it's a few minutes of server strain versus a constant moderate load (visible in page loading).
  2. A new sort of development environment

    I don't get it. I mean, I understand the parse tree storage (is that different from Intellisense/all other similar functions?), but that doesn't seem new. You could keep your asset/source/update/etc information in a database with that information already -- using many existing version control systems. How are you ditching the "file system?" Those "files" still exist SOMEWHERE. You still have to reference them somehow. Say someone writes a class that will load, parse, and play music files: How do I use that in my code? #include "jbob/music" ? use "music by jbob" ? I suppose you could automate grabbing the necessary sources from your parse tree DB, but is that really much of an improvement? How would you handle conflicting/redundant naming? I can't be the only person who's had to use several different IManagers in a single project. Wouldn't you end up doing things like jbobs::SoundManager vs local::SoundManager? AFAIK real-time builds are restricted by server availability and dependency/asset matching and good structures automate tests now. Basically, I don't get it. What does this environment help me do better?
  3. I think most MVC (for GUIs) explanations leave out the "you need to design around your input" bit. They rarely say you need to figure out what your internal logic needs to get from the user and there's your model (the logic + open-ended input). Ideally, that bit of code can be totally decoupled from the VC and tested separately. Since I do a lot of web programming, I like to think of the Model as my application, the View as the page shown to the user, and the Controller the link or <--> between View<-Controller->Model. Again to use chess, the model should take in moves and spit out what happens (eg: move rook->rook takes pawn). The controller takes input (eg: "E5 to E2", or "Tile33821 to Tile43832"), changes it to what the model needs ('BR@E5 to E2'), receives the response ('BR@E5 takes WP@E2'), and finally changes that into whatever the view needs ('Black rook takes white pawn', 'Animate Tile33821 to 33,23,53;Tile33821->AttackPawn'). Your text view may simply echo the response and wait for input, your graphical version may have a castle stomping a screaming pawn into oblivion. The point is that those actions are totally separated from the logic. With a proper MVC, all you need is the input information to easily add new views OR logic. One can even be coded without the other: you use the controller to make sure the back and forth is "as expected." Where lots of people seem to have trouble is that oftentimes the View requires more code than just GUI. Don't be afraid to add separate code to the View -- for instance, when the page loads 'IMPORTANT_MESSAGE_A' it should flash on top of the page, all others should appear normally. This will require a logic check, but also BELONGS in the View (or an overdesigned Controller). The graphics rendering loop SHOULD animate attacks and movement and such, even if it requires checking logic similar to the Model (that is, doing more or different things depending upon what the Model says). The Model shouldn't be doing any of your graphical work. That all seems to be a longwinded way for me to recommend overengineering the Controller (!). If you write a solid Model that runs your game and an awesome View/interface (or 4) to show it off, then you can get a bit hacky with the translator/Controller to make them fit together. Your code is still organized and easy to debug* even if the design feels messy. * - By using this checklist: Correct data leaving the View? (No: View, Yes: Continue) Correct data entering the Model? (No: Controller, Yes: Continue) Correct data leaving the Model? (No: Model, Yes: Continue) Correct data entering the View? (No: Controller, Yes: View) You know exactly what piece of the code has the problem and can independently test any section.
  4. If I'm reading your description correctly, you can separate the controller and view in the graphical display by having the display maintain itself until the model decides something needs to change. I'd image a board game could just continue showing the last frame, adjusting for input (eg: mouse movement, selection highlighting) -- though arguably that kind of behavior should be handled by the model. Realistically, particularly for complex graphical environments, you'll need a "graphics model" of some kind to handle all the extra processing the visual representation needs. Much of that (if not all) can be decoupled from the game logic but it still has to happen somewhere. In other applications, I've included that code towards the 'view' end of MVC. The renderer (if you know what I mean) needs to keep track of ongoing animations or visual cues or whatever but my game routine doesn't care. My way of figuring out how to handle generic input is to figure out what I need to do (using the application) and what my logic needs to know. I'll use chess as an example: Playing the game in text, I say '3A to 4B'. Playing the game visually, I click a piece and click the square to move. My game loop needs to know piece or original location, and new location. I have a one step (text) and two step (graphic) system that needs to be standardized for my game logic. So, I can add a "piece selection" step to the text display (making it two steps), where I send 'selected piece', receive possible locations, then send new location; or I leave it at one step (A to B, OK or NO) and leave the visual cues to that display. The two step solution is probably the purest MVC solution, but I'd use whichever fit best. Don't get too hung up on an elegant solution if you can find one that makes sense for you.
  5. Since the browser is crashing after running out of available memory, your problem is in your ajax responses. You are either sending too much data or the JS is hanging somewhere. Try watching your network traffic and the live DOM to see what's actually going on during each load using Firebug or whatever dev tool you prefer. Glancing over your code, you've got some strange things going on I don't understand. For instance, this block: <script type='text/javascript'> function turnlistener() { $('#main').load('battlegetnextunit.php'); }; $(function() { $(document).ready(turnlistener); }); </script> You keep resending turnlistener() unnecessarily. You only need it once. Use the $(document).ready() method OR the passing a function as an argument to jQuery method, having both is messy and redundant. But actually, use neither: The initial page load can directly insert the opening battle sequence. Your second player should begin longpolling at that point, waiting for the first player to act. Your response to the first action should start that player longpolling, after the second player sees the action you should stop polling and allow him to act. You have a lot of XHTML/HTML/CSS mistakes along with the goofy JS structure. Try removing all the backend logic to test your interface/ajax. Make a simple backend in PHP that simulates a typical battle (just generates the next stage of results whenever a player acts) and watch what happens. You say you're using JSON, but you aren't. That's not how .load() works and not what battlegetnextunit.php responds. I'm assuming your combat logic works (haven't looked hard at the code), your weak spot (and the bug) lies with your client-side code and server responses. Read over the jQuery API and some ajax/HTML/CSS tutorials to fix your logic and make your life easier. Hope that helps. EDIT: While there are many reasons classes are good, the example Cygnus gave isn't one of them. The reason is option 3: function round($x, $precision=0); round() will continue to work as expected in the legacy code but now include a precision option. This is also how you would want to change your $Math->round() method, not by setting member variables in the constructor. Rewriting your code to include a player class to get rid of all your duplicated loops and hard-to-read code is a spectacular idea. Game units lay very neatly into the objects that OOP is meant to express, take advantage of it!
  6. You can use .html() instead.
  7. You could shorten the database by selecting a "default" background and/or coming up with a simple system for large sections of the same background (it would depend on your regular patterns). I didn't follow the old link, but if your maps aren't going to change often, you can simply generate the map and save the image (instead of generating it each time). Then your database will only be a long version for editing and its makeup won't matter (much) because you rarely load the map that way. Saving will simultaneously update the database and replace the old map image. As to your main question: depending on your database, different structures will be faster -- I'll leave recommendations to someone who does more with different DBs, since I don't have any first-hand knowledge of best practices with lots of DB software. Don't be afraid to create multiple systems and benchmark them to see what works best for you.
  8. [web] Dreamweaver simple problems

    I'm going to second (third? fourth?) the CSS and/or server-side template system, if you're curious how most sites you browse maintain a consistent look. You should start learning CSS -- and do it OUT of Dreamweaver -- even if you can't make your whole site that way. IIRC, and from the Dreamweavered code I've worked with lately, Dreamweaver defaults to using more CSS to try and meet more XHTML standards. To expand on AverageMidget's example, you can do something like this with CSS: body { background-color: #000; font: 12px fixedsys,monospace; color: #0f0; } p { margin-left: 2em; padding-bottom: 20px; } div#logo { height: 250px; width: 500px; background-image: url(whatever.jpg); background-repeat: no-repeat; } And by using that stylesheet, you'll always have a green-on-black, monospace font (for the Matrix hacker look!), with your paragraphs indented, and the div with the id "logo" will include whatever.jpg in the background. Don't use frames unless you intend to have separate "windows" of content displayed. Basically, you don't want to use frames because you will rarely really want/need them. When you need frames, you'll know it. Feel free to copy/paste your HTML! If you're making a static site there's no point in wasting the server's time by processing included data. You should still use CSS to minimize data transfers (you only have to download the same stylesheet once), but simple sites don't even have that problem. That said, copy/pasting will likely be faster and easier for you to get started, which means you can keep working on your site, and will improve (redesign, update) it as you learn more. Just dive in! You'll get the hang of HTML et al in no time. W3Schools is great (my clients like it too). I get paid to work on websites and still use references like it all the time.
  9. This isn't about an operation five times vs. a different operation that comes to the same answer. But my point is why not? What can you possibly be doing that can't be rewritten as an algorithm to calculate X number of iterations? This is about calling update.php once per minute for five minutes, vs. calling it 5 times in a row. I don't see a difference here. There isn't one, per se, except for the server load. Calculating that calls for a lot more data on estimated stats and execution speeds than I feel like making up for an example. Also I think you'd have to append 31 zeros for your example, which is really just showing that squaring numbers that are 1 followed by zeroes is easy in any base. It's not a shortcut. Whoops -- yeah, did the wrong squares. The point is that it IS a shortcut: Shifting bits is a common optimization (Shifting left/right N places is the same as multiplying/dividing by 2^N) that most compilers (C/C++ at least) now do themselves because it's faster than actual multiplication or division. Different bases lend themselves to different mathematical tricks, but as long as computers run in binary those tricks are the fastest. Switching to a different base doesn't help you at all since you still have to do the work of converting it back to the base you're interested in which is even more work than manually squaring 2, 5 times in decimal Maybe that's easier for you, but the base conversion was to draw your attention back to the computer. It's running in binary, so what makes sense to you on paper isn't necessarily the same thing that makes sense in a computer. Maybe they don't teach the bit shifting thing anymore? I thought you might recognize the example. But whatever, just go with what works. You can always optimize later! I'm glad you've gotten it working.
  10. Quote:Whether it calls update.php 5 times after 5 minutes of zero activity or once a minute during those 5 minutes, it's the same amount of work done by the server This is rarely true in practice and completely wrong in theory. An operation 5 times is not equal to 1 operation that comes to the same answer. Example: Do this 5 times: n^2 = nnext, where n is initially 2. Convert the final answer to binary. Or take 2 in binary (10) and append five 0s (1000000 = 64). Just something to think about. PS: Learn to use cron/task scheduler/roll your own if you go that route. Dealing with the extra overhead of triggering it via HTTP (even just the transfer costs!) isn't worth it and can easily become a MAJOR problem. What if your connection goes down? What if the server is disconnected for updates?
  11. Session data is kept on the server, the user just passes the session ID around. PHP manages connecting the session ID (the ?PHPSESSID= when cookies are off) to your session variables. Anyway, if I'm reading jjac's problem correctly, you're worried about other people on your shared host getting to your session data? That's not really your problem, nor is it likely to happen (especially on any reputable host). If that kind of security breach happens, it'll be a big deal*. Slightly more likely is session hijacking, which you can (almost) totally defeat by saving the IP address at login and checking that before committing any changes. With that and a custom backend, hacking blindly at your site is rarely worth the effort. FWIW, as long as you never send $_SESSION['sqlPassword'] back to the client, they will never know the value. That's why you can't sit down at your friend's e-mail account and javascript out his password. You can look up session hijacking, fixation, and general cookie security if you're still worried. Feel free to apply as little/much of that as you want. Unless you've got real high security concerns, a little goes a long way. * - Afterthought: If anyone gains access to server files, they can probably or already did root the box, or can download copies of anyones database/files/whatever anyway. At least session data will expire, in some ways making it more secure (from this particular breach).
  12. You've got to be a LOT more specific to figure out how to make events 'tick' in a web environment. To take your main points: Players interact with each other. Spectacular! How? They fight and/or trade, I assume, from the army bit in the next sentence. Do you allow active/inactive fights? If so, all outcomes will be formulaic (pre-determined actions by inactive player). Your game logic will be something like ACTIVE_PLAYER attacks SUPERMAN, SUPERMAN not online (query updates for SUPERMAN, apply), SUPERMAN follows scripted battle. Fleets and armies are moving around in time. Training occurs in time. Probably nothing happens during transit/training, right? Or, if it does, those changes are effective after the movement/training? Then all changes can be applied when USER/PLANET/BASE/AREA is accessed after the end time. It would be far too complex to only compute relevant changes when the user can see it as you'd have to build up some kind of map of all the interactions between the player, the player he's interacting with, all players that player has interacted with etc. Why is it too complex? A user doesn't need to change AT ALL unless someone (the user himself or another player) accesses the user. When your battle/trade/display scripts access user data, they should confirm the data is timely (typically by including a LAST_ACCESSED field or separate, searchable update queue). You don't need to know (or care) what triggers your update method, you just need it to run prior to any interaction. I would avoid lumping all your check update routines at login because you'll still want progress to roll forward while users are playing. Especially at the beginning of your dev cycle, no one will be signing in, meaning you'll never have updates while playing. But really, what is happening EVERY minute? Interest on bank accounts? Auto-experience? Some sort of special power growing? Those are typical things (AFAIK) that can happen "constantly" in a game, but they are often not. Even some of the most complex growth patterns you can find (I did some crazy interest gains in Calc) can be figured in one step to adjust for time. Say you want them to gain 0.5% of their experience every minute and they don't login for exactly one week (10080 minutes). You just use a basic compound interest formula (assume 100 XP at logout 1 week ago - in the Wikipedia link, here n is 1): 100(1+.005)^10080 = 682185533694734340099690.06898055 XP when they login again. Also, that is a prime example of why you should avoid any kind of uncapped interest on games... The point is that your updates are probably just numbers changing by a formula and you can adjust that formula for ANY amount of time, making "on-demand" updates a simple, practical solution. Another thing to remember is you AREN'T Farmville or EVE. You aren't trying to balance simultaneous updates of 600,000 users in realtime because you have 500,000 online. Trying to design for those problems when you'll be successful with 10,000 regular players (not simultaneous) is absurd. Do you think about transferring exabytes of data every time you make a website? Anyway, feel like I'm straying from the initial point: Breakdown EXACTLY what is happening in your game and then figure out how to best keep it up-to-date. That means being much more specific than armies grow, people age; you have to figure out precisely how you will track that information (database design/formula work). I'm not out to dis cron jobs, even this usage, just that you need to consider if that's the best method. The only way you can do that is by knowing precisely what and why your 'update.php' does every minute.
  13. [web] JavaScript game loop

    I've got nothing new to add, just wanted to say Sik's method is much better than the hacked-up setIntervals I've used and it's probably the best (most consistent) solution I've seen. [bookmarked] Thanks for that!
  14. Sorry, you'd want to do a netstat -a or netstat -an. The first should have a line like [COMPUTER_NAME]:http - - LISTENING, the second would be 0.0.0.0:80 - - LISTENING or 127.0.0.1:80 - - LISTENING (-n forces numeric outputs). At any rate, XAMPP will more-or-less install whatever software you select as if you did them all yourself. You can follow any instructions for getting Apache working on Windows 7 without worrying about breaking the installation. Having direct access to the software will come in handy when you start wanting to mirror other server setups or try a unique configuration.
  15. Have you run netstat and confirmed you have something listening? Can you access the server EXTERNALLY -- that is, via your IP but not localhost/127.0.0.1. Did you check any/all firewalls? That's all I can think of from what you said. FWIW, my favorite insta-test-server software is XAMPP... Mostly because it installs everything normally with minimal extra/odd configurations. If you're changing conf files et al with WampServer you have to make sure you used the correct file (IIRC it has 3) and restart the server for any changes to take affect.