Page 1 of 2

Give yourself arrays

PostPosted: Mon Sep 26, 2011 10:33 am
by Fuzzy
Arrays are a pretty useful construct, and Bee Ant and I figure that talking about them might help you become more advanced in your skills. I'll start simple so that anyone that needs to catch up can.

For that reason we will use code written in the global code rather than the GE menu variable maker. To create an array of integers, type the following into the global script window.

Code: Select all
int enemyHealth[5];


This creates a global array of type int, named enemyHealth and gives it room for 5 integer numbers. You can create other types of arrays such as float, double, char and even Actor. We will deal with type actor last. You can also create 2d, 3d, 4d or any dimension of array, but 1d is the most flexible.

Arrays start counting(called the index) at zero. So that means that the last index is actually represented by 4. If you try to write outside the array you will get an out of bounds error.

You can set an array value by referencing it with a number after the name. Like this:

Code: Select all
enemyHealth[1] = 500;


and you can extract it a similar way.

Code: Select all
critterHealth = enemyHealth[1];


When you first create an array, its cells will be filled with random numbers(and not reliable random numbers either). So its smart to initialize them. I'll show you how.

Code: Select all
int enemyHealth[5] = {1, 2, 3, 4, 5};


So that is the basics of arrays. Lets see what Bee adds.

Re: Give yourself arrays

PostPosted: Mon Sep 26, 2011 11:09 am
by Bee-Ant
Here's how I use arrays...
#1 Global variables
Code: Select all
#define CharTotal 10    //define a fixed global variable value
char State[3][16]={"Stop","Walk"};    //define the player's state in string
char Direction[4][16]={"Left","Center","Right"};    //define the player's direction in string


#2 Attributes array
Code: Select all
int Atr[CharTotal][4]=    //define the character Attributes as [index][HP,Attak,Defense,Speed]
{
    100,125,90,100,    //Char1
    125,100,100,90,    //Char2
    90,100,100,125,    //Char3
    //etc
};
char Name[CharTotal][16]=    //define the character Name as [index][Name1,Name2,Name3,etc]
{
    "Char1","Char2","Char3", //etc
};


#3 How to use it on: Initiate player's attributes
For example you want to generate 3 (clonned) characters with random type. Player -> Create Actor -> Script Editor:
Code: Select all
int type=rand(10);    //get random number from 0 to 9, use it as the index
HP=Atr[type][0];    //get the HP value from Atr[index][hp,atk,def,spd]
Attack=Atr[type][1];
Defense=Atr[type][2];
Speed=Atr[type][3];


#4 How to use it on: Changing player's animations
First, set the animation code in Player -> Draw Actor -> Script Editor:
Code: Select all
char str[64];    //we need a local char variable to store string
sprintf(str,"%s%s%s",Name[type],State[walk],Direction[direct+1]);    //combine player Name+State+Direction, store it to "str"
ChangeAnimation("Event Actor", str, NO_CHANGE);    //change player animation according to "str"
x+=direct*walk*Speed/10;    //set the movement

In this case you have to have the following animation list:
  • Char1="Char1StopLeft","Char1StopRight","Char1WalkLeft","Char1WalkRight"
  • Char2="Char2StopLeft","Char2StopRight","Char2WalkLeft","Char2WalkRight"
  • Char3="Char3StopLeft","Char3StopRight","Char3WalkLeft","Char3WalkRight"
  • etc
Then, set the walking code in:
Player -> KeyDown -> Left -> ScriptEditor:
Code: Select all
walk=1; direct=-1;

Player -> KeyDown -> Right -> ScriptEditor:
Code: Select all
walk=1; direct=1;

Then, set the stopping code in:
Player -> KeyUp -> Left -> ScriptEditor:
Code: Select all
walk=0; direct=-1;

Player -> KeyUp -> Right -> ScriptEditor:
Code: Select all
walk=0; direct=1;


#5 How to use it on: Calculating the attack damage
For example you want to calculate the damage (with this formula-> damage=EnemyAtk*10/OwnDef) in Player -> Collision -> Enemy:
Code: Select all
int damage;
damage=Atr[collide.type][1]*10/Atr[type][2]; //or damage=collide.Attack*10/Defense;
HP-=damage;
if(HP<=0)//died action here


Actor variables list:
Code: Select all
int type,HP,Attack,Defense,Speed,walk,direct;


That's the base. You can expand it using the same style :)

Re: Give yourself arrays

PostPosted: Mon Sep 26, 2011 3:10 pm
by foleyjo
going to try and add something that I found helpful

If you want to use a variable to specify how many blocks the array holds it needs to be constant

Code: Select all
const int number = 10;
int array[number];

Re: Give yourself arrays

PostPosted: Tue Sep 27, 2011 1:16 am
by Fuzzy
foleyjo wrote:going to try and add something that I found helpful

If you want to use a variable to specify how many blocks the array holds it needs to be constant

Code: Select all
const int number = 10;
int array[number];


Thats a good safety measure.

Re: Give yourself arrays

PostPosted: Tue Sep 27, 2011 8:27 am
by CoFFiN6
This stuf is GOLDEN!!

Re: Give yourself arrays

PostPosted: Tue Sep 27, 2011 9:00 am
by foleyjo
Going to expand on what I said and show how it can be useful

Fuzzy said
Fuzzy wrote:When you first create an array, its cells will be filled with random numbers(and not reliable random numbers either). So its smart to initialize them. I'll show you how.

Code: Select all
int enemyHealth[5] = {1, 2, 3, 4, 5};




Now what if there were 100 characters. A for loop would be handy to add the values at the start of the game(Maybe in an initialize function called at the very start of the game)

Code: Select all
for (i  = 0; i<100;i++)
{
  enemyHealth[i] = i+1;
}


Now what if you had different for loops through your code. Everytime you add a new enemy you would need to change the values in each loop. 1 method to use is a constant variable. Then you just need to update the Enemies value each time

Declaration
Code: Select all
const int Enemies 100;
int enemyHealth[Enemies]

loop
Code: Select all
for(i=0;i<Enemies;i++)
{enemyHealth[Enemies] = i+1}


An alternative would to be use #define instead of the const int.

Re: Give yourself arrays

PostPosted: Tue Sep 27, 2011 9:54 am
by Bee-Ant
Here, my function for Item and Weapon management using arrays. Maybe useful for RPG developer :)
Code: Select all
const int MAX_SLOT=99;
char stuff_name[MAX_SLOT+1][32];
int stuff_atr[MAX_SLOT+1][2];
int item=0;
int weapon=1;
void delete_stuff(char*A,int type) //A is the stuff name
{
    int i,index;
    for(i=0;i<MAX_SLOT;i++) //search the stuff index
    {
        if(!strcmp(stuff_name[i],A)&&stuff_atr[i][0]==type)
        {
            index=i;i=MAX_SLOT; //gotcha
        }
    }
    strcpy(stuff_name[index],"");stuff_atr[index][0]=0;stuff_atr[index][1]=0; //delete the stuff
    for(i=index;i<MAX_SLOT;i++) //re-sort the stuff list
    {
        strcpy(stuff_name[i],stuff_name[i+1]);
        stuff_atr[i][0]=stuff_atr[i+1][0];
        stuff_atr[i][1]=stuff_atr[i+1][1];
    }
}
void use_stuff(char*A,int type,int amount) //A is the stuff name
{
    int i,index;
    for(i=0;i<MAX_SLOT;i++) //search the stuff index
    {
        if(!strcmp(stuff_name[i],A)&&stuff_atr[i][0]==type)
        {
            index=i;i=MAX_SLOT; //gotcha
        }
    }
    if(stuff_atr[index][1]>amount)
    {
        stuff_atr[index][1]-=amount; //use if current amount higher than the requested amount
    }
    if(stuff_atr[index][1]==amount)
    {
        delete_stuff(A,type); //delete if the current amount equal with the requested amount
    }
    if(stuff_atr[index][1]<amount)
    {
        //you can add some alert that the requested amount higher than the current amount here
    }
}
void add_stuff(char*A,int type,int amount) //A is the stuff name
{
    int i,index=MAX_SLOT+1;
    for(i=0;i<MAX_SLOT;i++) //search the last/empty stuff index
    {
        if(!strcmp(stuff_name[i],""))
        {
            index=i;i=MAX_SLOT; //gotcha
        }
    }
    if(index<MAX_SLOT+1) //if the slot isn't full yet, add the item
    {
        strcpy(stuff_name[index],A);
        stuff_atr[index][0]=type;
        stuff_atr[index][1]=amount;
    }
    if(index==MAX_SLOT+1) //if the slot is already full
    {
        //you can add some alert here
    }
}

Re: Give yourself arrays

PostPosted: Tue Sep 27, 2011 9:30 pm
by Game A Gogo
Fuzzy wrote:When you first create an array, its cells will be filled with random numbers(and not reliable random numbers either).


I just want to clarify, the numbers are not actually random, but previous values that were there in the memory space the array now is allocated at. If you just opened your computer, these numbers will most likely be 0, if you let your computer on for a few days now these would probably not be zero! as other programs would of have used this space in memory. As declaring a variable only means you're associating a certain space in your memory to that name, so you can access it without addressing it

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 6:17 am
by Fuzzy
Game A Gogo wrote:
Fuzzy wrote:When you first create an array, its cells will be filled with random numbers(and not reliable random numbers either).


I just want to clarify, the numbers are not actually random, but previous values that were there in the memory space the array now is allocated at. If you just opened your computer, these numbers will most likely be 0, if you let your computer on for a few days now these would probably not be zero! as other programs would of have used this space in memory. As declaring a variable only means you're associating a certain space in your memory to that name, so you can access it without addressing it


Nice clarification of why they are not reliable in their default value Gogo.

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 11:02 am
by lcl
Since we are now talking about arrays, I thought I'd send my integer array reseting function here.
Code: Select all
void resetArray(int * array, int lim)
{
     int i;

    for (i = 0; i < lim; i ++)
    {
        array[i] = 0;
    }
}

Usage:
Code: Select all
resetArray(myArray, 25);

That would reset an int array named myArray until the 25th cell. :)

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 11:33 am
by Game A Gogo
lcl wrote:Since we are now talking about arrays, I thought I'd send my integer array reseting function here.
Code: Select all
void resetArray(int * array, int lim)
{
     int i;

    for (i = 0; i < lim; i ++)
    {
        array[i] = 0;
    }
}

Usage:
Code: Select all
resetArray(myArray, 25);

That would reset an int array named myArray until the 25th cell. :)


Code: Select all
void resetArray(int * array)
{
     int i;

    for (i = 0; i < sizeof(array)/4; i ++)
    {
        array[i] = 0;
    }
}


just a little optimization, no need to specify a limit :)
since int's are 4 bytes long, an array of [10] would be 40 bytes long. sizeof() returns the size in bytes of something

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 11:51 am
by Fuzzy
lcl wrote:Since we are now talking about arrays, I thought I'd send my integer array reseting function here.
<snip>


That is a nice little function lcl. I was hoping people would post stuff like that in the topic.

Have you considered modifying it so that using zero or NULL for lim causes the function to use sizeof(array) instead? It would be an easy way to clear the whole thing.

Code: Select all
#define CLEAR NULL

void resetArray(int * array, int lim)
{
     int i;
     int stop = lim;

     if (stop == CLEAR)
     {
          stop = sizeof(array)/sizeof(int);
     }

    for (i = 0; i < stop; i ++)
    {
        array[i] = 0;
    }
}


usage:
Code: Select all
resetArray(myArray, CLEAR);


Hope you dont mind my modification. Untested but it should work. I added the stop variable so that I wasnt potentially modifying the lim value.

I like your function with its short list of parameters. If I needed more versatile function, such as slice resets or set to value, I would probably write a second function.

You can fake simple function headers with define. Lets say the complicated header looks like this:

Code: Select all
void setArray(int * array, int start, int lim, int setval)


Then:
Code: Select all
#define resetArray(array, lim) setArray(array, 0, lim, 0)
#define fillArray(array, value) setArray(array, 0, NULL, value)


usage:
Code: Select all
[code]resetArray(myArray, CLEAR);[/code]


Untested... but three functions for the price of one. I wouldnt advise going crazy with this technique though, as it makes it hard to bug hunt. Also the "functions" do not show up in the GE function list. You could also make wrapper functions that call setArray.

Code: Select all
void resetArray(int * array, int lim) { setArray(array, 0, lim, 0);}


And that might be better.

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 11:51 am
by lcl
Wow, nice GAG! :)
I tried to do it with sizeof() but I didn't know that int is 4 bytes.. :oops:
I should try to learn more about bytes.

EDIT:
Thanks Fuzzy!
That was really helpful!

Actually I wrote that function yesterday and thought it won't work but tested it today, and was
happy to see it did work. I hadn't use pointers for ints before and wasn't sure if it was possible.

Thank you for your help! :)

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 11:55 am
by Fuzzy
lcl wrote:Wow, nice GAG! :)
I tried to do it with sizeof() but I didn't know that int is 4 bytes.. :oops:
I should try to learn more about bytes.


It will only take a byte of your time.

Check my version for a 32/64 bit safe version.

Re: Give yourself arrays

PostPosted: Wed Sep 28, 2011 12:01 pm
by lcl
Fuzzy wrote:Check my version for a 32/64 bit safe version.

Oh, wow that's smart!