Moving data between types
BlitzPlus Forums/BlitzPlus Programming/Moving data between types
| ||
each type has its own fields. These variables are specific to that type itself, and can't be used anywhere else except between the for blah.blah = each blah loop and when you are initializing the variables. I have my tricky ways to move data between types, but I feel like there is a better way to do it. My current issue is... What is the best way to check if one object has collided with another? I can't really do the whole if imagescollide thing, because they are there own types and their x, y and images are of their own type. What is the best way to go about this? |
| ||
If you design a variable GLOBAL you can use its field also outside the FOR/EACH loop:Type Enemy Field No%, X%, Y% End Type Global Hulk.Enemy=New Enemy BlaBla WaitKey() Function BlaBla() Print Hulk\X End Function You can also swap this extern type member: Type Enemy Field No%, X%, Y% End Type Global Hulk.Enemy For i%=0 To 9 loc.Enemy =New Enemy loc\X=i*100 loc\Y=Rnd(99) loc\No=i Next BlaBla Print Hulk\X WaitKey() Function BlaBla() For loc.Enemy =Each Enemy If loc\No=5 Hulk=loc EndIf Next End Function |
| ||
There's no particular requirement that the variable be global, only that it be any valid variable other than the one controlling the For loop. A loop only automatically increments its controlling variable; anything you put anywhere else will stay where it is. (You should avoid using globals unless you actually need global access to a variable name: in Midimaster's example the value should just be returned by the function, since that's all that the global is actually being used for) You can also put objects straight into variable slots - either local, bank, array, or fields of other objects - as soon as they're created, and not need to loop over them with For at all unless you actually want to loop over the whole list. Once you have a valid variable containing an object, the fields can be used for any purpose and modified at any time. So: Local a.Thing = GetThing() Local b.Thing = GetThing() Local dist# = Sqr((a\x - b\x)^2 + (a\y - b\y)^2) If dist < a\radius Or dist < b\radius Then HandleThingCollision a, b ...is valid, if not especially illuminating. |
| ||
ALright so we're getting somewhere here. My next question is, say I wanted to spawn a new instance of that type somewhere outside the main program, like for example if you press space it'll spawn an enemy or something. Then I wanted to check image collision with another type, the player. What's the best way to do that? I tried declaring the type as global and then creating a new instance in my while wend loop. However, this doesn't work because I get an error or my program crashes. |
| ||
By itself that sounds more or less like a normal way to do things. Perhaps you could post some of your particular code? I don't know if this is on the right track, but remember that the type of a variable or value only affects what you can do with the whole variable or value; it doesn't place restrictions on what you use its component fields (if any) for - their own type does. So a player, that is an instace of PlayerType, and a bot, that is an instance of EnemyType, can't both be indiscriminately passed to the same comparison function (checking player/player, bot/bot, or player/bot without specifying) - but they can both contain e.g. an image field, and you can check collisions on the image without worrying about what the type of its owner is. e.g. Local p.Player = ..., e.Enemy = ... If ImagesCollide(p\img, p\x, p\y, 0, e\image, e\xpos, e\ypos, 0) Then ... Using different field names just to visually reinforce that the result of the expression carries no information about how it was obtained: an image is an image regardless of whether it was extracted from a field named img in an object of one type or a field named image in an object of another type. You could also factor out the common elements into a component type (e.g. "Movable"), that both bots and players might "own" instances of - that way you can just compare two Movables without needing to think about what they actually control. (This is a bit more complicated to implement.) Useful if you want to also have bots colliding with other bots, players hunting both players and bots, etc. |
| ||
normally you have one player, but a lot of enemies. Type TPlayer Field X%, Y%, Img% End Type Type TEnemy Field X%, Y%, Img% End Type Global Player.TPlayer= New TPlayer For i%=0 to 9 Enemy.TEnemy= New TEnemy Next Function CheckAllCollisions() For loc.TEnemy =Each TEnemy If ImagesCollide(Player\Img, Player\x, Player\y, 0, loc\Img, loc\x , loc\y, 0) Delete loc Endif Next End It is not necessary, that the player is GLOBAL, but it is more easy to understand for beginners.... |
| ||
Well basically how i did things was Type player field x,y,image end type type enemy field x,y,image end type player.player= new player player\x=100 player\y=100 player\image=loadimage("blfsdjklfaskd.png") enemy.enemy=new enemy enemy\x=200 enemy\y=200 enemy\image=loadimage("jkldsfjlkjadf.png") while not keyhit(1) cls for player.player = each player drawimage player\image,player\x,player\y player\x=player\x+rnd(-2,2) next for enemy.enemy = each enemy drawimage enemy\image,enemy\x,enemy\y enemy\y=enemy\y+rnd(-2,2) next flip wend NOW That is an extremely and simplified (and pointless) version of what I have so far (if i pasted what I really have it'd be a jumbled mess lol) SO for my example, what would be the best way to go about checking if the player\image collides with the enemy\image? I understand that the image handle kinda doesn't even matter, for some reason lol. It's just the x and y for each that I need to check against each other, which raises problems because they are in separate objects and in separate for loops. How I'd normally go about this is to simply declare a variable and name it like enemyx, and then one for enemyy, then for each iteration of the for next loop I'd make the enemy\x = enemyx, so that I can just check against that variable, not against the field of the enemy. Thanks a lot for helping though guys |
| ||
raises problems because they are in ... separate for loops Simplest solution: try nesting your loops: for player.player = each player for enemy.enemy = each enemy CheckCollision player\x, player\y, enemy\x, enemy\y ;(however you do this) next next So it loops over each player, and on each iteration checks every enemy against it. This method doesn't scale well (imagine: if you had a thousand of each, that's only two thousand things to draw on screen - not so bad - but a million collision checks), but it should be fine for say fewer than ten players and a couple of hundred enemies. For very large numbers of things you'd use a more complex approach, but no sense in getting complicated until you need it. Note also that you don't need to combine drawing and collision checking in the same section of code (in fact, it's a good idea to keep them separate). You should use non-nested loops for the drawing, or you'll end up with a lot of redundant overdraw. |