text to screen

Optimizing the processing for infinite cubes



Now we are ready to improve the previous program. We notice immediately two major issues. The first is that cubes pop up sometimes very close to us. Ideally, they all start behind our far clipping plane. The second problem is that we can go in any direction, and avoid the barrage of cubes. We'd like to be able to move left, right, up, or down, and have cubes continue to come.

The first problem is easily solved with some minor tweaks. The second problem is a bit... bigger. The idea is to give the sense that there are cubes everywhere. This means we want the player to be able to just press and hold, say, the left arrow key, and never outpace the cubes. This means that we need to have some cubes off to the sides "just in case." These cubes may never even be seen, but we need them to the left, right, above, and below the "user." This means more processing, but we can balance that. Keep in mind that, again, this will depend on your processing abilities. You can always decrease the amount of cubes, as well as change the pace at which you can move to save processing.

Let's get started. First, we're going to change set_vertices a bit by including the location of the "camera," or user.

def set_vertices(max_distance, min_distance = -20, camera_x = 0, camera_y = 0):

    camera_x = -1*int(camera_x)
    camera_y = -1*int(camera_y)

    
    x_value_change = random.randrange(camera_x-75,camera_x+75)
    y_value_change = random.randrange(camera_y-75,camera_y+75)
    
    z_value_change = random.randrange(-1*max_distance,min_distance)

    new_vertices = []

    for vert in vertices:
        new_vert = []

        new_x = vert[0] + x_value_change
        new_y = vert[1] + y_value_change
        new_z = vert[2] + z_value_change

        new_vert.append(new_x)
        new_vert.append(new_y)
        new_vert.append(new_z)

        new_vertices.append(new_vert)

    return new_vertices

Next, let's modify the main function's top a bit:

def main():
    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)


    max_distance = 100
    
    gluPerspective(45, (display[0]/display[1]), 0.1, max_distance)

    glTranslatef(0,0, -40)

    #object_passed = False

    x_move = 0
    y_move = 0

    cur_x = 0
    cur_y = 0

    game_speed = 2
    direction_speed = 2

    

    cube_dict = {}

    for x in range(50):
        cube_dict[x] =set_vertices(max_distance)

Notice the larger range, as well as cur_x and cur_y mostly. We've also added game_speed and direction_speed, so you can tweak things easier.

Since we're changing that, we need to change our event loop slightly as well:

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_move = direction_speed
                if event.key == pygame.K_RIGHT:
                    x_move = -1*direction_speed

                if event.key == pygame.K_UP:
                    y_move = -1*direction_speed
                if event.key == pygame.K_DOWN:
                    y_move = direction_speed

Now, not only can we tweak these speeds, but the game can also tweak them. A common thing to do is speed up the game to increase challenge.

Now to conclude our main function:

        x = glGetDoublev(GL_MODELVIEW_MATRIX)
        #print(x)

        
        camera_x = x[3][0]
        camera_y = x[3][1]
        camera_z = x[3][2]

        
        cur_x += x_move
        cur_y += y_move
        

                    
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glTranslatef(x_move,y_move,game_speed)



        for each_cube in cube_dict:
            Cube(cube_dict[each_cube])

        for each_cube in cube_dict:
            if camera_z <= cube_dict[each_cube][0][2]:
                new_max = int(-1*(camera_z-(max_distance*2)))
                cube_dict[each_cube] = set_vertices(new_max,int(camera_z-max_distance), cur_x, cur_y)

                

            
        pygame.display.flip()

Notice mainly the "cur_x" and "cur_y" additions, along with the new var game_speed in the translate function.

The next main change is in the generation of new cubes in the final for loop (in the above code).

The full code up to this point is:

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

import random

vertices = (
    (1, -1, -1),
    (1, 1, -1),
    (-1, 1, -1),
    (-1, -1, -1),
    (1, -1, 1),
    (1, 1, 1),
    (-1, -1, 1),
    (-1, 1, 1)
    )

edges = (
    (0,1),
    (0,3),
    (0,4),
    (2,1),
    (2,3),
    (2,7),
    (6,3),
    (6,4),
    (6,7),
    (5,1),
    (5,4),
    (5,7)
    )

surfaces = (
    (0,1,2,3),
    (3,2,7,6),
    (6,7,5,4),
    (4,5,1,0),
    (1,5,7,2),
    (4,0,3,6)
    )


colors = (
    (1,0,0),
    (0,1,0),
    (0,0,1),
    (0,1,0),
    (1,1,1),
    (0,1,1),
    (1,0,0),
    (0,1,0),
    (0,0,1),
    (1,0,0),
    (1,1,1),
    (0,1,1),
    )


##ground_vertices = (
##    (-10, -1.1, 20),
##    (10, -1.1, 20),
##    (-10, -1.1, -300),
##    (10, -1.1, -300),
##    )
##
##
##def ground():
##    glBegin(GL_QUADS)
##    for vertex in ground_vertices:
##        glColor3fv((0,0.5,0.5))
##        glVertex3fv(vertex)
##
##    glEnd()
        



def set_vertices(max_distance, min_distance = -20, camera_x = 0, camera_y = 0):

    camera_x = -1*int(camera_x)
    camera_y = -1*int(camera_y)

    
    x_value_change = random.randrange(camera_x-75,camera_x+75)
    y_value_change = random.randrange(camera_y-75,camera_y+75)
    
    z_value_change = random.randrange(-1*max_distance,min_distance)

    new_vertices = []

    for vert in vertices:
        new_vert = []

        new_x = vert[0] + x_value_change
        new_y = vert[1] + y_value_change
        new_z = vert[2] + z_value_change

        new_vert.append(new_x)
        new_vert.append(new_y)
        new_vert.append(new_z)

        new_vertices.append(new_vert)

    return new_vertices
        
    


def Cube(vertices):
    glBegin(GL_QUADS)
    
    for surface in surfaces:
        x = 0

        for vertex in surface:
            x+=1
            glColor3fv(colors[x])
            glVertex3fv(vertices[vertex])
        
    glEnd()
    


    
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(vertices[vertex])
    glEnd()


def main():
    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)


    max_distance = 100
    
    gluPerspective(45, (display[0]/display[1]), 0.1, max_distance)

    glTranslatef(0,0, -40)

    #object_passed = False

    x_move = 0
    y_move = 0

    cur_x = 0
    cur_y = 0

    game_speed = 2
    direction_speed = 2

    

    cube_dict = {}

    for x in range(50):
        cube_dict[x] =set_vertices(max_distance)

    #glRotatef(25, 2, 1, 0)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_move = direction_speed
                if event.key == pygame.K_RIGHT:
                    x_move = -1*direction_speed

                if event.key == pygame.K_UP:
                    y_move = -1*direction_speed
                if event.key == pygame.K_DOWN:
                    y_move = direction_speed


            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    x_move = 0

                if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                    y_move = 0

##            if event.type == pygame.MOUSEBUTTONDOWN:
##                if event.button == 4:
##                    glTranslatef(0,0,1.0)
##
##                if event.button == 5:
##                    glTranslatef(0,0,-1.0)
                    
                    

        

        #glRotatef(1, 3, 1, 1)

        x = glGetDoublev(GL_MODELVIEW_MATRIX)
        #print(x)

        
        camera_x = x[3][0]
        camera_y = x[3][1]
        camera_z = x[3][2]

        
        cur_x += x_move
        cur_y += y_move
        

                    
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glTranslatef(x_move,y_move,game_speed)



        for each_cube in cube_dict:
            Cube(cube_dict[each_cube])

        for each_cube in cube_dict:
            if camera_z <= cube_dict[each_cube][0][2]:
                new_max = int(-1*(camera_z-(max_distance*2)))
                cube_dict[each_cube] = set_vertices(new_max,int(camera_z-max_distance), cur_x, cur_y)

                

            
        pygame.display.flip()


main()
pygame.quit()
quit()

That's it for PyOpenGL tutorials for now. Next, you can head to the: for more tutorials!




  • OpenGL with PyOpenGL introduction and creation of Rotating Cube
  • Coloring Surfaces as well as understand some of the basic OpenGL code
  • Understanding navigation within the 3D environment via OpenGL
  • Moving the player automatically towards the cube
  • Random Cube Position
  • Adding Many Cubes to our Game
  • Adding a ground in OpenGL
  • Infinite flying cubes
  • Optimizing the processing for infinite cubes