An easy to use game engine/framework for python.

Overview

ursina ʕ •ᴥ•ʔゝ□

An easy to use game engine/framework for python.

Banner

Getting Started

  1. Install Python 3.6 or newer. https://www.python.org/downloads/
  2. Open cmd/terminal and type:
pip install ursina

If you want to install the newest version from git, you can install like this:

pip install git+https://github.com/pokepetter/ursina.git

If you want to easily edit the source, it's recommended to clone the git repo and install as develop like this. Make sure you have git installed. https://git-scm.com/

git clone https://github.com/pokepetter/ursina.git
python setup.py develop

Also install any of the optional dependencies you want from the list below, or install them all with:

pip install ursina[extras]

On some systems you might have to use pip3 instead of pip in order to use Python 3 and not the old Python 2.

Dependencies

  • python 3.6+
  • panda3d
  • screeninfo, for detecting screen resolution
  • hurry.filesize, for converting bytes to megabytes
  • pillow, for texture manipulation
  • psd-tools, for converting .psd files
  • blender, for converting .blend files
  • pyperclip, for copy/pasting

Examples

from ursina import *            # this will import everything we need from ursina with just one line.

app = Ursina()
ground = Entity(
    model = 'cube',
    color = color.magenta,
    z = -.1,
    y = -3,
    origin = (0, .5),
    scale = (50, 1, 10),
    collider = 'box',
    )

app.run()                       # opens a window and starts the game.

How do I make a game?

Ursina games are made by writing Python code. You can use any text editor you want, but personally I like to use Atom.

  1. Create an empty .py file called ursina_game.py
  2. Copy this text into your new file:
from ursina import *           # this will import everything we need from ursina with just one line.

app = Ursina()

player = Entity(
    model = 'cube' ,           # finds a 3d model by name
    color = color.orange,
    scale_y = 2
    )

def update():                  # update gets automatically called by the engine.
    player.x += held_keys['d'] * .1
    player.x -= held_keys['a'] * .1


app.run()                     # opens a window and starts the game.
  1. Type this in the terminal to start the game:

    python ursina_game.py
    

    If you use Atom, I recommend installing the package atom-python-run to run your scripts with the press of a button.

  2. You can now move the orange box around with 'a' and 'd'!

    To close the window, you can by default, press shift+q or press the red x. to disable this, write window.exit_button.enabled = False somewhere in your code.

Comments
  • AttributeError: 'Slider' object has no attribute 'knob'

    AttributeError: 'Slider' object has no attribute 'knob'

    When using the prefab Slider, I often get this error:

    File "/home/kanj/.local/lib/python3.10/site-packages/vitrix_engine-4.2.0-py3.10.egg/vitrix_engine/prefabs/slider.py", line 91, in update
        if self.knob.dragging:
    AttributeError: 'Slider' object has no attribute 'knob'
    

    Not only that, but I sometimes get another error that states something with the Color class has gone wrong, again related to the Slider. Is the Slider class a work or progress, or is this a bug? I have tried with the github version as well as the v4.1.1 on PyPi. Any ideas?

    opened by ShadityZ 13
  • Guide on how to texture an object

    Guide on how to texture an object

    This game engine is amazing! Unfortunately, especially to those not so experienced with 3d modelling / game development in general, it's quite hard to understand how to apply textures to the models.

    A guide on that would be great. Just two examples which I don't know how to realize:

    • I have a cube entity. The default one. How can I create a cube map texture (so not the same texture for every side of the cube) for it through the official Ursina engine? What does my texture need to look like? What methods do I need to call? Maybe I would like to texture your Minecraft code sample.

    • I have modelled some basic stuff in blender. Let's say it's a low-poly car. I just switched to edit mode, pulled around some corners and then exported to a .obj file. How would I texture that one? Would I have to apply textures in Blender and somehow export them? I'm lost.

    Thank you for your great work so far!

    opened by famecastle 13
  • Bypass

    Bypass "ursina" default window

    When running an app using ursina, you get a loading type screen that is black and has the title ursina. I find this a bit annoying. Is there a way to bypass this?

    opened by ShadityZ 12
  • ui no longer appearing after ursina v5 update

    ui no longer appearing after ursina v5 update

    Here's some sample code (rest of code positions, adds textures, sorts logic for inventory items, etc.).

    hotbar = Entity(model='quad',parent=camera.ui) hotbar.scale_y=0.08 hotbar.color=color.dark_gray hotbar.render_queue=0

    Instead of my former ui entities on camera.ui, I'm just getting a white diamond.

    Is there anything I need to change due to new update?

    Thanks for any help.

    opened by RedHenDev 11
  • [RESOLVED] [Improvements]  Some better import logic implementation to work better with most IDE's auto-completion?

    [RESOLVED] [Improvements] Some better import logic implementation to work better with most IDE's auto-completion?

    Hello. I've found this library very powerful and useful. But when I using this with my development environment, my IDE reported many errors about the demo code.

    Demo code works just fine, so I attempt to add type hints to bypass the issue, this also enables auto-completion feature.

    For example, usually we want to add type hints on variable to enforce IDE to use specified type to do auto-complete works. Like this:

    from ursina import *
    from ursina.window import Window  # Importing original class for window object
    
    window: Window  # Type hints here.
    window.fps_counter.enabled = False  # Auto complete should works here
    

    And in IDE, auto-complete works fine now.

    But running this code will cause a import error:

    Traceback (most recent call last):
      File "C:\Users\SuperMarioSF\PycharmProjects\ursina-test\main.py", line 6, in <module>
        from ursina.window import Window
    ImportError: cannot import name 'Window' from '<unknown module name>' (unknown location)
    

    I checked the code and found the module reference is overridden with a class object instance:

    sys.modules[__name__] = Window()
    

    This overrides module object itself, thus the origin module cannot be referenced anymore in runtime, caused original class cannot be accessed.

    I thought you implements in this way in order to implement object auto registration for Ursina related objects, but replacing module reference is really a bad idea. It may works fine, but many people rely on IDE features, like auto-completion and type checking, to keep productive.

    Maybe the object instance initialization code can be put in __init__.py file of the package root, and the class file name should different with object variable, to prevent module object name colliding with the variable name.

    If there is a suggested way to enable auto-completion and type checking, I'd like to know, maybe it also should be noted in documentations.

    Thanks for your attention.


    Tested with Visual Studio Code and JetBrains PyCharm Professional. Both IDEs struggle with those replaced module objects and cannot provide proper auto-completion and type checking features.

    opened by SuperMarioSF 11
  • NameError: name 'Ursina' is not defined

    NameError: name 'Ursina' is not defined

    Hello,

    I installed Ursina using pip (pip install ursina) and checked that it was there using pip list, however when running the example code on this page, I get this error:

    Traceback (most recent call last): File "[redacted]", line 1, in from ursina import * # Import the ursina engine File "[redacted]", line 3, in app = Ursina() # Initialise your Ursina app NameError: name 'Ursina' is not defined

    Code: from ursina import * # Import the ursina engine

    app = Ursina() # Initialise your Ursina app app.run() # Run the app

    I don't know where I have gone wrong. Any help appreciated, cheers.

    edit: removed code formatting as it isn't exactly working as i hoped it would.

    opened by Desiro444 11
  • difficult to use

    difficult to use

    Your engine is very difficult to use. After open the sample file rubiks_cube.py , I don't know how to operate it, nor can I shut it down. Restarting the host does not work. It is like being stuck. I only see a lot of graphics rotating back and forth. Please improve the engine, and the basic example can be used normally, and then upload it to github, OK?

    opened by haisheng666 10
  • Ursina can't compile to .exe file

    Ursina can't compile to .exe file

    Is it impossible to compile Ursina python file to .exe? here's the code I use to test compiling Ursina program to .exe type file

    from ursina import *
    app = Ursina()
    app.run()
    

    and the code to generate .exe file

    pyinstaller --onefile -w ss.py
    

    the Terminal shows that the compiling process was completed successfully

    1

    but the .exe file that came out can't be executed properly

    image

    and then I tried to bring up the console here's the Error Traceback image

    opened by LeeFuuChang 10
  • Assertion failed: get_num_pages() == 0 at line 60 of built1.10/include/dynamicTextFont.I

    Assertion failed: get_num_pages() == 0 at line 60 of built1.10/include/dynamicTextFont.I

    When running a modified version of the main_menu.py sample, I get this error when I try to integrate the loading_screen.py inside. Source code:

    import os
    from direct.stdpy import thread
    from ursina import *
    
    
    def start_game():
        app.destroy()
        os.system("python " + dir_path + "/game.py")
        os._exit(0)
    
    
    def playBackgroundMusic():
        global bgmusic
        bgmusic = Audio("background-music")
        bgmusic.loop = True
        bgmusic.play()
    
    
    class LoadingWheel(Entity):
        def __init__(self, **kwargs):
            super().__init__()
            self.parent = camera.ui
            self.point = Entity(parent=self, model=Circle(24, mode='point', thickness=.03), color=color.light_gray, y=.75, scale=2, texture='circle')
            self.point2 = Entity(parent=self, model=Circle(12, mode='point', thickness=.03), color=color.light_gray, y=.75, scale=1, texture='circle')
    
            self.scale = .025
            self.text_entity = Text(world_parent=self, text='loading...', origin=(0,1.5), color=color.light_gray)
            self.y = -.25
    
            self.bg = Entity(parent=self, model='quad', scale_x=camera.aspect_ratio, color=color.black, z=1)
            self.bg.scale *= 400
    
            for key, value in kwargs.items():
                setattr(self, key ,value)
    
    
        def update(self):
            self.point.rotation_y += 5
            self.point2.rotation_y += 3
    
    
    class MenuButton(Button):
        def __init__(self, text='', **kwargs):
            super().__init__(text, scale=(.25, .075), highlight_color=color.gray, **kwargs)
    
            for key, value in kwargs.items():
                setattr(self, key ,value)
    
    
    def load_menu():
        button_spacing = .075 * 1.25
        menu_parent = Entity(parent=camera.ui, y=.15)
        main_menu = Entity(parent=menu_parent)
        options_menu = Entity(parent=menu_parent)
    
    
        state_handler = Animator({
            'main_menu' : main_menu,
            'options_menu' : options_menu,
            }
        )
    
    
        main_menu.buttons = [
            MenuButton('Start', on_click=Func(start_game)),
            MenuButton('Options', on_click=Func(setattr, state_handler, 'state', 'options_menu')),
            MenuButton('Quit', on_click=Sequence(Wait(.01), Func(sys.exit))),
        ]
        for i, e in enumerate(main_menu.buttons):
            e.parent = main_menu
            e.y = (-i-2) * button_spacing
            e.enabled = False
    
    
        review_text = Text(parent=options_menu, x=.275, y=.25, text='Preview text', origin=(-.5,0))
        for t in [e for e in scene.entities if isinstance(e, Text)]:
            t.original_scale = t.scale
    
        text_scale_slider = Slider(0, 2, default=1, step=.1, dynamic=True, text='Text Size:', 
                                parent=options_menu, x=-.25)
        def set_text_scale():
            for t in [e for e in scene.entities if isinstance(e, Text) and hasattr(e, 'original_scale')]:
                t.scale = t.original_scale * text_scale_slider.value
        text_scale_slider.on_value_changed = set_text_scale
    
    
        options_back = MenuButton(parent=options_menu, text='Back', x=-.25, origin_x=-.5, 
                                on_click=Func(setattr, state_handler, 'state', 'main_menu'))
    
        for i, e in enumerate((text_scale_slider, options_back)):
            e.y = -i * button_spacing
    
    
    
        for menu in (main_menu, options_menu):
            def animate_in_menu(menu=menu):
                for i, e in enumerate(menu.children):
                    e.original_x = e.x
                    e.x += .1
                    e.animate_x(e.original_x, delay=i*.05, duration=.1, 
                                curve=curve.out_quad) # type: ignore
    
                    e.alpha = 0
                    e.animate('alpha', .7, delay=i*.05, duration=.1, 
                            curve=curve.out_quad) # type: ignore
    
                    if hasattr(e, 'text_entity'):
                        e.text_entity.alpha = 0
                        e.text_entity.animate('alpha', 1, delay=i*.05, duration=.1)
    
            menu.on_enable = animate_in_menu
    
    
        background = Entity(model='quad', texture='background', parent=camera.ui, 
                            scale=(camera.aspect_ratio,1), color=color.white, z=1)
    
    
        playBackgroundMusic()
        print('Loaded Menu')
        loading_screen.enabled = False
        for i, e in enumerate(main_menu.buttons):
            e.enabled = True
    
    
    app = Ursina()
    loading_screen = LoadingWheel(enabled=False)
    window.show_ursina_splash = False
    window.title = "Vitrix"
    window.borderless = False
    
    try:
        thread.start_new_thread(function=load_menu, args='')
    except Exception as e:
        print('error starting thread', e)
    
    loading_screen.enabled = True
    
    dir_path = os.path.dirname(os.path.realpath(__file__))
    
    
    
    app.run()
    
    

    This is the console output:

    package_folder: /home/kanj/.local/lib/python3.9/site-packages/ursina
    asset_folder: /home/kanj/Vitrix/vitrix
    OS: posix
    screen resolution: (1366, 768)
    Known pipe types:
      glxGraphicsPipe
    (4 aux display modules not yet loaded.)
    Xlib:  extension "XFree86-DGA" missing on display ":0".
    :pnmimage:png(warning): iCCP: known incorrect sRGB profile
    :pnmimage:png(warning): iCCP: known incorrect sRGB profile
    info: development mode: True
    application successfully started
    Assertion failed: get_num_pages() == 0 at line 60 of built1.10/include/dynamicTextFont.I
    Assertion failed: get_num_pages() == 0 at line 60 of built1.10/include/dynamicTextFont.I
    info: changed aspect ratio: 1.779 -> 1.779
    Loaded Menu
    
    opened by ShadityZ 9
  • No

    No "mouse wheel up" and "mouse wheel down" in keys_held

    I would want to make it so when I scroll make camera moves on the z axis but I can't because there's no way of knowing when the mouse wheel is scrolled from the update() function If it's possible let me know

    opened by BlockOG 9
  • issue with 2d platformer example

    issue with 2d platformer example

    Hey, on launching platformer example and clicking any button I'm getting: https://hastebin.com/setuyabeda.makefile

    Ubuntu 18.04, python 3.7.5. pip freeze under link above.

    opened by alexlep 9
  • 'space' key is invalid

    'space' key is invalid

    In the 'input_handler.py', the code set the keys ends with 'up' invalid. Therefore like 'space up' key is invalid, then many places are wrong. For example,:

    • in 'platformer_controller_2d.py' the 'jump' will not be triggerd for it should be triggered by 'space' key.
    opened by AL-377 0
  • Fixed TypeError bug when list_of_values was empty

    Fixed TypeError bug when list_of_values was empty

    The bug was presented when a Cylinder was created without a color_gradient kwarg specified. Traceback:

        l = len(list_of_values)
    TypeError: object of type 'NoneType' has no len()
    

    Not sure if this is the best approach to be honesst, but it does the work :)

    opened by Fer-Jg 4
  • The *.stl mesh imports mirrored

    The *.stl mesh imports mirrored

    Entity(model=_path, scale=(.1, .1, .1), y=-2, flipped_faces=False, ) loads as a mirrored object. without flipped_faces=False mesh is transparent. In blender or Paint3D it loads correct. What can be the problem?

    opened by fader111 2
  • FirstPersonController glitching through ceiling

    FirstPersonController glitching through ceiling

    I have had a problem with the FirstPersonController being able to jump up into the underside of meshs, and I have tried all sorts of coding to fix this, however nothing seems to be working. Is there anyway to stop this bug?

    opened by ZombiesLoveZGames 2
  • How to make FirstPersonController not look to the ground at initial spawn?

    How to make FirstPersonController not look to the ground at initial spawn?

    Hi,

    because this project looks so promising :sunglasses: I try to fiddle around with it. I try to get the player's first person camera NOT to look at the ground when initially spawning but did not find a working solution in the documentation or web.

    Can you give me a hint what else aside a player = FirstPersonController() has to be set to look along the X or Z axis and not downwards? I assumed look_at and look_at_2d to be a solution but did not manage to make it work.

    Thanks for any hint!

    opened by HenriWahl 2
Mandaw 2 Mar 1, 2022
Lint game data metafiles against GTA5.xsd for Rockstar's game engine (RAGE)

rage-lint Lint RAGE (only GTA5 at the moment) meta/XML files for validity based off of the GTA5.xsd generated from game code. This script accepts a se

GoatGeek 11 Sep 18, 2022
Quantum version of the classical Nim game. An automatic opponent allows to game to not be as easy as it seems.

Nim game Running the game To run the program just launch : python3 game.py Rules This game is inspiring from the Nim game. You are 2 players face to f

Michaël 1 Jan 8, 2022
Minecraft clone using Python Ursina game engine!

Minecraft clone using Python Ursina game engine!

Taehee Lee 35 Jan 3, 2023
Pyxel is a retro game engine for Python.

Pyxel is open source and free to use. Let's start making a retro game with Pyxel!

Takashi Kitao 11.2k Jan 9, 2023
A python game engine.

PursuedPyBear, also known as ppb, exists to be an educational resource. Most obviously used to teach computer science, it can be a useful tool for any topic that a simulation can be helpful.

PPB 235 Jan 8, 2023
A Game Engine Made in Python with the Pygame Module

MandawEngine A Game Engine Made in Python with the Pygame Module Discord: https://discord.gg/MPPqj9PNt3 Installation To Get The Latest Version of Mand

Mandaw 14 Jun 24, 2022
Hagia is a 2D game engine and toolset for Python.

HAGIA What is Hagia? Hagia is a 2D game engine and toolset for Python. Hagia has

star 3 Jun 1, 2022
Python game engine for 2D multiplayer online games.

LAN-Caster The goal of LAN-Caster is to provide an easy-to-use code base (game engine) for developing 2D multiplayer online games. LAN-Caster original

Douglas Bakewell 1 Feb 11, 2022
Open-source project written in the ursina engine, simulating the popular game Minecraft.

Voxelcraft is an open-source project written in the ursina engine, simulating the popular game Minecraft.

Calinescu Mihai 21 Oct 6, 2022
AXI Combat is a networked multiplayer game built on the AXI Visualizer 3D engine.

AXI_Combat AXI Combat is a networked multiplayer game built on the AXI Visualizer 3D engine. https://axi.x10.mx/Combat AXI Combat is released under th

. 0 Aug 2, 2022
Average Clicker Game (AVG) is a Python made game using tkinter

Average-Clicker-Game Average Clicker Game (AVG) is a Python clicker game not made with pygame but with tkinter, it has worker, worker upgrades, times

Zacky2613 1 Dec 21, 2021
Ice-Walker-Game - This repository is about the Ice Walker game made in Python.

Ice-Walker-Game Ce dépot contient le jeu Ice Walker programmé en Python. Les différentes grilles du jeu sont contenues dans le sous-dossier datas. Vou

Mohamed Amine SABIL 1 Jan 2, 2022
Adventure-Game - Adventure Game which is created using Python

Adventure Game ?? This is a Adventure Game which is created using Python. Featur

ArinjoyTheDev 1 Mar 19, 2022
Game-of-life - A simple python program to simulate and visualise the Conway's Game of life

Conway's game of life A simple python program to simulate and visualise the Conw

Dhravya Shah 3 Feb 20, 2022
Easy and fun game to play a bit. Written in python

NumGuesser Easy and fun game to play a bit. Written in python

Lodi#0001 4 May 22, 2022
Snake game mixed with Conway's Game of Life

SnakeOfLife Snake game mixed with Conway's Game of Life The rules are the same than a normal snake game but you have to avoid cells created by Conway'

Aidan 5 May 26, 2022
HTTP API for FGO game data. Transform the raw game data into something a bit more manageable.

FGO game data API HTTP API for FGO game data. Transform the raw game data into something a bit more manageable. View the API documentation here: https

Atlas Academy 51 Dec 26, 2022
A near-exact clone of google chrome's no internet game, or the "google dinosaur game", with some additions and extras.

dinoGame A near-exact clone of google chrome's no internet game, or the "google dinosaur game", with some additions and extras. Installation Download

null 1 Oct 26, 2021