Looping trough a type?
BlitzMax Forums/BlitzMax Programming/Looping trough a type?
| ||
hi! is there a way to loop trough a type without using a TList? i mean like this for blah:somelist = eachin somelist .... next |
| ||
If you store the types in a list, then yes, then thats the correct way actually :) It is done by using the Iterator implemented for tlist. |
| ||
the what? can you please show me a lil example :) ? you know, i'm beginning to learn bmax and i dont know nothing about it... |
| ||
is there a way to loop trough a type without using a TList? You could store instances in a different sort of data structure (ie array or TMap) but to iterate through a collection of instances you have to have collected them somewhere... and typically they will be in a list! (This is much like Blitz3D, the difference being that B3D only supports a single global list per custom type which is automatically-populated, so the list type itself is somewhat transparent.) |
| ||
hm ok. are there any useful references specificaly to this problem - maybee with an example? |
| ||
Type mytype Field value:Int End Type Type mytype2 Field value:Int End Type Global list:TList=New TList Global map:tmap=CreateMap() 'add 10 new object to a list For k=1 To 10 locty:mytype=New mytype list.addLast locty Next 'same list, different object-type For k=1 To 10 locty2:mytype2=New mytype2 locty2.value=K*1000 list.addlast locty2 MapInsert(map,"KEY "+String(k),locty2) 'save the object with the 'label-tag-key' KEY # Next 'as i don't know what object is I need to use the 'generic' Object type For obj:Object=EachIn list If mytype(obj) Print "Mytype..."+mytype(obj).value End If If mytype2(obj) Print "Mytype2..."+mytype2(obj).value End If Next Local who:Object=MapValueForKey(map,"KEY 7") If who If mytype(who) Print "who for 'key 7' is Mytype..."+mytype(who).value End If If mytype2(who) Print "who for 'key 7' is Mytype2..."+mytype2(who).value End If End If Probably not the best example of the world, but it explains the fact that a list can 'contain' different object-type. And a Map is a sort-of array with 'label' of each elements (=object-type) you store in. |
| ||
Heres a small example showing how to implement EachIn iteration for your own classes. |
| ||
this is really something :) thanks guys! |
| ||
You might be interested in Beginner's Guide to Bmax and Learning 2D Game Programming With BlitzMax . It should cover a lot of your starter questions and both are excellent. You might also want to check Absolute Newbie's Tutorial for Object Oriented Design if you're new to OO and, specifically, Bmax implementation of it. |
| ||
i'm not new to OOP, but i'm new to the bmax version of oop! i'll check out these three links. thx! |
| ||
well enumerators / iterators are quite common in any OO language on set / collection classes |
| ||
the above explanations are a little complex maybe, i certainly dont understand them after a quick look hmm, here is an explanation that makes sense to me..... when you create a type you can put the list into the type: blitzmax knows which global you are refering to because they are inside the different types (even though they are both called list) then when you create a new one you can add it to that list local s:ship s:ship=new ship listaddlast(ship.list,s) then to loop through: local s:ship for s:ship=eachin ship.list next |
| ||
move that "listaddlast(...)" intotype TShip global list:tlist=new tlist field _link:TLink method new() self._list.addlast(self) end method method remove() ' Will remove the object from the list realtime efficiently instead of "list.remove blabla" _link.remove() _link = null end method end type I would suggest using the standard naming conventions for BM as well in your code: Type names begin with T Private meant fields start with a _ |
| ||
that is better! i managed to implement this to my program. also i wonder why this is so complicated at all... |
| ||
also i wonder why this is so complicated at all... Are you saying it IS complicated or it is NOT? I struggled for a few months with BlitzMax but found using those tutorials made it all clear. It is now so intuitive, compared to B3D, that I have a lot of problems going back. |
| ||
Going back to B3D <shudder> Also I have noticed some examples on here demonstrating globals, this is really bad practiced and a bad example for someone learning oop, the whole point of oop is that *nothing* is global, and in a way there should be private and protected features in blitzmax to make variables and functions private to the class but there isn't, here is some code demonstrating private member variables and functions, this 'I think' being a c++ programmer, is good practiced in Bmax: Type CEnemy Function Create:CEnemy(x:Double, y:Double, file:String) local enemy:CEnemy = new CEnemy; enemy.m_x = x; enemy.m_y = y; enemy.m_image = LoadImage(image); enemy.m_enemy_list.AddLast(enemy); return enemy; End Function Method Draw() DrawImage(m_image, m_x, m_y); End Method Field m_x:Double, m_y:double; Field m_image:TImage; Field m_enemy_list:TList = CreateList(); End Type Graphics(800, 600); local meany:CEnemy = CEnemy.Create(10, 50, "enemy.jpg"); while not keyhit(KEY_ESCAPE) Cls; for local enemy:CEnemy = eachin enemy.m_enemy_list enemy.Draw(); Next Flip; Wend |
| ||
What is the idea of that sample? Show how not do to it? Its neither clean code nor is it OOP because in OOP you would not iterate over a list (either static or private) from outside the class. That totally breaks the idea of encapsulation which is the main purpose of OO Design. But in any way, your code is bad design there. Either CEnemy is the Enemy class. In that case, make the list global (Static in C++ / Java) to the type. It won't be global outside, it will just be global to all instances of that type. Currently each enemy has an own list of enemies .. good luck iterating over anything at all The other would be that you implement a factory and add the list there as field, that would be OOP as well. |
| ||
Just stick with Paxman's example - everyone else seems to have over complicated their examples with irrelevant stuff. |
| ||
Okay, change that code to do that and keep it nice and simple for a beginner to understand, that was a very basic example that you shouldn't make global objects, and far from NOT clean, it's just not clean in a sense that it's not true oop. Here is an extended version which I've just done, here we have what you have suggested, but it's more complex for a beginner to understand.SuperStrict Type CGod Final ' This is kind of a singleton pattern, this makes sure there is ' only ever one sole instance of the god class, but blitz does not support ' private constructors. Function getInstance:CGod() if instance = null then instance = new CGod; EndIf return instance; End Function ' public interface Method addEnemy:CEnemy(entity:CEnemy) m_entities.AddLast(entity); return entity; End Method Method Draw() For local iter:CEntity = eachin m_entities local pos_x:double = iter.getPositionX(); local pos_y:Double = iter.getPositionY(); local ent:CEntity = iter.getEntity(); iter.Draw(pos_x, pos_y); Next End Method Global instance:CGod; ' This should be private! Field m_entities:TList = CreateList(); ' The god stores all entities End Type Type CEntity Method getEntity:CEntity() return self; End Method Method getPositionX:Double() ' This should be a const method return m_x; End Method Method getPositionY:Double() ' This should be a const method return m_y; End Method Method Draw(x:Double, y:Double) abstract; Field m_x:Double, m_y:Double; End Type Type CEnemy Extends CEntity Function Create:CEnemy(x:Double, y:Double, file:String) local enemy:CEnemy = new CEnemy; enemy.m_x = x; enemy.m_y = y; enemy.m_image = LoadImage(file); return enemy; End Function Method Draw(x:Double, y:double) DrawImage(m_image, x, y); End Method Field m_image:TImage; End Type Local god:CGod = CGod.getInstance(); local enemy:CEnemy = god.addEnemy(new CEnemy.Create(10, 50, "media/enemy.bmp")); Graphics(800, 600); while not keyhit(KEY_ESCAPE) Cls; god.Draw(); Flip; Wend |
| ||
As you can see the god class creates and draws all entities created, as far as I'm aware of this is probably the best way of doing it, with variations of course. The god class would also create all the items in the game, levels and players etc. |
| ||
I didnt know you could use the Object command like that, pretty good, anything else an ex-Blitz3D user should know about like that? |
| ||
anything else an ex-Blitz3D user should know about like that? Orientation guide for existing Blitz users |
| ||
I'm more comfortable with Paxman's way of doing things. Suprisingly my code hasn't exploded or taken over the world. |
| ||
thanks |
| ||
I didnt know you could use the Object command like that, pretty good, anything else an ex-Blitz3D user should know about like that? Which part didn't you know? The Singleton? |
| ||
To save yourself time, I would suggest doing all basic tutorials of Assari they are a great place to start. And forget what you know about blitz, it has quite little in common with BM even when the syntax looks similar. |
| ||
Good advice, the above code has been converted from my c++ game framework, cut down, and it's a bit hectic, but once understood it works pretty well and makes a lot of logical sense, even better in c :) |
| ||
Which part didn't you know? The Singleton? the fact that you dont have to know what kind of type it is |
| ||
Which part are you refering too? Sorry for being a bit dim here :( I'm just not following you. |
| ||
@verfum, I don't believe Mr Paxman is referring to anything in your code rather the use of 'Object' cast from a user-defined type. |
| ||
yeah its useful |
| ||
Blitz2D/3D/+ like type access... |