Help with functions.

BlitzPlus Forums/BlitzPlus Programming/Help with functions.

indietom(Posted 2013) [#1]
Hi!
I'm trying to learn how to use blitzplus so I can team up with my friend at game jams. The problem is I don't get functions, I know how to make a normal simple function but it doesn't look nice.(this is how http://pastebin.com/ZW1FE30z)But I want them to look like this, http://pastebin.com/6zv3UDvC . When I do it this way nothing happens.

Thanks for any help.


Yasha(Posted 2013) [#2]
I ...think I can guess what you're trying to do, but it isn't clear. Can you explain in more detail what you want to achieve?


Also, you can put code directly in your forum posts:

{code}
Stuff
{/code}

^ replace the {} with [] and you get this:

Stuff



indietom(Posted 2013) [#3]
This is what I want to do in more detail.

This is what my friends' use:
 
fuction move()
 
if keyDown(down) then playerY = playerY + 5
if keyDown(up) then playerY = playerY - 5
if keyDown(right) then playerX = playerX + 5
if keyDown(left) then playerX = playerX - 5
 
if keyDown(s) then player2Y = player2Y + 5
if keyDown(w) then player2Y = player2Y - 5
if keyDown(r) then player2X = player2X + 5
if keyDown(d) then player2X = player2X - 5
 
end function
 
This is what I want mine to look like:
 
function controls(x,y,keyForDown,keyForUp,keyForLeft,keyForRight)
if keyDown(keyForDown) then y = y + 5
if keyDown(keyForUp) then y = y - 5
if keyDown(keyForRight) then x = x + 5
if keyDown(keyForLeft) then x = x - 5
 
end function
 
global playerX = 0;
global playerY = 0;
 
global player2X = 0;
global player2Y = 0;
 
; main loop
 contols(playerX,playerY,down,up,left,right)
 contols(player2X,player2Y,s,w,a,d)
; main loop



indietom(Posted 2013) [#4]
Here is my actual code to.
Graphics 640,480,0,0
SetBuffer BackBuffer()

Global b = 0

Global playerX = 0
Global playerY = 0
Global playerW = 24
Global playerH = 24

Global player2X = 48
Global player2Y = 0
Global player2W = 24
Global player2H = 24

While b = 0
 Cls
 If KeyHit(1) b = 1
 Rect playerX,playerY,playerW,playerH
 Rect player2X,player2Y,player2W,player2H
 controls(playerX,playerY,200,208,203,205)
 Flip
Wend
End

Function controls(x,y,keyForUp,KeyForDown,keyForLeft,keyForRight)

 If KeyDown(keyForUp) Then y = y - 5 ; 200
 If KeyDown(keyForDown) Then y = y + 5 ; 208
 If KeyDown(keyForLeft) Then x = x - 5 ; 203
 If KeyDown(keyForRight) Then x = x + 5 ; 205

End Function

Function collision(x,y,x2,y2)

 ;If x < x2 And x > x2 And y < y2 And y > y2

End Function



Floyd(Posted 2013) [#5]
Function controls(x,y,keyForUp,KeyForDown,keyForLeft,keyForRight)

 If KeyDown(keyForUp) Then y = y - 5 ; 200
 If KeyDown(keyForDown) Then y = y + 5 ; 208
 If KeyDown(keyForLeft) Then x = x - 5 ; 203
 If KeyDown(keyForRight) Then x = x + 5 ; 205

End Function

The problem here is that function arguments are always called by value. That means x,y are just local copies of the x,y in your main program. The horrible solution is to use global variables for x,y and not pass them to the function. The better way is a user-defined Type which holds relevant info for the things you want to move. Have x,y as Fields and pass the appropriate type object to the function.


Yasha(Posted 2013) [#6]
Floyd pretty much said it, but to expand that answer:

There are two types of variable (actually three, but never mind the third for now): local, and global. They differ in how they are handled by functions.

When you declare a global, that name is visible throughout your program. The one slot can be accessed and set by code anywhere, inside functions or out. It "lives" in the main program body, part of the basic chunk of data that makes up your program's core.

When you use a local (B+ will let you get away with not declaring them, but you should always do it anyway), it is only visible in the current scope. The outer level of the program is one scope; inside each function body is a separate scope. When you call a function, a new scope body is created with the local variables, and it gets destroyed when the function leaves, so there is also nothing shared between two calls of a function (if the same function is active twice at the same time through "recursion", each activation gets its own scope too, but don't worry about that right now).

A function's arguments are always declared as local to that function's scope. So when you call 'controls', new slots named x, y, etc. are created and then filled with the values passed in the function call - but these are separate slots from playerX, playerY, etc. At the end of the call these slots are destroyed so the changes you made to the x slot within the function body are lost.

As Floyd said, and you already discovered, one way to have a function affect the world outside it is to have it access globals. This works, but is rather ugly as it gets confusing later on when you have a lot of code. However, it will do for now (you can stop reading here if you want).


Since the arguments to a function are always copied, it may seem like there's no other way to affect external data, but actually there is: by passing in references to "things" that exist outside the function. While the reference itself is copied, the reference still points to the same "thing", and therefore when you access that "thing" through the parameter name, you can change it. For instance, you know this:

a = CreateImage(128, 128)
b = a        ;We still have just one image - it wasn't copied, but b and a both refer to it
a = 0        ;This doesn't affect b at all, it only overwrite the image *handle*


A simpler, very fast "thing" we can create is an array, which is just a block of memory where we can get at the internal components by a numeric index. Arrays clean up automatically (never need to delete them, they die at the end of their original scope just like variables), and can only be passed to functions rather than assigned to any old variables with '='. With an array you can do this:

Local dirs[2]    ;Array holding directions: 1 is x and 2 is y

Function controls(d[2], keyU, keyD, keyL, keyR)
    If KeyDown(keyU) Then d[2] = d[2] - 5 ; 200
    If KeyDown(keyD) Then d[2] = d[2] + 5 ; 208
    If KeyDown(keyL) Then d[1] = d[1] - 5 ; 203
    If KeyDown(keyR) Then d[1] = d[1] + 5 ; 205
End Function

controls dirs, 200, 208, 203, 205     ; Passes _a reference_ to the dirs array into the function
; where the reference will be called d but point to the same array


'd' and 'dirs' are two names pointing to the same "thing", in this case an array rather than an image, so modifying the array through 'd' will affect what you can later access through 'dirs'. This lets you change things outside of a function, without needing to use globals, which is handy because it makes it very visually explicit what is being changed. You can also affect things in multiple locations (you could pass any int-2 array to controls and modify it in this way).


Friek555(Posted 2013) [#7]
Oh, I didn't know this function

This is normal
This
is code
I
like
writing
in
code


Sorry for destroying this reasonable discussion, I just want to try out this
 awesome code