A few beginner questions

Find quick help here to get you started with Hollywood
Post Reply
amyren
Posts: 361
Joined: Thu May 02, 2019 11:53 am

A few beginner questions

Post by amyren »

I am trying to teach myself HollyWood and start with looking at some of the examples and in the manual, but I still have a few things I wonder about.

Looking at CircleText.hws that have the "Repeat - waitevent - forever" loop.
After reading a bit in the docs, I think I get a clue on how that works.
The program will stay in this loop, but will be triggered by the event set by SetInterval, so it goes through the p_mainloop once every 40ms.
So far so good.
Reading further, the doc say that SetInterval() always must be used with waitevent. And Waitevent should only be present once in every script.
The docs for SetIntervals also states that you can install as many intervals as you want in your script.
Then I asume that waitevent will need to use the identifier to know which event it is waiting for.
But in CircleText.hws example the SetInterval is given the ID 1, but the waitevent is left without an argument. I find that a bit confusing.

I read that the the exclamation mark (!) can be used in variable names. And I notice that it is used in some example scripts, like in the CircleText.hws.
I was confused by this, until I read the manual that it is simply a part of the variable name. But I wonde why is it used in that example on some variables and not on others. Did the author have some reason for this, to make certian variables stand out on a way, or is it just a coincidence?

gosub vs functions (Local vs global variables)
I did study some AmiBlitz earlier, and I noticed that it was considered bad programming practice to goto and gosub. One should use statements or functions instead. One of arguments for this was that then the variables was local and would not interfere with your variables in the main loop. One could get a variable to be global, but this was to be defined in each case.
In my case, I never got around to see the benefit of this. Since I wanted all my variables to be global, and therefore I found gosubs to be far easier to use (and understand).
How is this with HollyWood functions, are variables global for the program, or are they local for each function?
User avatar
jPV
Posts: 604
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: A few beginner questions

Post by jPV »

amyren wrote: Mon May 06, 2019 12:29 pm Looking at CircleText.hws that have the "Repeat - waitevent - forever" loop.
After reading a bit in the docs, I think I get a clue on how that works.
The program will stay in this loop, but will be triggered by the event set by SetInterval, so it goes through the p_mainloop once every 40ms.
So far so good.
Reading further, the doc say that SetInterval() always must be used with waitevent. And Waitevent should only be present once in every script.
The docs for SetIntervals also states that you can install as many intervals as you want in your script.
Then I asume that waitevent will need to use the identifier to know which event it is waiting for.
But in CircleText.hws example the SetInterval is given the ID 1, but the waitevent is left without an argument. I find that a bit confusing.
The WaitEvent function waits for any event to happen, and handles that accordingly. So, no matter how many events you have coming from whatever source (intervals, mouse clicks, key presses, GUI related events, etc), you only should have just one WaitEvent loop to handle them all. If you need to know which event was triggered, you can see it from the table WaitEvent sends to the called function. Other events aren't handled before the previously called function returns to the WaitEvent loop again, so don't derail your program from the functions called by events :)

Try this to see how it works (you can also try clicking the left mouse button):

Code: Select all

Function p_EventFunction(msg)
    NPrint("p_EventFunction was called by:", msg.action, msg.id)
EndFunction

NPrint("Wait a second...")
SetInterval(1, p_EventFunction, 2000)
Wait(50)
SetInterval(2, p_EventFunction, 2000)
InstallEventHandler({OnMouseDown = p_EventFunction})

Repeat
    WaitEvent
Forever
I read that the the exclamation mark (!) can be used in variable names. And I notice that it is used in some example scripts, like in the CircleText.hws.
I was confused by this, until I read the manual that it is simply a part of the variable name. But I wonde why is it used in that example on some variables and not on others. Did the author have some reason for this, to make certian variables stand out on a way, or is it just a coincidence?
It's just a style-guide suggestion, like told in the documentation here: https://www.hollywood-mal.com/docs/html ... mber_.html

So, it's not obligatory, but you can use ! for floating point values like this:
size = 3 ; this variable is used for integer values
speed! = 0.3 ; this variable is used for floats
How is this with HollyWood functions, are variables global for the program, or are they local for each function?
Variables are local only if they are function parameters or otherwise declared as local. If you just start using a variable at any place (even inside a function) it becomes a global if you don't state otherwise. Read this for a better explanation and reasoning why you should prefer local variables every time you can: https://www.hollywood-mal.com/docs/html ... cals_.html
amyren
Posts: 361
Joined: Thu May 02, 2019 11:53 am

Re: A few beginner questions

Post by amyren »

That was a very good explanation :)
Thank you very much.
Bugala
Posts: 1178
Joined: Sun Feb 14, 2010 7:11 pm

Re: A few beginner questions

Post by Bugala »

Hope I am not interpreting wrong here, but it sounds to me that what you really are asking here regarding gosub, function, etc. is actually matter of programming technics.

I am trying to give you couple of examples here to at least scratch the surface.

When you start programming, you think your programs very much in way of go from line 1 to line 2 to line 3...

But when you get more advanced, you are starting to think them more and more like lego bricks that can be moved from one program to another to build different kind of lego figures.

Function and Gosub are in nature very much same, as example:

Code: Select all

gosub myprinttext
myprinttext:
debuprint("hello world") return
(I dont know if this code actually works since I have never used those labels in Hollywood, but you get the idea)
vs

Code: Select all

function myprinttext()
debugprint("hello world")
endfunction

myprinttext()
These both would do the same.

However, when dealing with functions, you bydefault have ability to send some stuff with it:

Code: Select all

function myprinttext(texttobeprinted)
debugprint(texttobeprinted)
endfunction
 myprinttext("Hello World")
 myprinttext("Another text")
This still does the same as previous ones, except this can do other stuff too, with gosub you can achieve the same, but it is messier:

Code: Select all

texttoprint = "Hello world"
gosub myprinttext

myrpinttext:
debugprint(texttoprint)
return
When your program is small it doesnt really matter if you use gosub or function, but when your program gets bigger, then it starts to matter, since functions make code easier to read and use.

In Finnish language, Object Oriented programming is called "Creature programming" when directly transferred back to english. This term is actually very good in my opinion, since that is the idea, that you are creating cratures that you can keep moving around.

as example, at start when i was still programming with Amos and Blitzbasic, i used to do this way:

Code: Select all

player1.x = player1.x + 10
player2.x = player2.x + 10
player3.x = player3.x + 10
If I then decided to change their x speed to 20, i had to alter all those three lines, and on top of that, it was easy to make one of player1 accidentally become for example player1.x = player2.x + 10, making bugs come all around and sometimes diffiult to hunt down.

Nowadays I instead use functions and these creatures. Each player becomes a creature so to speak, I can do it for example by making the player a table:

Code: Select all

player1 = { x=100, y=200, hp=300...}
And i do the same to each other player too.

When it comes time to update the player, I will have for example following function:

Code: Select all

function moveplayerx(creature)
creature.x = creature.x +10
endfunction
Now when i wish to use that, I will use:

Code: Select all

moveplayerx(player1)
moveplayerx(player2)
moveplayerx(player3)
(Actually i would use foreach to go through each player, but for easier understanding i am doing this way)

what now happens is, that each time I am calling this function, I am sending this playertable (=creature) inside the function. Inside that function, the function dont care who came inside, but it is simply calling it creature. If one who enters the function is player1, then when I am changing "creature.x", it means it is actually changing player1.x. So when it returns from the function, player1.x have changed accordingly, or who ever i happened to send there.

And I dont have to restrict this to players only, I can send some monster inside that function as well, and monster.x will change accordingly.

This way I dont need to write hundreds of lines of code doing same thing to each individual player/monster, but I can just send them inside that function and one and same function handles them all to me. This is very simple.


This same thing also has to do with global/local variables. Once again, if your program is small, doesnt matter, but when it becomes bigger, it is good to start using local functions, since it is very easy to accidentally use same name twice and this might result in some unexpected behavior. As example following:

Code: Select all

function checkallplayers()
for n=1 to 4
   checkplayersfingers(player[n])
next n

function checkplayersfingers(playertocheck)
for n= 1 to 10
   if finger[n]=false then return
next n
endfunction
   
What just happened was, that I used same variable name "n" in both. When n=1 (first player) it goes to check player1:s fingers, when it goes there, it will go check each finger through, until n=10, and then it returns back to previous. However, now it encounters next n, and n is suddenly 11, so instead of checking player2s fingers, it thinks it already checked them all and returns from that for too resulting in only player1s fingers being checked ever. (I am not actually sure this would work this way, but theoretically at least)

To avoid this from happening however, do a small change:

Code: Select all

function checkallplayers()

for local n=1 to 4
   checkplayersfingers(player[n])
next n

function checkplayersfingers(playertocheck)

for local n=1 to 10
   if finger[n]=false then return
next n
endfunction
   
Now each of those for ns are local, which means that they are individuals only for their own loops. That basically when second local n is encountered, it is not moving "n" forward, but "clone n" forward, and this way the before mentioned never gets to happen.

As last about global variable vs locals, local is most of time better, since it causes less trouble. Local exists only in its local space, therefore it doesnt collide with other global variables accidentally, for in best case also your functions are like creatures in sense that you can move them from one program to other, as example:

Code: Select all

function difficultcalculation(number)
a = 50
b = 100
sum=a+b+number
endfunction
This difficult calculation can now be simply used with "difficultcalculation(10)" and it will result in 160.
For some reason, this calculation is useful on another program of mine too, so all I have to do is copy-paste this same function to that other program, and I can now use it same as before "difficultcalculation(10)" is still resulting 160, but oh and woe, now i have a bug that i finally realise have to do with my usage of a and b, for I am using those same variables elsewhere in my program too, and everytuime i use this function, these global variables get changed into 50 and 100. Had I used "local a = 50" and "local b=100" instead, I could have safely copy-pasted this function to my other program.

This copy-paste is also the idea in that try to keep your functions as independent as possible, less they use from outside, easier they are to use in other programs. In best case you are able to make your function completely independent in that it uses no global variables at any point, and usage is as simple as sending some creature inside it.

That basically you have two independent things there. Independent function, that uses independent creature.

You could have program number 3 which is using independent function from program 1, into which you send independent creature from program 2, and it works without needing to alter anything, and that is basically the aim.
amyren
Posts: 361
Joined: Thu May 02, 2019 11:53 am

Re: A few beginner questions

Post by amyren »

Bugala wrote: Mon May 06, 2019 4:49 pm Hope I am not interpreting wrong here, but it sounds to me that what you really are asking here regarding gosub, function, etc. is actually matter of programming technics.

I am trying to give you couple of examples here to at least scratch the surface.
Thank you. You are right it also was a question about programming technics.
I did read your examples, and the first part of your post explains a bit of the difference between a gosub and a function.
But the last parts of yor post got a bit to complicated for me now, I think I need to come back and re-read it after I had some more practice with using tables and functions.

BTW..I really liked your video tutorials for the Designer. I hope you will get that DemoBuilder running again one day, and have motivation to make some more.
Bugala
Posts: 1178
Joined: Sun Feb 14, 2010 7:11 pm

Re: A few beginner questions

Post by Bugala »

Thanks, I actually nowadays have Camtasia Studio since it was sold on Humblebundle one time, hence I actually have a chance to make tutorial videos again, and every now and then I do itch a bit to do them, but at least so far haven't. I do have been having a more extensive tutorial idea that would also have a bit about Ai and pathfinding for example, since those I haven't really seen much shown in beginners friendly way.

Anyway, it is when people like you mention about them that makes me think to make more of them every time. Perhaps one day.
Post Reply