gdscript_advanced.rst 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. .. _doc_gdscript_more_efficiently:
  2. GDScript: An introduction to dynamic languages
  3. ==============================================
  4. About
  5. -----
  6. This tutorial aims to be a quick reference for how to use GDScript more
  7. efficiently. It focuses on common cases specific to the language, but
  8. also covers a lot of information on dynamically typed languages.
  9. It's meant to be especially useful for programmers with little or no previous
  10. experience with dynamically typed languages.
  11. Dynamic nature
  12. --------------
  13. Pros & cons of dynamic typing
  14. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  15. GDScript is a Dynamically Typed language. As such, its main advantages
  16. are that:
  17. - The language is very simple to learn.
  18. - Most code can be written and changed quickly and without hassle.
  19. - Less code written means less errors & mistakes to fix.
  20. - Easier to read the code (less clutter).
  21. - No compilation is required to test.
  22. - Runtime is tiny.
  23. - Duck-typing and polymorphism by nature.
  24. While the main disadvantages are:
  25. - Less performance than statically typed languages.
  26. - More difficult to refactor (symbols can't be traced)
  27. - Some errors that would typically be detected at compile time in
  28. statically typed languages only appear while running the code
  29. (because expression parsing is more strict).
  30. - Less flexibility for code-completion (some variable types are only
  31. known at run-time).
  32. This, translated to reality, means that Godot+GDScript are a combination
  33. designed to create games very quickly and efficiently. For games that are very
  34. computationally intensive and can't benefit from the engine built-in
  35. tools (such as the Vector types, Physics Engine, Math library, etc), the
  36. possibility of using C++ is present too. This allows to still create the
  37. entire game in GDScript and add small bits of C++ in the areas that need
  38. a performance boost.
  39. Variables & assignment
  40. ~~~~~~~~~~~~~~~~~~~~~~
  41. All variables in a dynamically typed language are "variant"-like. This
  42. means that their type is not fixed, and is only modified through
  43. assignment. Example:
  44. Static:
  45. ::
  46. int a; // value uninitialized
  47. a = 5; // this is valid
  48. a = "Hi!"; // this is invalid
  49. Dynamic:
  50. ::
  51. var a # null by default
  52. a = 5 # valid, 'a' becomes an integer
  53. a = "Hi!" # valid, 'a' changed to a string
  54. As function arguments:
  55. ~~~~~~~~~~~~~~~~~~~~~~
  56. Functions are of dynamic nature too, which means they can be called with
  57. different arguments, for example:
  58. Static:
  59. ::
  60. void print_value(int value)
  61. {
  62. printf("value is %i\n",value);
  63. }
  64. [..]
  65. print_value(55); // valid
  66. print_value("Hello"); // invalid
  67. Dynamic:
  68. ::
  69. func print_value(value):
  70. print(value)
  71. [..]
  72. print_value(55) # valid
  73. print_value("Hello") # valid
  74. Pointers & referencing:
  75. ~~~~~~~~~~~~~~~~~~~~~~~
  76. In static languages such as C or C++ (and to some extent Java and C#),
  77. there is a distinction between a variable and a pointer/reference to a
  78. variable. The later allows the object to be modified by other functions
  79. by passing a reference to the original one.
  80. In C# or Java, everything not a built-in type (int, float, sometimes
  81. String) is always a pointer or a reference. References are also
  82. garbage-collected automatically, which means they are erased when no
  83. longer used. Dynamically typed languages tend to use this memory model
  84. too. Some Examples:
  85. - C++:
  86. .. code:: cpp
  87. void use_class(SomeClass *instance) {
  88. instance->use();
  89. }
  90. void do_something() {
  91. SomeClass *instance = new SomeClass; // created as pointer
  92. use_class(instance); // passed as pointer
  93. delete instance; // otherwise it will leak memory
  94. }
  95. - Java:
  96. .. code:: java
  97. @Override
  98. public final void use_class(SomeClass instance) {
  99. instance.use();
  100. }
  101. public final void do_something() {
  102. SomeClass instance = new SomeClass(); // created as reference
  103. use_class(instance); // passed as reference
  104. // garbage collector will get rid of it when not in
  105. // use and freeze your game randomly for a second
  106. }
  107. - GDScript:
  108. ::
  109. func use_class(instance); # does not care about class type
  110. instance.use() # will work with any class that has a ".use()" method.
  111. func do_something():
  112. var instance = SomeClass.new() # created as reference
  113. use_class(instance) # passed as reference
  114. # will be unreferenced and deleted
  115. In GDScript, only base types (int, float, string and the vector types)
  116. are passed by value to functions (value is copied). Everything else
  117. (instances, arrays, dictionaries, etc) is passed as reference. Classes
  118. that inherit :ref:`class_Reference` (the default if nothing is specified)
  119. will be freed when not used, but manual memory management is allowed too
  120. if inheriting manually from :ref:`class_Object`.
  121. Arrays
  122. ------
  123. Arrays in dynamically typed languages can contain many different mixed
  124. datatypes inside and are always dynamic (can be resized at any time).
  125. Compare for example arrays in statically typed languages:
  126. ::
  127. int *array = new int[4]; // create array
  128. array[0] = 10; // initialize manually
  129. array[1] = 20; // can't mix types
  130. array[2] = 40;
  131. array[3] = 60;
  132. // can't resize
  133. use_array(array); // passed as pointer
  134. delete[] array; // must be freed
  135. //or
  136. std::vector<int> array;
  137. array.resize(4);
  138. array[0] = 10; // initialize manually
  139. array[1] = 20; // can't mix types
  140. array[2] = 40;
  141. array[3] = 60;
  142. array.resize(3); // can be resized
  143. use_array(array); // passed reference or value
  144. // freed when stack ends
  145. And in GDScript:
  146. ::
  147. var array = [10, "hello", 40, 60] # simple, and can mix types
  148. array.resize(3) # can be resized
  149. use_array(array) # passed as reference
  150. # freed when no longer in use
  151. In dynamically typed languages, arrays can also double as other
  152. datatypes, such as lists:
  153. ::
  154. var array = []
  155. array.append(4)
  156. array.append(5)
  157. array.pop_front()
  158. Or unordered sets:
  159. ::
  160. var a = 20
  161. if a in [10, 20, 30]:
  162. print("We have a winner!")
  163. Dictionaries
  164. ------------
  165. Dictionaries are a very powerful tool in dynamically typed languages.
  166. Most programmers that come from statically typed languages (such as C++
  167. or C#) ignore their existence and make their life unnecessarily more
  168. difficult. This datatype is generally not present in such languages (or
  169. only on limited form).
  170. Dictionaries can map any value to any other value with complete
  171. disregard for the datatype used as either key or value. Contrary to
  172. popular belief, they are very efficient because they can be implemented
  173. with hash tables. They are, in fact, so efficient that some languages
  174. will go as far as implementing arrays as dictionaries.
  175. Example of Dictionary:
  176. ::
  177. var d = { "name": "john", "age": 22 } # simple syntax
  178. print("Name: ", d["name"], " Age: ", d["age"])
  179. Dictionaries are also dynamic, keys can be added or removed at any point
  180. at little cost:
  181. ::
  182. d["mother"] = "Rebecca" # addition
  183. d["age"] = 11 # modification
  184. d.erase("name") # removal
  185. In most cases, two-dimensional arrays can often be implemented more
  186. easily with dictionaries. Here's a simple battleship game example:
  187. ::
  188. # battleship game
  189. const SHIP = 0
  190. const SHIP_HIT = 1
  191. const WATER_HIT = 2
  192. var board = {}
  193. func initialize():
  194. board[Vector(1,1)] = SHIP
  195. board[Vector(1,2)] = SHIP
  196. board[Vector(1,3)] = SHIP
  197. func missile(pos):
  198. if pos in board: # something at that pos
  199. if board[pos] == SHIP: # there was a ship! hit it
  200. board[pos] = SHIP_HIT
  201. else:
  202. print("already hit here!") # hey dude you already hit here
  203. else: # nothing, mark as water
  204. board[pos] = WATER_HIT
  205. func game():
  206. initialize()
  207. missile(Vector2(1,1))
  208. missile(Vector2(5,8))
  209. missile(Vector2(2,3))
  210. Dictionaries can also be used as data markup or quick structures. While
  211. GDScript dictionaries resemble python dictionaries, it also supports Lua
  212. style syntax an indexing, which makes it very useful for writing initial
  213. states and quick structs:
  214. ::
  215. # same example, lua-style support
  216. # this syntax is a lot more readable and usable
  217. var d = {
  218. name = "john",
  219. age = 22
  220. }
  221. print("Name: ", d.name, " Age: ", d.age) # used "." based indexing
  222. # indexing
  223. d.mother = "rebecca"
  224. d["mother"] = "rebecca"
  225. d.name = "caroline" # if key exists, assignment does work, this is why it's like a quick struct.
  226. For & while
  227. -----------
  228. Iterating in some statically typed languages can be quite complex:
  229. ::
  230. const char* strings = new const char*[50];
  231. [..]
  232. for(int i=0; i<50; i++)
  233. {
  234. printf("value: %s\n", i, strings[i]);
  235. }
  236. // even in STL:
  237. for(std::list<std::string>::const_iterator it = strings.begin(); it != strings.end(); it++) {
  238. std::cout << *it << std::endl;
  239. }
  240. This is usually greatly simplified in dynamically typed languages:
  241. ::
  242. for s in strings:
  243. print(s)
  244. Container datatypes (arrays and dictionaries) are iterable. Dictionaries
  245. allow iterating the keys:
  246. ::
  247. for key in dict:
  248. print(key, " -> ", dict[key])
  249. Iterating with indices is also possible:
  250. ::
  251. for i in range(strings.size()):
  252. print(strings[i])
  253. The range() function can take 3 arguments:
  254. ::
  255. range(n) (will go from 0 to n-1)
  256. range(b, n) (will go from b to n-1)
  257. range(b, n, s) (will go from b to n-1, in steps of s)
  258. Some examples:
  259. ::
  260. for(int i=0; i<10; i++) {}
  261. for(int i=5; i<10; i++) {}
  262. for(int i=5; i<10; i+=2) {}
  263. Translate to:
  264. ::
  265. for i in range(10):
  266. for i in range(5, 10):
  267. for i in range(5, 10, 2):
  268. And backwards looping is done through a negative counter:
  269. ::
  270. for(int i=10; i>0; i--) {}
  271. becomes
  272. ::
  273. for i in range(10, 0, -1):
  274. While
  275. -----
  276. while() loops are the same everywhere:
  277. ::
  278. var i = 0
  279. while(i < strings.size()):
  280. print(strings[i])
  281. i += 1
  282. Duck typing
  283. -----------
  284. One of the most difficult concepts to grasp when moving from a
  285. statically typed language to a dynamic one is duck typing. Duck typing
  286. makes overall code design much simpler and straightforward to write, but
  287. it's not obvious how it works.
  288. As an example, imagine a situation where a big rock is falling down a
  289. tunnel, smashing everything on its way. The code for the rock, in a
  290. statically typed language would be something like:
  291. ::
  292. void BigRollingRock::on_object_hit(Smashable *entity)
  293. {
  294. entity->smash();
  295. }
  296. This way, everything that can be smashed by a rock would have to
  297. inherit Smashable. If a character, enemy, piece of furniture, small rock
  298. were all smashable, they would need to inherit from the class Smashable,
  299. possibly requiring multiple inheritance. If multiple inheritance was
  300. undesired, then they would have to inherit a common class like Entity.
  301. Yet, it would not be very elegant to add a virtual method ``smash()`` to
  302. Entity only if a few of them can be smashed.
  303. With dynamically typed languages, this is not a problem. Duck typing
  304. makes sure you only have to define a ``smash()`` function where required
  305. and that's it. No need to consider inheritance, base classes, etc.
  306. ::
  307. func _on_object_hit(object):
  308. object.smash()
  309. And that's it. If the object that hit the big rock has a smash() method,
  310. it will be called. No need for inheritance or polymorphism. Dynamically
  311. typed languages only care about the instance having the desired method
  312. or member, not what it inherits or the class type. The definition of
  313. Duck Typing should make this clearer:
  314. *"When I see a bird that walks like a duck and swims like a duck and
  315. quacks like a duck, I call that bird a duck"*
  316. In this case, it translates to:
  317. *"If the object can be smashed, don't care what it is, just smash it."*
  318. Yes, we should call it Hulk typing instead.
  319. It's possible that the object being hit doesn't have a smash() function.
  320. Some dynamically typed languages simply ignore a method call when it
  321. doesn't exist (like Objective C), but GDScript is more strict, so
  322. checking if the function exists is desirable:
  323. ::
  324. func _on_object_hit(object):
  325. if (object.has_method("smash")):
  326. object.smash()
  327. Then, simply define that method and anything the rock touches can be
  328. smashed.