Shape Invaderz!
BlitzMax Forums/BlitzMax Beginners Area/Shape Invaderz!
| ||
EDIT: This is an OLDER VERSION Please review the LATEST VERSION Here Just finished a Space Invaders clone. My primary focus is memorizing blitzmax code, especially OOP handling so I figured this would be a good exercise. I programmed this in 3 hours. It could have been done a lot faster but I had to reference code and had to tweak collisions, etc You can just copy/paste the code and play, no other downloads are required, please give me feedback! Highlights: The code uses Superstrict! The code uses different gamestates to handle titlescreen / game play / fail or win/ pause screen The code uses TLists The code uses polygon graphics thanks to Indiepath Wishes: I need to learn how to update the screen based on hertz instead of pass-thru's I need to learn how to make a highscore list Feedback welcome! |
| ||
Nice :) |
| ||
Very nice!!! I can only think of a few nitpicks ;) 1. Don't bother with bytes (or shorts) unless you have a reason to. You might think you're saving memory, but it'll be less than 1kb which is nothing, and they are actually slower than ints! Don't become paranoid though, it's very slight ;) But bytes and shorts are 8 and 16 bit respectively, which causes some minor inconvenience to a 32 bit processor, whereas 32 bit ints do not. (What happens on a 64 bit system, I'm not sure) 2. If you're going for OOP, don't use countlist(list), use list.count() :P 3. The colours for SetColor are integers, not floats/doubles. You are being needlessly rational :P (sorry maths joke) Make them ints.. or you could put them as bytes if you want to, as colours are in the range 0-255. 4. You are not being consistant with your capitalisation. Some type names have capitals, others are lower case. 5. Personally, I'd put the list declarations within the appropriate types themselves. I find it makes things better organised. 6. You only need to declare the type of a variable once. objectlist.AddLast obj:tplayer - the :tplayer is unnecessary, unwise even, as it already knows what kind obj is. If you've done it to remember that obj is a player in this case, it's better to rename obj to player. 7. Try using the Blide editor, you can download a free version. I find it easier to code in, than the editor that comes with BlitzMax. If you're up for it, here is some advanced code to show a better way of removing items from lists! The problem with list.remove(o), is that it needs to scan through the list, until it finds the object in question. If it's at the end of the list, it will potentially have to traverse the entire list looking for it! This, needless to say, is not very efficient. Although, in practice, the performance impact probably isn't that much. A better way nonetheless, is to store in each object a "link" to that object's position in the list. Then, when we need to remove it, we can pull it directly from the list. Here is the code. One thing you may notice, is the unusal way I've made the types, by using a create method instead of a create/make function. I'm just showing off and it isn't relevent to the problem :D It isn't inherently better or worse than the way you have done it, it's just an alternative. Which you may or may not find more natural :) The key thing is the me:TLink - this lets objects know where they are in the list. The New() method is a special built-in method, that you can add to. It is automatically ran when any object springs forth into existance, so I've put the code there to put it in the list. When removing the object, it's important to make the distinction between truely deleting the object, or just removing it from the list. An object is only deleted, when no more variables "reference" it. If the object exists only in the list, removing it will delete it. In my example, they also exist as local variables, so I have to remember to Null alice after killing it(her). I welcome comments from anybody about that method. I hope I haven't confused you but given you some useful tips! |
| ||
@ Skully! Thanks :) I enjoyed making it @Czar Flavius: Thanks a million for nitpicking my code! This is the only way I'm going to improve, so I really appreciate your time. 1. I didn't know that bytes would actually be slower! My whole reasoning for using them was to speed things up. I always thought Integers used more memory and I figured if I was dealing with numbers that were smaller than 1000 to store them as doubles. And true/falsies as Bytes! With that knowledge I'll have to rethink my coding. Too bad this bytes/double/int thing is a habit. So I guess there's no reason to mess with bytes or doubles at all then? 2. Why is list.count better? I'm assuming it's faster? 3. Didnt know Setcolor were integers, thanks a million :) 4. Yeah I got tired of hitting the shift key while coding. That was laziness, I'll try to be more consistent though as it DOES make it easier to read. 5. I think you're on to something with putting list decelerations in the types themselves. But if I wanted to declare them wouldn't I have to put them outside of the Type? Maybe one line above the type declaration? I found myself scrolling to the top of the file to reference the list names a few times so I think this would be helpful in speeding the coding process up. 6. objectlist.addlast obj:tplayer could be player.addlast player instead, more readable! 7. Oh yeah, I already am using BLIDE ;) Finally, I your code snippet looks unfamiliar to me, I'm seeing some new codez!! I'll have to study it for a bit (After I'm done updating my code to your suggestions!!!) tonight and apply that method. I'll touch more on it once I'm ready. Thanks again, I really appreciate the criticism as I want to improve my coding skills. |
| ||
2. Why is list.count better? I'm assuming it's faster? It'll be slightly faster (not that you will ever notice), but mainly because it is a call to the method on the Type, rather than a call to a procedural "wrapper" function. Since you mentioned you are interested in OOP, The Czar simply points out that using list.count is an OOP style call ;-) |
| ||
1. The effect is not huge, so don't panic about it :) You use floats and doubles when you are dealing with decimal numbers (your height for example). If the values are always going to be integer, there is no point using them. Bytes are used mainly when interfacing with outside code. For example, the programming language C models strings using arrays of bytes, so if you want to include C code in your program, you might need bytes then. But forget about that for ages and ages. 5. It's as easy as this Type tplayer Extends tGameobject Global playerlist:TList = CreateList() Field shotdelay:Float;) 6. I'm not too sure what you mean by this. Is there a reason you have an object list for everything, and seperate lists for the player etc which you use together? |
| ||
*cough*Global playerlist:TList = New TList *cough* :-p |
| ||
New TList or Createlist() ? that is the question! 5. thanks :) 6. The reason I had an object list for everything is so I could sweep through the entire list once on method.update() abstract for instance: for local obj:tgameobject = eachin objectlist obj.update() Next instead of for local obj:tobject1 = eachin object1list obj.update() Next for local obj:tobject2 = eachin object2list obj.update() Next And for object3 and 4 and 5 and 6 Thus reducing redundancy and lines of code. |
| ||
If you wanted to be really clever, you could have a list of lists ;) |
| ||
objectlist IS a list of lists.. The only thing I dont like about doing it my way is that I'm putting an instance in two lists, thus having to remove it from both lists. Reducing lines of code is my goal |
| ||
I agree that the lists should be inside the type itself. You can even name it _list or similar so you can cut and paste the handling code without worrying about what you called the TList. Seems silly to reference "tPlayer.playerlist" when you can reference "tPlayer._list". Also, you can then change your clearEverything function to: Function ClearEverything() tPlayer._list = Null tGameObject._list = Null ''etc End Function Or even better have a type function to clear the list and call it like so: tPlayer.Clear() |
| ||
Hi, thanks a lot for your help! Question: Using tPlayer._list = Null clears the list without having to For Next loop the list and clear them each one by one? If so that's fast! :D If I used it that way then how would I declare the list? I'm not really sure how I could apply the latest suggestions on lists and such. Not to be a burden, but care to elaborate? |
| ||
' Global list which holds all instances Global _list:TList ' ' This adds a new instance to the global list Method New() If _list = Null _list = New TList EndIf _list.addlast(Self) EndMethod Taken from here: http://blitzmax.com/Community/posts.php?topic=50285#573109 (see my adjustment of Fredborgs code) |
| ||
Amazing! Not sure why I should do it that way though? |
| ||
I think it's more trouble than its worth to delete the lists themselves, because you have to worry about making them again. If you just want to clear the list and start afresh, use list.Clear().Function ClearEverything() blahblahlist.Clear() ....... End Function The method you used originally, using the loops and the Remove list method, is VERY inefficient. From my previous post, can you deduce why? :) objectlist IS a list of lists. I don't think you follow what I mean, here is an example: (I've renamed objectlist to superlist)Global superlist:TList = CreateList() Global enemylist:TList = CreateList() superlist.AddLast(enemylist) Global playerlist:TList = CreateList() superlist.AddLast(playerlist) Global bulletlist:TList = CreateList() superlist.AddLast(bulletlist) Global playershots:TList = CreateList() superlist.AddLast(playershots) Global particlelist:TList = CreateList() superlist.AddLast(particlelist) Lists can contain any object, and lists themselves are objects! So superlist doesn't contain any game objects directly, but now contains all the above lists. When making, say a player, you only need to add it to the playerlist, NOT to superlist. '---- do not need anymore - superlist.AddLast obj playershots.AddLast obj To update all the objects in your game, use this: For Local a_list:TList = EachIn superlist For Local an_object:tGameobject = EachIn a_list an_object.update() Next Next The game will go through all lists in super list, and then go through all of them, and update the objects they contain. When you restart the game, you don't want to Clear superlist (as you'd have to add all the lists into it again) but should only clear its sublists. Function ClearEverything() For Local a_list:TList = EachIn superlist a_list.Clear() Next End Function |
| ||
THANK YOU! That makes PERFECT Sense! You're awesome! :) I can't wait to redo the codez. I'll post a more efficient version soon. I have learned that TLists are actually objects and that you can put them inside other lists, I had no idea this was possible until today.. again, thank you. |
| ||
Here's Version 2: UPDATE INFO: 1. Removed Bytes and Doubles and replaced them with Integers 2. Changed CountList() to List.Count() 3. Fixed inconsistencies with Code Capitalization 4. Added more Code Comments 5. Added a SuperList and put all Lists in there, thus removing lots of code redundancy! I wanted to declare the lists in the types themselves, but doing it this way brought me syntax errors! 6. Changed "objlist.addlast obj:tobj" to "objlist.addlast obj" 7. If the shapes reach the bottom you FAIL! Thanks a lot guys! Feedback is welcome! SuperStrict 'DrawGeom function is used to draw all the shapes in the game. Function DrawGeom(x:Float, y:Float, sides:Float, length:Float, angle:Float, r:Int = 255, g:Int = 255, b:Int = 255, glow:Int = True) Local aStep# = 360 / sides Length:Float = (length / 2) / Sin(aStep:Float / 2) 'Calculate the correct length of a side For Local a:Byte = 0 To sides - 1 Local x1:Float = x:Float - (Sin(angle + (aStep * a)) * length) Local y1:Float = y:Float - (Cos(angle + (aStep * a)) * length) Local x2:Float = x:Float - (Sin(angle + (aStep * (a + 1))) * length) Local y2:Float = y:Float - (Cos(angle + (aStep * (a + 1))) * length) If glow = True SetColor r / 4, g / 4, b / 4 DrawOval x1 - 5, y1 - 5, 11, 11 ' Draw Circle at Vertex End If SetColor r, g, b DrawLine x1, y1, x2, y2 ' Draw Connecting Lines Next End Function 'Initialize the Game ***************************************** 'Set the playfield Graphics 320, 260 'Declare Global Variables Global Direction:Int Global GameState:Int Global Level:Int Global PS:Int Global Score:Int 'Declare Constants Const MOVELEFT:Int = 0 Const MOVERIGHT:Int = 1 Const STATE_TITLE:Int = 0 Const STATE_PLAY:Int = 1 Const STATE_PAUSE:Int = 2 Const STATE_WIN:Int = 3 Const STATE_FAIL:Int = 4 'Create Object Lists Global SuperList:TList = New TList Global EnemyList:TList = New TList SuperList.AddLast(EnemyList) Global BulletList:TList = New TList SuperList.AddLast(BulletList) Global PlayerShots:TList = New TList SuperList.AddLast(PlayerShots) Global PlayerList:TList = New TList SuperList.AddLast(PlayerList) 'Game Initialized ***************************************** 'All objects contain x,y,xv,and yv variables Type tGameObject Field x:Float, y:Float, xv:Float, yv:Float Method update() Abstract End Type Type tEnemy Extends tGameObject 'Create additional fields that are used for the Enemy Type Field r:Int, g:Int, b:Int 'Colorsettings Field Sides:Float 'Sides settings Field Level:Int 'Level the Enemy is Field EnemyType:Int 'Type the Enemy is 'The Make function is used to create and confiugre a new Instance of the Enemy Function Make(x:Float, y:Float, EnemyType:Int = 1, Level:Int) Local NewEnemy:tEnemy = New tEnemy NewEnemy.x = x NewEnemy.y = y NewEnemy.EnemyType = EnemyType NewEnemy.Level = Level NewEnemy.xv = Level *.1 'The higher the level the faster the enemy will be If NewEnemy.xv > 2 NewEnemy.xv = 2 'No need to make it TOO fast though, cap it at 2 'Depending on the type, we confugre it's shape and color Select EnemyType Case 1 NewEnemy.r = 255 NewEnemy.g = 0 NewEnemy.b = 0 NewEnemy.Sides = 4 Case 2 NewEnemy.r = 0 NewEnemy.g = 255 NewEnemy.b = 0 NewEnemy.Sides = 3 Case 3 NewEnemy.r = 0 NewEnemy.g = 0 NewEnemy.b = 255 NewEnemy.Sides = 5 End Select 'Let's add it to the List EnemyList.AddLast(NewEnemy) End Function 'The Update Method updates the instance every step Method Update() 'Determine it's direction and move accordingly If Direction = MOVELEFT x:-xv If Direction = MOVERIGHT x:+xv 'If any Enemy it's the edge of the screen, 'move all enemies downward and reverse the direction If x < 0 Direction = MOVERIGHT For Local Enemy:tEnemy = EachIn EnemyList Enemy.y:+4 Next End If If x > 320 Direction = MOVELEFT For Local Enemy:tEnemy = EachIn EnemyList Enemy.y:+4 Next End If 'If the Enemy reaches the bottom, the game ends If y > 240 Then GameState = STATE_FAIL 'Draw the Enemy DrawGeom(x, y, Sides, 10, 0, r, g, b, False) ' make it shoot Local R:Int = Rnd(10000) 'The Higher the level the more frequent they shoot If R < Level + 1 tBullet.make(x, y) End Method End Type Type tPlayer Extends tGameObject Field ShotDelay:Float Function Make() Local NewPlayer:tPlayer = New tPlayer NewPlayer.x = 320 / 2 NewPlayer.y = 232 PlayerList.AddLast(NewPlayer) End Function Method Update() 'Increment the ShotDelay ShotDelay:+1 'Playership is controlled with arrow keys and Z If KeyDown(KEY_RIGHT) x:+3 If KeyDown(KEY_LEFT) x:-3 'Shoot if the ShotDelay permits If KeyHit(KEY_Z) And ShotDelay > 5 If PlayerShots.Count() < 2 tPlayerShot.Make(x, y) ;ShotDelay = 0 End If 'Bound the player in the playfield If x < 0 x = 0 If x > 304 x = 304 'Draw the player DrawGeom(x, y, 3, 16, 0,,, , False) End Method End Type Type tBullet Extends tGameObject 'Make Function Called when instance is created Function Make(x:Float, y:Float) Local Bullet:tBullet = New tBullet Bullet.x = x Bullet.y = y Bullet.yv = 3 Bulletlist.AddLast(Bullet) End Function 'Update Function called with each step Method Update() y:+yv 'Move the bulled downard, remove if out of bounds If y > 244 Then BulletList.Remove(Self) SetColor 255, 255, 0 DrawOval x, y, 4, 4 'Check for a collision with the Player For Local Player:tPlayer = EachIn PlayerList If Abs(Player.x - x - 2) < 10 And Abs(Player.y - y) < 8 BulletList.Remove(Self) GameState = STATE_FAIL End If Next End Method End Type Type tPlayerShot Extends tGameObject 'Make Function called when the Instance is created Function Make(x:Float, y:Float) Local PlayerShot:tPlayerShot = New tPlayerShot PlayerShot.x = x PlayerShot.y = y PlayerShot.yv = -8 'sets the speed to go upward 8 pixels per step playershots.AddLast(PlayerShot) End Function Method Update() y:+yv 'Move the shot 'Destroy the instance if out of bounds If y < - 4 Then PlayerShots.Remove(Self) 'Check for a collision with enemies For Local Enemy:tEnemy = EachIn EnemyList If Abs(Enemy.x - x - 2) < 8 And Abs(Enemy.y - y) < 10 If Enemy.EnemyType = 2 Score:+1 If Enemy.EnemyType = 1 Score:+15 If Enemy.EnemyType = 3 Score:+70 EnemyList.Remove(Enemy) PlayerShots.Remove(Self) End If Next 'Draw the Instance SetColor 0, 255, 255 DrawOval x, y, 2, 4 End Method End Type Function MakeGame(Level:Int) tPlayer.Make() For Local N:Int = 2 To 14 tEnemy.Make(N * 20, 16 * 2, 3, Level) Next For Local N:Int = 2 To 14 tEnemy.Make(N * 20, 16 * 4, 1, Level) Next For Local N:Int = 2 To 14 tEnemy.Make(N * 20, 16 * 6, 2, Level) Next End Function Function ClearEverything() For Local a_list:TList = EachIn SuperList a_list.Clear() Next End Function 'MAIN LOOP Repeat Cls 'Determine the GameState and act accordingly Select GameState Case STATE_TITLE DrawText "Shape Invaderz", 105, 20 DrawText "ARROW KEYS", 30, 90 DrawText "Z KEY", 30, 110 DrawText "P KEY", 30, 130 DrawText ". . .", 140, 90 DrawText ". . .", 140, 110 DrawText ". . .", 140, 130 DrawText "Move Ship", 200, 90 DrawText "Shoot", 200, 110 DrawText "Pause", 200, 130 DrawText "Press SPACE to play or ESC to Exit", 25, 220 If KeyHit(KEY_SPACE) Level = 1 SCORE = 0 MakeGame(Level) GameState = STATE_PLAY End If Case STATE_PLAY 'Update All Objects For Local a_list:TList = EachIn SuperList For Local an_object:tGameObject = EachIn a_list an_object.update() Next Next 'Pause the screen if player pushes the P Key If KeyHit (KEY_P) GameState = STATE_PAUSE 'Draw HUD SetColor 0, 0, 200 DrawLine 0, 240, 320, 240 SetColor 255, 255, 255 DrawText "Level:" + String(Level), 10, 244 DrawText "Score:" + String(Score), 200, 244 If CountList(EnemyList:TList) < 1 GameState = STATE_WIN Case STATE_PAUSE 'PS is used to Scroll the "Game paused" text PS:+1 If PS > 320 PS = -320 DrawText "Game PAUSED, Press SPACE to Continue", PS, 210 If KeyHit(KEY_SPACE) GameState = STATE_PLAY Case STATE_WIN DrawText "WIN!", 145, 20 DrawText "You Have owned Level " + String(Level) + "!!!!!!!!!!!!", 30, 60 DrawText "Press SPACE to CONTINUE or ESC to Exit", 06, 210 If KeyHit(KEY_SPACE) ClearEverything() Level:+1 MakeGame(Level) GameState = STATE_PLAY End If If KeyHit(KEY_ESCAPE) ClearEverything() GameState = STATE_TITLE End If Case STATE_FAIL DrawText "FAIL!", 145, 20 DrawText "You DIED on Level " + String(Level) + "!!!!!!!!!!!!", 30, 60 DrawText "You Scored " + String(Score) + " Points FTW", 10, 90 DrawText "Press SPACE to CONTINUE or ESC to Exit", 06, 210 If KeyHit(KEY_SPACE) ClearEverything() Level = 1 GameState = STATE_TITLE SetColor 255, 255, 255 End If End Select Flip Until KeyHit (KEY_ESCAPE) |
| ||
Cool little game ! I have learnt new things thanks to this thread :) I like your DrawGeom function. |
| ||
Thanks! The DrawGeom function was borrowed from Indiepath :) |
| ||
I read you wanted to make your lists part of the type they belonged to. In a (for a lack of a better word) 'real' OOP language that would be a 'static' member or field. I didn't think static members were supported but I had to google it anyway; http://www.blitzbasic.com/Community/posts.php?topic=59233 You can put the global inside the type which makes things a bit tidier. See the second Global? This is a bit subjective but I made the type self register with the global list so you don't have to worry about that anymore either. Function Make(x:Float, y:Float, EnemyType:Int = 1, Level:Int) If ( Not RegisteredToSuperList ) Then SuperList.AddLast(EnemyList) RegisteredToSuperList = 1 End If It's subjective because tEnemy is now tied to a global variable called SuperList which I don't like. If we we're taking tEnemy into it's own source file or module we could add a tEnemy.Init( SuperList:TList ) function or add the SuperList to the Make() function arguments. I personally wouldn't want tEnemy.EnemyList accessed anywhere apart from within the tEnemy code but I initially had to add the GetList() function for your bullet/collision updates. That was avoided by passing a bullet position to a tEnemy function and asking it to check for collisions... Function CheckCollision:tEnemy( x:Int, y:Int ) For Local Enemy:tEnemy = EachIn EnemyList If Abs(Enemy.x - x - 2) < 8 And Abs(Enemy.y - y) < 10 Return Enemy End If Next Return NULL End Function If it returns an enemy object you can act on it. All in all though, it's a very, very good job :) |
| ||
I think that's making it a bit more complicated than it needs to be. |
| ||
I wanted to keep the global list declaration inside the object code but I received syntax errors when combining with "superlist.addlast(tlist)" so I refrained from doing so. In the end I really REALLY like that I can parse through the superlist and update each object that way with a few lines of code. I have spent officially 12 hours on this project, I'm considering making it a 24 hour project then ending it there. I am thinking I'll make 24 hour game projects just to see where I'll go. I should do them from scratch, borrowing maths codes but remaining true to memorizing blitzmax coding. I have a newer version but I'm not sure if I should post it or not for a couple of reason, if you guys want me to I'll post it but it's got a huge amount of code! 1. I programmed a neat "mod" (per se) that allows me to type one line of code and get a fancy vector text font. For instance: VecDrawText("Hello World",x,y,size) draws the text in a neat vector style font. I painstakingly created the function(s) that draw each letter in the alphabet and all the numbers. However no other symbols so far(except chevrons but that was so I could draw a K) I'll post a separate topic on the matter, I think you guys might find it useful and I'd be happy to share it. |
| ||
but I received syntax errors If you post the errors, we can help you with them. When using a list outside of a type, you need to prefix it with the type name. So if you put Global playerlist:TList inside Type TPlayer, any code inside TPlayer can just say playerlist, but outside you need to write TPlayer.playerlist. |
| ||
I got 21910, died on level 20 :) Nice game. I think I'll try and figure out your source code a bit and have a play around. Might be a good starting point for others to do something with this. |
| ||
Hi guys, I have a download available for version .5 (the 12th hour of development) and would like some feedback. The latest version includes: VectorText - A font upgrade that is inefficient(I'm thankful for the guys who reviewed the VT code and pointing this out to me), I plan on changing this to a bitmap font by the time of completion. Shields - You now have destroyable shields that help protect you from enemy bullets, but also block yours (just like in space invaders) Fixed fail boundary - When the enemies reach the bottom you fail the game, before they went past the bottom. Added CTRL fire key - For those who have a different playstyle you may use the CTRL keys for firing. My primary reason is for accessibility, as one-handed people cannot play a game with the fire key being too far from the controls. Game Difficulty - I have re-programmed the way the enemies behave for a more balanced approach. I plan on releasing the source code once I finish the final 12 hours of this game project. Once I hit 24 hours it'll be completed, and after scrutiny I'd like to release a comprehensive tutorial for beginners on how to make this game. You can download it (500kb, zip file with 1 exe file) here: http://www.gamedev.net/community/gds/viewentry.asp?projectid=548722 |
| ||
OH one last thing: @ Czar: Here's my syntax error problem: Type tEnemy Extends tGameObject Global EnemyList:TList = New TList SuperList.AddLast(EnemyList) on the line "Superlist"... I get: Compile Error: Syntax error in user defined type declaration Build Error: failed to compile C:/BlitzMax/projects/ShapeInvaderz.bmx |
| ||
you have to put use of superlist.addlast(enemylist) in a method or function. you can do it like this: type tEnemy Extends TGameObject Global EnemyList:TList = New TList method new() SuperList.AddLast(EnemyList) End Method when you do: game = new TGameObject it will automatically call the "new" method you don't have to do this: game.new() the method new is used by the constructor to initialize any variables or do anything at the time of creating the current object. |
| ||
Jesse's code would try to add the enemylist to superlist everytime you created a new enemy, which isn't our intention. You should leave the superlist.adds outside of type declarations, and leave them where they were in the original code (in the initialize the game area), but move the Global declarations. Remember to call the lists outside the type block like this - TEnemy.EnemyList. You could perhaps remain the lists to just "list", to make it less wordy. So SuperList.AddLast(TEnemy.list).. SuperList.AddLast(TPlayer.list) etc |
| ||
I get the same syntax error if I move the global declarations but keep the superlist.addlast in the initialization area. I'm not exactly sure how to avoid them unless I just keep the list declaration in the top with the superlist.addlast(list) |
| ||
wrong post |
| ||
If you post the complete code we can help you solve the problem. That code doesn't tell us much other than, you are not following syntax rules somewhere. |
| ||
Ok here's the problem:SuperStrict Global SuperList:TList = New TList Type tEnemy Global EnemyList:TList = New TList SuperList.AddLast(EnemyList) End Type Creates same problem. It clearly highlights at "SuperList.AddLast(EnemyList)" as a syntax error. (Type Declaration) So, now try moving SuperList.AddLast(EnemyList) to the top as suggested: SuperStrict Global SuperList:TList = New TList SuperList.AddLast(EnemyList) Type tEnemy Global EnemyList:TList = New TList End Type Syntax Error @ SuperList.addlast(EnemyList) is now (missing EnemyList) NOW: The only way I can get it to work: Global SuperList:TList = New TList Global EnemyList:TList = New TList SuperList.AddLast(EnemyList) Type tEnemy End Type Thus I have to keep the enemylist creation outside of the type. |
| ||
If you're using the list outside of tEnemy, you need to call it tEnemy.EnemyList SuperStrict Global SuperList:TList = New TList SuperList.AddLast(tEnemy.EnemyList) Type tEnemy Global EnemyList:TList = New TList Method something_inside_the_type() Print Enemylist.Count() + " no need for tEnemy. inside here!" End Method End Type |
| ||
I wanted to use the list inside the tenemy to "tidy up the code" |
| ||
As Jesse said in post #27, you cant have code inside a type like that, it must be in a method or function...SuperStrict Global SuperList:TList = New TList Type tEnemy Global EnemyList:TList = New TList Method New() SuperList.AddLast(EnemyList) EndMethod End Type |
| ||
Thanks! Also Sorry Jesse I see you answered it but I didnt understand at the time :S I appreciate your help! |
| ||
OOPS, I just read post #28 :D I Didn't even notice its a global list in the type (its been a long night), anyway this is what you're after... SuperStrict Global SuperList:TList = New TList SuperList.AddLast(tEnemy.EnemyList) Type tEnemy Global EnemyList:TList = New TList End Type |
| ||
Yeah it was a late night for me too, not to mention how frustrating coding has been in the last day or so. Anyway, you can't put superlist.addlast(tenemy.enemylist) at the top there unless you put the enemylist at the top with it, just tyry it; doesn't work. EDIT: The only way you can put the superlist.addlast command inside the tenemy is if you put it into a method, but you don't want to keep adding the list into the superlist. From what I gather, you'd have to call the method only one time as some sort of init method. EDIT 2: It's too complicated to just get the list declaration in the enemy type. It's more practical to put the list declaration at the top of the file along with the superlist stuff. If you need to remember what the lists were called, it's easy to simply use BLIDE and use a split screen where one side shows the declarations and the other side shows where you're coding. |
| ||
I don't understand why you would want many lists inside a List if the objects are similar. The compiler is going to take longer to process if it has to determine what type of object the list contain. personally I would have an array of lists as the super list. That is not how I code but if I did that is how I would do it. in my games what I do is, I crate a list of baddies and two list of bullets(one for the baddies and one for the player). Each of the baddies extend from the base type. I use the base to process everything. like this: for bullets:Tbase = eachin bulletlist 'process bullet next there is a tutorial on OOP: Polymorphism for beginners It helped me out a bit, it Might help you also. |
| ||
The reason why I like the superlist is that you only have to iterate through the objects one time and update them all, so if you add new objects and add them to the superlist you do not have to add any additional code to update them. For instance: If you have 5 lists without a superlist you must make 5 for..next loops. If you have 5 lists within a superlist then you only need 1 for..next loop. (^_^)=b!! So instead of having several blocks of code to update all the objects in the game you only need one. This is why I believe I'll be using superlists from here on out. If you look at the top and read my first post I was not using a superlist at all. Someone showed me an interesting method (using superlists) and I think they are better than not using them. Lastly I'm not sure what the big deal is about these arrays or why you would want to put lists in array[]. It's far easier to read the code when things arent [0] or [4] .. just my humble opinion on the matter. I suppose if using brackets with numbers in them makes it easier to read for you then go for it. But one of the reasons why I like blitzmax so much is that you can put things in types instead of brackets and numbers. My only concern about using arrays and their funky brackets with numbers is that it could increase speed. But if the speed increase is negligable then they seem rather archaic. The whole purpose of BASIC is that its an easy language to read. using "dim" and [] brackets with numbers in them just isn't that easy for reading and it doesn't seem to be OOP but more like the times of QBasic and GWBasic etc. If I was going to program games with arrays all day then I'd probably be using DarkBASIC. |
| ||
Anyway, you can't put superlist.addlast(tenemy.enemylist) at the top there unless you put the enemylist at the top with it, just tyry it; doesn't work. I beg to differ, have you tried that code snippet? |
| ||
Quick tester...SuperStrict Global SuperList:TList = New TList SuperList.AddLast(tEnemy.EnemyList) New TEnemy New TEnemy New TEnemy Local list:TList, enemy:TEnemy For list=EachIn SuperList For enemy=EachIn list enemy.test() Next Next Type tEnemy Global EnemyList:TList = New TList Field Link:TLink = EnemyList.AddLast(Self) Field index%=EnemyList.Count() Method test() Print "Enemy "+index EndMethod End Type |
| ||
Awesome! I stand corrected! :D I had to put tenemy.enemylist instead of enemylist... I think this was mentioned earlier but it when right over my head, I really apologize for that. It finally makes sense! Yes it sunk in:) Thanks a million. For some reason I thought that if you put "Global" inside a Type it would be the same as putting a "Global" OUTSIDE of a type. So basically tenemy.list would be if I used a GLOBAL declaration of a list inside the type. Therefore I could have tbullet.list,tplayer.list,tenemy.list and I love the idea! Thanks a lot! |
| ||
Matt, just so you know, I am not picking on you. I don't know if I sound to rough. I was just trying to say that a group of lists in a list is not such a great idea,that arrays are faster and a better choice. at least in my opinion and mind I am no expert. I don't even code with arrays generally. The only time I have used arrays is with my tile map engine I have in the code archives. I do use lists a lot and now with direct link removal but that's for another topic. if you would like to take a look at how I code. you can take a look at my Community Framework contest entry here: http://www.filefront.com/13724392/bmfc_c.zip you can take a look at the source code. it's not too well optimized or complete as it was made in a hurry for the contest. but it works. |
| ||
Ok guys: I have the 21st hour source code for you. To play you need two blitzmax files.. UPDATES: MAJOR SPEED INCREASES! ***** 1 - Created a new VectorDraw_img_Text Function that saves all the letters into image files, and the font loads faster than DrawText() - The letters are still drawn with lines, but saved into uiamges using GrabImage() ***** 2 - All shapes are no longer drawn in realtime, but drawn int he beginning and then saved into images using GrabImage. ***** 3 - Using a more modern way to iterate through a string. It's amazing that these optimizations took me 9 hours to do, partially because I had a lot of learning to do and I appreciate the blitzmax community in helping me along the way! Filename "VectorText.bmx" Filename "ShapeInvaderz.bmx" Download the .8 version on gamedev here: http://www.gamedev.net/community/gds/viewentry.asp?projectid=548722&mode=gameinfo Enjoy!!! PS: @ Jesse, thanks :) No worries. I plan on using arrays more too. Sorry about the rant about arrays, kinda irrelevent. I'll check out your source, sounds interesting. |
| ||
I was just trying to say that a group of lists in a list is not such a great idea,that arrays are faster and a better choice I don't think it will make that much difference, at the end of the day.It's possible you could consider having only one list that stores all your objects, rather than multiple lists tied together. |
| ||
I don't think it will make that much difference, at the end of the day. I think it does, although I haven't really tested it. but I bet when you have hundreds of bullets and hundreds particles per say, and an instruction set have to determine if to assign it to a specific type of object or not, logic tells me it will definitely take a speed hit. Have you tried Grid Wars, from Mark Incitti if you haven't you can download the game including source code from my signature link. One of the reasons this game is so fast is his use of recycling of objects and use of arrays. nothing to figure out, no garbage collector taking over your program, no memory fragmentation, and no guessing. just smart coding. :) |
| ||
and an instruction set have to determine if to assign it to a specific type of object or not, logic tells me it will definitely take a speed hit. What does this mean? |
| ||
I know I am really bad at explaining stuff. Sorry. an "instruction set" is a set of code instructions assigned to do a specific task. it can be a function/call or even an simple if statement. Does that help? maybe not. Sorry, best I can do. There have to be code written to determine whether to assign the object type to a specified variable or not. When you have all different type of objects in a list, how is it determined to put one type of object into a variable or not when doing a For/EachIn loop. There is obviously some hidden code added to the executable by the compiler at the time of creating to deal with this type of situation. But then again, maybe I am wrong. I don't really know what's inside the Processor or the Bios. :) Just ignore me. I am in a different, and weird mentality. |
| ||
If all the objects in the list are of the same type, does that remove the problem? As each list only contains one type of object (tenemy, tplayer..) |
| ||
don't really know but I would guess the more it varies the more the work. consider it still have to go through all of the objects even if it only have to test one kind of object for collision or anything similar. |
| ||
That is going to happen anyway, to draw the objects and move the aliens and bullets, is it not? |
| ||
if you say so. Personally, I wouldn't do it that way. maybe it's my inexperience but I do think my way is faster/better. who knows, I might end up figuring out in the long run that your way is better. |
| ||
It's not that I'm saying my way is faster, per se, but rather on today's computers, it doesn't make enough difference to lose any sleep over ;) |
| ||
The game is fully finished and when compiled its only 64kb. Check the showcase for details! |