/
levchik
/
Maincraft1
Обзор
Документация
Войти
/
levchik
/
Maincraft1
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
minecraftcode
462 строки
17 KB
levchik
create minecraftcode
28 ноя 2025, 09:27
28 ноя 2025, 09:27
5a96762
Код
Авторство
О чём код?
import pygame import moderngl import numpy as np import math import random from pygame.locals import * import sys class Camera: def __init__(self): self.position = np.array([0.0, 15.0, 0.0]) self.rotation = np.array([0.0, 0.0]) self.speed = 5.0 self.mouse_sensitivity = 0.2 def update(self, dt, keys, mouse_rel): # Обработка вращения камеры self.rotation[0] += mouse_rel[0] * self.mouse_sensitivity * dt self.rotation[1] = max(-90, min(90, self.rotation[1] + mouse_rel[1] * self.mouse_sensitivity * dt)) # Направления движения rot_x = math.radians(self.rotation[0]) forward = np.array([-math.sin(rot_x), 0, -math.cos(rot_x)]) right = np.array([math.cos(rot_x), 0, -math.sin(rot_x)]) # Движение move = np.array([0.0, 0.0, 0.0]) if keys[pygame.K_w]: move += forward if keys[pygame.K_s]: move -= forward if keys[pygame.K_a]: move -= right if keys[pygame.K_d]: move += right if keys[pygame.K_SPACE]: move[1] += 1 if keys[pygame.K_LSHIFT]: move[1] -= 1 # Нормализация и применение скорости if np.linalg.norm(move) > 0: move = move / np.linalg.norm(move) self.position += move * self.speed * dt # Ограничение высоты (чтобы не упасть под землю) self.position[1] = max(1, self.position[1]) def get_view_matrix(self): rot_x = math.radians(self.rotation[0]) rot_y = math.radians(self.rotation[1]) # Вычисление направления взгляда direction = np.array([ math.cos(rot_y) * math.sin(rot_x), math.sin(rot_y), math.cos(rot_y) * math.cos(rot_x) ]) right = np.array([ math.sin(rot_x - math.pi/2), 0, math.cos(rot_x - math.pi/2) ]) up = np.cross(right, direction) # Матрица вида view = np.eye(4) view[0, :3] = right view[1, :3] = up view[2, :3] = direction view = view.T # Перевод translate = np.eye(4) translate[3, :3] = -self.position view = view @ translate return view.astype('f4') class Block: def __init__(self, block_type): self.type = block_type def get_color(self): colors = { 'grass': (0.2, 0.8, 0.2), 'dirt': (0.5, 0.3, 0.1), 'stone': (0.5, 0.5, 0.5), 'wood': (0.6, 0.4, 0.2), 'leaf': (0.1, 0.6, 0.1), 'water': (0.2, 0.3, 0.8), 'sand': (0.9, 0.8, 0.5) } return colors.get(self.type, (1, 1, 1)) class Mob: def __init__(self, mob_type, position): self.type = mob_type self.position = np.array(position, dtype='f4') self.velocity = np.array([0.0, 0.0, 0.0]) self.rotation = 0.0 self.health = 100 self.speed = 2.0 if mob_type == 'zombie' else 3.0 self.attack_cooldown = 0 def update(self, dt, player_pos, world): if self.type == 'zombie': # Простой ИИ зомби - следует за игроком direction = player_pos - self.position if np.linalg.norm(direction) > 0: direction = direction / np.linalg.norm(direction) self.velocity = direction * self.speed self.rotation = math.degrees(math.atan2(-direction[0], -direction[2])) elif self.type == 'cow': # Случайное блуждание коровы self.velocity[0] += random.uniform(-1, 1) * dt self.velocity[2] += random.uniform(-1, 1) * dt if np.linalg.norm(self.velocity) > 0: self.velocity = self.velocity / np.linalg.norm(self.velocity) * self.speed self.rotation = math.degrees(math.atan2(-self.velocity[0], -self.velocity[2])) # Гравитация self.velocity[1] -= 15.0 * dt # Простая проверка столкновений с землей ground_height = world.get_height_at(int(self.position[0]), int(self.position[2])) + 1 if self.position[1] <= ground_height: self.position[1] = ground_height self.velocity[1] = 0 # Обновление позиции self.position += self.velocity * dt # Ограничение позиции в пределах мира self.position[0] = max(1, min(world.width - 2, self.position[0])) self.position[2] = max(1, min(world.depth - 2, self.position[2])) if self.attack_cooldown > 0: self.attack_cooldown -= dt class World: def __init__(self, width=64, depth=64, height=32): self.width = width self.depth = depth self.height = height self.blocks = {} self.mobs = [] self.generate_terrain() self.generate_structures() self.spawn_mobs() def generate_terrain(self): # Генерация простого ландшафта for x in range(self.width): for z in range(self.depth): # Высота с использованием шума Перлина height = int(10 + 5 * math.sin(x * 0.2) * math.cos(z * 0.2)) for y in range(self.height): if y < height - 3: self.set_block(x, y, z, 'stone') elif y < height: self.set_block(x, y, z, 'dirt') elif y == height: if random.random() < 0.7: self.set_block(x, y, z, 'grass') else: self.set_block(x, y, z, 'sand') elif y < height + 5 and random.random() < 0.1: self.set_block(x, y, z, 'water') def generate_structures(self): # Генерация простых структур for _ in range(5): x = random.randint(5, self.width - 10) z = random.randint(5, self.depth - 10) y = self.get_height_at(x, z) self.generate_tree(x, y + 1, z) for _ in range(3): x = random.randint(5, self.width - 10) z = random.randint(5, self.depth - 10) y = self.get_height_at(x, z) self.generate_house(x, y + 1, z) def generate_tree(self, x, y, z): # Генерация дерева trunk_height = random.randint(4, 6) # Ствол for i in range(trunk_height): self.set_block(x, y + i, z, 'wood') # Листья for dx in range(-2, 3): for dz in range(-2, 3): for dy in range(2, 5): if abs(dx) + abs(dz) + abs(dy - 3) <= 3: self.set_block(x + dx, y + trunk_height + dy - 3, z + dz, 'leaf') def generate_house(self, x, y, z): # Генерация простого дома size = 5 # Фундамент и стены for dx in range(size): for dz in range(size): for dy in range(4): if dy == 0 or dy == 3 or dx == 0 or dx == size-1 or dz == 0 or dz == size-1: self.set_block(x + dx, y + dy, z + dz, 'wood') # Крыша for dx in range(-1, size + 1): for dz in range(-1, size + 1): self.set_block(x + dx, y + 4, z + dz, 'wood') # Дверь self.set_block(x + size//2, y + 1, z, None) self.set_block(x + size//2, y + 2, z, None) def spawn_mobs(self): # Спавн мобов for _ in range(8): x = random.randint(5, self.width - 5) z = random.randint(5, self.depth - 5) y = self.get_height_at(x, z) + 1 self.mobs.append(Mob('zombie', [x, y, z])) for _ in range(6): x = random.randint(5, self.width - 5) z = random.randint(5, self.depth - 5) y = self.get_height_at(x, z) + 1 self.mobs.append(Mob('cow', [x, y, z])) def set_block(self, x, y, z, block_type): if 0 <= x < self.width and 0 <= y < self.height and 0 <= z < self.depth: if block_type is None: if (x, y, z) in self.blocks: del self.blocks[(x, y, z)] else: self.blocks[(x, y, z)] = Block(block_type) def get_block(self, x, y, z): return self.blocks.get((x, y, z)) def get_height_at(self, x, z): for y in range(self.height - 1, -1, -1): if self.get_block(x, y, z): return y return 0 class MinecraftGame: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((1200, 800), pygame.OPENGL | pygame.DOUBLEBUF) pygame.display.set_caption("3D Minecraft-like Game") self.ctx = moderngl.create_context() self.clock = pygame.time.Clock() # Настройка OpenGL self.ctx.enable(moderngl.DEPTH_TEST | moderngl.CULL_FACE) # Создание объектов self.camera = Camera() self.world = World() # Создание шейдеров self.program = self.ctx.program( vertex_shader=''' #version 330 core layout(location=0) in vec3 in_position; layout(location=1) in vec3 in_color; out vec3 color; uniform mat4 projection; uniform mat4 view; uniform mat4 model; void main() { gl_Position = projection * view * model * vec4(in_position, 1.0); color = in_color; } ''', fragment_shader=''' #version 330 core in vec3 color; out vec4 frag_color; void main() { frag_color = vec4(color, 1.0); } ''' ) # Создание геометрии куба self.cube_vertices = self.create_cube_geometry() self.cube_vao = self.create_vao(self.cube_vertices) # Матрица проекции self.projection = self.create_projection_matrix() self.program['projection'].write(self.projection) # Переменные игры self.running = True self.flying = False def create_cube_geometry(self): # Вершины куба (позиция, цвет) vertices = [] # Определение вершин куба cube_vertices = [ # Передняя грань [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, 0.5], [-0.5, -0.5, 0.5], [0.5, 0.5, 0.5], [-0.5, 0.5, 0.5], # Задняя грань [-0.5, -0.5, -0.5], [0.5, 0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], # Левая грань [-0.5, -0.5, -0.5], [-0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [-0.5, -0.5, -0.5], [-0.5, 0.5, 0.5], [-0.5, 0.5, -0.5], # Правая грань [0.5, -0.5, -0.5], [0.5, 0.5, 0.5], [0.5, -0.5, 0.5], [0.5, -0.5, -0.5], [0.5, 0.5, -0.5], [0.5, 0.5, 0.5], # Верхняя грань [-0.5, 0.5, -0.5], [0.5, 0.5, 0.5], [0.5, 0.5, -0.5], [-0.5, 0.5, -0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5], # Нижняя грань [-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [0.5, -0.5, 0.5], [-0.5, -0.5, -0.5], [0.5, -0.5, 0.5], [-0.5, -0.5, 0.5], ] for i, vertex in enumerate(cube_vertices): # Добавляем позицию vertices.extend(vertex) # Добавляем базовый цвет (будет переопределен для каждого блока) vertices.extend([0.5, 0.5, 0.5]) return np.array(vertices, dtype='f4') def create_vao(self, vertices): vbo = self.ctx.buffer(vertices) vao = self.ctx.vertex_array( self.program, [ (vbo, '3f 3f', 'in_position', 'in_color') ] ) return vao def create_projection_matrix(self): aspect_ratio = self.screen.get_width() / self.screen.get_height() fov = 60.0 near = 0.1 far = 1000.0 f = 1.0 / math.tan(math.radians(fov) / 2.0) return np.array([ [f / aspect_ratio, 0, 0, 0], [0, f, 0, 0], [0, 0, (far + near) / (near - far), -1], [0, 0, (2 * far * near) / (near - far), 0] ], dtype='f4') def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: self.running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False elif event.key == pygame.K_f: self.flying = not self.flying self.camera.position[1] = max(1, self.camera.position[1]) def update(self, dt): keys = pygame.key.get_pressed() mouse_rel = pygame.mouse.get_rel() # Обновление камеры self.camera.update(dt, keys, mouse_rel) # Обновление мобов for mob in self.world.mobs[:]: mob.update(dt, self.camera.position, self.world) if mob.health <= 0: self.world.mobs.remove(mob) def render(self): # Очистка экрана self.ctx.clear(0.5, 0.7, 1.0) # Небесно-голубой цвет # Установка матрицы вида view_matrix = self.camera.get_view_matrix() self.program['view'].write(view_matrix) # Рендер блоков for (x, y, z), block in self.world.blocks.items(): model_matrix = np.eye(4, dtype='f4') model_matrix[:3, 3] = [x + 0.5, y + 0.5, z + 0.5] self.program['model'].write(model_matrix) # Установка цвета блока color = block.get_color() self.program['color'] = color self.cube_vao.render() # Рендер мобов for mob in self.world.mobs: self.render_mob(mob) def render_mob(self, mob): model_matrix = np.eye(4, dtype='f4') model_matrix[:3, 3] = mob.position model_matrix = model_matrix @ self.rotation_matrix(mob.rotation, [0, 1, 0]) self.program['model'].write(model_matrix) # Разные цвета для разных мобов if mob.type == 'zombie': self.program['color'] = (0.3, 0.5, 0.3) else: # cow self.program['color'] = (0.8, 0.6, 0.4) self.cube_vao.render() def rotation_matrix(self, angle_degrees, axis): angle = math.radians(angle_degrees) axis = np.array(axis) axis = axis / np.linalg.norm(axis) x, y, z = axis c, s = math.cos(angle), math.sin(angle) return np.array([ [c + x*x*(1-c), x*y*(1-c) - z*s, x*z*(1-c) + y*s, 0], [y*x*(1-c) + z*s, c + y*y*(1-c), y*z*(1-c) - x*s, 0], [z*x*(1-c) - y*s, z*y*(1-c) + x*s, c + z*z*(1-c), 0], [0, 0, 0, 1] ], dtype='f4') def run(self): pygame.mouse.set_visible(False) pygame.event.set_grab(True) while self.running: dt = self.clock.tick(60) / 1000.0 self.handle_events() self.update(dt) self.render() pygame.display.flip() pygame.quit() sys.exit() if __name__ == "__main__": game = MinecraftGame() game.run()