Multiplayer Enemy AI

0 favourites
From the Asset Store
Pixel Enemies for SHMUP consists of 45 enemy ship sprites to be used in your game.
  • Hello again,

    I have been building a simple multiplayer game. The objective of this RPG game is to play with up to three other people to defend against endless waves on enemies. I need help with the enemy AI. Here are some links to previous threads regarding the same game: construct.net/en/forum/construct-3/how-do-i-8/help-advanced-multiplayer-149654/page-3 construct.net/en/forum/construct-3/how-do-i-8/mulitplayer-room-selection-151339

    Here is the link to the project: dropbox.com/s/5z3c9o8y1zi4zrp/Wardens%20%285%29.c3p

    The enemies and player attacking are both somewhat broken. If the host attacks an enemy, it will get knocked back and take damage. Enemies will be killed upon running out of health. But if the host attacks two at once, only one will get knocked back and take damage, and the other one will become invincible. The peer cannot do any damage, probably because he or the enemies are not synced right. For the enemies, they will hop towards the crystal stand unless they get attacked. Then they are supposed to attack the last peer that hit them. For some reason they will not attack the peers; they will not move at all after being struck.

    Thanks in advance,

    Give me a Pixel

  • bump.

  • Can someone help me? AlceX, lennaert, , fredriksthlm, Ashley, newt?

    Sorry if I did not reference you here directly. You can still help me. Most of these people helped me previously with multiplayer.

  • I cannot help you with the enemy AI in your game sorry. Personally I have only used the Photon plugin, not the official multiplayer plugin in any project.

    My tip is, before creating an actual game, just try to fully understand the plugin you want to use. How to send messages correctly and what you need to sync and how.

    (It's a bit odd to just reference some random users and ask for help. But good luck!)

  • Thanks anyway. I've been waiting for a while and just want to get this game finished and published. Do you have any other ideas how to get help quickly?

  • bump.

  • But if the host attacks two at once, only one will get knocked back and take damage, and the other one will become invincible.

    This one is easy and isn't a multiplayer quirk! When the host overlaps two enemies, your Enemy_Hurt function is only running for one of the instances. This is because functions called on picked instances will only be called for ONE of the picked instances. If you want to have a function run for each picked instance you need to add a For Each before you run the function

    The reason the not-damaged enemy becomes invincible is because every action BEFORE the function IS able to run on all picked instances, meaning the enemy's Hurt variable is being set to 1, but he's not running the Enemy_hurt function, and so his Hurt never returns to 0

    The peer cannot do any damage, probably because he or the enemies are not synced right.

    In your code you have it so when the Peer is overlapping an enemy AND the peer's input 4th bit is set to 1, the peer will damage the enemy. The problem is with the 4th bit never being set to 1 by non-host peers. Here's where the problem is in your code:

    + Touch: On tap gesture on Attack_Button

    ----+ System: getbit(Peer.inputs, 4) = 0

    -----> Peer: Set Inputs to setbit(Self.inputs, 4, 1)

    You're not specifying that the peer should be checking and setting the bits for THEIR peer. Since you don't specify, the code is probably picking the first instance, which is the host's peer object. This is why it works for the host, because they are accidentally picking their own peer

    Also, most of your enemy code should be in the Host group. You don't want peers running logic for the enemies because things can happen differently on the Host's computer and the Peer's computer, resulting in mismatches game states and weird glitches. The peers should only be TOLD what is happening by the host (using the object syncing and via messages)

    For the enemies, they will hop towards the crystal stand unless they get attacked. Then they are supposed to attack the last peer that hit them. For some reason they will not attack the peers; they will not move at all after being struck.

    This is another problem that is not multiplayer-specific but is just how C3 works. Here's the code where the problem is:

    + Enemies: Hurt = 0

    ----+ Enemies: Last_Hit_PeerID = ""

    -----> Enemies: Set 8Direction vector X to cos(angle(Self.X,Self.Y,Crystal.X,Crystal.Y)) × Self.8Direction.Maxspeed

    -----> Enemies: Set 8Direction vector Y to sin(angle(Self.X,Self.Y,Crystal.X,Crystal.Y)) × Self.8Direction.Maxspeed

    ----+ System: Else

    ----+ Peer: PeerID = Enemies.Last_Hit_PeerID

    -----> Enemies: Set 8Direction vector X to cos(angle(Self.X,Self.Y,Peer.X,Peer.Y)) × Self.8Direction.Maxspeed

    -----> Enemies: Set 8Direction vector Y to sin(angle(Self.X,Self.Y,Peer.X,Peer.Y)) × Self.8Direction.Maxspeed

    I'll translate what is happening

    Pick ALL enemies where Hurt = 0

    From those enemies, go through them all and check which ones have a Last_Hit_By_Peerid variable that is set to ""

    For THOSE enemies, run movement logic

    NOW we skip past the 'else' because the first condition was met. There were enemies that had a Last_Hit_By_Peerid variable that is set to "", so the condition was true and the 'else' is skipped. You probably expected your code to treat all the enemies with an empty variable one way and all the other enemies another way. What actually happened is if there are ANY enemies who match the first condition, the second is skipped entirely

    To fix this you have some options

    1. Remove the else (This will go through your group of Hurt = 0 Enemies twice. Once to check for enemies with an empty Last Hit By variable and another time to check for enemies WITH a valid Last Hit By Variable)

    2. Add a For Each after Enemies: Hurt = 0 (This will run through each Enemy seperately, one at a time, and you can leave the else)

    These options may have different impacts on performance, which you can test for yourself

    Hope this helps :)

  • Thank you so much! I will certainly try those out and tell how they worked out.

  • All right, I looked at it. The first and last problems were solved, but the middle problem i'm still a little confused on.

    You're not specifying that the peer should be checking and setting the bits for THEIR peer. Since you don't specify, the code is probably picking the first instance, which is the host's peer object. This is why it works for the host, because they are accidentally picking their own peer

    How can I set the bits for my peer only?

    Also, most of your enemy code should be in the Host group. You don't want peers running logic for the enemies because things can happen differently on the Host's computer and the Peer's computer, resulting in mismatches game states and weird glitches. The peers should only be TOLD what is happening by the host (using the object syncing and via messages)

    What code exactly should be put into the host group?

    Please pardon my ignorance, I don't have much experience with multiplayer. Thanks,

    Give me a Pixel

  • Also, would I need to add an more code while moving 'most' of the code to the host group? An example project or a screenshot would be nice if possible.

    Thanks again,

    Give me a Pixel

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • How can I set the bits for my peer only?

    You can pick your peer using Peer.Peerid = Multiplayer.MyPeerID

    What code exactly should be put into the host group?

    Anything that controls serious elements of the gameplay. The creation and destruction of enemies, collision detection for inflicting damage, etc

    The host should be running the only "real" version of the game. The host should be moving the enemies, deciding when they've collided with peers, damaging them, destroying them, etc. The peer does not control any of this and must only receive information from the host describing what is happening

  • Well, thanks. I'll see what I can do.

  • I'm sorry man but I'm hopeless. I used the 'Peer.PeerID = Multiplayer.myID' expression and now the peer can damage enemies. The problem is that he cannot see their position or where he kills or damages them. I did move all the current enemy code into the host group. I need help syncing the enemies and telling the peer where they are and all the other stats. I think it would be easier if you just took the newest update (https://www.dropbox.com/s/qsja87myioo8p2r/Wardens%20%286%29.c3p?dl=0) and just modified it and shared it.

    Sorry this is taking so long, so thanks again,

    Give me a Pixel

  • bump.

  • You're not hopeless, multiplayer is just tricky

    The multiplayer code was actually fine, it ended up being a layer issue. I opened the debugger and saw that the peer did in fact have enemies spawning, but the enemies were invisible. The debugger said they were 100 opacity and Visible though, so I checked their layers and they were on the Collision layer while the Host's enemies were on the Object layer. I just added "Move Enemies to "Object" Layer" under common and it fixed

    I made 2 other changes:

    1. Made it quicker to login (so you can test faster)

    2. Moved your enemy spawn logic from under "Waves" group to under "Host" group

    I don't know if you read the multiplayer tutorial in full but I would recommend going through it. Multiplayer can be very complicated. It's good to know the core concepts like the difference between the Host and Peer: construct.net/en/tutorials/multiplayer-tutorial-1-concepts-579

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