Making Minecraft Using Ursina & Python! (1/19/25 blog post)

Ursina is an easy-to-use, open source 3D game engine that can run better than Pygame. Since Pygame has some issues with frame-rate, poor performance, and is not the best when making games with 3D capability, I won’t be using it (for this project). This is 3D games-wise, though. Pygame is still better and MUCH easier to use when making simpler looking games. Ursina only needs a few lines of code to really make a game, and is beginner friendly when making a 3D program. However, like Pygame, it does have some bugs that come with it such as player model issues, blend files unable to load, and collider issues when making a player model. Unfortunately, Ursina isn’t available for MacOS (you can use Panda3D though, which is available for MacOS and Windows).

Besides these issues, Ursina is quite powerful and a good option for a 3D game engine for beginners. Now, let’s get started.

INTRO TO URSINA

First and possibly the most obvious step is to install Ursina.

  • Open your terminal in whatever code editor you use and type in “pip install Ursina”
pip install Ursina
  • We’re now able to start coding. first import all objects of Ursina using the * character.
from ursina import *
  • Now, we must create and instance of the game. You can name this whatever you’d like, but for this it will be named “app” (I know, so creative).
app = Ursina()

*Make sure to add parenthesis at the end or the code will yell at you ( I learnt this the hard way numerous times).

  • Now, lets run it. This will create the interface where the game will be displayed.
from ursina import *
app = Ursina()
app.run()

* If you thought that it would look like something such as unity or unreal engine, remember that we are using Python, not C# or C++ lol.

  • The astronomically microscopic numbers on the top right-hand corner of the screen shows the frame rate, the number of entities on the screen, and the number of collisions.
  • Lets add an entity, which is a base object for anything in Ursina. This can be anything, like a square, a circle, a cube, etc… Anything you see on the screen will count as an entity. It will be automatically added to the game, rather than calling it in a loop. An entity doesn’t need a color (it will default to white if no color is stated).
test_square = Entity(model='circle', color=color.blue)
  • This will create circle at the center of the screen when we run the program.
  • Let’s change it to a different shape.
test_square = Entity(model='quad', color=color.blue) 
  • This will change the circle into a square which it known as a “quad” in Ursina.

* You are able to add 3D objects like cubes, but since we’re looking at only one side at the moment, it’s kind of redundant to call a 3D object at the moment. We’ll get to that later, though.

  • You can also scale the entity by passing a number for the x and y axies.
test_square = Entity(model='quad', color=color.blue, scale = (1, 4))
  • In this instance, the 1 is how wide the entity will be, and the 4 is how long.
  • You can also change the position of the entity. It uses the same way we changed the scale of the entity, but this time we use “position” (or “pos” if you’re too lazy to write the whole word out).
test_square = Entity(model='quad', color=color.blue, scale = (1, 4), position = (5, 1))
  • This will move the square up 1 unit and right 5 units.
  • It should be obvious, but the center of the screen is the origin point (0,0). Making the y-axis positive or negative will scale or move the entity up or down, same with the x-axis (I know this is obvious but this 3D engine is interesting and fun to mess around in).
  • Now, lets make a function to move the entity. You will simply call the object you want to move in the function, the axis you wish to change, and how fast it will move.
def update():
    test_square.x -= 1
  • This will move the entity to the left at a speed of 1. Now, that may sound slow, but watch this:
Don’t blink or you’ll miss it lol
  • Now obviously we need to slow it down, so we’ll use “time.dt”. This will be multiplied by the speed at which the object is going, and will adjust to any frame-rate.
def update():
    test_square.x -= 1 * time.dt
  • It will now look like this:

*Note to self: going to add more in the future!