r/pygame

▲ 46 r/pygame

Duck Hunt Clone( Feedback)

Hey everyone, this is my first coding project and I’ve made a clone of Duck Hunt. I’m looking for constructive feedback on how I can improve the code, especially in terms of structure, readability, and better practices.

I would appreciate any advice that helps me become a better developer.

Here’s my GitHub repo: https://github.com/Pranavnbhat/Duck\_Hunt\_pygame

Thanks in advance!

u/Some_Dude11203 — 24 hours ago
▲ 3 r/pygame+1 crossposts

How do I get collision to detect properly in pygame

Here is what the collision looks like fast that slow
https://imgur.com/a/JNVEdUV

player = Block(500, 300, 20, 20, "blue")

surfaceList = [Block(500, 100, 60, 10, "orange"), 
Block(500, 110, 60, 30, "red"),
Block(500, 140, 60, 10, "orange")]

--- MAIN LOOP ---

# COLLISION
collision_target = None # Track which surface the player is colliding with

target = player.rect.collidelist(surfaceList)

if target != -1:
    collision_target = target

if collision_target == 1 and key[pygame.K_SPACE] == target:
player.color = "green"
else:
player.color = "blue"

# Draw
for i in surfaceList:
    i.drawSurface(screen)

So I am trying to get the collision to detect when spacebar is hit and it works somewhat but it still not detecting properly. How can i fix this issue

u/TheEyebal — 22 hours ago
▲ 6 r/pygame

What's the best way to program multiple display windows?

In most of my games, I want to make a menu that has multiple different options. I've already tested a few, and with my button class, they work.

However, the way I've programmed the screens to work has a logic error. I've done it so I'm importing the screen from another file each time it's opened, but I've learnt that's not the best way to do it, at all. I'm using a new while loop each time the function to open the next window is called, and that's just "window layering".

I currently have a logic error: when I use the return button, instead of going onto the previous display, the return button takes the player all the way to the main menu instead.

Basically, I'm not satisfied at all with how my display windows are working and would really love some assistance on how to get multiple windows to work, please...!!! Thank youu

reddit.com
u/monibuec — 2 days ago
▲ 2 r/pygame

I can't install pygame

I'm trying to install Pygame, but I'm given this error message every time I try to. Is this a common error? How do I fix it?

u/LocalPlatypus994 — 1 day ago
▲ 3 r/pygame

Trying to put improve the look of exponentation

Howdy.

I've been trying to implement visible exponents for my Guessing Game (e.g :`x^(2)`) but the best I manage to do is `x**2`

So far, I've tried using `init_printing(use_unicode=True)` & `pprint` to achieve this but the result stays the same.

Any advice on how I could implement this?

Link to files (removed a lot of code to keep only necessary stuff) :

- https://paste.pythondiscord.com/QL3A

https://preview.redd.it/hv3z3ua9kowg1.png?width=1108&format=png&auto=webp&s=bc457c80dd0f2650365d83b0936241fdbbee2bf6

reddit.com
u/lifeintel9 — 1 day ago
▲ 5 r/pygame

Awesome book about 2D collision detection

Reading a book at the moment that gives a solid review of the maths required for collision detection and then covers putting that maths into practice - teaching a variety of collision detection methods. Great if you want to roll your own physics engine to suit the needs of your game without having to rely on 3rd party libraries that might be overkill or ill-suited for your requirements.

https://www.amazon.com/dp/B0G59K1RPR

reddit.com
u/mrshr3d — 2 days ago
▲ 38 r/pygame+2 crossposts

Nevu UI has been updated to v0.7.5

Changelog: https://github.com/GolemBebrov/nevu-ui/releases/tag/v,

0.7.5

This update focuses on improving quality and shorten length of code! also improving performance

Please star my project, on github, i will really appreciate it!

Code of the program on the video:

import nevu_ui as nv #(0.7.5, tested on: python 3.14.2)
import pygame #(pygame-ce)
import sys
import pyray as rl
pygame.init()


GLOBAL_FONT = "tests/vk_font.ttf" # CHANGE IT!!! if you wnant to change font


def create_border(name):
    return nv.BorderConfig(name = name, font = nv.load_font(GLOBAL_FONT, 20))


class UI:
    def __init__(self, root, res):
        self.root = root
        self.generate_base_constants()
        self.create_menu_base(res)
        self.create_menu_left(res)
        self.create_menu_scr(res)
        self.create_menu_group(res)


    def generate_base_constants(self):
        self.widget_style = nv.default_style(border_radius=5, border_width=0, colortheme=nv.ColorThemeLibrary.dracula, font_name=GLOBAL_FONT)
             
        self.widget_style2 = self.widget_style(border_radius=15*2)
        
        self.widget_size_s = (100, 50)
        self.widget_size_m = (150, 50)
        self.widget_size_l = (200, 50)
        self.widget_size_x = (250, 75) 
        self.widget_size_xl = (300, 50)
        self.widget_size_xxl = (400, 50)
        
        self.widget_kwargs = {"size": self.widget_size_l, "style": self.widget_style, "single_instance": True}
        self.widget_kwargs2 = {"size": self.widget_size_m, "style": self.widget_style2, "single_instance": True}
    
    def _on_style_click(self, *args, **kwargs):
        colotheme = args[1]
        self.menu.apply_style_patch_to_layout(colortheme=colotheme) 
        self.menu_left.apply_style_patch_to_layout(colortheme=colotheme)
    
    def create_menu_base(self, res):
        nv.nevu_object_globals.modify(**self.widget_kwargs)
        with nv.widget_globals.modify_temp(size = self.widget_size_s, style = self.widget_style(font_size = 25), subtheme_role=nv.SubThemeRole.TERTIARY):
            self.x = nv.Label("X:NAN", self.widget_size_s, self.widget_style(font_size=25))
            self.y = nv.Label("Y:NAN", self.widget_size_s, self.widget_style(font_size=25))
        
        coords_lay = nv.StackColumn(
            content = [
                (nv.Align.CENTER, self.x),
                (nv.Align.CENTER, self.y)
            ])
        
        self.mode = nv.ElementSwitcher(elements = ["Tile","Script","Group"], on_content_change = self.root.on_change_mode)
        mode_layout = nv.StackColumn(
            content = [
                (nv.Align.CENTER, nv.Label("Mode:", self.widget_size_l, subtheme_role = nv.SubThemeRole.TERTIARY)),
                (nv.Align.CENTER, self.mode)
            ])
        
        with nv.widget_globals.modify_temp(subtheme_role = nv.SubThemeRole.PRIMARY, style = self.widget_style2, size=50, active_rect_factor=0.8): #type: ignore
            self.wall = nv.RectCheckBox(on_toggle = self.root.stub)
            is_wall_layout = nv.StackRow(
                content = [
                    (nv.Align.CENTER, nv.Label("Wall:", self.widget_size_l)),
                    (nv.Align.CENTER, self.wall)
                ]
            )


            self.passable =  nv.RectCheckBox(on_toggle = self.root.stub, toggled=True)
            is_passable_layout = nv.StackRow(
                content = [
                    (nv.Align.CENTER, nv.Label("Passable:", self.widget_size_l)),
                    (nv.Align.CENTER, self.passable)
                ]
            )


        tile_attrs_layout = nv.StackColumn(
            content = [
                (nv.Align.CENTER, is_wall_layout),
                (nv.Align.CENTER, is_passable_layout)
            ], borders = create_border(name = "Traits")
        )
        
        file_layout = nv.StackRow(
            content = [
                (nv.Align.CENTER, nv.Label("TBD...", subtheme_role = nv.SubThemeRole.TERTIARY))
            ], borders = create_border(name = "Files")
        )
        
        left_panel_layout = nv.StackColumn(
            content = [
                (nv.Align.CENTER, tile_attrs_layout),
                (nv.Align.CENTER, file_layout)
            ]
        ) 
        white_line = nv.Widget((300, 3), self.widget_style(border_radius=5, border_width=0), single_instance = False,)
        with nv.widget_globals.modify_temp(**self.widget_kwargs2):
            scene_layout = nv.StackColumn(
                content = [
                    (nv.Align.CENTER, nv.Button(self.root.stub,"Save")),
                    (nv.Align.CENTER, white_line),
                    (nv.Align.CENTER, nv.Button(self.root.stub,"Load")),
                    (nv.Align.CENTER, white_line),
                    (nv.Align.CENTER, nv.Button(self.root.stub,"New")),
                ], borders = create_border(name = "Scene")
            )


            self.obj_lbl = nv.Label("Object", style=self.widget_style(border_radius=(0,15,15,0)))
            self.obj_btn = nv.Button(self.root.stub, "+", size=(50,50), style=self.widget_style(border_radius=(15,0,0,15)))
            pl_object_stack = nv.StackRow(
                content = [
                    (nv.Align.CENTER, self.obj_btn), (nv.Align.CENTER, self.obj_lbl)
                ], spacing = 2
            )
            
            self.door_lbl = nv.Label("+ Door", style=self.widget_style(border_radius=(0,15,15,0)))
            self.door_btn = nv.Button(self.root.stub, "+", size=(50,50), style=self.widget_style(border_radius=(15,0,0,15)))
            pl_door_stack = nv.StackRow(
                content = [
                    (nv.Align.CENTER, self.door_btn), (nv.Align.CENTER, self.door_lbl)
                ], spacing = 2
            )
            
            objects_layout = nv.StackColumn(
                content=[(nv.Align.CENTER, pl_object_stack),
                        (nv.Align.CENTER, pl_door_stack),
                ], borders = create_border(name = "Objects")
            )
        
        self.stylechk = nv.ElementSwitcher(self.widget_size_m, [["Material", nv.ColorThemeLibrary.material3_green], ["MaterialAlt", nv.ColorThemeLibrary.material3_dark],
                                                                ["Cat Dark", nv.ColorThemeLibrary.catppuccin_mocha], ["Cat Light", nv.ColorThemeLibrary.catppuccin_latte],
                                                                ["Box Dark", nv.ColorThemeLibrary.gruvbox_dark], ["Box Light", nv.ColorThemeLibrary.gruvbox_light],
                                                                ["Guthib", nv.ColorThemeLibrary.github_dark], ["Pastel", nv.ColorThemeLibrary.pastel_rose_light],
                                                                [1,nv.ColorThemeLibrary.dracula]
                                                                ], self.widget_style2, on_content_change = self._on_style_click)
        self.stylechklbl = nv.Label("Style:", self.widget_size_s, self.widget_style, subtheme_role = nv.SubThemeRole.TERTIARY)
        
        style_layout = nv.StackColumn(
            content = [
                (nv.Align.CENTER, self.stylechklbl),
                (nv.Align.CENTER, self.stylechk)
            ]
        )
        
        self.layer = nv.ElementSwitcher(self.widget_size_s, ["0","1","2","3","4","5","6","7","8","9","10"], self.widget_style2, on_content_change = self.root.stub)
        self.layerlbl = nv.Label("layer:", self.widget_size_s, self.widget_style, subtheme_role = nv.SubThemeRole.TERTIARY)
        
        layer_layout = nv.StackColumn(
            content = [
                (nv.Align.CENTER, self.layerlbl),
                (nv.Align.CENTER, self.layer)
            ]
        )
        self.layer.disactivate()
        self.layer.hide()
        self.layerlbl.hide()
        layer_style_layout = nv.StackColumn(
            content = [
                (nv.Align.CENTER, style_layout),
                (nv.Align.CENTER, layer_layout)
            ]
        )
        
        main_layout = nv.Grid([nv.fill%100, nv.fill%100], x = 6, y = 1,
                            content = {
                                (1, 1): coords_lay,
                                (2, 1): left_panel_layout,
                                (3.3, 1): scene_layout,
                                (4.33, 1): objects_layout,
                                (5.3, 1): layer_style_layout,
                                (5, 1): nv.Widget([5,nv.fill%100], nv.default_style(border_width=0)),
                                (6, 1): mode_layout
                            }, borders = create_border(name = "REDATOR"))
                            
        self.menu = nv.Menu(window, [res[0], 300], layout=main_layout, style=self.widget_style(border_radius=0, border_width=0,))
        self.menu.set_coordinates(0, res[1]-300) #pls dont watch at this bad code aaaaaaaahh
        
    def create_menu_scr(self, res):
        self.menuscr = nv.Menu(window, [400,300])
        self.menuscr.set_coordinates(res[0]-400, res[1]-600)
        
        self.scriptE = nv.Input(self.widget_size_xl, self.widget_style2, "Not selected", whitelist = nv.InputType.ALL_LETTERS+nv.InputType.ALL_SYMBOLS, on_change_function=self.root.stub) 
        self.scriptL = nv.Input(self.widget_size_xl, self.widget_style2, "Not selected", whitelist = nv.InputType.ALL_LETTERS+nv.InputType.ALL_SYMBOLS, on_change_function=self.root.stub) 
        
        enter_layout = nv.StackColumn(spacing = 5,
                                content = [(nv.Align.CENTER, nv.Label("Enter:", [110,35], self.widget_style(border_radius=4, font_size=20))),
                                        (nv.Align.CENTER, self.scriptE)])
        exit_layout = nv.StackColumn(spacing = 5,
                                content = [(nv.Align.CENTER, nv.Label("Exit:", [110,35], self.widget_style(border_radius=4, font_size=20))),
                                        (nv.Align.CENTER, self.scriptL)])
        
        script_layout = nv.ScrollableColumn([400,300], spacing = 12,
                                content = [(nv.Align.CENTER, nv.Label("Script:", [nv.fill%60, 35], self.widget_style(font_size=20))),
                                        (nv.Align.CENTER, enter_layout),
                                        (nv.Align.CENTER, exit_layout)])
        
        self.menuscr.layout = script_layout
        
    def create_menu_group(self, res):
        self.menugroup = nv.Menu(window, [400,300], self.widget_style(colortheme=nv.ColorThemeLibrary.catppuccin_mocha))
        self.menugroup.set_coordinates(res[0]-400, res[1]-600)
        
        self.scr_name = nv.Input(self.widget_size_xxl, self.widget_style2(border_radius=0), "Not selected", whitelist = list(nv.InputType.ALL_LETTERS+nv.InputType.ALL_SYMBOLS), on_change_function=self.root.stub)
        self.groupE = nv.Input(self.widget_size_xl, self.widget_style2, "Entry", whitelist = list(nv.InputType.ALL_LETTERS+nv.InputType.ALL_SYMBOLS+" "+nv.InputType.NUMBERS), on_change_function=self.root.stub)
        self.groupL = nv.Input(self.widget_size_xl, self.widget_style2, "Exit", whitelist = list(nv.InputType.ALL_LETTERS+nv.InputType.ALL_SYMBOLS+" "+nv.InputType.NUMBERS), on_change_function=self.root.stub)
        self.groupC = nv.Input(self.widget_size_xl, self.widget_style2, "Inside", whitelist = list(nv.InputType.ALL_LETTERS+nv.InputType.ALL_SYMBOLS+" "+nv.InputType.NUMBERS), on_change_function=self.root.stub)


        name_lay = nv.StackColumn(
                            content = [(nv.Align.LEFT, nv.Label("Name(Important):", [200,35], self.widget_style(border_radius=(0,15,15,0), font_size=20))),
                                    (nv.Align.LEFT, self.scr_name)]
        )


        enter_lay = nv.StackColumn(spacing=5,
                            content = [(nv.Align.CENTER, nv.Label("Entry:", [110,35], self.widget_style(border_radius=4, font_size=20))),
                                    (nv.Align.CENTER, self.groupE)])


        exit_lay = nv.StackColumn(spacing=5,
                            content = [(nv.Align.CENTER, nv.Label("Exit:", [110,35], self.widget_style(border_radius=4, font_size=20))),
                                    (nv.Align.CENTER, self.groupL)])


        inside_lay = nv.StackColumn(spacing=5,
                            content = [(nv.Align.CENTER, nv.Label("Inside:", [110,35], self.widget_style(border_radius=4, font_size=20))),
                                    (nv.Align.CENTER, self.groupC)])



        script_group_panel = nv.ScrollableColumn([100%nv.fill, 100%nv.fill], spacing = 5, id = "scr",
            content=[
                (nv.Align.CENTER, nv.Label("Script Group:", self.widget_size_xl, self.widget_style(font_size=20))),
                (nv.Align.CENTER, name_lay),
                (nv.Align.CENTER, enter_lay),
                (nv.Align.CENTER, exit_lay),
                (nv.Align.CENTER, inside_lay)
            ])
        
        self.menugroup.layout = script_group_panel
        
    def create_menu_left(self, res):
        self.menu_left = nv.Menu(window, [300,1080-300], style=self.widget_style2(border_radius=0, border_width=0))
        lay2 = nv.ScrollableColumn([300,1080-300],)
        with nv.widget_globals.modify_temp(subtheme_role = nv.SubThemeRole.PRIMARY, style = self.widget_style2()):
            self.name = nv.Input((250,50),None,"Name","Name",whitelist=list(nv.InputType.ALL_SYMBOLS+nv.InputType.NUMBERS),on_change_function=self.root.stub, single_instance=True)
            self.desc = nv.Input((250,50),None,"Description",on_change_function=self.root.stub, single_instance=True)
        lay2.add_item(self.name,nv.Align.CENTER)
        lay2.add_item(self.desc,nv.Align.CENTER)
        
        self.graphity = nv.RectCheckBox(35,self.widget_style2, on_toggle =self.root.stub, active_rect_factor=0.85)
        self.graphity_slider = nv.Slider((200,30),self.widget_style2(font_size=10), current_value = 50, start = 50, end = 100,)
        
        lay3 = nv.StackColumn(
            content=[
                (nv.Align.CENTER, nv.Label("Graphity mode:",(200,50),self.widget_style2, subtheme_role = nv.SubThemeRole.TERTIARY)),
                (nv.Align.CENTER, nv.StackColumn(content=[(nv.Align.CENTER, self.graphity_slider),(nv.Align.CENTER, self.graphity)]))
            ])
            
        lay2.add_item(lay3,nv.Align.CENTER)
        self.menu_left.layout = lay2
        nv.Widget()
        
    def draw(self):
        
        self.menu.draw()
        self.menu_left.draw()
        if self.root.mode =="Script": self.menuscr.draw()
        if self.root.mode =="Group": self.menugroup.draw()


    def update(self):
        self.menu.update()
        self.menu_left.update()
        if self.root.mode =="Script": self.menuscr.update()
        if self.root.mode =="Group": self.menugroup.update()



class App():
    def __init__(self,res):
        global window #Antipattern detected Ow<
        self.size = (res[0],res[1])
        window = nv.Window(self.size, resizable=True, backend=nv.Backend.Pygame) 
        self.window = window
        self.mode = "Tile"
        self.ui = UI(self,[res[0],res[1]])
        
        pygame.display.set_caption("Nevu UI Demo")


    def stub(self, *args, **kwargs):
        print("Action triggered:", args, kwargs)


    def on_change_mode(self, val, id):
        self.mode = val
        print(f"Mode changed to: {self.mode}")
        
        if self.mode != "Group":
            self.ui.layer.disactivate()
            self.ui.layer.hide()
            self.ui.layerlbl.hide()
        else:
            self.ui.layer.activate()
            self.ui.layer.show()
            self.ui.layerlbl.show()
            
    def update(self):
        self.window.update(pygame.event.get(), 999999999) #no limitz
        self.ui.update()
        
    def draw(self):
        self.window.display.fill((20, 20, 25, 255))
        self.ui.draw()
        #window.draw_overlay() #to draw layout borders!! uOu
        
    def run(self):
        font = pygame.Font(GLOBAL_FONT, 20)
        draw_fps = True
        while True:
            window.begin_frame()
            self.update()
            self.draw()
            if draw_fps:
                if nv.nevu_state.window.is_dtype.raylib:
                    rl.draw_fps(0,0)
                else:
                    self.window.display.blit(font.render(f"FPS: {str(nv.time.fps)}", True, (255, 255, 255)), (10,10))
            window.end_frame()
        
if __name__ == "__main__":
    app = App((1900, 1080))
    app.run()
u/Due_Engineer_7647 — 3 days ago
▲ 18 r/pygame

EvergreenMeadows: (Gameplay Feedback Needed)

Available on itch.io last version is for free!🙌🏽

u/DreamDev43 — 3 days ago
▲ 8 r/pygame

Graph Module

Made a graph module for plotting x and y values on graph

u/Physics2433 — 2 days ago
▲ 3 r/pygame+1 crossposts

ANN3 - Fun little arena shooter with a sneaky CPU opponent (Windows, free)

Hey r/IndieGame,

I just pushed a big update to Annihilators 3 (ANN3) and wanted to share the latest version!

It's a fast-paced 2D arena shooter with that classic 90s vibe — run around, shoot, dodge grenades, and try not to get obliterated by the heat-seeking bomb. Now with a full scoring system that makes every match feel more rewarding.

What's New / Highlights:

  • Smart single-player CPU that actually fights back — it collects weapons, dodges, and even goes into "panic mode" when you launch the heatbomb. It can steal highscore spots with funny names like "Subservient Chicken CPU" or "Captain Cheapshot CPU"!
  • New Scoring System — Body hits, headshots, grenade/landmine/heatbomb kills, and "perfect kills" all earn points. Chase your personal best!
  • Local Highscores — Top 10 list with names, dates, and weapons. Ties are sorted chronologically so the first player to hit a score stays on top.
  • Global Leaderboard (optional) — Submit your new #1 local record to the online leaderboard and see how you stack up against other players.
  • Bow & arrow weapon now fully supported for both players
  • Explosive heatbomb with screen shake + gamepad rumble
  • Grenades, landmines, blood splatters, and dramatic headshot close-ups
  • Multiple control options: keyboard (rebindable), mouse, or gamepad

Completely free, no ads, no microtransactions — just pure chaotic arena fun.

Download (Windows .exe):
https://oldskoolsourceman.itch.io/ann3

Quick Gameplay Demo (updated):
https://www.youtube.com/watch?v=GQwPRr7TNXE

Would love your feedback!

  • Is the CPU fun or too sneaky?
  • How does the new scoring/highscore chase feel?
  • Any bugs or balance issues?
  • What weapon combo is your favorite?

Thanks for checking it out — hope you have a blast!

(Also posted in r/playmygame)

https://preview.redd.it/xkmdsmgwratg1.jpg?width=1344&format=pjpg&auto=webp&s=7ecb39a7daab6774b0c87c28a56f88bc1944931d

reddit.com
u/CertainMagazine6383 — 3 days ago
🔥 Hot ▲ 61 r/pygame

New Updates

I've implemented some polish: enemies can apply knockback to the player, arrows that are shot can embed themselves into walls/floor, some enemies run away when their health is low, and you can open up a map to see the level, there are also some new enemies.

I'm mainly working on polish at the moment :)

u/Alert_Nectarine6631 — 4 days ago
▲ 11 r/pygame

AxisPy: A Python 2D Game Engine with AI Assistant (built with love and passion for python/pygame)

Hey r/pygame!

I've been a Python developer for years, I do everything with Python. My gamedev journey started with pygame back in 2016, and I've shipped several little games since then ( check some of them out on itch.io).

After exploring Godot, Unity, and Unreal, I kept hitting the same wall: I loved the visual editor workflow (hierarchy, scene view, inspector with components, one-click easy exports to mobile/web/PC), but I desperately wanted that experience in my favorite language and ecosystem.

So I built AxisPy.

AxisPy Logo

It's a fully Python-native 2D engine on top of pygame with:

  • Visual Editor: Scene/hierarchy view, inspector with components, asset manager
  • ECS Architecture: Modular game logic (entities, components, systems)
  • AI Assistant: Built-in LLM integration that can write scripts, create entities, add components, and debug your game (supports OpenAI, Claude, Gemini, OpenRouter, even local LLMs). Just ask it to "add a light to the ball" and it does it.
  • Export Targets: Web (pygbag), desktop (PyInstaller), with mobile in progress
  • Python Scripting

Video Demo:

Recorded a quick demo of a Breakout clone I built in AxisPy:

  • Walking through the entity hierarchy and scene view
  • Playing the game
  • Asking the AI Assistant to "add a light to the ball entity", it immediately attaches a Light component in the inspector

AxisPy Demo

Why I'm building this:

I'm not trying to compete with C++ engines on performance. I just love Python and pygame, I want to build games in a modern environment (like Unity/Godot) without leaving the Python ecosystem. That's it!

The engine isn't perfect yet, but the core is solid enough to ship PC and web games. If you've been wanting a Python-first engine with modern tooling, this might be for you.

Looking for:

  • Testers: try it, break it, tell me what hurts
  • Contributors: Its MIT licensed, feel free to make it better
  • Feedback: on workflow, AI integration, missing features, etc

If you're a Python dev who's been eyeing modern engines but didn't want to leave pygame behind let's build this together.

Links

AGAIN: I am not trying to compete with Unity/Godot, this is about empowering Python devs to build games in the language they already love.

Would love your thoughts!

u/bayodevartist — 4 days ago
▲ 2 r/pygame

A projection animation with My module

Made a point to project on basis of gravity in my module

u/Physics2433 — 2 days ago
▲ 4 r/pygame

First look at a Traditional Roguelike I am developing entirely in Pygame.

Hello everyone, after about a week of development I am ready to share the first look at my roguelike.

It is planned to be a Traditional 2D Roguelike Dungeon Crawler, with focus on more RPG character progression than most other Roguelikes. Main inspiration to the character progression/spell system was Divinity: Original Sin 2.

The Build/Character progression will revolve around 3 pillars, levels, items, and spells. Leveling up will grant you stat and skill points, which can be spent to boost your stats, or to increase your level in a "spell school". Items will give you increased stats/armor/etc., and many will have special custom effects.

The core of the gameplay loop, and what provides build variety, is the spell system. There are 12 spell schools, each with spells of levels 1-4. You start the game with 2 spell school points, and a 1st level spell of each one of those schools of your choosing. Then, to unlock more spells, you will need to find Scrolls.

A Scroll has 2 ways in which you can use it. One, you can use it to cast the spell it is assigned ONCE. Two, you can, if your level in it's spell's school is high enough, unlock the spell permantly in your Spellbook. This allows you to cast it at the cost of mana.

The game is developed 100% in pygame, as I believe that pygame is a good enough engine for a good roguelike game to be made in.

Anyways, here is the first look at the gameplay tests: https://www.youtube.com/watch?v=UY6zTaBa32Q, feel free to ask any questions you may have!

u/Wrong_Show_7608 — 5 days ago