




In my previous post about adding graphics to the C version of my Rogue-Like game, I mentioned experimenting with Raylib.
Raylib is an extensive framework or SDK that supports not only sprites and graphics, but also a multitude of features that I’m still discovering.
However, it still demands significant coding in C.
I opted for C because my game is aimed at retro systems. While C is considered low-level today, it’s still relatively high-level compared to assembly, especially when starting from scratch across multiple architectures.
A friend piqued my curiosity about the workload differences involved in recreating the game in a more user-friendly environment like Pygame. So, I decided to give it a try.
Why Not Use AI?
Before diving into my testing, you may be wondering why I didn’t just delegate the task to a large language model.
To clarify (please correct me if I’m mistaken!), I don’t believe current AI tools can effectively handle complex codebases with numerous library files. They may work for individual routines, but full programs? Not yet.
It would be fantastic to simply say, “Convert this game” and provide my C code, but I haven’t yet seen an AI tackle that level of complexity.
Pygame Maze Tests
The first step was to replicate the maze generation code, as this is crucial for testing fun gameplay and saves me from the hassle of manually designing levels.
I’ve tackled this before, so the task was mainly to ensure it aligned with the design choices I made in my existing game.
Essentially, it creates pathways by selecting random directions and backtracking when encountering dead ends.
Since the original game was designed for a 40×24 character screen, I approximated the pixel dimensions accordingly. While not ideal (“responsive” designs are better), it enabled me to progress.
My maze.py became the module for the game, adding a check to see if it was run as a script or imported:
def main():
pygame.init()
screen = pygame.display.set_mode((MAP_WIDTH * TILE_SIZE, MAP_HEIGHT * TILE_SIZE))
pygame.display.set_caption("Maze Game")
carveMaze()
placePlayer()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((0, 0, 0))
draw_map(screen)
pygame.display.flip()
pygame.quit()
if name == "main":
main()
Characters to Graphics
I faced a decision: should I draw the graphics first or get the game running?
I sidestepped that dilemma by generating bitmaps for each ASCII character instead:
# Create placeholder images for characters
def create_placeholder_image(char, filename):
font = pygame.font.SysFont('Roboto', TILE_SIZE)
image = pygame.Surface((TILE_SIZE, TILE_SIZE))
image.fill((0, 0, 0))
text_surface = font.render(char, True, (0, 255, 0))
image.blit(text_surface, (0, 0))
pygame.image.save(image, filename)
This process created small PNG files that resemble terminal emulator renders:
Movement Issues
This is where I encountered a challenge.
Pygame doesn’t seem to have a built-in “wait for a keypress” feature. Its event-based nature is understandable, given its primary use in action games.
However, my game is turn-based, typical of dungeon-crawler rogue games, where players should think through their moves rather than relying on quick reactions.
To navigate this, I implemented a state variable to pause the code:
# Main game loop
def game_loop(screen, images):
global player_x, player_y, old_x, old_y, direction_x, direction_y, health, score, magic, sword, weapon, keys, idols, room, in_play, run
pressed = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
pressed = True
if event.key == pygame.K_w:
move_player(0, -1)
elif event.key == pygame.K_a:
move_player(-1, 0)
elif event.key == pygame.K_s:
move_player(0, 1)
elif event.key == pygame.K_d:
move_player(1, 0)
elif event.key == pygame.K_q:
in_play = False
run = False
if pressed:
move_enemies()
screen.fill((0, 0, 0))
draw_map(screen, images)
pygame.display.flip()
time.sleep(0.1)
pressed = False
Enhanced Graphics
Now that my character can move around the screen with basic enemy movements and attacks in place, I can begin to envision gameplay.
Instead of sticking with ASCII placeholders, I imported each PNG into Aseprite and created simple game graphics.
I wanted to keep the color palette limited for compatibility with 16 and 32-bit systems, maintaining a retro aesthetic rather than aiming for AAA quality.
These graphics can be utilized regardless of my final approach, though I’m aiming for a more refined color palette for greater satisfaction with my game art.
Conclusion
So, is this approach superior?
There’s still plenty of work to do to fully recreate the game in Python. So far, I’ve only managed to enable a character to move within a maze, meaning the game is far from complete.
Ideally, switching from terminal rendering to bitmap rendering in Raylib would allow me to refine the mechanics without extensive rewrites; we’ll see how realistic that is.
Nonetheless, this endeavor isn’t wasted time; I’ve gained valuable insights into Pygame and created initial graphics that can be applied to whichever direction I ultimately choose!
Original article by retrogamecoders.com


