Type with arrays
BlitzMax Forums/BlitzMax Beginners Area/Type with arrays
| ||
Hello, I have one type and I would like it to make it as array. Type My_doors Field x:Byte 'position X on the map Field y:Byte 'position Y on the map Field state:Byte '1 opening 2 closing 3 opened 4 closed 5 locked 6 jammed Field have_button:Byte 'have a button to open or close it Field time_delay:Int 'animation speed Field frame:Byte 'sprite animation frame Field locked_with_item:String 'the item or key to unlock the door Field orientation:Byte 'horizontal or vertical EndType Global Doors[100] = New My_doors The example above is a type about creating my doors type. Is it possible to have the Doors type as an array for example 100 doors. I tried the example above and it doesn't work. Global Doors[100] = New My_doors <-The error is here The example above Thank you :) |
| ||
You're trying to assign a single door to the whole array. A door isn't 'an array of doors'.Global Doors:My_doors[100] Doors[0]=new My_doorsShould do it. However better to call the type 'My_door' because it represents a single door rather than an array of them. A nice trick you will sometimes see is something like this to automatically add new instances to a list. Add this code (including the global) inside your type definition. Globals Doors_List:TList=new TList Method New() Doors_List.AddLast(self) end methodThis creates a global list within the type (i.e. scope limited to the type). The New() function if it has been declared for a type is called automatically by Max immediately after a new instance has been created by the 'New' function, hence it's a useful place to put certain runtime initialistation code. Of course, you could adapt this to add the door to your array. I just find lists nicer to work with in most cases. <All code untested> |
| ||
Your code worked Global Doors:My_doors[100] Thank you :) Is it possible to add an array as a list? For example I have one array with name levels:String[99, 43, 43, 5] Does this works like this? Instead have 4D array with 99 levels I will have 3D array with as many levels add in the list. And is it possible to move the levels in the list up or down or delete some from list and how to access them? Something like this: Global all_levels:String[43, 43, 5] Global level_list:TList level_list.AddLast(all_levels) I tried it and dropped EXCEPTION ACCESS VIOLATION error |
| ||
Not sure why you want to add an array to a list, but should be doable. The EAV is because you need to create the list first with new(). |
| ||
I tried something and it compiled.Global all_levels:String[43, 43, 5] Global all_levels_list:TList = CreateList() 'all_levels_list = CreateList() all_levels[1, 1, 1] = "01" all_levels_list.AddLast(all_levels) all_levels[1, 1, 1] = "02" all_levels_list.AddLast(all_levels) I have all my map in array all_levels which is now 3D instead of 4D I created one variable which is a TList Then I created a list with this variable all_levels_list:TList = CreateList() Then I set in the all_levels array at 1,1,1 one string "01" Then I added this all_levels[1,1,1] in the list at position 0 of the list Then I just changed the data of position of the array 1,1,1 the same position with different data "02" And I added this new all_levels[1,1,1] in the list at position 1 of the list, because addlast just added the new array at the index 1 (Means the data added appended) in the list. Now the list with name all_levels_list contains two arrays at position 0 of the list the array all_levels[1,1,1]="01" and at position 1 of the list the array all_levels[1,1,1]="02" In fact both arrays are the same but there are different as I understood so far. How do I access the position index of the list all_levels the index 0 or index 1 in the list and change one of the arrays which contains in each of the indices? In my game I will have a level editor and I will add levels in a list of levels. Each adventure will have levels and the user when will need to create some adventure will add levels in the adventure (Levels=Dungeons) and then will have access in each level which is an array from a list of all_levels and make changes, change the map, change the order of each level in the whole list , or add levels above or add levels below or insert levels or arrange the levels inside the list etc.. Difficult? :P |
| ||
List entries point to entries- so you end up with a list that points twice to the same array. I don't think for this example lists are the best ideas- more useful for enemies and the like. IF you want a list of levels, then create a New() array for each level which will be 2D and add it to the level list. |
| ||
I will use my current code with levels as one 4D array. I would like to ask , is it possible to add a type in a list? Something like this: Type My_Items_on_the_floor Field x:Byte 'the position in the map X Field y:Byte 'the position in the map Y Field level:Byte 'the level the item is on Field position:Byte '4 item positions each square Field item:String 'the item EndType Global floor_item:My_Items_on_the_floor Global floor_items_list:TList = CreateList() floor_item.x = 1 floor_item.y = 1 floor_item.level = 1 floor_item.position=2 floor_item.item="01" 'Sword floor_items_list.AddFirst(floor_item) floor_item.item="02" 'Lock Picking tools floor_items_list.AddFirst(floor_item) But again how do I take access of this list for each item? What this command do? floor_items_list.ValueAtIndex(1) 'It seems set the index of the list It suppose to have selected the second item. DrawText "Item:" + floor_item.item, 0, 0 'It suppose to print the value of the selected index of the array. It doesn't work :( |
| ||
I thing I found my way to have access to my array in the list. I will convert the object in the list with cast. According to the previous example: I have one list with all of my levels Global all_levels_list:TList = CreateList() I have the array which hold my level data as a singular level Global the_level[43, 43, 5]:string I put some data in the array the_level[1,1,1]="01" I put the level in the list. all_levels_list.AddLast(the_level) The list contains only one level. Only one array. This array is an object. I change the data of the_level the_level[1,1,1]="02" The data seems to be the same but in fact is another one singular level. I add another one level in the list all_levels_list.AddLast(the_level) AddLast command adds one element at the end, appended. If I want to gain access to each of my levels first I need the index of the list. ValueAtIndex(0) command select the index in the list in my case there are 2 elements in the list the 0 and 1 Then I will need a temporary array to receive my converted data from the object to array format. So in this point I cast the object and convert it to my 3D array I had. The new temporary array is the_level_temp the_level_temp = String[,,] (all_levels_list.ValueAtIndex(0)) Then I can print my data in the array. DrawText "My array from list:" + the_level_temp[1, 1, 1], 540, 110 But there is a problem, if I will need to have access to a specific index , I only have access to the last element of the list even if I use ValueAtIndex(0) I am close but I don't know how to fix it and have the correct index not the last one in the list. |
| ||
I tried the above example with just string variable and it worked and I was able to have the index of the list correctly selected. With arrays it presents only the last object in the list. The example with just simple string variables. Global item:String Global floor_items_list:TList = CreateList() floor_items_list.AddLast("01") 'add one sword floor_items_list.AddLast("02") 'add a lock picking tools floor_items_list.AddLast("03") 'add healing potion item= String (floor_items_list.ValueAtIndex(0)) DrawText "Item List:" + item, 540, 90 item= String (floor_items_list.ValueAtIndex(1)) DrawText "Item List:" + item, 540, 100 item= String (floor_items_list.ValueAtIndex(2)) DrawText "Item List:" + item, 540, 110 The code above worked. But the code with arrays in the list , I receive only the last from the list. And something else How to convert an object to a type with cast? Can types be elements of a list? Thank you :) |
| ||
Wooo wooo wooo.... keep it simple man. Walk before you try to run. First off, forget for a moment all the complications and many fields you envisage for your game. Let's work with the basic concepts and keep the examples as lean as possible to demonstrate the coding problem. Type instances can be elements of a list. You already know that- you've been adding doors to a list and seen it running. Type conversion is done with: casted:myType=myType(object) You don't really need it though- lists store any type and you don't have to convert. You're still making the same mistake I explained to you earlier- you added an object to the list, changed a field in the object then added it again. Result, you get two pointers to the identical object in the list, which is not what you want. Please go back and re-read what I said earlier. Also, consider declaring meaningful constants rather than using 'magic numbers', e.g. const ITEM_SWORD=1 |
| ||
You're still making the same mistake I explained to you earlier- you added an object to the list, changed a field in the object then added it again. Result, you get two pointers to the identical object in the list, which is not what you want. Please go back and re-read what I said earlier. Also, consider declaring meaningful constants rather than using 'magic numbers', e.g. I added the same object twice because if you add the same object you will have 2 objects in the list. I added it twice deliberately. The object is not the same the first is the_level[1,1,1]="01" The second is the_level[1,1,1]="02" Why the ValueAtIndex(0) points to the last object. You are saying about the same mistake, explain the mistake. In my lists I want to put same objects or similar objects too. Thank you for the type conversion from the object, I will try it. (I don't know if it will work) If the list with arrays will not work I will use my old method. I bother you here , because the manual don't explain all of these in a way to understand them and there are not much tutorials. |
| ||
You don't have 2 objects in the list- you have one object in there twice. The list points to the objects, it does not hold copies of the object. ValueAtIndex(0) points to the first object. The problem is that the first object and the second object are one and the same. The list is pointing to the same object twice. Any changes you make to 'the_level' will be reflected by both elements in the list- the variable 'the_level', and both your list items are all referring to the same block of memory. If you want multiple copies capable of holding independent data, you have to create them. You do this with another call to New(). If you only call New() once, you only have one object. ball:Tball=new Tball ball:Tball=new Tball 'The variable ball now references the second ball 'we created. We overwrote the pointer to the first one 'so it is lost and will be eaten by the garbage collector. MyList.AddLast(ball) 'the second ball we created was added to the list ball:Tball=new Tball 'This variable now points to the newly created (third) 'ball, but the second ball is not lost cos the list 'remembers where it is. |
| ||
So always if I want to add a new level in my levels_list need to use new? I understand your concept but not yet the code. Why so many complexities? Global all_levels_list:TList = CreateList() the list prepared Global the_level[43, 43, 5]:string the array which contains the map prepared the_level[1,1,1]="01" put something in the array all_levels_list.AddLast(the_level) and OK I just added the first What next? the_level= new the_level? I want to create another object with the same name Or do I need to convert this array with name the_level as TLevel for example? Something like this? the_level:TLevel=new the_level maybe? What is the "TLevel"? in your example Tball... This is the point I am confused. |
| ||
Where do I will find in depth complete tutorials for these. The language help sucks completely. You need to bother a lots of people in the forums and wait for someone to answer or understand what you try to say and people they are not obliged to answer any newbie questions and in most cases people they are very kind and try to help but I am so newbie and I have used a lots of basics and I confuse the code. I have used: GWBASIC QUICK BASIC DARK BASIC PLAY BASIC VISUAL BASIC BLITZ MAX NOW And all of these must be similar. |
| ||
double post |
| ||
Hiya, http://www.blitzbasic.com/Community/topics.php?forum=112 seems a pretty good place to start. Plenty of tutorials and complete working examples. There is actually an example of how to use the debugger with using your final problem in your other post (Passing strings to a type) as an example to debug. http://www.blitzbasic.com/Community/posts.php?topic=95478 |
| ||
Takis, I think you are over-complicating it and I don't know how to explain the concept in any more ways. Dave has given you some links which may explain better. If you are using a 3D array, no need to add it to a list. A single 3D array describes all the levels, no need for a list of them. |
| ||
If you are using a 3D array, no need to add it to a list. A single 3D array describes all the levels, no need for a list of them. In fact I am using 4D array and I will remain with my way I use my levels and I will not put them in list. On last thing is to understand how to add a type in a list. I didn't understand the example of John Galt above. |
| ||
Multiple levels can get confusing if you're using large arrays, and it seems like your trying to store too much information into one array, I don't know your game so I may be wrong. You don't have to use Lists if you don't want to. It all depends on your game and how things/objects within your game interact. I made a simple puzzle game which you used two 'craft' of different sizes to move blocks of different sizes through a maze using this design pattern. I'm not saying this is the best approach to use, it's just that the type of game, the way the objects interact with each other and also the ease of reading the code at a later date were deciding factors for me to use this approach. In fact if I recall correctly I did try to do it with Lists but it got confusing as I needed to know which game items were directly next to each other and/or within each other so I decided to use arrays, Your game will undoubtedly be different and may in fact benefit from Lists - it's a source code design that only you can make as you know the game. Anyway here is an outline of my approach in my game :- Type GameLevelManager Field CurrentLevel:Int ' Index in to the array of the AllGameLevels Field AllGameLevels:GameLevel[] ' Array of game levels [...] EndType Type GameLevel Field Screen:GameScreen Field GameBlock:Block[] ' The block data thats changed during gameplay Field StoredBlock:Block[] ' The original block data that all GameBlock(s) are restored at every new game Field NoOfBlocks:Int [...] EndType Type GameScreen Field Map[32,24] ' 2D array of solid background collision data Field Images:AnimatedImage[32,24] ' 2D array of graphic tiles [...] EndType Type Block Field Image:AnimatedImage Field Collision:[,] ' Initial unknown size of 2D array collision data for a block - can be made up of different shape - imagine tetris shapes Field Width,Height ' Used to know the width and height of the collision Field MapPosX,MapPosY ' Position of the block inside the Screen 2D array Field ScrPosX,ScrPosY ' Screen pixel position of the block [...] EndType Using this structure allows me to use the GameLevelManager to very easily display any screen by changing the CurrentLevel variable within the code. The GameLevel type itself is then responsible for drawing itself and any game objects within that level: Each GameLevel contains :- 1) Screen:GameScreen : contains background solid collision data ( never moves within the game ) and an array of images ( non collision ) to display at the corresponding 2D tile position ( later converted to pixel screen coords ). 2) GameBlock:Block[] : is a 1D array of Block(s). During loading and initialising I use GameBlock = New Block[NumOfBlocks]. Then loop through each item in the array and use GameBlock[i] = New Block, where 'i' will be the variable of a For..Next loop counting from 0 to up NumOfBlocks. On any screen there can a different number of blocks - for eg. some screens have 10 blocks, some have 5. 3) StoredBlock:Block[] : is a 1D array of the Block(s). These blocks contain the original initial state of each GameBlock ( map position for eg ). This array is the exact same size as the GameBlock array. This data is copied into the GameBlock array every time a NEW game is started. Each GameBlock contains :- 1) Image:AnimatedImage : AnimatedImage is my own Type that I made for using animated images that will automatically update and animate themselves with a single call to an update method. You could use a simple static image. ( Max2D TImage ) 2) Collision[,] : a 2D array ( unknown at compile time time ) that contains the collision data. Image the shape of a Tetris block, some parts are solid, some parts are not. This allows for different shapes - even hollow shapes. During loading and initialisation - If I want a block that is 5 units wide and 3 units high then I use Collision = New Int[5,3]. Later I access the collision array with something like Data = Collision[2,1] for eg. 3) Width,Height are the values relating to the Collision array. There are other ways to find the size of any array but this is cleanest way to read the source at a later date. So you can know see how a single game level is made up of a background screen with graphics and collision data for the background, how game items can be stored for use during gameplay and also restored for each new game, and also see how each game item has its own data - all with an object oriented approach. |
| ||
. |
| ||
On last thing is to understand how to add a type in a list. You're either not reading what is being posted or you have a fundamental misunderstanding somewhere.Type Talien 'This is where you declare your type 'The declaration is the template for all objects of this type you 'will create field x,y end type myAlien:Talien=new Talien 'here we create a new alien 'based on the template myList:TList=new TList myList.AddLast(myAlien) 'here we add a 'type' to a list 'as has been demonstrated many times 'now in this thread |
| ||
In my game I use one 4 Dimension array which contains the data for all levels. The array must be 4D because each level doesn't have only X and Y position but there are and the 4 sides of walls around each square. I describe my array as: Levels[number_of_levels,x_squares,y_squares,four_wall_sides] I prefer the list because my game is complete dynamic. For example I was asked about how to add a type in a list. Because I will have a dynamic item system. When you will travel in the dungeons and in levels you will able to pick up items from the floor and put the items back to the floor. Each square can contain 4 item positions and these items are infinite. If I will use array for my items on the floor of the dungeon, I will need to be in the limit of the array. I have different arrays for my other elements of my game. For example I have one single array for the players inventory. In my game I use most types. For example if I want to put other objects in my dungeons as doors, stairs , alcoves, pits, traps , monsters , I use types with a limited array. The alcoves can contain only 5 small items so I will not need any list. The monsters, doors , traps and other kinds of decorations in the dungeon I use types with arrays but the arrays in these types are small up to 100 which means each level can contain up to 100 stairs , 100 alcoves, 100 doors, 100 monsters, 100 decorations etc... But the items are something that can be in larger amount. ![]() In the image you see above you see how my game looks like. You see the dungeon and one door in front. At the floor I will drop my items. The items are the objects that are more than 100 and large arrays will consume more memory or if the player drop more that 100 items in one square the game must drop one message to say to player don't drop other item in this square or dynamically change the size of the array of max items will exist in this square. Also there will be and level editor which means you will able to create your own adventures, new dungeons and adding levels dynamic with list will be perfect. For now I have my array to hold up to 99 levels which are very much and each level have 40x40 square which are enough for one huge adventure. About my graphics I use one large image array which holds my graphics and the engine arrange the graphics and create the dungeons and decoration. For now I don't have any problems with memory and most of data hold byte types of data. Even if you have 256 items by 4 per square you allocate 1024 bytes memory for each square or 1.6Mbyte memory per level, but is impossible to have all squares full with 1024 items and all of these squares with 1.638.400 items. Even with an array I can do my work and 100 items per square are very much , no one player will even able to put 400 items in one square. In few words I don't have much data and there is enough memory. (For now) I don't have push the language to its limits yet. But list will be better for example with the level editor if the levels are in a list you will able to manipulate the levels order or move levels up or down or insert levels above or bellow. You can do this with arrays too, just copy the level with a temporary array erase the current position of the array and then copy the temporary array to a new position and you have move your level above or bellow. But learning how the list work is better as a knowledge. Also I don't know if I am able to resize the array but I don't know if it is possible to resize the multiple dimension array of a type on run time. In case these complex list will not work , I will use the simpler lists. Just adding a string in a simple list which describes what item added in the list what position on the map, what position on the square what level. A string like "i01mx10my12sp1" i01 means item 01 , lvl07 means the item is on the level 7, mx10 means map x 10 , my mean map y 12 sp means square position 1. And I will use this simple list code. Local list_of_items:TList = New TList list_of_items.AddLast("i01lvl07mx10my12sp1") But I was prefer adding a type in the list. :) |
| ||
Looking at your screenshots you seem to know what you're doing and have got reasonably far, so I won't try to corrupt with my thoughts of level storage design anymore :D But list will be better for example with the level editor if the levels are in a list you will able to manipulate the levels order or move levels up or down or insert levels above or bellow. You can do this with arrays too, just copy the level with a temporary array erase the current position of the array and then copy the temporary array to a new position and you have move your level above or bellow. But learning how the list work is better as a knowledge. You will need to understand how the TList is put together. It uses a TLink type. TLinks have a 'previous' TLink and a next 'TLink' and its actaully the TLink that stores your data, not the TList. The TList just stores multiple TLinks. So if you want to move an item before another item, you will need the TLink(s) associated with each item ( ListFindLink will return the TLink ) then use the RemoveLink function to remove it and use the TList method .InsertBeforeLink ( or .InsertAfterLink to insert after ) to insert the TLinks where you want them. You can then loop through the list and see that the items have indeed moved position. |
| ||
Looking at your screenshots you seem to know what you're doing and have got reasonably far, so I won't try to corrupt with my thoughts of level storage design anymore :D You are not corrupting anything if you just help me to understand how things work then you will be one of the guys who play my game when I will finished quicker. If I will understand how these lists work not only with simple lists, but lists with arrays , lists with types , lists with types, with multiple dimensional arrays, these casts and other things in the future , you will help me to learn the language quicker and create very nice games. :) No one corrupts anything and I thanks to all these nice and very kind people who help me to finish my game. |
| ||
Ok, no worries, one step at a time A simple list with swapping items, note that you need to the actual objects that you want to manipulate. In this simple example the 'objects' are strings. Global List:TList = New TList List.AddLast("Level1") List.AddLast("Level2") List.AddLast("Level3") ' Displaying the contents of the list is easy as the contents are strings. For Local i$ = EachIn List Print i Next Print ' Lets swap Level3 and Level2 Local L3:TLink = List.FindLink("Level3") List.Remove("Level2") List.InsertAfterLink "Level2",L3 ' Insert an instance of Object "Level2" after TLink L3 in the List ' Display the list For i$ = EachIn List Print i Next |
| ||
Why using i$ instead of i? It suppose to be a number. Could you show me an example how to add and remove one object in a list with types. One example with type without array and one example with single or multiple dimensions array For example I have one type which holds my items. Type My_items field x.byte field y:byte field item:string Endtype Global items:My_items = new My_items Global Items_List:TList = new TList Items_List.AddLast(items) Then how to make a new object to able to add more item types elements in the list and don't see only the last one? Using Items_List.ValueAtIndex(0) command. And what kind of cast do I need to convert this object element in the list back to the type format to able to get access to it with the normal "." DOT items.item="01" And the one with multiple dimension array like: Type My_items field x.byte field y:byte field item:string Endtype Global items:My_items[41, 5] For lvl = 1 To 40 For All_Positions = 1 To 4 items[lvl, All_Positions ] = New My_items Next Next I keep your example for future reference. Thank you :D |
| ||
A small example for using a list would be something like this...Strict Type My_item Field _x:Byte Field _y:Byte Field _item:String Method Create:My_item(x:Byte,y:Byte,item$) _x = x _y = y _item = item Return Self EndMethod Method Debug() Print "x: " + _x +" y: " + _y + " item: " + _item EndMethod EndType ' Initialise the item list Global Items_List:TList = New TList RestoreData ItemsData Local ItemCount ReadData ItemCount For Local i = 0 Until ItemCount Local x,y,itemname$ ReadData x,y,itemname$ Local NewItem:My_item = New My_item.Create(x,y,itemname) Items_List.AddLast(NewItem) Next ' Display the items in the list Print "~nDisplay the List items using the 'EachIn' operator..." For Local Item:My_item = EachIn Items_list Item.Debug Next ' Or another way to step through the list could be using TLink(s)... Print "~nDisplay the List manually using TLink(s) and cast the value of a TLink to a My_Item..." Local ItemLink:TLink = Items_List.FirstLink() While ItemLink <> Null Local Item:My_item = My_item( ItemLink.Value() ) ' NOTE the cast!! ItemLink.Value() will return Object type so cast from Object to My_item Item.Debug ItemLink = ItemLink.NextLink() Wend ' another way using ValueAtIndex Print "~nDisplay the list using ValueAtIndex..." For Local i = 0 Until 3 Local Item:My_item = My_Item( Items_List.ValueAtIndex(i) ) ' Notice the cast here again WriteStdout "List Index " + i + ": " Item.Debug Next #ItemsData DefData 3 ' No of items in the data DefData 1,1,"01" DefData 6,2,"02" DefData 3,8,"03" There a couple of things to note here in the example. First, there is a 'helper' method within the item type to create an fill each type with data in one easy command. When you want a new instance of an item you can now use Local Item:My_item = New My_item.Create(1,1,"item information"). Makes things really simple and you have reasonably tidy code to read on later. And second, there is also the cast from 'Object' to 'My_item' that I've commented in the code. You can attempt to cast from any type to any other type ( Object is also a Type, its the default base type of ALL types ) and the code will run but it doesn't mean the cast will be successful - you should really ALWAYS check if the item that you cast to is valid, so in the examples above you would double check the cast using... Local Item:My_item = My_Item( List.ValueAtIndex(0) ) If Item = Null ' the cast WASNT successful. [...] Endif Of course cast checking only applies if you are putting different Type(s) within the same TList. Before going any further, may I ask why you choose to use '01' '02' '03' for the item,item ?? |
| ||
Your code I very interesting , I am at work now and I will see it after few hours. My types in the list are the same so I will not need to check if the cast is correct. But your example is nice to have and this option too. I understand some of your code and I see and new things like DefData which I don't know what is this. Read and restore data which I don't know what are these. It seems something like the old data command of quickbasic and when we use the read command to read these data. Something like enumerations to add the items in the list. The confusing code is this bellow RestoreData ItemsData Local ItemCount ReadData ItemCount For Local i = 0 Until ItemCount Local x,y,itemname$ ReadData x,y,itemname$ Local NewItem:My_item = New My_item.Create(x,y,itemname) Items_List.AddLast(NewItem) Next For me it will be easier to use a code like. Local NewItem:My_item = New My_item.Create(1,1,"01") The readData x,y,itemname$ just read the defData after the #ItemsData I have not undestood this RestoreData and ReadData much but using the variables directly is the same. Your code seems to be perfect for my game, I will adopt it in my code and when I will finish some basic item system I will send you a demo. Now I am working with the multiple arrays in types, to add my decorations in my dungeons, doors, alcoves,stairs, pits. When I will finish the door decoration of the dungeon I will post a demo to see what I have done so far. |
| ||
Read and restore data which I don't know what are these. It seems something like the old data command of quickbasic and when we use the read command to read these data. Yes, they are old classic Basic commands - I only used them here for the purpose of producing a working example. Normally I would load the data from a file in a similar way. If you were to do the same then you could make a completely separate editor application which will save the level data from the editor, then in the main game you would load that data. The readData x,y,itemname$ just read the defData after the #ItemsData Yes, thats correct too. ReadData can be confusing at first as it has its own internal hidden pointer. We don't have access to it. The only thing we can do is point the internal pointer to a label ( the #ItemData ) using the Restore command. Then ReadData will read the first piece of data from the next DefData statement and update its own internal pointer to point to the next data within the same or any following DefData statements. Does that make sense ? ReadData x,y,itemname$ is exactly the same as ReadData x ReadData y ReadData itemname$ The confusing code is this bellow Looking at the data :- #ItemsData DefData 3 ' No of items in the data DefData 1,1,"01" DefData 6,2,"02" DefData 3,8,"03" and the code RestoreData ItemsData Local ItemCount ReadData ItemCount For Local i = 0 Until ItemCount Local x,y,itemname$ ReadData x,y,itemname$ Local NewItem:My_item = New My_item.Create(x,y,itemname) Items_List.AddLast(NewItem) Next RestoreData ItemsData and #ItemsData are related. Its sets the internal ReadData pointer to point to any DefData statements after the #ItemsData label. Local ItemCount ReadData ItemCount will read the integer '3' from the first DefData statement into the ItemCount variable, and adjust its internal ReadData pointer to point to the next piece of data in either the same DefData statement or any next DefData statements. For Local i = 0 until ItemCount [...]Next is the same as For Local i = 0 Until 3[...]Next ( which is also exactly the same as For i = 0 To ItemCount - 1 ) Local x,y,itemname$ ReadData x,y,itemname$ will read 2 integers and 1 string value from the next DefData statement, ie. DefData 1,1,"01" and place the values into the variables x,y,itemname$ Local NewItem:My_item = New My_Item.Create(x,y,itemname) does a couple of things in one line- it will create a New My_item object BUT using the Create method of the My_item Type to do so ( if you have a New method in the Type then that WILL still be called first, just like a standard constructor method ). However, for this to work correctly you will notice in the Create method that the return type is a 'My_item' Method Create:My_Item([...]) and also notice at the end of the method there is a Return Self. This will return itself as a return value - ie return a My_item Type. This is then stored in the local variable Local NewItem:My_item. We then store that new object in the list using the Items_List.AddLast(NewItem) To better understand how it is working I advise you to build in Debug mode and put a DebugStop before the For.Next loop statement then use the debugger to step into the methods one statement at a time. The loop continues using the For...Next loop reading and storing 3 new My_Item objects into the list. Once the loop exits the only reference you have for those items are in the Items_List itself. For me it will be easier to use a code like. Local NewItem:My_item = New My_item.Create(1,1,"01") What happens when/if you want to write an editor - you mentioned that you will do. Also what if you want hundreds of items? Then you'll have hundreds of those lines, which is ok, but could get difficult to read and very repetitive to type out. Using data, either as DefData or loading data from a file, is the usual route to take and a better source code design. |
| ||
You are a perfect teacher and thank you very very much for your huge patience and effort you put and you stayed to teach me how nice things work. You are very kind. Now I will finish my doors decoration for my game using for now types with 2D arrays , I will post one quick version and then I will start making some experiment with this new nice code to create my inventory and item system. One last thing if you would like just show me how to add one 3D array in a list. And how to cast this object in the list back to 3D array again. And the most of core things in the engine will be ready. As we spoke about level editor I have started something. Very early adventure editor. ![]() Is in the early stage and I use ifsogui for my buttons and gadgets. - I have made and research in forums and I found how to save my adventure and encrypt it to avoid cheaters. - I have found how to open files and save and load data. - I use koriolis zip module to load my graphics fonts and other data from compressed files. - I found in the forums how to have a splash screen when my game loads in the beginning - I found how to make light effects in my game from the forums again. If I will find and how to store my data back to zip files with password, I will be able to create and plugins and add ons for my game or the user will be able to generate stand alone adventures. This will be a future option. (Koriolis zip module is not capable to store files in zip) I will find how to load video clips or some compressed video clips which don't occupies large amount as the normal avi files for my cut scenes or intros or in game progress videos. Also this divX encoder is not usable. Another one thing I will need to find is how to able to have bitmap fonts, I load truetype (ttf) fonts and I want my game being translated to many languages and there are problems with fonts or code pages or unicode and you can see the text correctly in some computers and wrong in others, so the bitmap functions will be very nice. For now I use true type fonts. I will not bother you for this stuff yet because I have other priorities. I build the core engine of the game for now. Again millions of thanks to all kind people here and the development goes very nice. |
| ||
One last thing if you would like just show me how to add one 3D array in a list. And how to cast this object in the list back to 3D array again. Sure, no probs... Strict ' A random 3d array filled with data Global RandomArray[10,10,10] For Local x = 0 Until 10 For Local y = 0 Until 10 For Local z = 0 Until 10 RandomArray[x,y,z] = x * 100 + y * 10 + z Next Next Next Global List:TList = New TList List.AddLast(RandomArray) Local CopyOfArray:Int[,,] = Int[,,]( List.First() ) ' Access array as normal Print CopyOfArray[3,2,1] Casting is easy, however you need to think about what you are casting to then use the parenthesis around the object that you want to cast from. In this case this want to cast to a 3d array of integers. We don't even have to know how many elements are in the array. The command List.First() returns an Object type so to cast to a 3d array of integers you use Local CopyOfArray[,,] ' Integer array of unknown size but 3 dimensions. CopyOfArray = Int[,,]( List.First() ) ' Cast from Object to 3 dimension array of integers. The game looks promising. Good luck with it :) |
| ||
Another one thing I will need to find is how to able to have bitmap fonts, I load truetype (ttf) fonts and I want my game being translated to many languages and there are problems with fonts or code pages or unicode and you can see the text correctly in some computers and wrong in others, so the bitmap functions will be very nice. For now I use true type fonts. There are lots of fonts which support the popular parts of unicode (ASCII, cyrillic, Japanese, Simplified Chinese, etc). If you store all your texts as UTF-8, you should have no problems loading them for different languages in your game. |
| ||
I made some test and I tried Greek Language and when I was load the text from a file I was seen the text with different characters and when I was typed the text from the source code directly I saw the text correctly. Also I tried and other fonts and I had a negative effect. The text directly from the source code was with different characters and the text which loaded from file was correctly. Note: The text I am creating, I create it with notepad and I save it as ANSI. If you have some text editor which saves the texts better I am open for suggestions. I plan to write the game in English - Greek - Polish - French - German - Spanish - Italian languages. |
| ||
On Windows, I use Notepad++ for text editing. It has good unicode support. It's not a good idea to have your unicode texts directly in the source - better to load them in from an external file. This way you know everything is correctly encoded (UTF-8, or whatever you decide to use) BlitzMax's native Strings are stored in memory as UCS-2 (like a partly cut-down version of UTF-16). I personally always use UTF-8 for text with BlitzMax as it is well supported across multiple platforms. |
| ||
Thank you , I will try to find Notepad++ My door functions are almost ready. |
| ||
I am very happy to announce that I have finish the door functions and I have uploaded one small demo to see what I have created so far. I used the code you gave me above. You are moving with arrow keys or numeric pad keys. You are turn left and right with 7 and 9. With Numeric pad MINUS and PLUS , change the light level of the level. Also you can move with navigation arrows on interface. You can change the order of items in inventory. You can't put items of player hands yet. You can't put items on the floor yet. (When I write the code which gave me I will post next demo). Download the small demo from cloud box link bellow: https://app.box.com/s/ioksz3rn2q5ukkh47cop |
| ||
What's there is good, IMHO! Only two small thoughts: I think the doors should really open a bit quicker, perhaps x2 for regular doors. Not every door in a dungeon is a "special event"... The compass rose turns waaaay too slowly. I can move very quickly through the corridors, turn etc. but I wait 3-4 seconds for the compass to show the right direction? In this case I wouldn't use it at all. |
| ||
Did you like it? About doors, I will do them little faster if you want. About compass, in real world one compass doesn't turns very quickly even if you change direction fast. But I will make it little faster but not very fast. In my computer I have more than 400 frames per second and I see a fast enough speed here. Later on I will try to have a fix frames per second. When my game become larger and I will have smaller frames per second. For now I don't have any problem with frames per second and I see my game in nice speed. For animations I use timers so the speed must be the same in any computer, but this depends how much frames per second you have and how fast video card you have too. But I believe the graphics are 2D and you don't need any very fast computer. ------- In the next version I will use fixed refresh rate at 60 FPS so the speed will be the same in most computers. |
| ||
> Did you like it? Yes, it's very faithful to the old Eye of the Beholder or Dungeon Master type games. Did you draw the graphics yourself or did you have help? > For animations I use timers so the speed must be the same in any computer, but this depends how much frames per second you have and how fast video card you have too. OK, now I understand - my graphics are always locked to the monitor frame rate which is 60 fp/s. When your game will get slower (with A.I., more effects etc.) you will notice that the compass gets slower, too. I don't see a difference between what you call "animations" and the animation of the compass - you should also make it speed independent. |
| ||
In the next version I will lock in 60 frames per second and the animations will be much faster. I tested the game here with 60 frames per second and was veryyyyyy slow and I fixed it. I don't see a difference between what you call "animations" and the animation of the compass - you should also make it speed independent. The doors opening and closing are animations , the compass needle turning is an animation, the gargoyle wings in the magic panel is an animation , the torch flame is an animation. Each animation is independent. The file updated with normal animation and fixed 60 frames per second. https://app.box.com/s/ioksz3rn2q5ukkh47cop |
| ||
That's much better! I have no further complaints right now... ;-) |
| ||
Perfect, I will post another version when it will be ready. |