Showing posts with label Tutorial. Show all posts
Showing posts with label Tutorial. Show all posts

Wednesday, May 22, 2013

Using Dynamic Arrays in UnrealScript

Dynamic Array is a collection of data items that can be resized during the execution of the game.

A Dynamic Array is a variable type declared as follows:

var array < arrayType > arrayName ;

The array type can be primitives such as int and float or any class such as Actor and Pawn.

A Dynamic Array can also be defined as local variable within a function using the keyword "local".

The current size of a Dynamic Array can be found in their Length attribute. Access to the individual elements of a Dynamic Array can be done with an index in the same way as in a static array. Remember that the index of an array always starts from 0.

A simple example using Dynamic Array:
class EnemyTypes extends Actor;

var array <int> enemyTypeList;


function int getEnemyType(int index)
{
    if(index < 0 || index >= enemyTypeList.Length) 
    {
        return -1;  // Error: Invalid Index
    } 
    else 
    {
        return enemyTypeList[ index ];
    }
}

function setEnemyType(int index, int enemyType)
{
    if(index >= 0 && enemyType >= 0)
    {
        enemyTypeList[ index ] = enemyType;
    }
}

Note that in the above example, in the function setEnemyType(), there is no problem if the index is greater than the current size of the array, because a Dynamic Array will increase its size to store the required index.

There are some functions that are part of a Dynamic Array. Below are the main ones:

  • AddItem( Element ): Adds an Element to the end of the Dynamic Array. The Element must be the same type of the Dynamic Array.
  • RemoveItem( Element ): Removes an Element of the Dynamic Array.
  • InsertItem( int Index, Element): Inserts an Element in the Dynamic Array at the specified index.
  • Find( Element ): Search for the Element within the Dynamic Array and returns the index of the found element, or "-1" if not found.

I did an example that creates a random amount of Shield Belts (class UTGameContent.UTDroppedShieldBelt) in random positions. The Shield Belts instances that were created are added to a Dynamic Array. After creating all Shield Belts, the Dynamic Array is iterated using the ForEach operator to register in the Log the position of each Shield Belt created.

Code and image of this example:
class TestDynamicArrays extends UTGame;

var array <UTDroppedShieldBelt> shieldList;

function StartMatch()
{
    local UTDroppedShieldBelt shieldInstance;    
    local vector shieldLocation;
    local int totalShields;    
    
    super.StartMatch();

    totalShields = 10 + Rand(10);     
    
    do
    {
        //Choose a random position
        shieldLocation.X = -1000 + Rand(2001); //-1000 to 1000;
        shieldLocation.Y = -1000 + Rand(2001); //-1000 to 1000;
        shieldLocation.Z = 50 ;
    
        shieldInstance = spawn(class 'UTGameContent.UTDroppedShieldBelt', , ,shieldLocation);
        
        shieldList.addItem( shieldInstance );        
                
    } until ( shieldList.Length == totalShields ) ;
    
    `Log("TOTAL OF SHIELDS =" @ shieldList.Length);
    
    //write in the log the position of all shields
    foreach shieldList( shieldInstance )
    {
      `Log( "Location =" @ shieldInstance.Location );
    }
}


This log shows what was registered in one of the executions of the example.
[0294.02] ScriptLog: TOTAL OF SHIELDS = 18
[0294.02] ScriptLog: Location = -390.00,183.00,50.00
[0294.02] ScriptLog: Location = -946.00,-300.00,50.00
[0294.02] ScriptLog: Location = -101.00,133.00,50.00
[0294.02] ScriptLog: Location = 225.00,701.00,50.00
[0294.02] ScriptLog: Location = 611.00,-908.00,50.00
[0294.02] ScriptLog: Location = -650.00,-532.00,50.00
[0294.02] ScriptLog: Location = -550.00,449.00,50.00
[0294.02] ScriptLog: Location = -245.00,531.00,50.00
[0294.02] ScriptLog: Location = 307.00,-890.00,50.00
[0294.02] ScriptLog: Location = -14.00,-534.00,50.00
[0294.02] ScriptLog: Location = -191.00,101.00,50.00
[0294.02] ScriptLog: Location = -756.00,832.00,50.00
[0294.02] ScriptLog: Location = 796.00,390.00,50.00
[0294.02] ScriptLog: Location = -833.00,-915.00,50.00
[0294.02] ScriptLog: Location = 780.00,-248.00,50.00
[0294.02] ScriptLog: Location = 492.00,841.00,50.00
[0294.02] ScriptLog: Location = 461.00,-526.00,50.00
[0294.02] ScriptLog: Location = 179.00,-266.00,50.00

Monday, April 15, 2013

Iterating with ForEach in UnrealScript

Before talk about iteration let's imagine an example. Say you built a game that in the levels there are several UTWeaponPickupFactory actors, but only one of them will have a special behavior that will be programmed in UnrealScript.

The UTWeaponPickupFactory class is found in this class hierarchy:



For this example I will place in the level several UTWeaponPickupFactory actors as shown in the image below.



I selected one of the UTWeaponPickupFactory actors, opened the Properties Window (F4 key) and set the "Tag" property with the value SPECIAL_FACTORY. This Tag property is in the Object category as seen in this image.


When starting the game we need to iterate through all the UTWeaponPickupFactory actors until find the one that has the value SPECIAL_FACTORY in the "Tag" property. When find it we will store the object reference of the current UTWeaponPickupFactory actor to be able to handle it in UnrealScript.

That's what this code does.
class TestIteration extends UTGame;

var UTWeaponPickupFactory SpecialFactory;

function StartMatch()
{
    local UTWeaponPickupFactory factory;
   
    Super.StartMatch();
   
    foreach DynamicActors( class'UTWeaponPickupFactory', factory )
    {
       
      if( factory.tag == 'SPECIAL_FACTORY' ) 
      {
        SpecialFactory = factory;
        break;     // Ends the search
      }
    }
    
    Broadcast( self, " Object Name =" @ SpecialFactory.name) ;    
}

To test this code in UDK set the Game Type to "TestIteration". (UDK Menu: View -> WorldProperties -> Game Type

The "foreach" command works with one type of function known as Iterator. These functions have two parameters, the first parameter specifies the type of actor that it should search and the second is a variable that will receive the reference of the current actor in each iteration.

DynamicActors() is the most used iterator function. It searches in the Actors that are not StaticMeshActor. There are several other iterator functions. The main iterators are declared together in the Actor class, just search for "iterator" in the file Actor.uc.

There are other important iterators declared in the WorldInfo class (Actor->Info->ZoneInfo->WorldInfo). To use them you need to put a variable of the type "WorldInfo" in front of the iterator function name. All Actors have a "WorldInfo" variable. Code Sample:
//Extract from GameInfo.uc (Actor->Info->GameInfo)

function StartBots()
{
    local Controller P;

    foreach WorldInfo.AllControllers(class'Controller', P)
    {
        if (P.bIsPlayer && !P.IsA('PlayerController'))
        {
            if (WorldInfo.NetMode == NM_Standalone)
            {
                RestartPlayer(P);
            }
            else
            {
                P.GotoState('Dead','MPStart');
            }
        }
    }
}

Sunday, October 9, 2011

UDK Game Programming: UnrealScript

I'm starting a series of tutorials about UDK Game Programming with UnrealScript. The UDK (Unreal Development Kit) can be downloaded at this link: www.udk.com

UnrealScript is an object-oriented language like Java, but it has many new features targeted for the implementation of games.

Programming a new game with UnrealScript can be very complex, but as Lao Tzu said:

"A journey of a thousand miles must begin with a single step."