python - Pygame: Rect Objects Don't Render Properly in For Loops -
i'm using pygame develop game , i've decided i'd group gui objects in dictionary so:
gui_objects = { # guiobject parameters define rect (for positioning) , background colour. "healthbar" : guiobject((10, 10, 100, 20), colour.blue), "mini_map" : guiobject((10, 400, 50, 50), colour.white) }
the reason i'm grouping gui objects can modify them like:
gui_objects.get("mini_map").set_enabled(false)
now, when want render gui objects screen, did this:
for key, value in gui_objects.iteritems(): value.render(screen)
this works, reason, white "mini_map" guiobject gets rendered underneath "healthbar" guiobject. decided put "mini_map" above "healthbar" in dictionary, changed nothing. here's weird part. if render gui objects separately, is, calling render() functions separately, this:
gui_objects.get("healthbar").render(screen) gui_objects.get("mini_map" ).render(screen)
then guiobjects overlap properly. question is, why guiobjects not overlap when render them using loop? yet overlap fine when rendered separately?
unfortunately, can't upload images because don't have enough reputation ¬_¬ but, here's source code:
import pygame # definition of few colours class colour(object): white = (255, 255, 255) grey = (128, 128, 128) blue = ( 64, 128, 255) # guiobject rectangle colour @ moment (for testing purposes). class guiobject(object): def __init__(self, rect, colour): self.rect = rect self.colour = colour def render(self, screen): pygame.draw.rect(screen, self.colour, self.rect) def main(): ############################################################################ # initialise pygame.init() screen = pygame.display.set_mode((800, 600)) # if render_type = 0 render guiobjects using loop # if render_type = 1 render guiobjects separately. render_type = 1 gui_objects = { "hpbar_bg" : guiobject(( 0, 0, 150, 600), (colour.blue)), "enemy_hpbar" : guiobject((10, 10, 200, 400), (colour.white)), } ############################################################################ # main loop while true: ######################################################################## # event handling event in pygame.event.get(): if event.type == pygame.quit: pygame.quit() exit(0) ######################################################################## # render screen.fill((0, 0, 0)) # here, render guiobjects. if render_type == 0: # loop messes overlapping. key, value in gui_objects.iteritems(): value.render(screen) elif render_type == 1: # works fine. gui_objects.get("hpbar_bg").render(screen) gui_objects.get("enemy_hpbar").render(screen) pygame.display.flip() if __name__ == "__main__": main()
has got clue why overlapping guiobjects doesn't work when using loop?
i hope i've explained myself enough. if not, ask , i'll try clarify.
because dictionaries aren't ordered , drawing objects in different order other method.
a dictionary not designed holding objects need stay in order.
you can either:
- use pygame render group instead.
this pygame-recommended way store groups of objects going drawn, have convert gui objects sprites believe. edit: also, pygame render groups still not ordered wouldn't solve particular problem.
- use list of tuples
[(name,value),...]
instead (this similar current method because that'siteritems()
dictionary method returns).
here code re-written using method 2:
import pygame # definition of few colours class colour(object): white = (255, 255, 255) grey = (128, 128, 128) blue = ( 64, 128, 255) # guiobject rectangle colour @ moment (for testing purposes). class guiobject(object): def __init__(self, rect, colour): self.rect = rect self.colour = colour def render(self, screen): pygame.draw.rect(screen, self.colour, self.rect) def main(): ############################################################################ # initialise pygame.init() screen = pygame.display.set_mode((800, 600)) # if render_type = 0 render guiobjects using loop # if render_type = 1 render guiobjects separately. render_type = 0 gui_objects = [ ("hpbar_bg", guiobject(( 0, 0, 150, 600), (colour.blue))), ("enemy_hpbar", guiobject((10, 10, 200, 400), (colour.white))), ] ############################################################################ # main loop while true: ######################################################################## # event handling event in pygame.event.get(): if event.type == pygame.quit: pygame.quit() exit(0) ######################################################################## # render screen.fill((0, 0, 0)) # here, render guiobjects. if render_type == 0: # loop no longer messes overlapping. key, value in gui_objects: value.render(screen) pygame.display.flip() if __name__ == "__main__": main()
because able things gui_objects.hpbar_bg.set_enabled(false)
third option:
- restructuring code contain gui within class itself, , order drawing of components within draw method.
here example of 3 doesn't deviate far you've got:
import pygame # definition of few colours class colour(object): white = (255, 255, 255) grey = (128, 128, 128) blue = ( 64, 128, 255) # guiobject rectangle colour @ moment (for testing purposes). class guiobject(object): def __init__(self, rect, colour): self.rect = rect self.colour = colour self.enabled = true def render(self, screen): if self.enabled: pygame.draw.rect(screen, self.colour, self.rect) class gui(object): def __init__(self): self.hpbar_bg = guiobject(( 0, 0, 150, 600), (colour.blue)) self.enemy_hpbar = guiobject((10, 10, 200, 400), (colour.white)) self.enabled = true def render(self, screen): #render gui in order want if self.enabled: self.hpbar_bg.render(screen) self.enemy_hpbar.render(screen) def main(): ############################################################################ # initialise pygame.init() screen = pygame.display.set_mode((800, 600)) gui = gui() #uncomment enabled/disabled behavior #gui.hpbar_bg.enabled = false #or disable whole gui #gui.enabled = false ############################################################################ # main loop while true: ######################################################################## # event handling event in pygame.event.get(): if event.type == pygame.quit: pygame.quit() exit(0) ######################################################################## # render screen.fill((0, 0, 0)) # render gui gui.render(screen) pygame.display.flip() if __name__ == "__main__": main()
Comments
Post a Comment