Edit #2: Alright I got home and whipped up a little example. I'm not the best at being "pythonic" but here you can hopefully see how I create a surface for the log, populate it with rendered text, and THEN blit it onto the main surface (which for this example is just a black space). Dividing your pygame UI up into HUD sections is a big part of jumping from making text-based programs to working with pygame's surfaces. Please forgive my use of magic numbers.
# A little pygame console
# press "t" to add messages to the continuously updatding HUD element
import pygame
pygame.init()
# constants
RES = (800, 600)
FPS = 30
MAIN_SURFACE = pygame.display.set_mode(RES)
CLOCK = pygame.time.Clock()
pygame.display.set_caption("Example Console UI Element")
the_font = pygame.font.Font(None, 32)
message_log = []
def console_print(message):
message_log.append(message)
def update_log():
# create a surface for the log:
# This one the same width as the RESOLUTION and 1/3 the height
log_surf = pygame.Surface((RES[0], RES[1] // 3))
log_surf.fill((80, 80, 80))
# Populate it with, say, the last three messages:
# Note: You could do this in a more elegant loop if you wanted to.
# You would probably be served by checking to see if you have any messages at all before
# searching through the message log, to avoid looking for elements that aren't in the list.
# for this example I added 3 placeholder messages at the start of the main function
# to avoid that problem here.
new_log = []
m1 = message_log[-1]
m2 = message_log[-2]
m3 = message_log[-3]
new_log.append(m1)
new_log.append(m2)
new_log.append(m3)
font_y = 0
for m in new_log:
message = the_font.render(m, False, (255, 255, 255))
log_surf.blit(message, (0, font_y))
font_y += 34 # gives a little padding for the next message
# blit it to the main surface in a spot where it'll fit snugly:
# sorry for the magic numbers, ideally you would pre-define these positions
# as variables
MAIN_SURFACE.blit(log_surf, (0, 400))
def update():
MAIN_SURFACE.fill((0, 0, 0))
update_log()
pygame.display.flip()
def main():
console_print("Placeholder message 1")
console_print("Placholder message 2")
console_print("Placeholder message 3")
messages = 0
running = True
while running:
for event in pygame.event.get():
if event.type is pygame.QUIT:
running = False
if event.type is pygame.KEYDOWN:
if event.key == pygame.K_t:
# advance the turn as an example
messages += 1
console_print("Message # " + str(messages))
# test in the terminal
print("Message # " + str(messages))
update()
CLOCK.tick(FPS)
pygame.quit()
if __name__ == "__main__":
main()
There you go! By messing around with the numbers here you can hopefully get a feel for messing with surface dimensions. I apologize in advance if this is stylistically bad but it's worked well for me in many projects. Pygame has built-in sub-surface capabilities but I have not deeply explored those at all. Hard-coding your dimensions is not a bad way to start, I feel. I hope that helps and good luck!