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 |