Global Types Problem
Blitz3D Forums/Blitz3D Beginners Area/Global Types Problem
| ||
I'm having trouble with one of my global type collections. It seems that although I create my movement vector type and set it to have a value, that value is turned null when I run it in another function, despite that my type collection is global. Hopefully someone might be able to see what I'm doing wrong. I'll post the relevant snippets. Here is the code I'm using for creating the missle which, in turn, establishes the movement vector. ;Set up the basic missle. It will be run in RunAllMissles() ;Add more code if the missle has explosions, arcing, ect. Missles.Missle = New Missle Missles = User\Lasers Missles\X# = User\X# Missles\Y# = User\Y# Missles\Z# = User\Z# Missles\Speed# = User\Speed# Missles\ObjectNum = CopyEntity(User\Lasers\ObjectNum) PositionEntity Missles\ObjectNum, Missles\X#, Missles\Y#, Missles\Z# Missles\Move = New Vector Missles\Rotation = New Vector Missles\Move = ScaleVect(User\Rotation, Sync(Missles\Speed#)) ;Please note that when I write the vector to my debug log it is displayed normally. Now for the code where I run the missle, and also where if I try to read any of the X#, Y# or Z# values of the vector it will cause an error claiming the values haven't been initialized: Function RunAllMissles(Player.Player) ;This will run every missle For Missles.Missle = Each Missle If Missles\ObjectNum > 0 If EntityDistance(Missles\ObjectNum, Player\ObjectNum) < 500 ;If the missle is still active then run it X# = Missles\X# ;+ Missles\Move\X# Y# = Missles\Y# ;+ Missles\Move\Y# Z# = Missles\Z# ;+ Missles\Move\Z# PositionEntity Missles\ObjectNum, X#, Y#, Z# Else FreeEntity Missles\ObjectNum Delete Missles EndIf EndIf Next End Function So if anyone has any idea what I might be doing that would cause my global type to simply 'lose' its attatched vector for movement I'd be grateful. Sorry if my problem isn't clear enough. I can post the entire code if you guys need it, although I doubt any of you want to sift through 300 lines of code... |
| ||
Looked at the code briefly and noticed that you assigned have a new Vector to the Move field but then assigned the same field with the output of a function. If your function does not return a Vector type then this could be the problem. At any rate, it is probably creating an unused type. |
| ||
ScaleVect() is a function I have that multiplies a vector by a scalar and returns the coresponding vector. It isn't the problem as it and all my other vector library functions work fine in the other sections of my code. What I am confused about is if by having a nested type the 'nested' type becomes local accidentally? Or perhaps I am required to do something that I am forgetting. I run through the missles type collection using a For Each loop. I don't know whether this has anything to do with how I am using that loop. I'm not that experienced with regards to using types so I don't know whether I'm following bad programming practices that would cause this. I have no idea why my vector is being turned into a null one. |
| ||
I think the problem may be with Missles\X# = User\X#,ect... Whenever I try to asign one type value to another I get entity must be a type. Mabye asign a variable to User\X# where it is updated like user_x#=User\X#? |
| ||
No, that isn't it. The position of the missles is fine. Its just the movement vector isn't copying over, so the missles stay in one place after I've shot them, that is if I comment out the movement code, as with the code in it crashes saying that the movement vector doesn't exist. Also, when adding in an intialized flag, it seems that none of the missles have been 'initialized' at all! So it is as if the missles type collection doesn't appear to exist for the purposes of the RunAllMissles function, however in the main loop of my program and the function that created the missles it appears normally. But as soon as I try accessing the function in the RunAllMissles it is basically telling me that there is nothing there... Ugh! |
| ||
Okay I've done a little more testing. Apparently there isn't a global problem, or function problem. It now appears that the missles simply aren't being saved at all after they are created. I'm stuck. I now have no idea where the problems are in my code so I'll post all of it. If someone has any clue what I'm screwing up I'd be eternally grateful. ;Include the vector mathematics library Include "vector.bb" ;Include the blitz basic demo start code Include "start.bb" ;Setup all non-type global variables Global CameraHandle = 0 Global ScreenWidth = 640 Global ScreenHeight = 480 ;Friction will be used to slow the ship. 1 is no friction, 0 is absolute friction Global Friction# = .5 ;Default Sync Global SyncRate# = 100 Global Missles.Missle ;-------------------------------- ;---------MAIN PROGRAM----------- ;-------------------------------- GameEnds = 0 User.Player = SetupGame() Repeat StartSync# = MilliSecs() ;=========== ControlPlayer(User) UpdateCamera() ;=========== ;Use a counter as AI modifications aren't necessary every loop AICounter = AICounter+1 If AICounter > 5 AICounter = 0 RunAllAI() EndIf ;The AI is modified every 5 loops. Enemies are controlled every loop, however. RunAllEnemies() ;=========== RunAllMissles(User) RunAllExplosions() ;=========== GameEnds = Triggers() ;=========== UpdateWorld RenderWorld Flip ;=========== SetSync(StartSync#) Until GameEnds Or KeyHit(1) End ;-------------------------------- ;================================ ;-------------------------------- ;TYPES ;Player Type Type Player Field X# ;x position Field Y# ;y position Field Z# ;z position Field Move.Vector = New Vector ;vector controlling movement Field Rotation.Vector = New Vector ;vector controlling current rotation Field Thrust.Vector = New Vector ;vector controlling the thrusting Field Manuever# ;regulates the factor by which the object can pivot Field Speed# ;regulates speed by using this as a maximum value Field Health ;the players health Field ObjectNum ;the object number Field BrushNum ;the brush number holding texture and data Field AttackReflex ;controls time since last attacking Field StunReflex ;controls time since recovering from an attack Field Lasers.Missle = New Missle End Type ;Enemy Type Type Enemy Field X# ;x position Field Y# ;y position Field Z# ;z position Field Move.Vector = New Vector ;vector controlling movement Field Rotation.Vector = New Vector ;vector controlling current rotation Field Impulse.Vector = New Vector ;vector controlling AI impulse behavior Field Speed# ;regulates speed by using this as a maximum value Field Manuever# ;regulates the factor by which the object can pivot Field Health ;the enemy's health Field ObjectNum ;the object number Field BrushNum ;the brush number holding texture and data Field AttackReflex ;controls time since last attacking Field StunReflex ;controls time since recovering from an attack Field Species ;used to regulate what type of AI actions to take ; 0 = Red (swarming) :: 1 = Blue (sneaker) :: 2 = Green (missler) Field Projectile.Missle = New Missle ;stores the type of projectile the object uses Field AI ;This value is used to determine what action the enemy performed End Type ;Missle Type ;A type used to represent projectile fire Type Missle Field X# ;x position Field Y# ;y position Field Z# ;z position Field Move.Vector = New Vector ;vector controlling movement Field Rotation.Vector = New Vector ;vector controlling rotation (arcing projectile) Field Speed# ;controls the speed of the missle Field Maneuverability# ;controls the pivoting capabilities of arcing projectiles Field ObjectNum ;stores the object number of the projectile Field BrushNum ;stores the brush number (or texture number) of the projectile Field Detonate.Explosion = New Explosion ;stores the explosion type of the projectile on impact Field Damage ;controls the power of the missle Field Effect ;controls the effect of the missle Field Reflex ;controls the time since firing the missle Field Species ;used to regulate what type of movement the missle follows Field Initialized ;Flag storing whether the missle has been initialized or not End Type ;Explosion Type Type Explosion Field X# ;x position Field Y# ;y position Field Z# ;z position Field Damage ;controls the damage of the explosion Field Size# ;controls the maximum size of the explosion,speed and duration Field ObjectNum ;stores the object number of the explosion Field BrushNum ;stores the brush number of the explosion Field SoundHandle ;stores the sound handle of the explosion Field Effect ;controls the effect of the explosion End Type ;Functions Function ControlPlayer(User.Player) ;This function acts upon the user input and applies the appropriate ;action ;INPUT Firing = 0 Thrusting = 0 Strafe = 0 MoveMouse ScreenWidth/2, ScreenHeight/2 If KeyDown(57) Then Firing = 1 If MouseDown(1) Then Thrusting = 1 If MouseDown(2) Then Strafe = 1 ;Fire lasers If Firing = 1 And MilliSecs()-User\AttackReflex > 500 User\AttackReflex = MilliSecs() ;Set up the basic missle. It will be run in RunAllMissles() ;Add more code if the missle has explosions, arcing, ect. Missles.Missle = New Missle Missles = User\Lasers Missles\X# = User\X# Missles\Y# = User\Y# Missles\Z# = User\Z# Missles\Speed# = User\Lasers\Speed# Missles\ObjectNum = CopyEntity(User\Lasers\ObjectNum) PositionEntity Missles\ObjectNum, Missles\X#, Missles\Y#, Missles\Z# Missles\Move = New Vector Missles\Rotation = New Vector Missles\Move = ScaleVect(User\Rotation, Sync(Missles\Speed#)) Missles\Initialized = 1 EndIf ;Apply Rotation If Not Strafe M# = User\Manuever ;Movement style using mouse speed rather than position YAng# = WrapAngle(EntityYaw(User\ObjectNum)-M#*MouseXSpeed()) XAng# = WrapAngle(EntityPitch(User\ObjectNum)+M#*MouseYSpeed()) If XAng# > 70 And XAng# < 180 Then XAng# = 70 If XAng# < 290 And XAng# > 180 Then XAng# = 290 RotateEntity User\ObjectNum, XAng#, YAng#, 0 ;Set the rotation vector to the current orientation User\Rotation = AngToVect(WrapAngle(YAng#-90), XAng#) EndIf ;Add to Thrust Vectors If Thrusting If Strafe ;If the player has strafing engines on the thrust vectors will lie perpendicular to the rotation Else ;For normal movement the thrust vector is simply a magnitude of the rotation vector User\Thrust = User\Rotation User\Thrust = ScaleVect(User\Thrust, (Sync(User\Speed#)-VectLength(User\Move))*.025) EndIf EndIf ;Calculate and reposition movement User\Move = ScaleVect(User\Move, 1.0-Sync(Friction#)) ;Stop ship if it is moving too slowly If VectLength(User\Move) < 3*Sync(Friction#) Then User\Move = ScaleVect(User\Move, 0) User\Move = AddVect(User\Move, User\Thrust) User\Thrust\X# = 0 User\Thrust\Y# = 0 User\Thrust\Z# = 0 User\X# = User\X# + User\Move\X# User\Y# = User\Y# + User\Move\Y# User\Z# = User\Z# + User\Move\Z# PositionEntity User\ObjectNum, User\X#, User\Y#, User\Z# ;Update Camera PointEntity CameraHandle, User\ObjectNum End Function Function UpdateCamera() ;This function updates the camera End Function Function EnemyAI(AI.Enemy) ;This function will be run to determine what the enemies will do ;It will send the result to the ControlEnemy() function End Function Function ControlEnemy(Num.Enemy) ;This will control physics for the enemy based on their AI reaction End Function Function ControlExplosion(Num.Explosion) ;This will run a specified explosion End Function Function RunAllAI() ;This will run all of the specified AI's End Function Function RunAllEnemies() ;This will run all of the enemies End Function Function RunAllMissles(User.Player) ;This will run every missle For Missles.Missle = Each Missle If Missles\ObjectNum > 0 And Missles\Initialized = 1 If EntityDistance(Missles\ObjectNum, User\ObjectNum) < 500 ;If the missle is still active then run it X# = Missles\X# + Missles\Move\X# Y# = Missles\Y# + Missles\Move\Y# Z# = Missles\Z# + Missles\Move\Z# PositionEntity Missles\ObjectNum, X#, Y#, Z# Else FreeEntity Missles\ObjectNum Delete Missles EndIf EndIf Next End Function Function RunAllExplosions() ;This will run every explosion End Function Function Triggers() ;This function basically checks to see whether the player has reached the goal ;and to see whether the player has died. ;It may serve as a simple template for other triggers in the full version End Function Function SetupGame.Player() ;This function sets up the game it is used as a more primitive function which ;will later be used for more advanced world loading commands ;Set up the player object SeedRnd(MilliSecs()) User.Player = New Player User\Move = ScaleVect(AngToVect(0, 0), 0) User\Thrust = ScaleVect(AngToVect(0, 0), 0) User\Rotation = ScaleVect(AngToVect(0, 0), 1) User\Health = 6 User\ObjectNum = LoadMesh("spaceship.x") User\BrushNum = LoadBrush("spaceship.bmp") PaintEntity User\ObjectNum, User\BrushNum User\AttackReflex = MilliSecs() User\StunReflex = MilliSecs() User\Speed# = 60.0 User\Manuever# = .5 User\Lasers = New Missle User\Lasers\ObjectNum = LoadSprite("big_spark.bmp") HideEntity User\Lasers\ObjectNum User\Lasers\Speed# = 80.0 ;Setup Camera stuff CameraHandle = CreateCamera(User\ObjectNum) PositionEntity CameraHandle, 0, 0, -30 PointEntity CameraHandle, User\ObjectNum ;Set up some cubes for spacial orientation For X = 1 To 100 Num = CreateCube() PositionEntity Num, Rand(300), Rand(300), Rand(300) Next Return User End Function ;////////Sync Functions///////// Function Sync#(Value#) ;This function will sync a value based on the syncrate Return Value#/SyncRate# End Function Function SetSync(StartSync) ;This will set up the SyncRate values and smooth them with the last sync value ;to prevent jerkiness If MilliSecs()-StartSync > 1 SyncRate# = (SyncRate#*.5)+((1000.0/(MilliSecs()-StartSync))*.5) Else SyncRate# = 1000.0 EndIf End Function |
| ||
Show us your ScaleVect function, please. <EDIT> Wow, I speak and you obey... 45 seconds earlier! =D (Ok, ok, you didn't post the ScaleVect function, but you posted enough code that I think I know what the problem is.) Look here: ;Set up the basic missle. It will be run in RunAllMissles() ;Add more code if the missle has explosions, arcing, ect. Missles.Missle = New Missle Missles = User\Lasers Missles\X# = User\X# Missles\Y# = User\Y# Missles\Z# = User\Z# Missles\Speed# = User\Lasers\Speed# Missles\ObjectNum = CopyEntity(User\Lasers\ObjectNum) PositionEntity Missles\ObjectNum, Missles\X#, Missles\Y#, Missles\Z# Missles\Move = New Vector Missles\Rotation = New Vector ... Here you create a new Missle and assign a pointer called Missles to it. But then you assign Missles to the same Missle that User\Lasers points to... and you forget about the one you just Newed! Then you go about "initializing" everything in the old object, replacing the old values that were in User\Lasers. So you end up with a ton of empty Missle objects with un-initialized Vectors and such. That's what I see anyway. What you should do is put in a debugging function that prints out the values of all your type objects, so you'll always know how many there are and which ones are valid if you have a question. Also, you don't need to put "New <type>" within your Field declaration. I don't think it does anything at all, but it can be misleading. One more thing. Not that it matters in your program, but it's spelled "missile". Just in case you write some in-game help text for the user or something. |
| ||
I think my problem must be with my understanding of how type structures work. So your saying that by having the code Missles = User\Lasers That I am not making all the data from User\Lasers into my 'newed' missle (figure I might as well be consistant with spelling at this point ;) ) but actually having everything I now assign to missles simply be assigned to User\Lasers? I'm really confused now. What I wanted was to have the new missles object use all the stuff from user\lasers so that it can use that as a default. And then modify that. So in essence when I use the New command I am not creating a new object but a new pointer that points to an object? And that when I use code like Missle = User\Laser I am simply moving the pointer to User\Laser not copying over all the data from User\Laser into the new object in Missle? Would I have to move every variable individually in order to move the contents from one object into another? Sorry, I'm fairly new at this... |
| ||
So your saying that by having the code Missles = User\Lasers That I am not making all the data from User\Lasers into my 'newed' missle (figure I might as well be consistant with spelling at this point ;) ) but actually having everything I now assign to missles simply be assigned to User\Lasers? That's correct, because Missles points to the same object as User\Lasers ("Missles = User\Lasers"). You are copying the address to the object, not the object. So in essence when I use the New command I am not creating a new object but a new pointer that points to an object? No, that statement is backwards. Whenever you use New, you are creating a new object. However, whenever you use =, you are creating a new variable (or changing an already-initialized one) that points to that object. (For example, in "car1.automobile = New automobile", "car1" is a 32-bit Blitz pointer that points to the actual automobile data object that you just Newed. You can change car1 anytime, or assign another variable to it, ala "car2.automobile = car1".) And that when I use code like Missle = User\Laser I am simply moving the pointer to User\Laser not copying over all the data from User\Laser into the new object in Missle? Almost! You are creating a second pointer that points to the same object. Correct, you are not copying the data from User\Laser into the new object. Would I have to move every variable individually in order to move the contents from one object into another? Exactly. (Except "copy" would be the better term, instead of move.) Sorry, I'm fairly new at this... Don't apologize; you're just like anybody else.I guess the things to remember are: 1) Whenever you use New, you are creating a new data object from your custom type blueprint. It gets added to the end of the linked list of objects of that type. 2) The only way to reference a type object that you have created are through First <objecttype>, Last <objecttype>, Before <objectptr>, After <objectptr>, <objectptr> = Each <objecttype>, or <objectptr> 2) You can have any number of pointers pointing to any object of their type, or to no object at all. They can change, too. 3) To copy object data, you must copy each field individually. |
| ||
Okay I found a major flaw in my vector libraries. While not the source of my current problem, it seems I was using the New statement on all of my vector calls... while it tooks some reworking, now none of my vector math functions actually create any new vectors. Which is good because I assume that would probably bog things down if I had thousands if not millions of vector objects lying around... |