Skip to content

Instantly share code, notes, and snippets.

@downthecrop
Last active July 23, 2021 07:37
Show Gist options
  • Save downthecrop/5b41cbd23744487bafbf600db458e774 to your computer and use it in GitHub Desktop.
Save downthecrop/5b41cbd23744487bafbf600db458e774 to your computer and use it in GitHub Desktop.
Cropcraft with real neighbor checking!
import eel,math,pyglet,time
from pyglet.gl import *
from pyglet.window import *
from pyglet import image
FACES=[(0,1,0),(0,-1,0),(-1,0,0),(1,0,0),(0,0,1),(0,0,-1),(0,0,0)]
TEX=0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,1
@eel.expose
def say_hello_py(self):
print("called from JS")
set_tex("grass_top.png")
def set_tex(tex):
global current_tex
current_tex = pyglet.graphics.TextureGroup(pyglet.image.load(tex).get_texture())
glEnable(GL_TEXTURE_2D)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
def cube_vertices(x, y, z, n=.5):
return [
x-n,y+n,z-n, x-n,y+n,z+n, x+n,y+n,z+n, x+n,y+n,z-n, # top
x-n,y-n,z-n, x+n,y-n,z-n, x+n,y-n,z+n, x-n,y-n,z+n, # bottom
x-n,y-n,z-n, x-n,y-n,z+n, x-n,y+n,z+n, x-n,y+n,z-n, # left
x+n,y-n,z+n, x+n,y-n,z-n, x+n,y+n,z-n, x+n,y+n,z+n, # right
x-n,y-n,z+n, x+n,y-n,z+n, x+n,y+n,z+n, x-n,y+n,z+n, # front
x+n,y-n,z-n, x-n,y-n,z-n, x-n,y+n,z-n, x+n,y+n,z-n, # back
]
class World:
def __init__(self,x=16,y=16,z=16):
set_tex("dirt.png")
self.batch = pyglet.graphics.Batch()
self._shown = {}
self.blocks = set()
self.gen_world(x,y,z)
def add_block(self,pos):
self.blocks.add(pos)
self.show_block(pos)
self.check_neighbors(pos)
def del_block(self,pos):
self.blocks.remove(pos)
self._shown.pop(pos).delete()
self.check_neighbors(pos)
def show_block(self,pos):
x,y,z = pos
if pos not in self._shown:
self._shown[pos] = self.batch.add(24, GL_QUADS, current_tex,('v3f/static', cube_vertices(x, y, z)),('t2f/static', TEX))
def hide_block(self,pos):
self._shown.pop(pos).delete()
def hit_test(self, pos, vector,m=8):
dx, dy, dz = vector
previous = None
for _ in range(m*4):
x,y,z = pos
block = (round(x), round(y), round(z))
if block != previous and block in self._shown:
return block, previous
previous = block
pos = x + dx / m, y + dy / m, z + dz / m
return None, None
def check_neighbors(self, pos):
x,y,z = pos
for dx, dy, dz in FACES:
block = (x + dx, y + dy, z + dz)
if block not in self.blocks:
continue
elif self.exposed(block):
self.show_block(block)
elif block in self._shown:
self.hide_block(block)
def exposed(self, pos):
x,y,z = pos
for dx, dy, dz in FACES:
if (x + dx, y + dy, z + dz) not in self.blocks:
return True
return False
def gen_world(self,x_max,y_max,z_max):
x,y,z = 0,0,0
while z < z_max:
while y < y_max:
while x < x_max:
self.blocks.add((x,y,z))
x += 1
x = 0
y += 1
y = 0
z += 1
for block in self.blocks:
self.add_block(block)
class Player:
def __init__(self, pos=(0, 0, 0), rot=(0, 0)):
self.pos = list(pos)
self.rot = list(rot)
self.speed = .2
class Window(pyglet.window.Window):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
x,y,z = 16,16,16
self.lock = True
self.hud_position = self.width/2-364
self.fps_display = pyglet.window.FPSDisplay(self)
self.hud = image.load('hud.png')
self.active = image.load('active.png')
self.keys = key.KeyStateHandler()
self.push_handlers(self.keys)
self.offset = 0
t = time.perf_counter()
self.world = World(x,y,z)
print("World Gen in ",time.perf_counter() - t)
self.player = Player((x-10,y+5,z-10),(-90,0))
self.label = pyglet.text.Label('+',
font_name='Times New Roman',
font_size=36,
x=self.width/2,
y=self.height/2,
anchor_x='center', anchor_y='center')
pyglet.clock.schedule(self.game_loop)
def push(self):
glPushMatrix()
rot = self.player.rot
x,y,z = self.player.pos
glRotatef(-rot[0],1,0,0)
glRotatef(-rot[1],0,1,0)
glTranslatef(-x, -y, -z)
def clean(self):
glLoadIdentity()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
def set3d(self):
self.clean()
gluPerspective(70, self.width/self.height, 0.05, 1000)
glMatrixMode(GL_MODELVIEW)
def set2d(self):
self.clean()
glOrtho(0, float(self.width),0, float(self.height), 0, 1)
glMatrixMode(GL_MODELVIEW)
def on_mouse_motion(self,x,y,dx,dy):
if self.lock:
rot = self.player.rot
rot[0] += dy/8
rot[1] -= dx/8
if rot[0]>90: rot[0] = 90
elif rot[0] < -90: rot[0] = -90
def on_mouse_scroll(self, x, y, scroll_x, scroll_y):
self.move_active_indicator(-80) if (scroll_y > 0) else self.move_active_indicator(80)
def on_mouse_press(self, x, y, button, pos):
hit,previous = self.world.hit_test(self.player.pos,self.sight_vector(self.player))
if button == 4 and previous: self.world.add_block(previous)
elif button == 1 and hit: self.world.del_block(hit)
def on_key_press(self, KEY, _MOD):
if KEY == key.ESCAPE:
self.close()
if KEY == key.E:
self.lock = not self.lock
self.set_exclusive_mouse(self.lock)
if KEY == key.M:
eel.init('web')
eel.start('craft.html')
def player_movement(self):
rotY = -self.player.rot[1]/180*math.pi
dx, dz = math.sin(rotY), math.cos(rotY)
keys = self.keys
pos = self.player.pos
s = self.player.speed
if keys[key.W]: pos[0] += dx*s; pos[2] -= dz*s
if keys[key.S]: pos[0] -= dx*s; pos[2] += dz*s
if keys[key.A]: pos[0] -= dz*s; pos[2] -= dx*s
if keys[key.D]: pos[0] += dz*s; pos[2] += dx*s
if keys[key.SPACE]: pos[1] += s
if keys[key.LSHIFT]: pos[1] -= s
def sight_vector(self,player):
y,x = player.rot
m = math.cos(math.radians(y))
dy = math.sin(math.radians(y))
dx = math.cos(math.radians(-x - 90)) * m
dz = math.sin(math.radians(-x - 90)) * m
return (dx, dy, dz)
def move_active_indicator(self,move):
self.offset += move
if (self.offset > 650): self.offset = 0
elif (self.offset < 0): self.offset = 640
def draw_focused_block(self):
block = self.world.hit_test(self.player.pos, self.sight_vector(self.player))[0]
if block:
x, y, z = block
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
pyglet.graphics.draw(24, GL_QUADS, ('v3f', cube_vertices(x, y, z)))
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
def game_loop(self,dt):
self.player_movement()
def draw_hud(self):
self.label.draw()
self.active.blit(self.hud_position+self.offset, 0, 0) #Front
self.hud.blit(self.hud_position, 0, 0) #HUD
def on_draw(self):
self.clear()
self.set3d()
self.push()
self.world.batch.draw()
self.draw_focused_block()
self.set2d()
self.draw_hud()
self.fps_display.draw()
glPopMatrix()
if __name__ == '__main__':
window = Window(1280,720, caption='Cropcraft', vsync=True, resizable=True)
@window.event
def on_resize(width, height):
window.label = pyglet.text.Label('+',
font_name='Times New Roman',
font_size=36,
x=width/2,
y=height/2,
anchor_x='center', anchor_y='center')
window.hud_position = width/2-364
#Face Culling
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glFrontFace(GL_CCW)
#FOG
glEnable(GL_FOG)
glFogfv(GL_FOG_COLOR, (GLfloat * 4)(0.5, 0.69, 1.0, 1))
glHint(GL_FOG_HINT, GL_FASTEST)
glFogi(GL_FOG_MODE, GL_LINEAR)
glFogf(GL_FOG_START, 40.0)
glFogf(GL_FOG_END, 60.0)
#Skybox/Void color
glClearColor(0.5,0.7,1,1)
pyglet.app.run()
@downthecrop
Copy link
Author

downthecrop commented Jul 23, 2021

dirt
hud
active

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment