Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - TheExDeus

706
Programming Help / Re: Question on variables and arrays (important)
« on: May 11, 2014, 06:43:13 am »
Quote
So in terms of performance would I be better off using data structs ? I notice with the ds you can insert, move, copy, delete individual, find, etc, far more efficient than the arrays,
They just have functions for that. In case of regular arrays you would have to do that yourself, so depending on your own implementation it can be both slower and faster. Usually regular arrays are faster than ds, because data structures are classes with their own overhead. So if you just want to store stuff, then regular arrays would probably be faster (even if the array is big). If you want to remove/add elements, shuffle or sort, then using a data structure would be better (mostly because they already have those functions). There is problem with current data structures though - for GM compatibility they usually don't use a regular class (the std container), but some custom one. So the performance of ds_list, for example, could be worse than using std::list in C++.

You can see std containers here: http://www.cplusplus.com/reference/stl/
They have a good information on differences between them. So you can see how std::list (which is a dynamic array) is different from std::vector (which is also a dynamic array). One is fast at inserting, other is fast at lookup, the third is fast at sorting. So depending on your need you would take the one works fastest. In ENIGMA most of the ds are std::map as far as I remember. And that is actually quite slow.

707
Glad to hear that. Hope you won't have a bazillion problems (most probably you will have :P).

708
Quote
Is that draw event triggered anytime, even outside the boundaries of the screen?
Yes, draw event is triggered always. That is because you can draw anywhere inside the draw event no matter where the instance is located. Like you could put "x = y = -100;" (so it's outside the room), but still draw_sprite(spr,0,10,10) (so draw it 10,10). That is why we cannot optimize that. If you use the default draw event, then we could technically take sprite into account and not draw that, but that is also not done now (I think). It's possible any performance gains would be minimal (the only advantage would be possibly less texture switching as we don't have a texture atlas). But if you draw sprites only at instance positions, then you can use things like instance deactivation to not render things outside view.

709
Programming Help / Re: Question on variables and arrays (important)
« on: May 10, 2014, 07:16:52 pm »
There is a difference between "int a;" and "a;". So there is the same difference between "int a[300];" and "a[300];". By default (if you don't specify anything - including type) the variable (or array) is in object local scope. So when you typed "a[300];" you created an array local to the object. If you typed "int a[300];" it would be an integer array local to the script. If you typed "local int a[300];" it would be an integer array local to the object again.

Quote
local a[300]
local b[300]
instead right ?
No. Typing "a[300]" is essentially the same as saying "local a[300]" (although I think that could even be an error if you can declare it that way). You have to specify "local" only when declaring type, because in GM when you declare a type the variable becomes automatically temporary to the script (GM has only one type "var").

Quote
So in other words I should NOT be using anything
in the create event that is variable declaration
such as

a = 30;
etc. 
You can use that just fine. The only way to declare anything temporary to the script it to declare it with a type, but without "local". So if you say "a = 30;", then it will work fine and will be local to the object. If you type "var a = 30;" (or any type like "int" instead of "var") then it will be local to the script. If you type "local int a = 30;" then it will be local to object again.

Quote
Was I right to use this type of array for what I needed done above ? or are there better ways ?
No, it's ok. I usually use data structures instead of arrays. That would allow me to easily change the size (while running the game) and iterate the values easier (and/or safer).

Quote
Also what happens to variables declared in room creation code, and those created in scripts, do the ones in scripts remain active as long as the game is running, and room creation code as long as the room is active ?
Variables in room creation code are temporary to that code and are deleted when the creation ends (unless the variables are global of course). Scripts on the other hand are usually ran by objects, so if you type "a = 5;" in a script, and then execute that script from obj_a create event (or any event), then "a" would become a variable for obj_a (and its value would be 5). If you made the variable temporary (like "var a = 5;") then of course it will be temporary for the script.

710
Issues Help Desk / Re: Blend mode not working in DX9
« on: May 10, 2014, 07:02:56 pm »
Apparently has been fixed now. The circle function had to be changed. Blend modes worked fine.

711
Programming Help / Re: Question on variables and arrays (important)
« on: May 10, 2014, 07:46:11 am »
Quote
1. What if I don't know in advance the size of my array and would like to leave it dynamic how would I go about?
If you want dynamic then don't use static arrays. Using "new" and "delete" is even a lot worse idea, so just use data structures instead. In ENIGMA they are like ds_grid or ds_list, while in C++ they are std::map or std::vector (vector especially being useful, as that is a dynamic array).

Quote
2. Let's say I do not need the array anymore but want to free the memory used of a[0] to a[99]  (the array I declared), how would I do this ?
If you use a ds, then there is ds_..._free or ds_..._destroy function. In C++ you CANNOT (and need not) delete a static array. It will be deleted when it gets out of the scope. Be it function (in ENIGMA called script), loop or class (in ENIGMA called object). So if you type "int a[100]" in create then it will be deleted at the end of create code (because that is how you define a temporary variable). If you type "local int a[100]" then it will only be deleted when the instance is deleted. If you want to have dynamic arrays, then use data structures. Don't use "new" or "delete" as they most often cause memory leaks.

Quote
3. IS it necessary to manually free all variable and arrays before my program exits or is it done automatically ?
No it's done automatically, as usually none of them are declared via "new", then they are all destroyed by C++ runtime when you close the process. Even if they we declared with "new" they would still be deleted, but would be called a memory leak.

Quote
let's say I have Obj1 in LGM, in create event I declare a variable array a[100].  This is for obj1.  Let's say obj1 is destroyed, does that mean the memory allocated to a[100] is freed with it?
Yes. But you have to declare it "local int a[100];" or otherwise ("int a[100]") will free the memory at the end of the Create event (or more precisely at the end of the code).

Quote
I don't want to be in a situation where I make use of extensive arrays in a program, and that when the user exits the memory is still reserved, and re-run the program, new memory is allocated, whilst the old memory allocation is still active ,etc........eventually  draining memory.
That cannot really happen. Even if you don't free any memory, the OS and the runtime will free it for you when the program ends. So it's impossible for a program to reserve memory when the process is ended. That is true universally in all modern OS's (windows, mac, linux, android), but there could still be some which doesn't do that (maybe some embedded real-time OS's specific for micro-controllers or something). http://stackoverflow.com/questions/2213627/when-you-exit-a-c-application-is-the-malloc-ed-memory-automatically-freed

Quote
I don't want to be in a situation where I make use of extensive arrays in a program, and that when the user exits the memory is still reserved, and re-run the program, new memory is allocated, whilst the old memory allocation is still active ,etc........eventually  draining memory.
If you declare a static array, then the reserved amount is the same as the memory used. So if char is 1 byte, then "char a[1000]" will reserve and automatically take 1000bytes. In C++ you can use sizeof() to determine sizes of arrays or types. http://www.cplusplus.com/faq/sequences/arrays/sizeof-array/

Also note, ENIGMA's parser is very broken now and it doesn't support pure C++ or even parts of EDL. So declaring an array with a type will probably not work (like this will probably error "int a[5]; a[0] = 0;"). So everything said in this topic applies to C++ (and the ds part applies to ENIGMA), but they are not yet interchangeable.

712
If the "visible" box is checked, then it draws the "Draw event". The default Draw event (which you cannot see) has just "draw_self()" in it which draws self. On the other hand if override that event (by adding your own code/D&D actions or just a comment to the "Draw event"), then the default one will not run and nothing will be drawn. You should be able to see that yourself in the game. If you don't see anything, then it probably doesn't draw anything. Of course if you haven't assigned a sprite to the object, then it won't draw anything either.

713
Quote
BTW, what function do I use to find out the length of an array?
As onpon pointed out, the C++ array doesn't support that. You should either save the length in a variable on your own or use a datastructure (ds_ functions).
Though it is possible we will support getting length for GM arrays. We could make it work because the arrays in GM are dynamic and they are wrapped in some other class even now. So it should be possible to make it work. But if you use C++ style arrays, then you won't have that possibility. For example in ENIGMA you can write (or at least "should write", as I am pretty sure this is broken now):
Code: [Select]
int array[10];
array[0] = 5;
This is a pure C++ array and as they are static size at compile time, you cannot get length directly. You could write something like sizeof(array) and then figure it out from that, but usually it's meant that the user already knows the size.

714
Quote
On an expert level yes I used BASIC and I can swear on my life that it worked differently.
The difference is that in Basic you probably didn't have an engine. I think you didn't even draw anything to a rendering context. All you did was output to console. That is a lot different then rendering to screen. That is where your misunderstanding came from. If you had used some graphics engine with BASIC you would have noticed the same thing you noticed here.

Quote
Understood.  So, in this example, how can I make an object move 100 pixels (1 pixel at a time) using a for / loop then ? 
If you actually want to see the object move, then you shouldn't use a for loop (unless you want to use the screen_redraw() "hack"). If you want 1 pixel at a time, then that means you need to increment the position 1 pixel per step. That means adding x+=1 to a step event. That's it.

Quote
So in which cases then would a for loop be properly used in a step event ?
Well, whenever you have to loop something. Like looping over objects or looping over arrays. Previously you showed a code used for a collision that used the while loop. That is a very popular place to use it. Basically you use it the same places you would in C++ or BASIC or anything else. If you wanted to move a box 1 pixel at a time and render that movement on the screen, then you wouldn't use a for(){} in BASIC either.

Quote
Now, I applied what I learned in how for loop works in other languages and done something with arrays.
You could just put the loop in create. No need to have it in step if you only run it once.

Quote
Is it correct what I did above  ? Is the coding clean
or is there a better way to do the above?
It's ok. I would probably just use an alarm.

So to recap. This is what your code looks like in ENIGMA (or any game engine):
Code: [Select]
while (true){
    //start logic, like your step event
    for (i=0; i < 99; i++)
    {
draw_text(10,10,"Count: "+string(i));
    }
    //end logic

    screen_redraw();
}
So it's a loop inside a loop. The first loop is the main one and executes once per step. The inner one is your step event that gets executed. And screen_redraw() is the function that actually draws something on the screen. You should notice from this example why your previous codes didn't work as you expected. When you understand you are already in an infinite loop, then it should be easier for you to make things. Like if you wanted your object to move to x = 100 with 1 pixel per step, then you just do this:
Code: [Select]
//Create event
x = 0;

//Step event
if (x<100) ++x;
So this is actually easier and shorter than what you wanted to do with the for loop.

edit:
Also, you could technically do what you want with threading. You could create a script and place something like this in it (haven't tested it):
Code: [Select]
for (var i=0; i<100; ++i){
   obj_someobject.x = i;
   sleep(1/room_speed);
}
And then call that with script_thread() (probably in Create event). What this would do is change the object's x position, the go to sleep for 1 step during which time the screen should redraw in the main thread. Then you modify the position again and sleep again. Until the loop is finished. But this isn't a good solution, as it can cause race conditions, consume more resources and create jerky movement (like it's possible during a slowdown that the object moves twice in one step instead of once).

715
Quote
Maybe I am not explaining myself correctly or what I want to do
You explained clearly enough. And I explained on why your thinking is wrong. I also gave numerous examples on how it works and how to replicate what you want.

Quote
print it sequentially across the screen.
It prints in the console. You can do show_error(string(i),false) with widget None and get the same thing. That would print to console while inside the for loop.
On the other hand ENIGMA renders on graphics context by the GPU. OpenGL and DirectX don't render on the screen anything when you just say "draw_text()", it renders on a buffer (to be technical it doesn't render anything at all until the end of the frame). Then the last thing the driver does when the frame ends is render whole thing on the screen. This is called double buffering and is what most graphical programs/games use. So your for(){draw_text();} doesn't render anything on the screen. And it wouldn't render anything on the screen no matter what engine, graphics system or driver you use. It's just not going to do that, because it's not meant to. The only way to render things on the screen during a loop is by redrawing (swapping buffers) in the for loop. That is what my screen_redraw() example code did.

Quote
Instead you could do this in the Draw GUI event (with a visible object depth):
That will not do what he wants. He thinks that code will render a number i on the screen and then increment per frame. That is not how it works.

716
I think you replied to the wrong thread. By the power of deduction I think you wanted to post in the thread about Dropbox Packrat?

717
Off-Topic / Re: The choice was obvious, and it wasn't Enigma
« on: May 07, 2014, 01:51:11 pm »
The Dropbox ones are going to hold only for 30 days. Unless you paid for the packrat thing.

718
Quote
Now, there are other ways of doing this, and initially I tried using for but it did not work :(
What you posted are NOT other ways to do that. They do something completely different.

Quote
This does not work......for some odd reason i starts at 100.
It's not odd at all. A for loop repeats the code inside it until a condition is met (http://en.wikipedia.org/wiki/For_loop). In this case that means drawing 100 times (numbers from 0 to 99) in one step. After that loop i will be 99 (because it will have added one 99 times to it in that step). The next step it will be reset to 0 (the initializer in the for loop) and then draw 100 times again. After which i will be again 99.

Quote
Does nothing, nothing gets drawn so this proves the code is not being executed.
It does draw something. It draw the text (like in the for loop) for one step (the very first one). After which the i is more than 99 and the while(){} never executes again in the next steps (because unlike in the for loop, the i is never reset to 0 in this case).

Quote
Looked in GMS's docs, and that is how they document while and how it's supposed to be used.
I think you don't really understand how cycles work. Or how steps work. The code you put in events like draw or step are executed once every frame (called step in GM). By default there are 30 frames per second (changeable in room settings). Create event (where you set i to 0) is ran only once, when the object is created (in the beginning of the room). So all of the codes you posted work just fine. They would work like that in GM, ENIGMA, C++, Basic, Python or anywhere else.

Quote
This works, so why does a simple counter loop with while does not ? :(
It works just like you coded it. There are no bugs or problems with while, for or repeat cycles.

Quote
In this example the object should move 1 pixel at a time until it moved 100 total pixels.
No it shouldn't. As I mentioned before Draw event (the one actually drawing to the screen) is executed once per frame. While the for(){} you have created here executes 100 times per frame. So when using that loop you should see the object at x=100 in every frame.
Imagine the code like this:
Code: [Select]
//In step 10 here x = 100
for (i=0; i<100; i++){ //Here x = 0
 x = i; //Here it is changed 100 times
}
//Here x = 100 again

//Here the draw happens and you actually see the object drawn at x,y position which is always 100
As you can see x will always be 100 in this case and the object will always be on the same position.

Quote
Result when run, i is 100 instantly,
As it should be.

Read up on loops. You said you used Basic before, I think they had loops too.

edit:
Quote
This should start counting from 0 and increment i by 1 every step.
No, it shouldn't. Your for(){} cycle is executed inside ONE step. You execute it every step from the beginning. You cannot have one script execute spanning multiple steps. Like this is impossible:
Code: [Select]
//Step event code

x = 0;
//Now do some magic to change steps
x = 1;
The "magic" part is impossible.

What you can do is call screen redraw manually. Like you could do this:
Code: [Select]
//Step event
for (i=0; i < 99; i++)
{
screen_redraw();
}

//Draw event
draw_text(10,10,"Count: "+string(i));
But that wouldn't change the step or execute any other code. It would just call all draw events. So that would work like the original code, but consume a lot more resources (as there isn't a frame rate limit here) and if you put screen_redraw() in draw, then that causes an infinite loop that crashes the game (that is normal as you are calling a draw event from a draw event from a draw event...). The screen_redraw() is most used to render screen to a surface:
Code: [Select]
//Step event
surface_set_target(screen_surf);
screen_redraw();
surface_reset_target();
This would draw everything that is on the screen to the surface. Another popular use for screen_redraw() in the old days was to create loading bars. As GM didn't have threading, then the game usually froze when executing an intensive script (like loading a large level from a file). To create a loading bar you needed to redraw the screen while the script was executing and that was done via screen_redraw(). Like so:
Code: [Select]
//Script that is slow
loading_bar = 0;
//Load models or something that takes 2 seconds
loading_bar = 10;
screen_redraw();
//Load map that takes 5 seconds
loading_bar = 50;
screen_redraw();
//Do some init or something that takes 7 seconds
loading_bar = 100;
scree_redraw();

//Draw event
draw_rectangle(10,10,10+loading_bar,50,0); //Draws the loading bar
So in this case even though the same script is executing in the same thread, the loading bar is still drawn as animating. No other events or scripts are called though (unless they happen in the draw event). So no "step" has actually happened.
In ENIGMA we have functions like script_thread() that would be a more proper way to do this.

719
Specs might be ok. But the OS might be a problem. No one really has tested Win98 with ENIGMA so there could be dependency problems. If you compile using GL1.1 you should be ok.

720
Programming Help / Re: C++ questions!
« on: May 05, 2014, 06:21:44 am »
The only thing I have ever used for C++ is MinGW. I just take any IDE (Code::Blocks being my favorite, but you can also use Notepad++ or just plain freaking notepad) and I compile everything with makefiles and cmd. So i'm pretty old school with all that. But I know even IDE's like MS Visual Studio support MinGW in one respect or another. At least it supports compiling on Linux machines remotely (I used VisualGDB plugin to do that for RaspberryPi from Windows). I think there is a plugin or something like that to interface with MinGW as well. This would give you access to Intellisense and maybe even makefile generation, while still using plain C++ and MinGW compiler.