Enemy Coding Concepts in Multiplayer

  • I'm really curious to see what some other people think that have used the Multiplayer plugin, or knows a bit about coding MP games.

    So I have player inputs working well, and I'm getting to the portion of the code where the enemies are coded. I'm curious on your guys' take or ideas on the best way to achieve this. I'll have plenty of different enemy types, but for now lets just stick with the traditional "run towards you constantly" variety. So far, I have this:

    1. I basically set all the code for the enemies to behave the way they will (animations, triggers, etc.). However, ONLY the host determines when an enemy is active, and who the enemy is chasing, and then relays that message.

    ie

    if Host
    
    [ul]
    	[li]Pick Nearest Player[/li]
    [/ul]       - If Zombie distance < 25, set Zombie.chaseTarget to Player.peerID
           - Send MP Message (Zombie.instance, Player.peerID)
    
    [ul]
    	[li]On MP Message, pick Zombie instance, set chaseTarget to peerID[/li]
    [/ul]
    [ul]
    	[li]For Each Zombie[/li]
    [/ul]      - Chase Player by peerID
    [/code:wlf1lmmo]
    
    It works.  However, you will get slight differences depending on the latency of where that enemy is.  But technically, it's all aesthetic.  So if you're lagging like crazy; yes, it might look like you're friend is hitting air and killing an enemy on the other side of the screen every once in a while.
    
    Truthfully, I don't know how else do this without tons of bandwidth.  
    
    Any other ideas?
  • I'm really curious to see what some other people think that have used the Multiplayer plugin, or knows a bit about coding MP games.

    So I have player inputs working well, and I'm getting to the portion of the code where the enemies are coded. I'm curious on your guys' take or ideas on the best way to achieve this. I'll have plenty of different enemy types, but for now lets just stick with the traditional "run towards you constantly" variety. So far, I have this:

    1. I basically set all the code for the enemies to behave the way they will (animations, triggers, etc.). However, ONLY the host determines when an enemy is active, and who the enemy is chasing, and then relays that message.

    ie

    > if Host
    
    - Pick Nearest Player
           - If Zombie distance < 25, set Zombie.chaseTarget to Player.peerID
           - Send MP Message (Zombie.instance, Player.peerID)
    
    - On MP Message, pick Zombie instance, set chaseTarget to peerID
    
    - For Each Zombie
          - Chase Player by peerID
    [/code:22phpea0]
    
    It works.  However, you will get slight differences depending on the latency of where that enemy is.  But technically, it's all aesthetic.  So if you're lagging like crazy; yes, it might look like you're friend is hitting air and killing an enemy on the other side of the screen every once in a while.
    
    Truthfully, I don't know how else do this without tons of bandwidth.  
    
    Any other ideas?
    

    instead of pick nearest zombie, which what does is picking all your zombies and counts their distance on a loop even if their outside the screen.... you can use a two number comparison and compare your current position to zombie position that is in screen on a distance of 200 pixels 300. that way it will limit the loop that is going on to just a few zombies around you since other zombies dont matter if they are to far or not seen, that should lower your cpu and bandwidth required to update your moves.

    think small always when you build multiplayer games, small coding and small areas, never large areas.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Generally I think it is best to allow only the host to control the enemy movements and simply sync those instances with the peer. That way you will always be working with the same game state.

    Have you tried that and disliked the result? You can always do some tricky things to simulate predictable effects on the peers side before waiting for a MP message to make the peer experience better.

    If you were determined to keep it low latency friendly you could always keep what you have and periodically update the positions of enemies through MP messages - just to make sure they stay on predictable paths.

  • - good point! Not sure how I missed that

    GenkiGenga - yes, that's exactly what I'm doing right now. It works fine as is, and even with TONS of simulated latency, it "works" (albeit a bit strange).

    For the most part, what I'm doing will likely be fine, but I was curious since I've never seen a tutorial or suggestion to do anything else (and since you can't really sync THAT many objects, what else would you do?)

  • Oh ok, I thought you were having both the host and peer do their own pathing.

    I would think it wouldn't be a problem unless you are syncing over 20-30 enemies at a time, I haven't tested that many though.

    I guess if you were dealing with potentially hundreds you could clump some together and sync a group as one object, breaking them up again when you needed to. Hopefully it wont be an issue for you.

  • - to be honest, I haven't even tried syncing the enemies. I was just afraid that if I did so, and some layouts had a ton of enemies, that it would not react very well. I might give it a shot. Is there a syncing tutorial for enemies anywhere?

    Also, noticed a small issue with the concept of checking distance and outside their screen - it doesn't actuallly pick a zombie, so whoever the first zombie was picked is what will do that check. Unfortunately you DO need for each at the beginning of the loop, if I'm not mistaken.

  • It is really quite simple once you start playing around with it. There are good examples in the ghost shooter and pong demo.

    Basically on the start of layout you sync objects between the host and peer (playing with the precision to see what you can get away with) and from that point forward those objects will react for the peer as they do for the host.

    For this mini example lets use 'position only'. Once this is done the host can instruct zombies to move and the position will be maintained on the peer side. If the peer tries to have events moving enemies they will constantly be fighting the control of the host's position (and losing). The peer can however still manipulate animations and variables from their side with this setup. Just note that these wont be shared so you will still need the peer to send MP messages when needed to the host letting them know of changes and vice versa.

    You can also sync variables but for the sake of this example lets just leave it at position only. Not much bandwidth needed for updating X and Y positions with today's internet.

    I said it to someone else recently but playing with the demos that are provided is the best way to familiarize yourself with what you can do imo. Change variables etc. See what breaks and what bends.

    Regarding the distance check, Yeah if you want more than one zombie to share the event you need a for each.

    Code it up any way you like (there is a lot of different ways you could approach it) but when in doubt remember that the debug button is your friend. You can go into 'profile view' and see how your logic fairs. Taking up a good percentage of your cpu (time to make some adjustments). If not then I personally wouldn't worry too much.

  • GenkiGenga - Wow, I didn't think it would be so easy... it actually seems to work pretty well. Now, getting into numbers...the inboundBandwidth / outboundBandwidth is constantly ~1500-3000. Is this okay? Or is that WAY too high? This would save so much hassle and potential failure...

    There will be up to 50-60 enemies in a layout at one time - mostly one 5-6 different enemy types, but just wondering if that's WAY too many objects. I'm only syncing position, though. (this is how many enemies I have in the test layout causing 1500-3000 bandwidth)

  • Change variables etc. See what breaks and what bends.

  • raz2002 - truthfully, you can't really see what breaks and bends in multiplayer. I live in the US - our internet is nearly unparalleled. Most people here have incredibly fast connections. It makes it hard to know what other people who aren't so fortunate will deal with when playing our games.

  • That isn't too bad for that many enemies. The readings come out in bytes so its 1.5 to 3kb per second, seems reasonable to me. A quick bit of research and I found world of warcraft typically uses around 4 times that amount.

    The distance between the players is the biggest concern. You can simulate latency in the multiplayer object, just make sure only to trigger it on the host side.

    Just out of curiosity, how do you have your peer movement set up? 1500 inbound seems a bit high compared to using the sync with client input method (the way it is set up in the ghost shooter demo).

    Not that it is necessarily a bad thing mind you.

  • GenkiGenga

    Actually I only have ~150 with JUST peer input. I'm not syncing the player objects due to lag on the input of the peer side. I'm basically setting variables on a player object to 0 or 1 based on whether a button is DOWN or UP, and then sending a message to the other player that "this player just pressed this button". When you let go of a button, I'm syncing the player position, as well. This way both players have absolute control of their character without having to worry about lag.

    That's good to know about the kb thing! I might be able to keep this idea then

  • Sounds good for the peer. The challenges you face with this style is collisions. Things like, if you are allowing your peer to move without the host authorizing it and the peer walks over a powerup while the host has done the same thing - who actually picks up the item? Do they both get it?

    Build the game around the limitations for the best experience.

    If that proves to be too much of a problem in the long run what you can do is use the sync with inputs method and add on top of that the peer also has it's own movement (I mentioned that the peer fights for control but with a low latency environment this can be enough to feel like there is no lag on the peer side while maintaining a persistent game state between the two).

    Keep up the good work mate, I look forward to seeing a demo

  • GenkiGenga

    That's a really good point - I hadn't considered collisions like that.

    I could always sync an upgrade, thought, couldn't I? (ie Upgrade.isTaken = 0, if overlap set to 1). I'll have to play around with that, for sure though. The game will be limited in that regard, anyway, so it won't be TOO much to figure out.

    Thanks for all your help, and I'll definitely keep you posted!

    Steve

  • No worries mate, a pleasure.

    You could sync the power-up and use the host to determine the collision, that would avoid the problem of both of them picking it up - but there will still be times where the peer sees them self pick up the object first but they don't have it (since it goes by what the host sees). There isn't really a perfect solution for peer to peer (other than designing the game around the shortcomings) but it is a small price to pay for a server-less gaming experience.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)