Problems with types

Blitz3D Forums/Blitz3D Beginners Area/Problems with types

Valgar(Posted 2009) [#1]
Hello everyone
I have a problem with my code and i can't figure out whats wrong.
Basically i have types for enemy,player,bullets,enemy bullets.
The way i create the types is the following:
1)player is created OUTSIDE main loop (a typical while ---> wend) once,and its coordinates are mousex and y
2)if i press a button an enemy is created
3)i update player position
4)i update enemy position
5)main loop is finished if i press esc

Everything is working fine until i create an enemy....
I get a debugger warning telling me that a variable doesnt exist.
That variable is the one(within the enemy type) that store the player coordinates(i do this cause i have some code that send the enemy toward the position that the player had when the enemy was created)
If i put the create player code inside the main loop everything works fine,but the problem is that i create an instance of the player type everytime the main loop is repeated,causing a row of player images,cause i just call the function without any condition (unlike the enemy,which is created based on a keypress).
I try to write down some code to make it clear...

If i replace the variables that store the enemy coordinates with simple Mousex() and Mousey() everything works ok,but its not what i want because i use the mouse coordinates at the moment for debugging purposes(i replace mouse coordinates with proper variables when everything works fine...).
So i suspect that if i create a type outside the main loop its variables doesnt get updated inside the main loop....correct me if i am wrong!
Here is the section of the code that create the enemy:

The lines that give me the error are "enemy\px=player\posx" and "enemy\py=player\posy" ......
If anyone has any suggestion i can stop hitting the wall with my head... :P
Thanks in advance!


lo-tekk(Posted 2009) [#2]
Maybe you forgot to make your player globally accessible then ?

Something like:

Global player.PlayerType

player=createplayer(100,100)



You might change your createplayer() function to return an instance of the created player.


Valgar(Posted 2009) [#3]
Hello.
No the type is globally accessible.
What do you mean by changing the function to return an instance?


_PJ_(Posted 2009) [#4]
By changing the function to return an instance, means essentially:

Type MyType
Field Whatever%
End Type

Function ReturnType.MyType()
Local CreateType.MyType= New NewType
CreateType\Whatever%=1
Return CreateType\MyType
End Function



So that when the enemey instance of the type is created, you can 'do stuff' to that particular enemy:

Local NewBaddie.MyType
If (If KeyHit(2)) Then NewBaddie.MyType=ReturnType.MyType()



_PJ_(Posted 2009) [#5]
Oops sorry for double-post---

So i suspect that if i create a type outside the main loop its variables doesnt get updated inside the main loop....correct me if i am wrong!



This is why you would ened to access the ACTUAL INSTANCE of the type.

For example, in your DisplayPlayer() and DisplayEnemy() functions I would guess that you aren't selecting types but instead using variables (maybe from the Type Fields) that are currently un-declared.

Could you post teh code to these functions?

From what I can assume, they should be something like:


Function DisplayPlayer()
Local GetPlayer.PlayerType = First Player
DrawImage GetPlayer\Immagin%,MouseX(),MouseY()
End Functionm

Function DisplayEnemy()
Local GetEnemy.EnemyType
For GetEnemy.EnemyType = Each EnemyType
DrawImage GetEnemy\Immagin%,GetEnemy\posizx,GetEnemy\poiszy
Next
End Function




Valgar(Posted 2009) [#6]
Hello
Sorry for delay,but i was too busy sleeping... :P
I post the whole code here,cause i think i just dont understand how to use types (and thats a basic thing to understand...).

I think i cant grasp the concept of returning an instance so i can do stuff with it.
Thanks in advance


Valgar(Posted 2009) [#7]
I just noticed that i posted an updated version of the code sorry...
In that code what doesnt work is the "updatebullet()" function...and the enemies are updated just because i have declared into the main loop the variables that store the player coordinates as mousex() and mousey()...
I am stuck,i have tried everything i know to make it work.


_PJ_(Posted 2009) [#8]
I was 'scared' of using ypes for a long time, until somehow they suddenly finally made sense!

Looking at your code

The first thing I noticed was the lines:

Global player.player
Global enemy.enemy

Every time that you refer to a Type with the "label.type" syntax you are telling Blitz that out of any created 'instances' of a Type, (instances are created whenever you use 'New ' ) you are referring specifically to a particular one. In the cases above, a specific instance of the 'player' type which you have labelled 'player' and a specific instance of the 'enemy' type which you have labelled 'enemy'

Since you will need to deal with more than one enemy, I removed the
Global enemy.enemy
since we don't NEED to deal with any one in particular.

Assuming there will be only one player, then it doesn't matter that we have player.player used throughout and the instance of player.player is global.

Back to the 'enemies', in the creation function:
Function create_enemy(energia,immagine,moto,posizx,posizy,power,speed,weapon)


You have identified
	enemy.enemy = New enemy


This is part of the main problem.
As enemy.enemy was global, then you are ALWAYS making the same instance (enemy.enemy) = the NEW instance created.

Instead, I've added in:

Local enemy.enemy = New enemy

[/code]
So the enemy.enemy is JUST FOR THE NEW instance we are creating with the function.


When you come to DisplayEnemy, because previously you had a single global label for enemy.enemy, when you called For / Each, the label was removed from the New enemy created ion order for it to apply to the 'For/Each pointer', so your enemies would not ever be found correctly.

However, with a LOCAL enemy.enemy, For/Each works perfectly and should iterate through all the enemies correctly.


Function displayEnemy()
	Local enemy.enemy
	For enemy.enemy=Each enemy



Now, all that remains is to ensure that the remaining functions, such as zigzag, create ebullet homing etc. know WHICH enemy to deal with.

There's two ways to approach this:

1 - Process EVERY enemy in a For/Each loop
2 - Ensure the function accepts the enemy Type instance as a parameter to identify which enemy it's dealing with.

This largely depends on where the code is called from, but here's examples:

Function createEbullet(ShootingEnemy.enemy)
	ebullet.enemybullet=New enemybullet
	ebullet\image=enemybullet
	ebullet\posx=ShootingEnemy\posx
	ebullet\posy=ShootingEnemy\posy+10
	ebullet\speed=8
	ebullet\power=ShootingEnemy\power
End Function


Function homing()
Local enemy.enemy
For enemy.enemy=Each enemy
;ADDED TO ENSURE UPDATES TO PLAYER POSITION ARE NOTICED BY THE ENEMY
	enemy\px=player\posx					;player position
	enemy\py=player\posy					;player position
	enemy\pa#=Rand(-180,180)		;player angle
	enemy\bx=enemy\bx+Cos(enemy\ba)*enemy\bs;*.1		;update enemy according to calculated angle
	enemy\by=enemy\by-Sin(enemy\ba)*enemy\bs;*.1
	enemy\posx=enemy\bx	;x coord updated
	enemy\posy=enemy\by	;y coord updated
	enemy\name=2 ; not sure what this is for........
Next
End Function





For Createpbullet, because player.player is global, and hopefully tthere's only one layer, then it will know that player.player refers to the ionly instance we created.

_____________________________________________________________________

That should go some way to get your code working better.

As for types generally, I'll see if I can describe them in a way that makes sense:


1. A Type is a 'collection' of data
2. The data in Each Type is stored as INSTANCES.
3. Each INSTANCE contains information according to FIELDS.
4. FIELDS can contain various types of data such as strings, integers and object handles, or floating points. (They can also contain pointers to other Type instances or arrays, but that's not important here)

Example:

To set up a Type containing information about pets, I first need to declare the Type and what Fields it will have. I know I want to have the pets' names, the type of animal it is, and how old each pet is. The first two fields, then (Name$ and Animal$) will be strings, the third, Age% will be a number, so an Integer should do)
Type MyPets
Field Name$
Field Animal$
Field Age%
End Type

Now I need to add in the data. To start with, I need to put in my pet dog, Rufus. Rufus is 7 years old.

Because there's no entries at all yet, and specifically, no entries for Rufus, I need to make a NEW INSTANCE.
This means using the 'New' command.
However, to let Blitz know when I am filling out the data for Rufus, that I am dealing with this NEW INSTANCE, I have to give the Instance a label.

The label I will use is "MyInstance"
Local MyInstance.MyPets = New MyPets


Note that the "MyInstance" label for this NEW INSTANCE is Local. Unlike variables, though the actual data that will be stored in the INSTANCE will be retained within the Type (The Type will retain the data for ALL the instances created within it) what it means having a Local label, is that once I've finished dealing with the New INSTANCE, I can re-use the label elsewhere, it will no longer be relevant to Rufus' INSTANCE.

Let's carry on though, and fill out the data for Rufus (this current NEW INSTANCE).
MyInstance\Name$="Rufus"
MyInstance\Animal$="Dog"
MyInstance\Age%=7

That's it. Rufus now hasan INSTANCE in the Type!

We can add more pets, re-using the "MyInstance" label because it was a Local one...

MyInstance.MyPets = New MyPets
MyInstance\Name$="Church"
MyInstance\Animal$="Cat"
MyInstance\Age%=666

MyInstance.MyPets = New MyPets
MyInstance\Name$="Nemo"
MyInstance\Animal$="Fish"
MyInstance\Age%=1


Now what happens when we want to find information about the pets?

We can do this in two ways, one is to pick out a specific pet, (a specific instance) OR to search through ALL the instances (all the pets)

In order to identify any INSTANCES of the Type, we need a label to do so. We can still use the "MyInstance" label if we wish.

*Re-Using the same label when it's Local doesn't have any particular consequences, aside from that once you exit the function where it's used, or re-assign the label to another Instance, then it no longer has any meaning relating to the prior instance.

So, let's see if we can pick out "Church" the cat from the Type.
Knowing it was the second of three INSTANCES made, I can find "Church"'s INSTANCE by the use of BEFORE, AFTER, FIRST and LAST commands (being #2 of 3, means it's the INSTANCE AFTER #1(First) and the INSTANCE BEFORE 3#(Last) i.e.:

MyInstance.MyPets = After First MyPets
MyInstance.MyPets = Before Last MyPets


These would both result in Church's INSTANCE

But what if I didn't know how many pets there were, or whereabouts Church was?

Then, I'd have to search through all instances and Pick the one for Church from the list:

For MyInstance.MyPets = Each MyPets


Luckily, we know Church's name so we can distinguish his INSTANCE from another:
If MyInstance\Name$="Church" Then


We might need further clarification, just in case we had a dog called "Church", too or something
If ((MyInstance\Name$="Church") And (MyInstance\Animal$="Cat")) Then


Either way, we have identified Church from all the others. If we used the For/Each loop method, we ought to ensure the loop doesn't carry on now we have the Instance we want...

For MyInstance.MyPets = Each MyPets
If ((MyInstance\Name$="Church") And (MyInstance\Animal$="Cat")) Then Exit
Next


Now, we need to think about modifying or editing some of the values given to the fields of these instances. As an example, I'm gonna look at 'Age'

The above code has selected a specific INSTANCE for us. Thanks to the 'Exit' command, just after the 'Next' we can carry on, knowing that "MyInstance.MyPets" is a label that refers to the Instance where the field Name$="Church" and the field Animal$="Cat".
So if the next line was
Print Str(MyInstance\Age%)

It would print Church's Age!

If it was Church's birthday, I could simply alter the value too...
MyInstance\Age%=((MyInstance\Age%)+1)


Let's say, that today IS Church's birthday - he's gonna be 667 !
So as we already determined how to separate Church from the rest, now all we need to do is update the value of that INSTANCE.

BUT! I don't want to have to program every obne again each birthday for each pet, so wouldn't it be great if I had a single function that could do it - perhaps on their birthdays (which is recorded elsewhere for simplicity's sake) there's a function called "Birthday()" Which then does the work...

To make sure we get the right pert's birthday though, we'll give the Birthday() function two parameters, Name and Animal.

Function Birthday(Name$,Animal$)


Our birthday function will use the ideas already presented above all together:
So the first theing the Birthday function needs to do, is declare the Local label (because, being in a function, any previous uses will now have been 'forgotten', and we want to let Blitz know that we are labelling the MyPets Type instances)
Function Birthday(Name$,Animal$)
Local MyInstance.MyPets

However, we're not making any new Instances, only updating the existing ones, so we'll need that For/Each loop...
Function Birthday(Name$,Animal$)
Local MyInstance.MyPets
For MyInstance.MyPets = Each MyPets


And again, we need to identify the precise instance accordng to our parameters of Name$ and Animal$

So...

Function Birthday(Name$,Animal$)
Local MyInstance.MyPets
For MyInstance.MyPets = Each MyPets
If ((MyInstance\Name$="Church") And (MyInstance\Animal$="Cat")) Then Exit
Next

Now, we have the right Instance, we can add a year to their current age, and print it, to confirm the change!

Function Birthday(Name$,Animal$)
Local MyInstance.MyPets
For MyInstance.MyPets = Each MyPets
If ((MyInstance\Name$="Church") And (MyInstance\Animal$="Cat")) Then Exit
Next
MyInstance\Age%=((MyInstance\Age%)+1)
Print "Happy Birthday! "+Str(MyInstance\Age%)+" Today!"


SO now we can idenitify, retrieve and modiify individual instances. But one thing may seem a liittle annoying....
Every time the birthday function is run, it has to search through EVERY instanec of the type?
Go through ALL THE PETS just to find which one's birthday it is???

At some point, yes. A search will need to be made. HOWEVER -
If that particular instance is ever identified with a label, it can be passed to a function on it's own, OR maybe stored with a Global label.

Let's just say (you may have guessed) that Church, the cat is my favourite pet. So I'm gonna honour him with the status of having a Global label :)

Global FavouritePet.MyPets


Way back when I was entering the data, and I gave Church's information as:
MyInstance.MyPets = New MyPets
MyInstance\Name$="Church"
MyInstance\Animal$="Cat"
MyInstance\Age%=666

We were using the Local, re-usable label of "MyInstance". After thee lines for the Cat, I shall make sure that the Global FavouritePet points to this particular Instance.
MyInstance.MyPets = New MyPets
MyInstance\Name$="Church"
MyInstance\Animal$="Cat"
MyInstance\Age%=666
Global FavouritePet.MyPets = MyInstance


There. Now, even if the label MyInstance changes (as in, changes which Instance it refers to), FavouritePet.MyPets as always going to point to the Instance for Church. (UNLESS I ever use FacouritePet.MyPet= ..... again! )

Having a specific instance can be handy for functions that deal with Instances rather than each of these functions needing to search through the entire Types.

For ecample, the birthday function could be:

Function Birthday(BirthdayInstance.MyPets)
BirthdayInstance\Age%=((BirthdayInstance\Age%)+1)
Print "Happy Birthday! "+Str(BirthdayInstance\Age%)+" Today!"
End Function


And as a special treat...

Function Birthday(BirthdayInstance.MyPets)
BirthdayInstance\Age%=((BirthdayInstance\Age%)+1)
Print "Happy Birthday! "+Str(BirthdayInstance\Age%)+" Today!"
If BirthdayInstace.MyPets = FavouritePet.MyPets Then Print "Have Some Cake!"
End Function


Lastly, What if I wanted that function to get hold of the Instance so I knew when it was a Pet s birthday, and whose birthday it was?

For now, we need to assume another Field was added to the Type:
Field DateOfBirth$


And for simplicity's sake, the DateOfBirth$ field contains dates in the format "01/Jan/1999" as a string. (The same as CurrentDate() returns).

So here's where our search of all the pets comes in...
Instead of checking for names, though, we're looking for whether the date of birth matches the CurrentDate()

Technically, this is (shortening each date to ignore the year, it's only day and month we need)
((Left$(MyInstance\DateOfBirth$,Len(MyInstance\DateOfBirth$)-5))=(Left$(CurrentDate$(),Len(CurrentDate$()-5)))


Function CheckDate()
Local MyInstance.MyPets
For MyInstance.MyPets=Each MyPets
If 
((Left$(MyInstance\DateOfBirth$,Len(MyInstance\DateOfBirth$)-5))=(Left$(CurrentDate$(),Len(CurrentDate$()-5)))


However - unlike before, when we were searching for name$ and/or animal$, this time, we need to account for the fact that it's possible that more than one pet could have a birthday on the same date!
This means, we no longer can just 'Exit' the loop here, but must allow the loop to continue until ALL the pets have been iterated through.

But this - you may have guessed - will give us problems. How will we know which Pet is which after the loop has iterated because MyInstance at the end of the For/Each loop will only = whatever "Last MyPets" is.

That's where it comes in handy, that we had changed the Birthday Function to accept an Instance as a parameter. We have the IF line in our CheckDate function to identify the valid ce(s) so can pass that to the Birthday Function, then continue the loop as normal...

Function CheckDate()
Local MyInstance.MyPets
For MyInstance.MyPets=Each MyPets
If 
((Left$(MyInstance\DateOfBirth$,Len(MyInstance\DateOfBirth$)-5))=(Left$(CurrentDate$(),Len(CurrentDate$()-5))) Then Birthday(MyInstance.MyPets)
Next
End Function


Lastly, Let's look at returning an Instance from a function:

We know how to accept an instance as a parameter to a function with
Function Birthday(BirthdayInstance.Mypets)


BirthdayInstance.MyPets is the Instance passed IN to the function Birthday()

Just as, say, for
KeyDown(1)


1 is the value passed IN to the function KeyDown()

Tghe difference, of course, is that BirthdayInstance.MyPets has the label "BirthdayInstance" specifying which instance of MyPets is being used, because just using "MyPets" would not clarify exactly which instancve out of the whole MyPets Type you meant.

In the KeyDown example, 1 is just that, the number, without any labels or handles or anything, because there's nothing else that 1 can represent.

So, to get an Instance OUT of a function, we need a label attached to the function to specify the particular instance:

Function GetInstance.MyPets()


This ensures for us that whenever we call "GetInstance()" we should expect the result to be a Type instance of MyPets.

We can use this as a step in our birthday program:
Note the Return line returns a labelled Instance like the Function name.
Function GetInstance.MyPets(Date$)
Local MyInstance.MyPets
For MyInstance.MyPets = Each MyPets
((Left$(MyInstance\DateOfBirth$,Len(MyInstance\DateOfBirth$)-5))=(Left$(CurrentDate$(),Len(CurrentDate$()-5))) Then Return MyInstance.MyPets
Next
End Function

Which can operate with a modified CheckDate() Function:
Function CheckDate()
Local MyDate$=CurerentDate()
Birthday(GetInstance.MyPets(MyDate$))
End Function


So from start to finish, all our Functions dealing with Types:

Type MyPets
	Field Name$
	Field Animal$
	Field Age%
	Field DateOfBirth$
End Type

Local MyInstance.MyPets = New MyPets
MyInstance\Name$="Rufus"
MyInstance\Animal$="Dog"
MyInstance\Age%=7
MyInstance\DateOfBirth$="3/Mar/2002"
MyInstance.MyPets = New MyPets

MyInstance\Name$="Church"
MyInstance\Animal$="Cat"
MyInstance\Age%=666
MyInstance\DateOfBirth$="6/Jun/1343"
Global FavouritePet.MyPets = MyInstance.MyPets

MyInstance.MyPets = New MyPets
MyInstance\Name$="Nemo"
MyInstance\Animal$="Fish"
MyInstance\Age%=1
MyInstance\DateOfBirth$="16/Aug/2008"

Function Birthday(BirthdayInstance.MyPets)
	BirthdayInstance\Age%=((BirthdayInstance\Age%)+1)
	Print "Happy Birthday! "+Str(BirthdayInstance\Age%)+" Today!"
	If BirthdayInstace.MyPets = FavouritePet.MyPets Then Print "Have Some Cake!"
End Function

Function GetInstance.MyPets(Date$)
	Local MyInstance.MyPets
	For MyInstance.MyPets = Each MyPets
	((Left$(MyInstance\DateOfBirth$,Len(MyInstance\DateOfBirth$)-5))=(Left$(CurrentDate$(),Len(CurrentDate$()-5)))) Then Return MyInstance.MyPets
Next
End Function

Function CheckDate()
	Local MyDate$=CurerentDate()
	Birthday(GetInstance.MyPets(MyDate$))
End Function



Valgar(Posted 2009) [#9]
Thank you very much!
Now i am carefully studying what you just wrote.
I knew the problem was with types and how i was using them....it seems that i lacked the basics.
I really appreciate your help,hope someday i could be of help somehow :)


Valgar(Posted 2009) [#10]
I have made some modification in the code to work locally.
Apparently now i am able to use the single player i create outside the main loop but the enemies now act very wierd,with increased speed and movements that i havent made.
It seems the variables that store the positions are all mixing things up.
The code now is without images and can be run if "copy&paste":

Maybe i am iterating trough the instances in the wrong way?


Valgar(Posted 2009) [#11]
I am sure the error lies in the way i iterate trough the instances in the 3 movement functions....and i think the error is cause i use a "for enemy=each enemy" loop instead of sorting the type based on the movement "flag"....
but even after carefully studying all the examples (i admit now i know more than before) i cant figure out how to do it.


Valgar(Posted 2009) [#12]
Can't make it working.
After various trying it seems i can't get the grasp of it.
What give me the problem is that i have a main function that make enemies ( a type called "enemy")and one that display all enemies("displayenemy()");inside this function i call 3 others functions based on a type field ("enemy\motion")....
If the field is 1 i call the "straight" function
If its 2 i call the "homing" one
If its 3 i call the "zigzag" one
Those 3 functions deals with the enemy movement,so i dont have to type all the movement code everytime i call the displayenemy() (not that it matters...cause i call that just once! but its just to understand how to use functions inside functions that deals with types...).
If i type the code inside the main display function everything works fine,but if i use separate functions everything get jerky with all sort of funny results(like enemies stopping or going twice the speed)!
I am sure the error lies in the 3 sub functions....and how i try to access a particular type instance..but i definitely cant understand why,cause the code i write kind of make sense.
The main function is:
Function displayEnemy()
	Local enemy.enemy
	For enemy.enemy=Each enemy
		Select enemy\motion	;we choose different coordinates based on the type of motion we choose
			Case 1 
				Color 255,0,0
				;enemy\posy=enemy\posy+enemy\speed	;we update just the y coordinates of enemies
				straight()
			Case 2
				Color 255,255,0
				;enemy\bx=enemy\bx+Cos(enemy\ba)*enemy\bs;*.1		;update enemy according to calculated angle
				;enemy\by=enemy\by-Sin(enemy\ba)*enemy\bs;*.1
				;enemy\posx=enemy\bx	;x coord updated
				;enemy\posy=enemy\by	;y coord updated
				homing()
			Case 3
				Color 0,255,255
				;enemy\posx=enemy\posx+enemy\direzione	;this initiate the movement on the x axis
				;enemy\posy=enemy\posy+enemy\speed/3	;this initiate the movement on the y axis half the speed of the one on the x axis
				;If enemy\posx=>enemy\borderdx	;if the enemy reach its right border limit
				;	enemy\posx=enemy\posx-enemy\speed	;this tell the enemy to start to move to the left
				;	enemy\direzione=-enemy\speed	;important! this tell the enemy that its direction is the opposite now
				;EndIf
				;If enemy\posx=<enemy\bordersx	;if the enemy reach its left border limit
				;	enemy\posx=enemy\posx+enemy\speed	;this tell the enemy to start move to the right
				;	enemy\direzione=+enemy\speed	;important! this tell the enemy that its direction is the opposite now
				;EndIf
				zigzag()
		End Select
		Rect enemy\posx,enemy\posy,20,20,True
		enemy\lifespan=enemy\lifespan-1	;we decrease the lifespan by 1 unit
		If enemy\lifespan=<0 Then Delete enemy	;when lifespan reach 0 its deleted
	Next
End Function

I have commented the lines of code that are part of the 3 sub functions just to show the difference.
Here is the 3 sub functions:
1)
Function homing()
	Color 0,0,255
	Local enemy.enemy
	For enemy.enemy=Each enemy
		If enemy\motion=2 Then Exit
	Next
	enemy\bx=enemy\bx+Cos(enemy\ba)*enemy\bs;*.1		;update enemy according to calculated angle
	enemy\by=enemy\by-Sin(enemy\ba)*enemy\bs;*.1
	enemy\posx=enemy\bx	;x coord updated
	enemy\posy=enemy\by	;y coord updated
End Function

2)
Function straight()
	Color 255,0,0
	Local enemy.enemy
	For enemy.enemy=Each enemy
		If enemy\motion=1 Then Exit
	Next
	enemy\posy=enemy\posy+enemy\speed	;we update just the y coordinates of enemies
End Function

3)
Function zigzag()
	Color 0,255,0
	Local enemy.enemy
	For enemy.enemy=Each enemy
		If enemy\motion=3 Then Exit
	Next
		enemy\posx=enemy\posx+enemy\direzione	;this initiate the movement on the x axis
		enemy\posy=enemy\posy+enemy\speed/3	;this initiate the movement on the y axis half the speed of the one on the x axis
		If enemy\posx=>enemy\borderdx	;if the enemy reach its right border limit
			enemy\posx=enemy\posx-enemy\speed	;this tell the enemy to start to move to the left
			enemy\direzione=-enemy\speed	;important! this tell the enemy that its direction is the opposite now
		EndIf
		If enemy\posx=<enemy\bordersx	;if the enemy reach its left border limit
			enemy\posx=enemy\posx+enemy\speed	;this tell the enemy to start move to the right
			enemy\direzione=+enemy\speed	;important! this tell the enemy that its direction is the opposite now
		EndIf
End Function


Anyone have any idea how i can make the 3 sub functions work properly?


Stevie G(Posted 2009) [#13]
This should work.

You need to pass the instance of the enemy type to the movement functions so that the function knows which one you want to move. You do not need to iterate through every instance within the function as you already know it!!



Alternatively, you could contain everything in a single update function ..

Function UpdateEnemy()

	Local e.enemy

	For e.enemy = Each enemy

		Select e\motion
	
			Case 1	;straight
			
			Color 255,0,0
				e\posy=e\posy+e\speed	;we update just the y coordinates of enemies
			
			Case 2	;homing
			
			Color 0,0,255
				e\bx=e\bx+Cos(e\ba)*e\bs;*.1		;update enemy according to calculated angle
				e\by=e\by-Sin(e\ba)*e\bs;*.1
				e\posx=e\bx	;x coord updated
				e\posy=e\by	;y coord updated
			
			Case 3	;zigzag
			
				Color 0,255,0
				e\posx=e\posx+e\direzione	;this initiate the movement on the x axis
				e\posy=e\posy+e\speed/3	;this initiate the movement on the y axis half the speed of the one on the x axis
				If e\posx=>e\borderdx	;if the enemy reach its right border limit
					e\posx=e\posx-e\speed	;this tell the enemy to start to move to the left
					e\direzione=-e\speed	;important! this tell the enemy that its direction is the opposite now
				EndIf
				If e\posx=<e\bordersx	;if the enemy reach its left border limit
					e\posx=e\posx+e\speed	;this tell the enemy to start move to the right
					e\direzione=+e\speed	;important! this tell the enemy that its direction is the opposite now
				EndIf

		End Select
	
		Rect e\posx,e\posy,20,20,True
		e\lifespan=e\lifespan-1	;we decrease the lifespan by 1 unit
		If e\lifespan=<0 Then Delete e	;when lifespan reach 0 its deleted

	Next

End Function


I'm not sure if deleting a type instance when iterating through them is a good idea - although I guess it depends on what you are doing with them.

Hope this helps.


Valgar(Posted 2009) [#14]
Wow thanks a lot!
That work perfectly now.
I quite didn't understood the mechanics to pass an instance of a type trough a function....and honestly i still can't grasp it properly i am afraid....i have to spend more time doing simple examples.

I delete the type instance because i dont want the enemy to exist forever even if i dont destroy it(to free up resources).
Do you think its better to put the delete code outside the "for----next" loop?