Skip to content
← Back to Community
3D Game Engine
Profile icon
TurtleAndrew

This program renders a procedurally generated landscape in 3D. The perspective is off because I have to lower the fov(field of view) and shrink the size of the screen because repl runs pygame much slower and only allows the screen to be up to 800x 800 not the usual size I use 1200x 750. Also you will have to wait a moment for the program to create a map every time you start the game. I'm also sorry for any lag as pygame just isn't designed for 3D combined with using an online programing website to run it. The program also uses color blending and a basic shader based on the angle of the triangle being colored. Finally, I would recommend making the program window as big as possible for the best viewing experience.

Controls:

WASD(forward, left, backward, right)
Space(up)
Right Shift(Not left)(left)

Interesting facts:

There are 22500 polygons(triangles) in each map
There are 67500 3D points the program has to convert to 2D

Some images of the program running on my computer(not running on repl and without a max render distance):

Screen Shot 2020-10-11 at 1.33.26 PM
Screen Shot 2020-10-11 at 1.35.08 PM

And here's some more images of the world(not ran on repl) using my ray tracing lighting system that traces a ray from each point to the sun and check to see if it collides with anything. This feature is to slow for repl and will not be implemented. In this image I was getting around 0.3 fps:

Screen Shot 2020-10-16 at 7.32.19 PM
Screen Shot 2020-10-16 at 7.35.01 PM
Screen Shot 2020-10-16 at 7.35.59 PM

How to project 3D objects using math and code:

If you want to make a 3D game, first, I wouldn't recommend pygame or repl. The best way to go about it would be to use one of the following, Open GL, Unreal Engine, Unity, and Godot. There are other libraries and game engines that will also allow for 3D games but those are some popular ones that are a great starting point. But if you do want to use pygame or another python3 library(with some minor modifications to the code), some of the code is shown bellow starting with the most complicated snippet of code that calculates the position to draw each 3D point on the screen:

def convert_3D_to_2D(vec3_pos): vec3_dist = [vec3_player_pos[0] - vec3_pos[0], vec3_player_pos[1] - vec3_pos[1], vec3_player_pos[2] - vec3_pos[2]] vec2_intercection_point = [0, 0] try: m = vec3_dist[1] / vec3_dist[2] except ZeroDivisionError: m = 0 y = m * player_fov + vec3_pos[1] vec2_intercection_point[1] = y try: m2 = vec3_dist[0] / vec3_dist[2] except ZeroDivisionError: m2 = 0 y2 = m2 * player_fov + vec3_pos[0] inwerds = y2 vec2_intercection_point[0] = inwerds return vec2_intercection_point

Than from there, if you want to get the color and some other data about the object the code to do that it:

new_points = [] for triangle in mesh: if int(triangle[0][2]) - int(vec3_player_pos[2]) in range(-100, render_dist) and int(triangle[0][0]) - int(vec3_player_pos[0]) in range(-100, render_dist2): vec2_1 = convert_3D_to_2D(triangle[0]) vec2_2 = convert_3D_to_2D(triangle[1]) vec2_3 = convert_3D_to_2D(triangle[2]) # draw the triangle if int(vec2_1[0]) in range(0, width * 3) and int(vec2_1[1]) in range(1, height * 3) and int(vec2_2[0]) in range(0, width * 3) and int(vec2_2[1]) in range(1, height * 3) and int(vec2_3[0]) in range(0, width * 3) and int(vec2_3[1]) in range(1, height * 3): # shading the color based on the angle on the triangle shaded2 = (triangle[0][1] - triangle[2][1]) * 2 # the next line is the color of your mesh, change it to be any rgb color you want object_color = (0, 180, 0) color = (clamp(clamp(object_color[0] - shaded2, object_color[0]] - 25, object_color[0] + 25), 0, 255), clamp(clamp(object_color[1] - shaded2, object_color[1] - 25, object_color[1] + 25), 0, 255), clamp(clamp(object_color[2] - shaded2, > object_color[2] - 25, object_color[2] + 25), 0, 255))

And the code to draw the new object using the data obtained from the code above is bellow:

for n in new_points: pygame.draw.polygon(screen, n[3], [n[0], n[1], n[2]])

To make both these functions work, you will need to have the var mesh be a list of list with each of the lists in the mesh variable being a list of three vector3(x, y, z) positions aka the positions of each of the 3 points on a triangle. You can also change the objects color by changing object_color to any rgb(red, green, blue) value you want.
One more function needed to make the functions above work is bellow:

def clamp(value, min_, max_): return min(max(value, min_), max_)

If you need any help getting this code to work than you can ask in the comments and I will try to get back to you and help you make your own(mostly) 3D game. I have not implemented collision detection and do not plan on doing and the same for some other features so I will only be able to help you to a certain level before your going to have to go off on your own. I hope this code will help you and here's a link to a more in depth tutorial I posted:

Click Here To Go To The Tutorial
Click Here To Go To My Ray Tracer

I hope you enjoy!

Voters
Profile icon
elburg
Profile icon
Darkcucaracha7
Profile icon
CustomDev
Profile icon
Eybhe2
Profile icon
BananaJellyfish
Profile icon
badst
Profile icon
TheOceanFace
Profile icon
ANDREWVOSS
Profile icon
TurtleAndrew
Comments
hotnewtop
Profile icon
JonDoeBeep

And you somehow did this with a 2d game library

Profile icon
TurtleAndrew

@JonDoeBeep
Yes, 3D graphics are 2D graphics. You just have to convert the 3D point to a 2D point. There's a link to a tutorial I posted that explains the math and how it works. You basically create two 1D lines and find the intersection point of the players eye at z 30. The number 30 would be the players fov aka field fo view.

Profile icon
JonDoeBeep

@TurtleAndrew
I know, I was praising you. I have trouble doing 3d in 2d libraries. My games always run at like 2 frames per minute

Profile icon
TurtleAndrew

@JonDoeBeep
It dose run slower because I have not implemented a lot of features that 3D game engines would normally use.

Profile icon
TurtleAndrew

@JonDoeBeep
Mine to, it runs about 4 - 12 fps when not running on repl without a maximum render distance.

Profile icon
TurtleAndrew

@TurtleAndrew
This is also my first 3D game fyi.

Profile icon
TurtleAndrew

@TurtleAndrew
That would be about 1 - 3 fps on repl

Profile icon
JonDoeBeep

@TurtleAndrew
yours ran wayy faster than mine. I got to look up some tutorials

Profile icon
TurtleAndrew

@JonDoeBeep
I can help you make yours run faster. Also pygame just runs so slow on repl. Nothing will ever make it run fast. A game that runs at 15 fps which is pretty normal for me on repl runs at like 2.

Profile icon
TurtleAndrew

@JonDoeBeep
If you know linear equations than the math behind the 3D to 2D conversions would be very understandable.

Profile icon
TurtleAndrew

@TurtleAndrew
There's some images above of what the program can do when not running on repl at about 4 fps.

Profile icon
TurtleAndrew

@JonDoeBeep
If you want help, I can help you make it run faster.

Profile icon
TurtleAndrew

@JonDoeBeep
I'm also working on a ray tracer. It's not very close to working and runs at about 1/5 a frame per minute.

Profile icon
TheOceanFace

what

Profile icon
TurtleAndrew

@ethanshaozz1928
? What do you mean by "what"?

Profile icon
littlepenguin

Cool!

Profile icon
TurtleAndrew