Can anyone explain this?

BlitzMax Forums/BlitzMax Programming/Can anyone explain this?

Ash_UK(Posted 2006) [#1]
Hi People. I am having a major problem here. I am just trying to make a simple Space Invaders game in BMax to practice my programming. For some reason this code I have typed below is giving me an error saying:

"Unhandled Exception:Attempt to access field or method of Null Object"

The line which is highlighted is indicated by the arrow below:

Here is the code:


Graphics 800,600,0
HideMouse()


Local Player:TSpaceShip = TSpaceShip.CreateShip(0,500)
Local GameObjectList:TList = CreateList()


While Not KeyHit(KEY_ESCAPE)

	Cls 
	
	For Objects:TGameObject = EachIn GameObjectList
	
		Objects.UpdateShip()
		Objects.DrawShip()
		
	Next
	
	Flip
	
Wend







Type TGameObject

	Field X:Int
	Field y:Int
	Field Speed:Int = 5
	Field Image:TImage
	
	
	Method DrawShip()
		
		DrawImage Image,X,Y
		
	End Method
	
	Method UpdateShip() Abstract
	
End Type




Type TSpaceShip Extends TGameObject
	
	Function CreateShip:TSpaceShip(xstart:Int,ystart:Int)
	
		Local Ship:TSpaceShip = New TSpaceShip
		
		Ship.X = xstart
		Ship.Y = ystart
		Ship.Image = LoadImage("Images/ShipImage.png")
		
		ListAddLast GameObjectList,Ship <----------
		
		Return Ship
		
	End Function
	
	
	Method UpdateShip()
	
		If KeyDown(KEY_LEFT) Then X:-Speed
		If KeyDown(KEY_RIGHT) Then X:+Speed
		
		If X<0 Then X = 0
		If X> 700 Then X = 700
		
	End Method
	
End Type




I just can't seem to figure this out. I know the answer is probably looking me right in the face, but at the moment I just can't see it and it's driving me up the wall.

Thank you for any help.


MrHanson(Posted 2006) [#2]
I would probably do it this way at the beginning of your code. You are tyring to add to the GameObjectList before you are creating it. Instead of adding your object to the list in your create function try this:


Local GameObjectList:TList = CreateList()
Local Player:TSpaceShip = TSpaceShip.CreateShip(0,500)
ListAddLast GameObjectList,TSpaceShip

Actually if you create your list first before you create your ship it shoud work the way you have it.


LarsG(Posted 2006) [#3]
You're creating an object (and putting it in the list), before you have mad the actual list to put it in..
so move the creatlist line over the createship line..

oh, and you need to make the list global.. :)

cheers


MrHanson(Posted 2006) [#4]
Oh ya forgot to tell you make your list and ship global.


Ash_UK(Posted 2006) [#5]
Ahh, excellent :-D Thank you guys so very much! I really appriciate it. This has had me riddled for quite some time. Now I can progress :o)

Thank you once again!


H&K(Posted 2006) [#6]
I know you've fixed the problem but this,
Local GameObjectList:TList = CreateList()
Which I assume you've changed to Global.
Make it a global field of TGameObject
Type TGameObject
        Global List:TList = CreateList()
	Field X:Int
	Field y:Int
	Field Speed:Int = 5
	Field Image:TImage
...
...
End Type
You dont need to change its name, but TGameObject.List makes more sence than TGameObject.GameObjectList. Then change all GameObjectList to TGameObject.List

This is just a sudjestion, but it seems right to me to stick the object list inside the object. Global are like fuctions they are concidered to belong to the type, rather than an indivigual instance.


Ash_UK(Posted 2006) [#7]
Hmm, I didn't know that. Thanks H&K I will take your advice and put the object list within the TGameObject type :o)

Thanks for pointing that out for me. Very much appriciated :o)


Red Ocktober(Posted 2006) [#8]
two things.... two questions...

first... more of a comment instead of a question... something about that just doesn't look right... i dunno... something fundamentally wrong declaring something with global scope inside a TYPE....

anyway...

2nd question... if a new gameobject created this way looses scope, is the List also destoyed...

--Mike


Jim Teeuwen(Posted 2006) [#9]
Red Oktober: Global fields are like static variables.
They are completely seperated from any type Instances.
Creating/Destroying instances of your type will not affect the global members.


Ash_UK(Posted 2006) [#10]
Hi Mike. Hmm, I wouldn't have thought so, because the type is just a blueprint to create the object. The objects are created with only the variables held in fields. Global Variables are used only once within the original type and are mainly used for the functions and methods used within the type.

Hope this answers your question Mike :o)

I also hope I'm right :p


Ash


Ash_UK(Posted 2006) [#11]
My appologies Jim :o) I didn't realise someone had already posted whilst I was replying ;o)


Red Ocktober(Posted 2006) [#12]
thx guys... that explains it...

i dunno though... it seems contrary to the whole purpose of encapsulating the properties of a TYPE or CLASS though...

ahhhh, maybe i'm missing something here... i'll follow the discussion... maybe i'll get it eventually... don't wanna sidetrack the thread from the original topic...

thx again...

--Mike


H&K(Posted 2006) [#13]
@Red,

Basicly the type provides two types of fields. Those specific to each instance of the type, ie "Normal" fields, and those accociated with the type itself. (This is the same as the difference between Methods and Functions)

So anything you only want one of, you stick in a global. (Ie All my Aliens have one graphic, so the whole type just contains Global graphic:TImage for example. An alternative to this, is to have a field for each image, but point them all to the same one)
In this case, Ash wants one list of the type TGameObject. To not put it in the type/Class, whilst doable, is counter intuitive, because the list is intrinsic with the type.
On a simple nameing level, the global can be reffered to as "List", within any functions or methods of the type, because its full name is TGameObject.List. As it can in any other type that has a seperate list of instances, because each Type, is also a "namespace"

Now maybe this seems contrary to the whole purpose of encapsulating the properties of a TYPE or CLASS, but the List IS a property of the Type, so it also needs to be within the definition. Not to put it in the type, would infact decapsulate the type.

Are you moving over to Bmax, (and do you think decapsulate is a real word)?


Red Ocktober(Posted 2006) [#14]
Are you moving over to Bmax, (and do you think decapsulate is a real word)?

i definitely will be... hopefully sooner than later... got a few issues to deal with before i start spending computer funds again though... the least being the judge's decisions on equitable distribution... and my avoiding any possible suggestion of dissipation of assets...

in short, as soon as i can, or when the 3D module comes out... whichever is first :)


Now maybe this seems contrary to the whole purpose of encapsulating the properties of a TYPE or CLASS, but the List IS a property of the Type, so it also needs to be within the definition. Not to put it in the type, would infact decapsulate the type.


from what i'm reading, i would be compelled to disagree here... i would maintain the LIST externally, it does not appear to be a property of the TYPE if it is accessable and changeable outside the TYPE definition...

the TYPE should contain a separate field that can be associated with the LIST, or can obtain values from the list... but the LIST itself looks like it should be its own independent entity.

again... not being that intimate with BMax coding, i may be missing something here...

** added **

after thinking about this again, i now don't even see the need for a LIST at all... could you tell me what is the purpose or function of the LIST...


--Mike


Jim Teeuwen(Posted 2006) [#15]
The purpose is to maintain a list of all created instances of a given type. Blitz3D and Blitz+ did this all for you internally. You could then use 'For blah = Each MyType' to loop through all instances.

Blitzmax does not create this list for you. You need to maintain/create it manually in order to not loose the instances you created. You can then use 'For blah:mytype = EachIn MyList' to loop through them.


Yan(Posted 2006) [#16]
BMax doesn't keep an internal list of objects like BB does.

[edit]
Bah...Distracted mid post again...
[/edit]


Red Ocktober(Posted 2006) [#17]
ahhh, ok... i see, thx...

well, that's no good :) ok, nevermind that...

next question... why would you need to loop through all the instances? are you doing this to call an update method for each instance, or something else...

(serious question)

--Mike


Jim Teeuwen(Posted 2006) [#18]
For any reason you would do that in Blitz+ or Blitz3d.
Indeed to call some update methods or whatever.

The reason for keeping a list has a more important reason though.

Consider the following:
type A
 field blah:int;
end type

local myA1:A = new A;
local myA2:A = new A;


doing this will create 2 instances of type A and store them in the variables myA1 and myA2.
Let's say you did this inside a function, this would mean that as soon as the function is finished executing, these 2 variables go 'out of scope' and they will be marked for garbage collecting. This means that the 2 instances you just created will be destroyed.

In blitz3d/Blitz+ this was not the case, because internally, b3d/b+ would add the instances you create to a list and you had to manually delete any instance when needed.

Getting the same functionality as B3D/B+ in Blitzmax requires that you add the instance to a List. This list makes sure that there is always at least 1 reference to your type instance and it will not be destroyed.

A simple way to 'automate' this is to add/remove the type instance to the List in it's Constructor/Destructors.

Type MyBaseType
  Global List:TList = new TList;

  Method New()
    List.AddLast( Self ); '// as son as this instance is created, add it to the list.
  End Method


  Method Dispose()
     List.Remove( Self ); '// as soon as this instance requires being destroyed, remove its last existing reference, in the List.
  End method
end Type


Note that in the example I have not used the standard Delete() Method that is normall used as a type's Destructor, but I have used a custom Dispose() Method. The reason for this is the Chicken or the Egg problem.

Delete() gets automaticly called when the object is being consumed by the Garbage Collector. The same way New() is being called when you create a new instance of your type.
But, the garbage collector only kicks in, if there is No more reference to the Type instance. So here you have the problem that Delete() will never be called, because there will always be at least 1 reference to the object stored in the list. Therefor we use a custom Dispose() method to force the object removal from the List. After this is done, Delete() will be called at some point.


Any other types you create that require maintaining a list, can simply inherit from this BaseType.

Type SomeCharacterType Extends MyBaseType
   Field Image:TImage;

  Method New()
    Image = CreateImage(....);
  End Method


  Method Dispose() '// We can even Override the Dispose method from the MyBaseType type.
    Image = null;
    Super.Dispose(); '// In order to keep the original functionality, you must manually call Super.Dispose() here though.
  End Method
End Type


This ensures that SomeCharacterType will automaticly make use of the List and you dont have to keep track of it here as well. Remember to call SomeCharacterType.Dispose() to actually delete it if you wish to so though.


Red Ocktober(Posted 2006) [#19]
you mean there is no way in BMax to send or respond to events or messages...

i could see having to loop through instances to 'update' objects in B3D, but surely BMax must have progressed past this...

ok... hear me out on this please...

the whole idea of creating a class from which objects can be instantiated is so that these objects can be self contained entities... once one comes into being, being capable taking care of itself... allowing external access to its exposed functionality to maintain a symbiance with the 'world' it exists in... denying access to private data and functions...

create an object, and the constructor does all the initial stuff... delete it, and the destructor cleans up...

while it is 'alive' shouldn't the 'game' environment that this object exists in send constant update messages from which the objects update method could automatically keep it current... and thus eliminating this kludgey type methodology of maintaining a LIST to track these objects...

--Mike


Jim Teeuwen(Posted 2006) [#20]
the methodology you use is the same as you describe as being 'kludgy' only difference is that the game environment will do it for you :)

That would add just an extra layer ontop of the Type/Class system that Bmax uses. B3D/B+ did this, but bmax allows you more intimate control over this by handling it yourself.

As far as accessing an individual objects methods/properties directly, ofcourse thats still possible, but youll have to make a reference to that specific object in the form of a variable.

Global MyObj:SomeType = new SomeType; '// create the object

... some code
MyObj.DoSomething();
...
MyObj.DoSomethingElse();


this is still possible ofcourse.

The List in my example merely exists to make sure that these created objects do not get deleted at random.
The fact that you can loop through it to access all of the objects individually is merely an added bonus.


As far as responding to messages and events, im not sure what you mean. You can create a nice EventHandling system using Function pointers, but thats out of the scope of this thread and generally a very different subject.


Red Ocktober(Posted 2006) [#21]
the methodology you use is the same as you describe as being 'kludgy' only difference is that the game environment will do it for you :)


not at all Jim... the kludge is the LIST to track objects... my method would eliminate the need for a LIST entirely... and make the object self contained... as they should be...

but first, tell me... can BMax send messages or raise events so objects can respond to em?


if so... then i would suggest your framework for your app is at fault... if you see the ability to loop through a list of objects as a bonus, then you are missing a key concept...

i would suggest that you first concentrate on making a GAME class (TYPE)... which does nothing more than initialize and maintain the game environment, provide a gameclock or tick event/message sender, and provide any functionality for the game to be aware of it's place in the system, be a good windows app, as well as to serialization of any persistant data that the game may require...

only after this has been done are you in a position to start creating GAMEOBJECT class (type)... which itself should only provide the base functionality for an object to exist inside the game environment set up by the single instance of your GAME class...



--Mike


H&K(Posted 2006) [#22]
It has progressed past the "having to loop through instances to 'update' objects", its progressed to "having to write the list to loop through instances to 'update' objects"

I know it probably seems a backwards step, (and I might agree), but now I can hold the objects in any structure I feel like, without the overhead of the inherent list of B3d. Its one of the reasons ppl who have moved over say it takes longer.

As to putting the List in the object, "I would maintain the LIST externally, it does not appear to be a property of the TYPE if it is accessable and changeable outside the TYPE definition"
This is personal preferance, as I said, but Why is it changeable outside the Type? Only because you make it so. It would normaly only be used by Functions, but these can be functions of the type, and have no need to be global

I must admit that the "you mean there is no way in BMax to send or respond to events or messages...", came out of nowhere, and and on heart, I dont know what you mean.
If I want any part of the type to post a message, (for example NEW(), I can post a message from new


Jim Teeuwen(Posted 2006) [#23]
Yes it has a set of Event functions that allows a basic Messaging system.
I have never used it myself though. I use a custom Eventhandling system that works like the Event system in C#/.NET.


Red Ocktober(Posted 2006) [#24]
I must admit that the "you mean there is no way in BMax to send or respond to events or messages...", came out of nowhere, and and on heart, I dont know what you mean.



ok... BMax...VB.net... basically similar languages.. right...

read this --> http://www.devcity.net/Articles/25/1/20020316.aspx

i'm not too good at explaining concepts...

--Mike


Red Ocktober(Posted 2006) [#25]
OK Jim... good...

gimme a second...

--Mike


Jim Teeuwen(Posted 2006) [#26]
Those Delegates are exactly what I am using in my custom Event system. The system provided by BMax works like the Win32 Messaging System as far as I can tell.


Red Ocktober(Posted 2006) [#27]
ok.. then why not use this in your overall framework as well...

like i mentioned above... create a GAME class which does nothing more than initialize any instance of itself, setting up initial params, and then enters a main loop at this point...

nothing more... we'll worry about the other stuff later...

now, within the main loop, have it send an event out once every iteration of the loop...

then create an overridable method that handles the event...

next create a GAMEOBJECT class... one that does nothing more than respond to the event the GAME class is posting...


in VB i do it this way...

1-create the GAME class which posts an update event continuously...
2- create an Update Method in the GAME class which handles the update event... make this overridable and inheritable...
3- create a GAMEOBJECT class which inherits GAME, and in tun, its update method... now every game object will be automatically update itself... override the functionality...
4- create specific game object classes which inherit the base GAMEOBJECT functionality and will be self updateable, and will contain the specific functionality that you want it to have in the game...

just whip up a simple template of this to test the concept...

each object will now be a self contained instance of its class... no LIST required...

--Mike


H&K(Posted 2006) [#28]
You can do that if you want. And in fact my only code arhieve post is to do just that, (well I wrote it to be inhereted to do that). But most ppl here are used to the internal list al la BPlus, and the first thing they want, is it back.
(In fact I think Ash posted an earler post asking about it)


Jim Teeuwen(Posted 2006) [#29]
Red: thats whatI allready use. infact, here is the Manager that does all that.



Type Manager Extends IDisposable

'// Vars
	Global Instance:Manager = New Manager;

	Field Driver:TGraphicsDriver;
	Field VSync:Int, IsRunning:Byte;
	Field State:Int, OldState:Int;
	Field RandomSeed:Long;
	Field DatabaseFile:String;
	Field DBase:Database;

	'// Delegates
	Field SceneLoadFunc()
	Field SceneInputFunc( time:Float )
	Field SceneRenderFunc( time:Float )
	Field SceneUnloadFunc()
	Field SceneStateFunc( currstate:Int, prevstate:Int )

'// Ctor
	Method New()
		Self.VSync = True;
		Self.IsRunning = False;
		Self.RandomSeed = GetTickCount();
		Self.DatabaseFile = "data.bin";
		Self.DBase = Database.Create( DatabaseFile );
	End Method


'// Methods
	Method Start()

		SceneLoadFunc();
		IsRunning = True;

		Repeat
		
			Timer.Instance.Update();
			Local time:Float = Timer.Instance.GetTimeMSec() / 1000.0;
			
			Cls();
			
			ResetCollisions();
	
			SceneInputFunc( time );
			SceneRenderFunc( time );

			Flip(VSync);

		Until( AppTerminate() Or (Not IsRunning) )
		
		SceneUnloadFunc();
	
	End Method
	Method Stop()
		IsRunning = False;
	End Method
	Method SetState( newstate:Int )
		OldState = State;
		State = newstate;
		SceneStateFunc( State, OldState );
	End Method
	Method Initialize:Byte( gw:Int, gh:Int, gd:Int = 0, hz:Int = 60, flags:Int = 0, forcedDriver:TGraphicsDriver = Null )
	
		If( forcedDriver = Null ) Then
?Win32
			Driver = D3D7Max2DDriver();
?
?Linux
			Driver = GLMax2DDriver();
?
?MacOS
			Driver = GLMax2DDriver();
?
		Else
			Driver = forcedDriver;
		End If
		
		Try
			SetGraphicsDriver(Driver);
			Graphics( gw, gh, gd, hz, flags );

			Print( "Graphics Context Created for driver: " + Driver.ToString() );
			
			Local s:String = "";
			
			If( gd = 0 ) Then
				s  = " (Windowed)";
			Else
				s = " @ " + gd + " (" + hz + "hz.)";
			End If
			Print( "Selected Displaymode: " + gw + "x" + gh + s );

		Catch e:Object
			Notify( e.ToString(), True );
			Return False;
		End Try
		
		HideMouse();
		AutoMidHandle( True );

		Return True;
	End Method
	Method Dispose()
		If( Self.DBase <> Null ) Then
			If( Self.DBase.IsOpen ) Then
				Self.DBase.Close();
			End If
		End If
	
		ShowMouse();
		GCCollect();
		End;
	End Method
	
	
'// Functions

End Type


this is a Generic class that sets up the display, creates the needed vars and settings to run the game and then handles the Mainloop. The mainloop in turn simple triggers the needed events for Setup, Rendering, Inputhandling and unloading.

the way to use this is simple:

If( Manager.Instance.Initialize( 800,600, 0 ) ) Then

	'// Hook the available events
	Manager.Instance.SceneLoadFunc = SceneLoadCallback;
	Manager.Instance.SceneRenderFunc = SceneRenderCallback;
	Manager.Instance.SceneInputFunc = SceneInputCallback;
	Manager.Instance.SceneUnloadFunc = SceneUnloadCallback;
	Manager.Instance.SceneStateFunc = SceneStateCallback;

	'// Start the whole thing up.
	Manager.Instance.Start();

End If

'// Dispose of any resources.
Manager.Instance.Dispose();



All i have to do is create a Game file that simply handles the events mentioned above:
- SceneLoadCallback -- Handle scene loading
- SceneRenderCallback -- called every loop to do the drawing.
- SceneInputCallback -- called every loop to handle Input
- SceneUnloadCallback -- Handle Scene unloading
- SceneStateCallback -- optional State change event handler

Function SceneRenderCallback( time:Float )
End Function

Function SceneInputCallback( time:Float )
	If( KeyHit( KEY_ESCAPE ) ) Then Manager.Instance.Stop();

End Function

Function SceneLoadCallback()
End Function
			
Function SceneUnloadCallback()
End Function

Function SceneStateCallback( currstate:Int, prevstate:Int )
End Function


All this stuff is getting far out of scope of what the thread was intended for though.


H&K(Posted 2006) [#30]
I think the salent point to the original thread, irrelevent of if you follow Jims code, is
Global Instance:Manager = New Manager;
Where the objects class, (Instance Type), holds an instance of itself, which is self creating

I know this is not a list, which is the real bases of the thread, but I would like to ask Jim:
Why, if as it stands there is to be only one instance of manager
	Field Driver:TGraphicsDriver;
	Field VSync:Int, IsRunning:Byte;
	Field State:Int, OldState:Int;
	Field RandomSeed:Long;
	Field DatabaseFile:String;
	Field DBase:Database;

	'// Delegates
	Field SceneLoadFunc()
	Field SceneInputFunc( time:Float )
	Field SceneRenderFunc( time:Float )
	Field SceneUnloadFunc()
	Field SceneStateFunc( currstate:Int, prevstate:Int )
All these could be Globals of the type, yet have been made fields instead?

Im assuming its because they have no allocation at original referance, but would like your reason if different. Because I would have been tempted to put this
		Self.VSync = True;
		Self.IsRunning = False;
		Self.RandomSeed = GetTickCount();
		Self.DatabaseFile = "data.bin";
		Self.DBase = Database.Create( DatabaseFile );
Into the Field/Global declarations


Jim Teeuwen(Posted 2006) [#31]
That's a valid question.
There is no real performance related reason for this (in this case anyways), but merely a 'code of conduct' when it comes to OOP programming.

This type of doing things is called a Design Pattern (http://www.dofactory.com/). This one in particular is called a Singleton(http://www.dofactory.com/Patterns/PatternSingleton.aspx).


Ensure a class has only one instance and provide a global point of access to it.



Design patterns are meant to standardize the layout of code and offer solutions to potential pittfalls that may occur in OOP programming.

The reason I am using it here is because the situation faced here is best solved using a Singleton. And simply because it has become a habbit I picked up working with C#/.NET.

This does bring us back to the original post: Why do I make the 'Instance' variable Part of the Type and not have it outside the Type? This to is done partly as per the Design pattern specification. In my view, this Instance is the 'Entry Point' or 'Door' to the only available version of my Manager class. And therefor it has very strong ties to the Type/Class itself. Which gives only one logical solution, make it part of the Class/Type itself.

Also, as said, I have been using Design Patterns in C# rather extensively and C# does not support Global Variables or Functions. Wlell, not in the sense that Blitzmax knows them anyways. C# only supports Static and Constant members for a class, which can only be defined as a part of a class (as is done in the code in my Manager type).

When dealing with OO code it may be wise to read up on Design patterns. Some of them are rather complicated and some may not serve you any purpose what so ever, but if anything, they provide a usefull insight into the way of thinking behind OOP programming and may help you solve some potential problems you may encounter, before they actually happen by sticking with a tried and tested way of designing your code.

Note that contrary to what some OO guru's may tell you, Design patterns are NOT the Be-all-end-all. They are not some magical way to make your program Bugfree and the easiest to understand code you have ever written. That's bogus. Also some patterns are expressly made to cover some very very rare situations and will hardly ever proove usefull. Also many patterns are geared towards everyday use in commercial software design, where performance is not often as paramount as in a high stakes environment as a Game. So you may, at times, want to do things your own way because it's simply a lot more efficient and squeezes just a few more Fps out of your engine.

Think of these patterns as Guidelines, not Rules.

Ironically, even the hardcore OO programmers, who used to be completely full of Design Patterns, have realized this and they created 'Anti Patterns'. Yes that's right, these are official :p

Anti-patterns, also referred to as pitfalls, are classes of commonly-reinvented bad solutions to problems. They are studied, as a category, in order that they may be avoided in the future, and that instances of them may be recognized when investigating non-working systems


They are not just for study though, but also used in situations where a regular Design pattern just wont do the job.


H&K(Posted 2006) [#32]
LOL.

Basicaly then its just a universal standardization? (Well in this case)
Im gald that there is such a thing, and I suppose that if I wanted a Job in the Industry I should really follow them ;)

I agree TOTALY with having a standardization, its just that because Im a "Lone" programmer I have my Own.

As a guide to everyone, once you are happy with your level of oop, go back and standardize all your types.


Red Ocktober(Posted 2006) [#33]
This does bring us back to the original post: Why do I make the 'Instance' variable Part of the Type and not have it outside the Type? This to is done partly as per the Design pattern specification.


isn't it apparent that by the nature of it being global... it *IS* scoped out of the TYPE, as well as being scoped out of the instance variable... so it really doesn't matter where you declare it, inside the type or outside the type...

this is totally bad... sorry... it's bad, bad, bad...

i've tried to see it from your point of view, but i can only conclude that your point of view needs to look at this again...


--Mike


REDi(Posted 2006) [#34]
isn't it apparent that by the nature of it being global... it *IS* scoped out of the TYPE, as well as being scoped out of the instance variable... so it really doesn't matter where you declare it, inside the type or outside the type...


Sorry Red but this is wrong, if you declare a global inside a type, it only has scope inside that type, its global to any instance of that type.

also if you declare a global in a function, its scoped inside that function, you cant "see" it in your main program. the advantage to this is that it doesnt change between function calls.


Red Ocktober(Posted 2006) [#35]
thx REDI... my bad... that explains a lot...

so a global inside a function is similar to a static var?

--Mike


H&K(Posted 2006) [#36]
lol @ red.

Jim posted this in anwser to your very first post
Red Oktober: Global fields are like static variables.
They are completely seperated from any type Instances.
Creating/Destroying instances of your type will not affect the global members.

Honestly, you cannot "get your head around" this sort of thing, until you actualy sit down and start to use it, loads of things people post here, make no sence at all, until you are in a similar situation, then you get a "slap the forehead" moment

(At the moment Im enjoying being 2 mths ahead of you at Bmax, so please take your time decideing to move) ;)


Red Ocktober(Posted 2006) [#37]
that's not what i just asked HK... read the question again...

i'm talking about globals declared inside functions now... not inside types...

you outta be more concerned with reading the question before responding to it :) and your 2 months only means that i'll probably wind up bugging you with more questions...

ya see, i'm much more comfortable with c++... even VB.net... as compared to BMax... this whole concept of using a list to track instances of types is contrary to anything i'm accustomed to... but REDI's explanation sorta made it clear why it's being done here...

try and create a global variable inside a vb6 function for that matter...

and why do ya think that by default, variables inside c functions are local, and static vars inside c functions are not global...

there's valid reasons why this isn't normally allowed... hence, i ask the question about how it's done in BMax...


--Mike


H&K(Posted 2006) [#38]
Hang-on, dont you use a list to keep track of objects in B3d. My mistake if not.

Yep, I probably should have read the question more carefully. But heh, as the answer to both was "They are similar to a static var", I figured you had just changed the wording of the question slightly.

And red, I dont care what Vb.net does.

But on a serious note, If you are more comfortable with c++, why not just move to that instead of Bmax. I use Bmax cos its easyer and I cannot use c++, even though Bmax doesnt have any 3d engine. You want a 3d engine, and seem to know/Understand c++. I seems strange to me to try to struggle with a language that in counterintuitive to a language you already know, and the language you know is at least as powerful, has all the things that you want, (typedef, protected friend etc), AND, loads of 3d engines


Red Ocktober(Posted 2006) [#39]
Hang-on, dont you use a list to keep track of objects in B3d.
why would you when for a.type=each type is available... i guess you could if you realy wanted to...

I dont care what Vb.net does.

you should... not only does a large part of the programming world do, but VB.Net is as close BMax as your likely to see in another programming language...

and what about c or c++... do ya care about what it does...

ahhh probably not... that may be why you find it so easy to accept that a global is really not a global in one context, and a global is not really a global in a second context as well in BMax...

could ya either answer my last question or let someone who knows, answer it before we start playing piss ass with each other :)

it would seem that in some one context, a global is actually a static var... and in another, a global is actually a shared or protected var...

that's what i'm trying to find out...



--Mike


H&K(Posted 2006) [#40]
lol @ red.
"a.type=each type" is a list


Red Ocktober(Posted 2006) [#41]
you idyut... :)
that's a loop construct for types in B3d...

--Mike


H&K(Posted 2006) [#42]
Yep, its a loop construct to loop though a list

BUT, as I dont use B3d, Im quite happy to be wrong


Dreamora(Posted 2006) [#43]
And if you have a list in BM, then it would be

for local a:type = eachin that_list_that_containts_object_of_type

' blabla
next

;-)


Red Ocktober(Posted 2006) [#44]
a special list that B3D maintains internally... a TYPE LIST... more like a collection...

which sorta makes the need to maintain a separate one a lil obtuse...

which raises still another question... does BMax maintain a similar collection... it seems not...

as I dont use B3d, Im quite happy to be wrong
well, i'm glad you're happy to be wrong... but this isn't really about you now... is it...

i'm trying to objectively come to a conclusion... you wanna personalize it, like you usually do, as being some sorta test of your BMax IQ, or something...

could ya wait till the serious questions have been responded to, then we can play...

ok :)


--Mike


tonyg(Posted 2006) [#45]
BB automatically has an internal list of objects of whatever type.
Bmax allows multiple, but manual, lists to be created and populated.
At first it seems extra effort but turns out to be very useful.
If you really want you can use BMax types as per BB but I think people would be missing out.
P.S. What's the question?


H&K(Posted 2006) [#46]
!!
which raises still another question... does BMax maintain a similar collection... it seems not...
!!
Three quarters of the posts on this thread are about this?

Ps. Normaly I dont answer your questions, because you only ask them on edits. Why not ask the question first, then edit it.
However, I take point with your sudjestion that I was making this a personal thing. I do make them personal on General, but not on the programing boards.

Anyway. Thats Me done, on this thread about using a user implemented list in Bmax becasue it doesnt have the same implementation as BPlus or b3d


Red Ocktober(Posted 2006) [#47]
thx tonyG for the explanation...

i can see now why Jim implemented his list the way he did...


@ HK...
i didn't suggest that you were making it personal... i stated it outright as a fact...

BUT, as I dont use B3d, Im quite happy to be wrong
based on that statement...
who cares... noone's grading you here... and i'm sure noone really thinks any less of you because of it...
why did you feel the need to defend your being wrong...
or to proudly announce that you are happy about being wrong... that kinda reasoning just escapes me altogether...

look above... i was wrong about the scope of a GLOBAL variables in BMAX... yet, you don't see me defending it when REDI was good enough to explain it to me, now do you...

all i'm trying to do is understand the differences between OO concepts in c++, VB, VB.net, and BMax... seeing as i will soon be using it... i'm NOT trying to turn a thread which poses some important questions into a thing about me... or you...

loosen up a bit dude... we're all gonna make mistakes about something here... you might consider being glad to be corrected, and not being glad to be misinformed...

... i know i am.

--Mike


REDi(Posted 2006) [#48]
so a global inside a function is similar to a static var?

Exactly :)

I would prefer globals in types/functions to be renamed to static, and fields renamed to local, just for clarity.