Not drawing multiple images.
BlitzMax Forums/BlitzMax Beginners Area/Not drawing multiple images.
| ||
So after defeating the nefarious level editor I'm now working on the primary game, I have it pulling the actual level information, everything is going well except for drawning my enemies. If I make it draw a rectangle for each enemy it works fine, but when I try to have it draw the actual "Villain" image it only draws the first one and leaves the rest blank. This tells me that my DrawSprite() is probably the issue, but I can't see the problem. SuperStrict Include "openlevel.bmx" AppTitle="Platform Game" Const gwidth:Int = 1280 Const gheight:Int = 1024 Graphics gwidth, gheight Global scn_left:Int = 0 Global scn_top:Int = 0 Global Spritelist:TList = CreateList() For Local x:Int = 0 To mapx-1 For Local y:Int = 0 To mapy-1 For Local z:Int = 0 To mapz-1 If map[x,y,4] > -1 Then Global H:hero = Hero.Create("images/hero.png",(x*tsize)-scn_left,(y*tsize) - scn_top) If map[x,y,3] = 0 Then Global E:Enemy = Enemy.Create("images/Villain.png",(x*tsize)-scn_left,(y*tsize) - scn_top) Next Next Next Repeat Cls For Local H:Hero = EachIn Spritelist H.UpdateSprites() Next For Local a:Sprite = EachIn Spritelist a.DrawSprites() Next Flip Until AppTerminate() Or KeyHit(Key_escape) Type Sprite Field x:Int Field y:Int Field I:TImage Method DrawSprites() DrawImage I,x,y End Method End Type Type Hero Extends Sprite Function Create:Hero(File:String,xstart:Int,ystart:Int) Local H:Hero = New Hero H.x=xstart H.y=ystart H.I=LoadImage(file) ListAddLast Spritelist, H Return H End Function Method UpdateSprites() If KeyDown(key_left) Then x = x - 5 If KeyDown(key_right) Then x = x + 5 End Method End Type Type Enemy Extends Sprite Function Create:Enemy(File:String,xstart:Int,ystart:Int) Local E:Enemy = New Enemy E.x=xstart E.y=ystart E.I=LoadImage(file) ListAddLast Spritelist, E Return E End Function Method UpdateSprites() End Method End Type End |
| ||
Change your looping and dont create Globals in a loop ;)Global H:Hero ' Dont need Global E:Enemy For Local x:Int = 0 To mapx-1 For Local y:Int = 0 To mapy-1 For Local z:Int = 0 To mapz-1 If map[x,y,4] > -1 Then H = Hero.Create("images/hero.png",(x*tsize)-scn_left,(y*tsize) - scn_top) If map[x,y,3] = 0 Then Enemy.Create("images/Villain.png",(x*tsize)-scn_left,(y*tsize) - scn_top) Next Next Next Last edited 2012 |
| ||
I would replaceFor Local H:Hero = EachIn Spritelist H.UpdateSprites() Next For Local a:Sprite = EachIn Spritelist a.DrawSprites() Next with 'both types extend from sprite, so we can use that 'that way we replace a loop of a maybe-big-list with type checks 'use such style if MORE THAN ONE hero is possible in the list For Local a:Sprite = EachIn Spritelist if Hero(a) <> null then Hero(a).UpdateSprites() a.DrawSprites() Next or better: 'we stored hero as global - no need to look for it. H.UpdateSprites() For Local a:Sprite = EachIn Spritelist a.DrawSprites() Next To check the images/drawimage-part - replace: Type Sprite Field x:Int Field y:Int Field I:TImage Method DrawSprites() DrawImage I,x,y End Method End Type with Type Sprite Field x:Int Field y:Int Field I:TImage Method DrawSprites() if I<>null DrawImage(I,x,y) else DrawRect(x,y,20,20) 'print "missing sprite image XYZ drawn at x="+x+" y="+y endif End Method End Type Hope that helps a bit. bye Ron PS: if you know that enemies share images, make a TMap with Sprites and access them that way and not with LoadImage(url) multiple times. - create map - check existance of object by url as key - insert object (Timage) to map with url as key You can do the same with other resources in your application. |
| ||
Okay so I did everything suggested (aside from the Tmap, I need to learn more about those) and it's working, almost too well. Now for some reason it's drawing multiple images of the Hero sprite, only one of which actually exists as an object created by the hero type, if I remove H from the Spritelist then it deletes the sprite that I have control over and just leaves a static image that's standing at the starting XY coordinates. Edit: I tested the sprites for the enemies and they aren't affected by this issue, so it's just an issue with the hero for some reason. Last edited 2012 |
| ||
Try this (also I added the TMap stuff that Derron talked about and I added some code so I code actually run (eg mapx, mapy etc):SuperStrict AppTitle="Platform Game" Const WIDTH:Int = 1280 Const HEIGHT:Int = 1024 Graphics WIDTH, HEIGHT Global scn_left:Int = 0 Global scn_top:Int = 0 Global sprite_list:TList = CreateList() Global mapx:Int = 20 Global mapy:Int = 20 Global mapz:Int = 20 Global tsize:Int = 30 Global map:Int[,,] Global h:THero Global images:TImageBank = New TImageBank LoadImages() PopulateMap() Local heroCreated:Int = False For Local x:Int = 0 To mapx - 1 For Local y:Int = 0 To mapy - 1 For Local z:Int = 0 To mapz - 1 If map[x,y,4] > -1 And Not heroCreated Then h = THero.Create(images.Get("hero"),(x*tsize)-scn_left,(y*tsize) - scn_top) heroCreated = True EndIf If map[x,y,3] = 0 Then TEnemy.Create(images.Get("Villain"),(x*tsize)-scn_left,(y*tsize) - scn_top) Next Next Next Repeat Cls h.UpdateSprite() For Local a:TSprite = EachIn sprite_list a.DrawSprite() Next Flip Until AppTerminate() Or KeyHit(KEY_ESCAPE) Function LoadImages() images.Load("images/hero.png") images.Load("images/Villain.png") EndFunction Function PopulateMap() map = New Int[mapx, mapy, mapz] For Local x:Int = 0 To mapx - 1 For Local y:Int = 0 To mapy - 1 For Local z:Int = 0 To mapz - 1 map[x, y, z] = Rand(0, 10) Next Next Next EndFunction Type TSprite Field x:Int Field y:Int Field image:TImage Method DrawSprite() DrawImage image,x,y End Method End Type Type THero Extends TSprite Function Create:THero(image:TImage, xstart:Int, ystart:Int) Local h:THero = New THero h.x = xstart h.y = ystart h.image = image sprite_list.AddLast(h) Return h End Function Method UpdateSprite() If KeyDown(key_left) Then x = x - 5 If KeyDown(key_right) Then x = x + 5 End Method End Type Type TEnemy Extends TSprite Function Create:TEnemy(image:TImage, xstart:Int, ystart:Int) Local e:TEnemy = New TEnemy e.x = xstart e.y = ystart e.image = image sprite_list.AddLast(e) Return e End Function Method UpdateSprite() End Method End Type Type TImageBank Extends TMap Method Load(name:String) Local i:TImage = LoadImage(name) If i = Null Then RuntimeError "Error - Cannot load image "+name Insert(StripAll(Upper(name)), i) EndMethod Method Get:TImage(name:String) Local i:TImage = TImage(ValueForKey(Upper(name))) If i = Null Then RuntimeError "Error - Cannot find image "+name Return i EndMethod EndType End Last edited 2012 Last edited 2012 |
| ||
@therevills [bbcode] Global h:THero ... Local heroCreated:Int = False ... If map[x,y,4] > -1 And Not heroCreated Then h = THero.Create(images.Get("hero"),(x*tsize)-scn_left,(y*tsize) - scn_top) heroCreated = True EndIf [/bbcode] could be stripped by... [bbcode] Global h:THero = Null ... If map[x,y,4] > -1 And h = null h = THero.Create(images.Get("hero"),(x*tsize)-scn_left,(y*tsize) - scn_top) EndIf [/bbcode] Think a "null" check is not that work intensive :D @awesome Try to get some code which you can post here for us to test. Another hint: instead of calling a type's method "UpdateSprites" you should consider calling it "Update" and "Draw" and the object containing the list can then have a function (methods if instances) like "UpdateAll". If you run into problems like "but Hero extends sprite and has to have a method 'draw' too" try something like : [bbcode] Type THero field sprite:TSprite field name:string="My Hero" ... Method Draw() self.sprite.Draw() End Method End Type [/bbcode] That's needed as you won't be able to extend a class and overwrite the parents methods in Blitzmax (for adding further parameters and so on). Extend types if they share something - so eg. Renderables but do not extend from attributes they have. [bbcode] 'object having some values associated but needs some nifty helpers Type TCoord field x:float field y:float ... Method IsSame(otherTCoord) ... Method IsSameXY(x:float,y:float) ... End Type Type TRenderable field coord:TCoord ... 'abstract methods are defined in all the ancestors Method Draw() abstract ... End Type Type TSprite extends TRenderable field image:TImage ... Method Draw() DrawImage(self.image, self.coord.x, self.coord,y) ... End Method End Type Type THero field sprite:TSprite 'here we can store the coord of last cycle 'or before we started some moving action - a backup :D 'but this won't be that easy if extending the things field lastCoord:TCoord Method Draw(additionalParameterLikeOverwriteSomething:int = 0) self.sprite.Draw() End Method End Type 'do the same for Type TEnemy 'but this time you can extend different Enemies... TFireElemental extends TEnemy 'then just change sprites, or update-behaviour Type TLevel field blocksAndEntityList... field enemiesList:TList ... End Type Type TGame field hero:THero field currentLevel:TLevel ... Method Update() hero.update() for local enemy:TEnemy = eachin self.currentLevel.enemiesList enemy.update() next End Method ... 'same for Method Draw()... End Type ... [/bbcode] Ok it's not tested as I wrote it now and I might be run into offtopic or some kind of tutorial for "oop in BlitzMax" ... think I finish my posting here :D bye Ron |