Page 1 of 1

Making game as school project

PostPosted: Tue Feb 12, 2013 11:08 am
by Ravenshood
As the title says, I am making a game as a school project.
I decided to make it whit game editor because I have gotten used to GE while making some small amateur games.
The game that I am making as a school project is Turn-based RPG whit Tile-based movement and top down view. I have not decided what is the theme as of yet.

Current issue: I need to make an AI to move the enemy actor, but I am not sure how to handle any obstacles (such as the wall). I can make it stop on them, but to make them go around rocks seems lot harder. So, how to I make the enemy go around a wall to reach you?

P.S.
If my code seems to be done all wrong, please tell me now.
This is also my first post so I am not completely sure if I am at the right place in these forums.
Sorry for my English, not a native speaker.

Re: Making game as school project

PostPosted: Tue Feb 19, 2013 11:07 am
by moonforge
Okay... That's some pretty advanced code in your player actor...

If you want your enemy to move, you just need to make it so that on key up, it makes a move (kind of like your character) depending on where your character is relevant to the enemy. Basically, you'll need to use variables ting.x, ting.y, enemy.x, and enemy.y. These variables show the x and y coordinates of your actors. What you'll need is some if statements on the enemy to show if the player (ting.x and ting.y) are greater or lower than its current x and y. It will then need to move based on that decision. For the wall, it gets a bit trickier. There are a few ways to handle that problem.

First, you could subtract wall.x -enemy.x and if it is really small, don't allow movement to the left or something, but that gets complicated. The other option would be having four region actors where the enemy could be next to the wall. These would affect the enemy when it touches them, so that the enemy cannot move to the left, or down, or right, ect.

~moonforge

Re: Making game as school project

PostPosted: Fri Feb 22, 2013 3:55 am
by bamby1983
EDIT: I have created a more detailed tutorial on this along with additional options on what the AI actor would do if the player moves out of range. You can read this tutorial here.

Hi Raven,

If you're looking to make the AI controlled actor move to the player controlled actor AND there is some way he can actually get there (which means the AI actor is not totally sealed off), then you can achieve this using the techniques described below.

First, you will need to understand how to set up basic pathfinding for your actors. This tutorial explains how to do this in detail. Just remember to use clones with animations instead of clone arrays as highlighted at the start and end of this tutorial.

Once you know how to do this, the rest is really simple. The AI actor only needs to figure out:
1) When to move
2) Where to move

You can achieve both these in a single, easy step. The following code shows how (I'll explain WHERE to use this code later in this thread).

Code: Select all
if ( distance(Soldier.x, Soldier.y, AI_Actor.x, AI_Actor.y)<=170) {
    MoveTo("AI_Actor", 0, 0, 2.5, "Soldier", "Avoid_This");
                                                                  }


The IF-Statement in the above code checks whether the two actors are close enough to initiate the move. I've used a distance of 170 pixels in the above example, but you can replace this value with anything you require. When the distance between the two actors is less than or equal to the specified distance, the AI actor will start moving towards the player controlled actor (which, in this example, is a Soldier).

The MoveTo function consists of the following parameters:
"AI_Actor" - This is the actor that will be moving
0, 0 - These are the relative X and Y co-ordinates of the actor we will be following
2.5 - This is the speed at which the AI actor will move. I've kept this value 0.5 lower than the player controlled actor so the player can outrun it and so that the AI actor does not stick like a leech to him after reaching him
"Soldier" - This is the player controlled actor that the AI actor will be following
"Avoid_This" - This is the set of cloned objects that will serve as the obstacles to be avoided. In case of this example, they are walls


Now for the but about WHERE to use this code. There are two places you can use this code.

The first is in the "Draw" event. This event executes every frame so long as the actor to which it is assigned is visible on the screen. Using the above code here ensures that the AI actor follows the player's path as closely as possible. It is also the easier of the two methods but has one major drawback. Because the MoveTo command is called every frame, the AI actor tends to move into the actor to be avoided (in this case, the walls) and tends to get stuck there at times. This is due to a bug in this command. This is the main reason why I do not recommend this method although it is easier than the next one.

The second method is the one that I recommend. Create a timer with a duration of 500 (the time is in milliseconds so this is equal to half a second) and set it to recur indefinitely. This timer should be created using the "CreateTimer" function in script editor. The event that causes this timer to be created is the AI actor's "Create Actor" event. This means that as soon as the AI Actor is created (which means that it exists in the game), the timer will execute every half a second. Place the code provided earlier in this post in the Timer event (let me know if you need help with how to work with Timers). The code will execute every 0.5 seconds, which means that the AI actor will follow the player as before but any course correction will take 0.5 seconds to occur. In practice, this is a small amount of time and actually adds a feeling of realism to the game as it doesn't appear unrealistically snappy. Most importantly, this approach eliminates the bug encountered in the first method because the MoveTo function is no longer called on every frame. The result is smooth pathfinding with realistic course correction.

I have tested all that I wrote above and confirmed that it worked as expected. The attached zip file contains a working version of the above example using the second method (which involves a timer). You can left-click a spot on the floor (NOT the walls) to make the player controlled actor (the soldier) move there. Try moving the soldier to the top right corner of the passageway (the AI-controlled actor - the guy in the blue shirt - is on the other side with a small bathroom with checked tiles between the two). When the distance between the two is less than 170 pixels, the guy in the blue shirt (the AI actor) will follow the soldier by walking around the walls and through the doors. Even if you move the soldier away into another room, the AI actor will keep following him until the distance between the two exceeds 170 pixels. Even then, the AI actor will continue moving until the point that corresponds to the soldier's position when he was last 170 pixels away. If you do not want this to happen, you can do either of the following:
1) Add an "else" statement telling the AI actor to either stop moving (use the same MoveTo function with "AI_Actor" in place of "Soldier" so he moves to 0,0 relative to his own position - which means he stops moving)
2) Use different co-ordinates with the view actor or Game center as reference if you want the AI actor to return to a predefined point on the map.

Re: Making game as school project

PostPosted: Fri Feb 22, 2013 4:27 pm
by bamby1983
I just wanted to add that I have now created a more detailed tutorial on this along with additional options on what the AI actor would do if the player moves out of range. You can read this tutorial here and ignore my post above if you haven't read it already.

Re: Making game as school project

PostPosted: Mon Feb 25, 2013 10:50 am
by Ravenshood
moonforge wrote:Okay... That's some pretty advanced code in your player actor...

If you want your enemy to move, you just need to make it so that on key up, it makes a move (kind of like your character) depending on where your character is relevant to the enemy. Basically, you'll need to use variables ting.x, ting.y, enemy.x, and enemy.y. These variables show the x and y coordinates of your actors. What you'll need is some if statements on the enemy to show if the player (ting.x and ting.y) are greater or lower than its current x and y. It will then need to move based on that decision. For the wall, it gets a bit trickier. There are a few ways to handle that problem.

First, you could subtract wall.x -enemy.x and if it is really small, don't allow movement to the left or something, but that gets complicated. The other option would be having four region actors where the enemy could be next to the wall. These would affect the enemy when it touches them, so that the enemy cannot move to the left, or down, or right, ect.

~moonforge



That actually seems like the best idea. Making variables like wall.x and wall.y and then using them to make the enemy go around stones. only problem I see there is that there will be a lot to type but life ain't easy anyway.
I will try using that as soon as I can wrap my head around it.

bamby1983 wrote:I just wanted to add that I have now created a more detailed tutorial on this along with additional options on what the AI actor would do if the player moves out of range. You can read this tutorial here and ignore my post above if you haven't read it already.


While your tutorial is good, it sadly does not explain how do i make enemy pathing when the game is tile-based

Re: Making game as school project

PostPosted: Tue Feb 26, 2013 1:43 am
by bamby1983
Aah I didn't realize it was tile based. :(

Well in that case you're best of using moonforge's method. If you wanna make it easier and your grid is uniform, you could always write a code to automatically detect the x and y values of obstacles (like walls, stones, etc.) and automate the subtraction process.

As a guideline, here's something you can use to base the automation code upon. For the following code to work, all obstacles will have to be clones of the same actor. The can have different animations though. The cloning is a requirement to make the automation code below easier to create. For the purpose of the example, we will assume that the obstacle actor is named "Obstacle" and the clones will be Obstacle.0, Obstacle.1 and so on.

The following code would need to be added to the "Create Actor" event of the "view" actor so that it is called as soon as the game begins.

Code: Select all
int obstacles_num=10; // Number of obstacles in the game file - change this to adjust the number of obstacles in your game
int obstacle_x[obstacles_num]; // List of X-Coordinates of obstacles
int obstacle_y[obstacles_num];// List of Y-Coordinates of obstacles

void initObstacles() { // Initializing values of obstacle co-ordinates
   
    int i;
    char actor_name[30]; // For dynamic actor name creation
    for (i=0;i<=obstacles_num-1;i++) { // The "-1" is because the array index starts from zero although we count the number of obstacles starting from the number 1
    sprintf(actor_name, "Obstacle.%d", i); // Creating actor name dynamically
   obstacle_x[i]=getclone(actor_name)->x; // Fetch the X co-ordinates of the clone
   obstacle_y[i]=getclone(actor_name)->y; // Fetch the Y co-ordinates of the clone
                                                     }
                              }


You can then fetch the value of the obstacle co-ordinates using the obstacle_x[] and obstacle_y[] arrays above. The array index will be the same as the clone number, which can be fetched using the "cloneindex" variable. If your grid is uniform, it should be easy to figure out an equation to find the grid square based on these co-ordinates.

You will still need to find a way to tell the AI actor how to circumvent the obstacle, though. That will need additional coding in addition to that explained above.

Re: Making game as school project

PostPosted: Fri Mar 01, 2013 8:49 am
by Ravenshood
I must ask one thing before i start the coding. Which way is better?
Having one big IF statement:
Code: Select all
if(player.X>X && player.Y>Y && player.X-X>=player.Y-Y && X+1 != wall.X)
{
     X++;
}


or to have it in multiple IF statements inside each other:
Code: Select all
if(player.X>X)
{
     if(player.Y>Y)
     {
          if(player.X-X>=player.Y-Y)
          {
               if(X+1 != wall.X)
               {
                    X++;
               }
          }
      }
}


Which one is better?

Re: Making game as school project

PostPosted: Fri Mar 01, 2013 9:13 am
by skydereign
One big if is better. Since you are using &&, it runs through them from left to right and if any of one of them is false, than the entire thing is false (so it doesn't have to continue checking the if statements). Therefore, you don't get any extra edge by nesting the if statements. But now, what if you want something to happen if that condition is false? You can't do that with the broken up if very cleanly. So, sticking with the bigger if makes more sense.

Re: Making game as school project

PostPosted: Fri Mar 01, 2013 9:42 am
by Ravenshood
skydereign wrote:One big if is better. Since you are using &&, it runs through them from left to right and if any of one of them is false, than the entire thing is false (so it doesn't have to continue checking the if statements). Therefore, you don't get any extra edge by nesting the if statements. But now, what if you want something to happen if that condition is false? You can't do that with the broken up if very cleanly. So, sticking with the bigger if makes more sense.


Ok. Thank you for the help and also great thanks for making the code originally! I never would have been able to even start this project if it were not for the code you made! :mrgreen:

Re: Making game as school project

PostPosted: Fri Mar 01, 2013 9:47 am
by skydereign
Ravenshood wrote:Ok. Thank you for the help and also great thanks for making the code originally! I never would have been able to even start this project if it were not for the code you made! :mrgreen:

I'm glad it could help. Though looking back at the code, it could/should have been done a lot better/cleaner. But it was enough to get you started, so that's good.

Re: Making game as school project

PostPosted: Tue Mar 12, 2013 11:35 am
by Ravenshood
Just a quick question.
Are the switch statements unneeded in the following code?:
Code: Select all
if(ting.Y==Y && ting.X-1>X)
   {
      if(Y==wall.Y && X+1 == wall.X)
      {
         switch(tilegrid[X][Y+1])
         {
            case 0:
            tilegrid[X][Y]=0;
            Y++;
            break;
         }
      }
      else
      {
      switch(tilegrid[X+1][Y])
         {
            case 0:
            tilegrid[X][Y]=0;
            X++;
            break;
         }
      }
   }

Re: Making game as school project

PostPosted: Tue Mar 12, 2013 5:28 pm
by skydereign
Ravenshood wrote:Just a quick question.
Are the switch statements unneeded in the following code?:

They aren't redundant necessarily, if that is what you mean. You can either convert them into an if statement or restructure the code if you want. But those switch statements are checking to see if moving right/down is free, and moving in that direction. You are the one working on the game, so you should know what the values stand for and how they act in the game.

Re: Making game as school project

PostPosted: Mon Mar 18, 2013 10:21 am
by Ravenshood
So I finally got the AI for the enemy done, but it only works when there is only one enemy and only one wall piece. It stops moving on the sides of additional walls or any other enemies. How could i fix this?

Re: Making game as school project

PostPosted: Mon Mar 18, 2013 6:34 pm
by skydereign
I would highly recommend refactoring the enemy's draw actor script and using functions. You have eight or so chunks of pretty much the same code, which makes it rather hard to tinker with. You'll probably fix the problem as well by doing that.