Last active
July 23, 2021 07:37
-
-
Save downthecrop/5b41cbd23744487bafbf600db458e774 to your computer and use it in GitHub Desktop.
Cropcraft with real neighbor checking!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Author
downthecrop
commented
Jul 23, 2021
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment