В последнее время я экспериментировал с pyglet python 3.7.2 opengl.
Я пытаюсь сделать клон майнкрафт.
Хотя при добавлении большого количества кубов у меня возникали некоторые проблемы с производительностью. Так что, чтобы это исправить, мне нужно только визуализировать необходимые лица / лица, которые увидит игрок. Я хочу, чтобы код проверял, есть ли воздух / ничего рядом с гранью куба, а затем только визуализировал лицо с воздухом / ничем рядом с ним.
Я пытался glEnable(GL_CULL_FACE)
, это работает до некоторой степени, но не так хорошо. Он не отображает внутреннюю часть куба, но все же отображает внешнюю часть кубов, которые игрок не должен видеть.
from pyglet.gl import *
from pyglet.window import key
import math
#Somehow should increase performance, I think, by disabling error check.
pyglet.options['debug_gl'] = False
#If you get an unindent error ctrl+x then ctrl+c the code.4
class Model:
#This def runs at the start.
def __init__(self):
self.num_of_cubes = 0
#Textures
self.grass_top = self.get_tex('grass_top.png')
self.grass_side = self.get_tex('grass_side.png')
self.dirt = self.get_tex('dirt.png')
#Texture groups
#None yet
self.tex_coords = ('t2f', (0,0, 1,0, 1,1, 0,1))
print("Initializing Model.")
x,y,z = 0,0,-1
X,Y,Z = x+1,y+1,z+1
'''If you put the batch inside add_cube() then it'll delete
the batch and the cubes inside and only render the last cube.'''
self.batch = pyglet.graphics.Batch()
#Color of model (variable) (deprecated)
#color = ('c3f',(1,1,1,)*4)
#Cube generator
for x in range(-16,16):
for z in range(-16,16):
self.add_cube(x,-2,-z,self.dirt,self.dirt,self.dirt)
self.add_cube(x,-1,-z,self.grass_side,self.grass_top,self.dirt)
print(self.num_of_cubes)
def get_tex(self,file):
tex = pyglet.image.load(file).texture
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST)
return pyglet.graphics.TextureGroup(tex)
def add_cube(self,arg1,arg2,arg3,tex_side,tex_top,tex_bottom):
self.num_of_cubes += 1
#Location of cube
x,y,z = arg1,arg2,arg3
X,Y,Z = x+1,y+1,z+1
#Cube sides
self.batch.add(4,GL_QUADS,tex_side,('v3f',(X,y,z, x,y,z, x,Y,z, X,Y,z, )),self.tex_coords) #Back
self.batch.add(4,GL_QUADS,tex_side,('v3f',(x,y,Z, X,y,Z, X,Y,Z, x,Y,Z, )),self.tex_coords) #Front
self.batch.add(4,GL_QUADS,tex_side,('v3f',(x,y,z, x,y,Z, x,Y,Z, x,Y,z, )),self.tex_coords) #Left
self.batch.add(4,GL_QUADS,tex_side,('v3f',(X,y,Z, X,y,z, X,Y,z, X,Y,Z, )),self.tex_coords) #Right
self.batch.add(4,GL_QUADS,tex_top,('v3f',(x,Y,Z, X,Y,Z, X,Y,z, x,Y,z, )),self.tex_coords) #Top
self.batch.add(4,GL_QUADS,tex_bottom,('v3f',(x,y,z, X,y,z, X,y,Z, x,y,Z, )),self.tex_coords) #Bottom
def draw(self):
#Draws everything in batch groups
self.batch.draw()
class Player:
#Movement config
FLY_SPEED = 9
WALK_SPEED = 4
GRAVITY = 0.1 #The lower it is the stronger it is, I know, weird.
JUMP_FORCE = (2*GRAVITY)**.5
def __init__(self,pos=(0,0,0),rot=(0,0)):
self.pos = list(pos)
self.rot = list(rot)
self.flying = True
self.dy = 0
def mouse_motion(self,dx,dy):
dx/=8; dy/=8; self.rot[0]+=dy; self.rot[1]-=dx
if self.rot[0]>90: self.rot[0] = 90
elif self.rot[0]<-90: self.rot[0] = -90
def jump(self):
print("Jumped.")
def update(self,dt,keys):
#self.pos[0] is "X", [1] is "Y", [2] is "Z"
'''s = dt*10
rotY = -self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if keys[key.W]: self.pos[0]+=dx; self.pos[2]-=dz
if keys[key.S]: self.pos[0]-=dx; self.pos[2]+=dz
if keys[key.A]: self.pos[0]-=dz; self.pos[2]-=dx
if keys[key.D]: self.pos[0]+=dz; self.pos[2]+=dx
if keys[key.SPACE]: self.pos[1]+=s
if keys[key.LSHIFT]: self.pos[1]-=s'''
s = dt*self.FLY_SPEED if self.flying else dt*self.WALK_SPEED
rotY = -self.rot[1]/180*math.pi
dx,dz = s*math.sin(rotY),s*math.cos(rotY)
if self.flying:
if keys[key.SPACE]: self.pos[1]+=s
if keys[key.LSHIFT]: self.pos[1]-=s
elif keys[key.SPACE]: self.jump()
if keys[key.W]: self.pos[0]+=dx; self.pos[2]-=dz
if keys[key.S]: self.pos[0]-=dx; self.pos[2]+=dz
if keys[key.A]: self.pos[0]-=dz; self.pos[2]-=dx
if keys[key.D]: self.pos[0]+=dz; self.pos[2]+=dx
class Window(pyglet.window.Window):
def push(self,pos,rot): glPushMatrix(); glRotatef(-rot[0],1,0,0); glRotatef(-rot[1],0,1,0); glTranslatef(-pos[0],-pos[1],-pos[2],)
def Projection(self): glMatrixMode(GL_PROJECTION); glLoadIdentity()
def Model(self): glMatrixMode(GL_MODELVIEW); glLoadIdentity()
def set2d(self): self.Projection(); gluOrtho2D(0,self.width,0,self.height); self.Model()
def set3d(self): self.Projection(); gluPerspective(70,self.width/self.height,0.05,1000); self.Model()
def setLock(self,state): self.lock = state; self.set_exclusive_mouse(state)
lock = False; mouse_lock = property(lambda self:self.lock,setLock)
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.set_minimum_size(300,200)
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
pyglet.clock.schedule(self.update)
self.fps_counter = pyglet.clock.ClockDisplay()
self.model = Model()
self.player = Player((0.5,1.5,1.5),(-30,0))
self.on_fps = False
def on_mouse_motion(self,x,y,dx,dy):
if self.mouse_lock: self.player.mouse_motion(dx,dy)
def on_key_press(self,KEY,MOD):
if KEY == key.ESCAPE: self.close()
elif KEY == key.E: self.mouse_lock = not self.mouse_lock
elif KEY == key.TAB: self.on_fps = not self.on_fps;
def update(self,dt):
self.player.update(dt,self.keys)
def on_draw(self):
self.clear()
self.set3d()
self.push(self.player.pos,self.player.rot)
self.model.draw()
glPopMatrix()
if self.on_fps == True:
#Eveything after this is rendered 2d, I presume.
self.set2d()
self.fps_counter.draw()
if __name__ == "__main__":
window = Window(width=400,height=300,caption="Pyglet Cube",resizable=True)
glClearColor(0.5, 0.7, 1, 1);
glEnable(GL_ALPHA_TEST)
glEnable(GL_DEPTH_TEST) #Makes it so you can't see faces through other faces.
glEnable(GL_CULL_FACE) #Enables culling, doesn't render the faces you can't see. Increases performance.
pyglet.app.run()