- Joined
- Jul 10, 2007
- Messages
- 6,306
These essays address how one would put standard programming concepts into JASS along with non-standard ones : P
These would work off of pretty simple systems that you could design for your own map or download from a site like the hive. These systems would be designed according to the concepts discussed in these essays.
Some of these could be inserted into vjass as well =).
Please feel free to comment or ask questions about programming concepts that you'd love to do in JASS but you have no idea how to do it.
Examples:
OpenGL done in JASS
Dynamic Classes done in JASS
C++ Memory Handling in JASS
Creating a C++ array in JASS
Maximizing speed using multi-threading techniques in JASS
feel free to ask anything you're curious about : )
Table of Contents - Search for these titles to jump from title to title
Multi-Threading Concept
Handling Memory Like C++
Multi-Threading Concept
Most of us know what a thread is and what it means to create multi-threading applications and systems for both inside and outside of warcraft 3, but for those who don't know, a thread is a stream of code (or calculations). To put it in more simpler terms, it can be described as car lanes on a road. When you have one lane, only one car can go through it at any given position. When you have 2 lanes, you can have 2 cars right next to each other both going through at the exact same time. This can go on. Now, there is something that has to be noted. Warcraft 3 doesn't let you create your own threads. You are allowed to run on threads that are already pre-defined. Your wants to use the threads are put into a stack. There are 6 threads per player. These aren't regular threads and wc3 doesn't let a user create a pre-defined thread. Another thing, the main function also runs on it's own thread so it's suggested that you never ever let the main function close. Put the thread to sleep or w/e. You can still maximize speed with multi-threading concepts (allocating your data to run as quickly as possible).
So, let's say you have 3 functions that are called within another function ,for example:
function randomstuff takes nothing returns nothing
call stuff1()
call stuff2()
call stuff3()
endfunction
Let's say that these 3 functions don't work off of each other and might as well go at once. We have 2 things which can make these go at once (one will add ugly code in the background, but is faster. The other allows for dynamic function calling using strings).
function randomstuff takes nothing returns nothing
call ExecuteFunc("stuff1")
call ExecuteFunc("stuff2")
call stuff3.execute()
endfunction
All three of these will start a new thread.
So, you're probably thinking at this point, threads are pretty cool and they can make my map run a lot faster! : O. Just imagine rewriting your main function in your map to be completely multi-threaded.
Well, while multi-threading can be awesome, you can't pass any information to these threads in JASS and there is no way for the function to wait for the new thread to finnish. So, let's analyze these issues.
1. Inability to send data to a new thread-
Eep
2. Unable to wait for new threads to finnish before continuing on
Example-
call ExecuteFunc("func1")
call ExecuteFunc("func2_that_needs_func_1")
In this example, func2 would start before func1 would get a chance to set the information up which would result in errors, crashes, and all sorts of fun things : D.
So, why not just call the function regularly in these cases?
Example-
call func1()
call ExecuteFunc("func2_that_needs_func_1")
Well, one issue you can have in this case is what could be called crashing a thread. Another thing is you can't maximize the speed. Let's say you only need the first 2 lines of function 1 to happen and then you can continue on to function 2. Let's say there are 100 lines of executed code in function one. That's 98 lines of code of wasted time.
So, how do we maximize speed? Well, what we can do is create a thread structure to connect our threads together.
Let's say we have a function called CreateThread, which creates a new thread structure and dynamically gives it a unique ID, so we could have like-
local integer ThreadID = ThreadTable.CreateThread()
In the background, CreateThread would be a method within ThreadTable that would auto generate our cache and so on for our new thread and store it in the global data structure called ThreadTable : o.
Ok, let's rewind here. Exactly what am I talking about when I'm saying ThreadTable, CreateThread, and so on. Threads are created via ExecuteFunc and .execute ><. Does the CreateThread Method use one of these things to create a new thread or what?
No, not really. What happens is if you were to create a design like this, you could set up a Global Thread Table that would initialize at the very start of the map. This thread table would contain function IDs (an array of various functions (strings)), storage arrays (storing units, integers, and what not), a boolean array (booleans to determine whether a thread is being used or not), and well, yea. So, what are these thread things we're talking about anyways?
Well, we know a regular thread is used to calculate information. When we're talking about thread tables and creating new threads in these cases, we're talking about mediums to transfer information between threads.
So wait? We can send local variables into other threads? that's impossible.
Well, the only work-around would be to either use the game cache or global variables. that's why we have our global structure for thread information.
So wait? When we create a new thread all we're doing is creating a space to store information and a pointer to it so we can access it later on?
Example-
Big Table
A pointer to the big table that's stored in a local variable
Well, if we do this, we get a pointer and what not to access our big table (like the indexes of the arrays), but how do we send this to the new function if we can't send any data at all?
Well, remember our function table? Well, can't we use that? So let's say we create a variable for each thread that stores a function ID.
So for example, like this
Thread[ThreadID].FunctionID = FunctionID in our Function Table
FunctionTable-
Function[1] = Our Spiffy Function
Function[2] = Our other spiffy function
Each index in the array would be the function ID
Now, when we start up a new thread that calls that function
call ExecuteFunc("Our Spiffy Function")
that function can start up by looking through all current threads that aren't being accessed and that contain its own function ID. So if we call 2 functions and have 2 pointers for those functions, they'll each get information for them.
Now, what does this mean? If you send data to a function within a new thread, that data won't necessarily make it to that specific function if another function that's the exact same would be called at once. So let's say you have 2 threads that are doing the same thing and they both start up new threads that do the same thing. Let's say we have an x1 and an x2 (thread1 and thread2). It could look something like this
Thread1- Sends x1 to Thread1New
Thread2- Sends x2 to Thread2New
Thread1New searches for an x1 with it's function ID, meaning it might either find x1 or x2
Let's say it finds x2
Thread1New closes off x2 so nothing else can retrieve it's info
Thread2New searches and because the only data that's left is x1, it recieves x1
Thread2New closes off x1 so nothing else can retrieve it's info
So
Thread1- Sends x1 to Thread1New
Thread2- Sends x2 to Thread2New
Thread1New recieves x2
Thread2New recieves x1
The data just jumped threads! : O. Yes, this is possible with a design like this. Does it really matter though? Let's say the functions do this
set y = y + x (x being the recieved data)
Let's say one piece of data applies it for like a treasure chest (increase the coins in it) and the other sends it to a bank (inceases the gold in the bank)
Well, since each function is the same, the properties for where to send it would be in the data
So let's say that in x1 and x2, there's a value, the integer that increases the gold, and a value of where to send the gold (either to the bank or to the treasure chest).
So now it turns like this
set y[xproperty] = y[xproperty] + x[value]
Now what this means is that it doesn't matter what specific instanced function receives the data so long as it's the same function. No matter what, the gold in the bank will go up and the gold in the treasure chest will go up by the right amounts.
So when we're sending data to a new thread, we really don't care which thread it goes to. All we care about is that it makes it to the right function : p, doesn't matter what thread the function comes from.
So, we learned how to send data in between threads and how to sort of design a basic system to do this. What exactly would the speed increase be for using a design like this?
Well, it really depends on how much code you're going through. A system like this would also prevent thread crashes because every function would get its very own thread. If you're just calling one function, it'd probably go slower with this system. If you're calling 30 functions, it'd go faster. It really depends on how much data you're handling.
Cool, so I'd only use a design like this for heavy data functions, like initializing 398230580348590 variables and creating a bundle of units or running a very complex combat system?
Well, yea... : p
But the functions still won't wait for the new threads to finish. How do I make them wait??
Well, remember our function state variable that closes off functions. When a new thread is created, you need to create different states for that thread.
State 0 = empty thread
State 1 = full thread waiting to be xfered
State 2 = received thread
Function States-
State 0 = Calculating data
State 1 = Finished calculating
This means that we can do 2 things to wait
Method #1:
If we want to wait for the thread to finish transferring, we'd just create a loop in the function that has a sleep timeout of .01 and just constantly checks the Thread's State for 0 using the ThreadID we got initially.
Method #2:
We store the original function's Function ID (the function calling the other function) into the Thread so that the called Function can call back on the original Function. From here we can create steps in the original function.
Example:
function1
checkstep (could be an if statement)
createthread
storedata
storestep (an integer)
call function2
function2
searchforthread
retrievedata
canstoredata
call function1
function1
checkstep
possibleretrievedata
possiblestoredata
call function3
etc etc
at the very end you'd have a DestroyThread, which would clear out the thread and remove it from the indexes and set its state to 0 .
Now you're probably thinking, jeezes, the timer would sure take up a lot. The steps seem kinda messy though if I use if statements.
Well, you don't have to use if statements : P. You could create a library of actions for each function within a data structure using methods and what not to make it really spiffy and organized.
So, now we know work-arounds for sending data in between threads and making functions wait for threads to finish sending data or for threads to totally finish up everything in them : D.
Would this be faster?
In some cases, yes, in some cases, no.
Is it worth it?
If you really want a spiffy as fast as possible map utilizing everything you can use, yes.
-------------------------------------------
Handling Memory Like C++
In C++, you can handle you own memory : D. What does this mean?
Well, variables are actually pointers to memory. They contain automatic index values of where the memory is stored. (not literally, but for our explanation on how to do this in JASS, yes)
It's really much like an array (not really, but for for the JASS design, yes)
Once again, this is an explanation for doing this in JASS****
Let's say that we have a variable called var and it contains a value of 3
The variable doesn't actually contain the value of 3, but rather a pointer to the place in memory where 3 is stored, almost like this.
(once again, this is dif from regular C++, C++, all 3 of these would be the same. C++ has a special thingie for retrieving the pointer to the memory. The normal variable would be the value that it points to in memory. You can set the memory value by changing the variable or the memory. In JASS, it works more like the below example) Yes, I'm inserting these little notes for people who are freaking out over my explanations .
var = 0
memory[var] = 3
In C++, you can either retrieve the 3 or you can retrieve the pointer value of 0. Now, how is this useful? Well, let's say you want to set variables dynamically. Let's say that a function can handle a type of data. Now, let's say we have 20 different global variables that are that type of data. We want to set a specific one.
Now, when passing information into functions (JASS), you can pass values and data types, but you can't pass variable names.
For example
integer x = 0
call function1(x)
That would not send the variable x into function1. It would just send the value of x, which is 0. Now, let's say we really wanted to pass the actual group of memory that x had into the function. Well, how can we do this in a scripting language???
Well, the way to do it is to set up our own C++ memory thing (This isn't like regular C++ memory, it's just a work-around to get very similar results) and to work all variables off of it. This means we create a huge array that I'm calling memory for now and we set all of our variables to contain indexes for that array. We also set our variable arrays to just contain indexes for that array + x, x being the index of our variable.
Here's a kinky example:
memory[0] = 0
memory[1] = 0
memory[2] = 0
variable1 = 0 (this accesses memory[0])
variable2[0] = 1+index (index is 0)
variable2[1] = 1+index (index is 1)
You're probably going, what's the point of this. Well, the point of this is passing actual variables through functions and not just their values. If we treat every variable as only a pointer to a piece of data and we use that pointer to access the data, then we can change that data because there's only one variable name. Here's an example.
set memory[variable1] = 10
call test(variabiable1,30)
function test takes integer variable1 returns nothing
set memory[variable1] = memory[variable] + 30
endfunction
Now, this seems pretty simplistic, but it makes it so you can manage your own memory (not literally, but similar) and allows you to pass actual spaces of memory (once again, not literally, but similar) into functions and not just values. How could this be useful? A lot of ways .
Hey, so now that we know how to do this, how can this play a role in everything? Well, let's say that we have a function that uses an equation to damage something dynamically in a combat system. Let's say there are 100 unique cases of units on the map each stored in their own little space of memory (memory where data structure is stored).
So one attacks the other. Now, normally, all we can do is retrieve the values of the damage, send that through the function, and then damage the unit per an event. Now, with this new feature, we can send the actual structures through the variables (not the values, but the entire structures themselves) and act upon those : D. We can retrieve the data within the actual damage function, and let's say we have custom hp, so we can act upon that hp within the structure. Creating a full custom combat system like this would not be able to retrieve triggering units, so it's very important that we are able to pass variables and what-not through functions. This means that all functions must only contain pointers to our special memory array and cannot contain actual values.
So, with this set up, we change our crappo jasso memory management (none at all) into memory management that's somewhat similar to C++.
So really, the only use for this is if you wanted to set any given variable to a value. Remember, normally you have to write out
x = x + 1
You can't suddenly change it to y or whatever during the game. To get around this, people use arrays and what not, which are icky. Yes, we're still using arrays, but we're working it a bit differently. Yes, this does take up more memory because we're using pointers and such (double to be precise), but for those cases where you need something like this, you can work those variables into a memory management thingie in the background like this. If every variable in your entire map needed this, well then, God Help You. Go learn C++.
Essays will continue on later = ).
These would work off of pretty simple systems that you could design for your own map or download from a site like the hive. These systems would be designed according to the concepts discussed in these essays.
Some of these could be inserted into vjass as well =).
Please feel free to comment or ask questions about programming concepts that you'd love to do in JASS but you have no idea how to do it.
Examples:
OpenGL done in JASS
Dynamic Classes done in JASS
C++ Memory Handling in JASS
Creating a C++ array in JASS
Maximizing speed using multi-threading techniques in JASS
feel free to ask anything you're curious about : )
Table of Contents - Search for these titles to jump from title to title
Multi-Threading Concept
Handling Memory Like C++
Multi-Threading Concept
Most of us know what a thread is and what it means to create multi-threading applications and systems for both inside and outside of warcraft 3, but for those who don't know, a thread is a stream of code (or calculations). To put it in more simpler terms, it can be described as car lanes on a road. When you have one lane, only one car can go through it at any given position. When you have 2 lanes, you can have 2 cars right next to each other both going through at the exact same time. This can go on. Now, there is something that has to be noted. Warcraft 3 doesn't let you create your own threads. You are allowed to run on threads that are already pre-defined. Your wants to use the threads are put into a stack. There are 6 threads per player. These aren't regular threads and wc3 doesn't let a user create a pre-defined thread. Another thing, the main function also runs on it's own thread so it's suggested that you never ever let the main function close. Put the thread to sleep or w/e. You can still maximize speed with multi-threading concepts (allocating your data to run as quickly as possible).
So, let's say you have 3 functions that are called within another function ,for example:
function randomstuff takes nothing returns nothing
call stuff1()
call stuff2()
call stuff3()
endfunction
Let's say that these 3 functions don't work off of each other and might as well go at once. We have 2 things which can make these go at once (one will add ugly code in the background, but is faster. The other allows for dynamic function calling using strings).
function randomstuff takes nothing returns nothing
call ExecuteFunc("stuff1")
call ExecuteFunc("stuff2")
call stuff3.execute()
endfunction
All three of these will start a new thread.
So, you're probably thinking at this point, threads are pretty cool and they can make my map run a lot faster! : O. Just imagine rewriting your main function in your map to be completely multi-threaded.
Well, while multi-threading can be awesome, you can't pass any information to these threads in JASS and there is no way for the function to wait for the new thread to finnish. So, let's analyze these issues.
1. Inability to send data to a new thread-
Eep
2. Unable to wait for new threads to finnish before continuing on
Example-
call ExecuteFunc("func1")
call ExecuteFunc("func2_that_needs_func_1")
In this example, func2 would start before func1 would get a chance to set the information up which would result in errors, crashes, and all sorts of fun things : D.
So, why not just call the function regularly in these cases?
Example-
call func1()
call ExecuteFunc("func2_that_needs_func_1")
Well, one issue you can have in this case is what could be called crashing a thread. Another thing is you can't maximize the speed. Let's say you only need the first 2 lines of function 1 to happen and then you can continue on to function 2. Let's say there are 100 lines of executed code in function one. That's 98 lines of code of wasted time.
So, how do we maximize speed? Well, what we can do is create a thread structure to connect our threads together.
Let's say we have a function called CreateThread, which creates a new thread structure and dynamically gives it a unique ID, so we could have like-
local integer ThreadID = ThreadTable.CreateThread()
In the background, CreateThread would be a method within ThreadTable that would auto generate our cache and so on for our new thread and store it in the global data structure called ThreadTable : o.
Ok, let's rewind here. Exactly what am I talking about when I'm saying ThreadTable, CreateThread, and so on. Threads are created via ExecuteFunc and .execute ><. Does the CreateThread Method use one of these things to create a new thread or what?
No, not really. What happens is if you were to create a design like this, you could set up a Global Thread Table that would initialize at the very start of the map. This thread table would contain function IDs (an array of various functions (strings)), storage arrays (storing units, integers, and what not), a boolean array (booleans to determine whether a thread is being used or not), and well, yea. So, what are these thread things we're talking about anyways?
Well, we know a regular thread is used to calculate information. When we're talking about thread tables and creating new threads in these cases, we're talking about mediums to transfer information between threads.
So wait? We can send local variables into other threads? that's impossible.
Well, the only work-around would be to either use the game cache or global variables. that's why we have our global structure for thread information.
So wait? When we create a new thread all we're doing is creating a space to store information and a pointer to it so we can access it later on?
Example-
Big Table
A pointer to the big table that's stored in a local variable
Well, if we do this, we get a pointer and what not to access our big table (like the indexes of the arrays), but how do we send this to the new function if we can't send any data at all?
Well, remember our function table? Well, can't we use that? So let's say we create a variable for each thread that stores a function ID.
So for example, like this
Thread[ThreadID].FunctionID = FunctionID in our Function Table
FunctionTable-
Function[1] = Our Spiffy Function
Function[2] = Our other spiffy function
Each index in the array would be the function ID
Now, when we start up a new thread that calls that function
call ExecuteFunc("Our Spiffy Function")
that function can start up by looking through all current threads that aren't being accessed and that contain its own function ID. So if we call 2 functions and have 2 pointers for those functions, they'll each get information for them.
Now, what does this mean? If you send data to a function within a new thread, that data won't necessarily make it to that specific function if another function that's the exact same would be called at once. So let's say you have 2 threads that are doing the same thing and they both start up new threads that do the same thing. Let's say we have an x1 and an x2 (thread1 and thread2). It could look something like this
Thread1- Sends x1 to Thread1New
Thread2- Sends x2 to Thread2New
Thread1New searches for an x1 with it's function ID, meaning it might either find x1 or x2
Let's say it finds x2
Thread1New closes off x2 so nothing else can retrieve it's info
Thread2New searches and because the only data that's left is x1, it recieves x1
Thread2New closes off x1 so nothing else can retrieve it's info
So
Thread1- Sends x1 to Thread1New
Thread2- Sends x2 to Thread2New
Thread1New recieves x2
Thread2New recieves x1
The data just jumped threads! : O. Yes, this is possible with a design like this. Does it really matter though? Let's say the functions do this
set y = y + x (x being the recieved data)
Let's say one piece of data applies it for like a treasure chest (increase the coins in it) and the other sends it to a bank (inceases the gold in the bank)
Well, since each function is the same, the properties for where to send it would be in the data
So let's say that in x1 and x2, there's a value, the integer that increases the gold, and a value of where to send the gold (either to the bank or to the treasure chest).
So now it turns like this
set y[xproperty] = y[xproperty] + x[value]
Now what this means is that it doesn't matter what specific instanced function receives the data so long as it's the same function. No matter what, the gold in the bank will go up and the gold in the treasure chest will go up by the right amounts.
So when we're sending data to a new thread, we really don't care which thread it goes to. All we care about is that it makes it to the right function : p, doesn't matter what thread the function comes from.
So, we learned how to send data in between threads and how to sort of design a basic system to do this. What exactly would the speed increase be for using a design like this?
Well, it really depends on how much code you're going through. A system like this would also prevent thread crashes because every function would get its very own thread. If you're just calling one function, it'd probably go slower with this system. If you're calling 30 functions, it'd go faster. It really depends on how much data you're handling.
Cool, so I'd only use a design like this for heavy data functions, like initializing 398230580348590 variables and creating a bundle of units or running a very complex combat system?
Well, yea... : p
But the functions still won't wait for the new threads to finish. How do I make them wait??
Well, remember our function state variable that closes off functions. When a new thread is created, you need to create different states for that thread.
State 0 = empty thread
State 1 = full thread waiting to be xfered
State 2 = received thread
Function States-
State 0 = Calculating data
State 1 = Finished calculating
This means that we can do 2 things to wait
Method #1:
If we want to wait for the thread to finish transferring, we'd just create a loop in the function that has a sleep timeout of .01 and just constantly checks the Thread's State for 0 using the ThreadID we got initially.
Method #2:
We store the original function's Function ID (the function calling the other function) into the Thread so that the called Function can call back on the original Function. From here we can create steps in the original function.
Example:
function1
checkstep (could be an if statement)
createthread
storedata
storestep (an integer)
call function2
function2
searchforthread
retrievedata
canstoredata
call function1
function1
checkstep
possibleretrievedata
possiblestoredata
call function3
etc etc
at the very end you'd have a DestroyThread, which would clear out the thread and remove it from the indexes and set its state to 0 .
Now you're probably thinking, jeezes, the timer would sure take up a lot. The steps seem kinda messy though if I use if statements.
Well, you don't have to use if statements : P. You could create a library of actions for each function within a data structure using methods and what not to make it really spiffy and organized.
So, now we know work-arounds for sending data in between threads and making functions wait for threads to finish sending data or for threads to totally finish up everything in them : D.
Would this be faster?
In some cases, yes, in some cases, no.
Is it worth it?
If you really want a spiffy as fast as possible map utilizing everything you can use, yes.
-------------------------------------------
Handling Memory Like C++
In C++, you can handle you own memory : D. What does this mean?
Well, variables are actually pointers to memory. They contain automatic index values of where the memory is stored. (not literally, but for our explanation on how to do this in JASS, yes)
It's really much like an array (not really, but for for the JASS design, yes)
Once again, this is an explanation for doing this in JASS****
Let's say that we have a variable called var and it contains a value of 3
The variable doesn't actually contain the value of 3, but rather a pointer to the place in memory where 3 is stored, almost like this.
(once again, this is dif from regular C++, C++, all 3 of these would be the same. C++ has a special thingie for retrieving the pointer to the memory. The normal variable would be the value that it points to in memory. You can set the memory value by changing the variable or the memory. In JASS, it works more like the below example) Yes, I'm inserting these little notes for people who are freaking out over my explanations .
var = 0
memory[var] = 3
In C++, you can either retrieve the 3 or you can retrieve the pointer value of 0. Now, how is this useful? Well, let's say you want to set variables dynamically. Let's say that a function can handle a type of data. Now, let's say we have 20 different global variables that are that type of data. We want to set a specific one.
Now, when passing information into functions (JASS), you can pass values and data types, but you can't pass variable names.
For example
integer x = 0
call function1(x)
That would not send the variable x into function1. It would just send the value of x, which is 0. Now, let's say we really wanted to pass the actual group of memory that x had into the function. Well, how can we do this in a scripting language???
Well, the way to do it is to set up our own C++ memory thing (This isn't like regular C++ memory, it's just a work-around to get very similar results) and to work all variables off of it. This means we create a huge array that I'm calling memory for now and we set all of our variables to contain indexes for that array. We also set our variable arrays to just contain indexes for that array + x, x being the index of our variable.
Here's a kinky example:
memory[0] = 0
memory[1] = 0
memory[2] = 0
variable1 = 0 (this accesses memory[0])
variable2[0] = 1+index (index is 0)
variable2[1] = 1+index (index is 1)
You're probably going, what's the point of this. Well, the point of this is passing actual variables through functions and not just their values. If we treat every variable as only a pointer to a piece of data and we use that pointer to access the data, then we can change that data because there's only one variable name. Here's an example.
set memory[variable1] = 10
call test(variabiable1,30)
function test takes integer variable1 returns nothing
set memory[variable1] = memory[variable] + 30
endfunction
Now, this seems pretty simplistic, but it makes it so you can manage your own memory (not literally, but similar) and allows you to pass actual spaces of memory (once again, not literally, but similar) into functions and not just values. How could this be useful? A lot of ways .
Hey, so now that we know how to do this, how can this play a role in everything? Well, let's say that we have a function that uses an equation to damage something dynamically in a combat system. Let's say there are 100 unique cases of units on the map each stored in their own little space of memory (memory where data structure is stored).
So one attacks the other. Now, normally, all we can do is retrieve the values of the damage, send that through the function, and then damage the unit per an event. Now, with this new feature, we can send the actual structures through the variables (not the values, but the entire structures themselves) and act upon those : D. We can retrieve the data within the actual damage function, and let's say we have custom hp, so we can act upon that hp within the structure. Creating a full custom combat system like this would not be able to retrieve triggering units, so it's very important that we are able to pass variables and what-not through functions. This means that all functions must only contain pointers to our special memory array and cannot contain actual values.
So, with this set up, we change our crappo jasso memory management (none at all) into memory management that's somewhat similar to C++.
So really, the only use for this is if you wanted to set any given variable to a value. Remember, normally you have to write out
x = x + 1
You can't suddenly change it to y or whatever during the game. To get around this, people use arrays and what not, which are icky. Yes, we're still using arrays, but we're working it a bit differently. Yes, this does take up more memory because we're using pointers and such (double to be precise), but for those cases where you need something like this, you can work those variables into a memory management thingie in the background like this. If every variable in your entire map needed this, well then, God Help You. Go learn C++.
Essays will continue on later = ).
Last edited: