Python实现我的世界小游戏源代码


Posted in Python onMarch 02, 2021

我的世界小游戏使用方法:

移动

前进:W,后退:S,向左:A,向右:D,环顾四周:鼠标,跳起:空格键,切换飞行模式:Tab;

选择建筑材料

砖:1,草:2,沙子:3,删除建筑:鼠标左键单击,创建建筑块:鼠标右键单击

ESC退出程序。

完整程序包请通过文末地址下载,程序运行截图如下:

Python实现我的世界小游戏源代码

from __future__ import division

import sys
import math
import random
import time

from collections import deque
from pyglet import image
from pyglet.gl import *
from pyglet.graphics import TextureGroup
from pyglet.window import key, mouse

TICKS_PER_SEC = 60

# Size of sectors used to ease block loading.
SECTOR_SIZE = 16

WALKING_SPEED = 5
FLYING_SPEED = 15

GRAVITY = 20.0
MAX_JUMP_HEIGHT = 1.0 # About the height of a block.
# To derive the formula for calculating jump speed, first solve
#  v_t = v_0 + a * t
# for the time at which you achieve maximum height, where a is the acceleration
# due to gravity and v_t = 0. This gives:
#  t = - v_0 / a
# Use t and the desired MAX_JUMP_HEIGHT to solve for v_0 (jump speed) in
#  s = s_0 + v_0 * t + (a * t^2) / 2
JUMP_SPEED = math.sqrt(2 * GRAVITY * MAX_JUMP_HEIGHT)
TERMINAL_VELOCITY = 50

PLAYER_HEIGHT = 2

if sys.version_info[0] >= 3:
  xrange = range

def cube_vertices(x, y, z, n):
  """ Return the vertices of the cube at position x, y, z with size 2*n.

  """
  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
  ]


def tex_coord(x, y, n=4):
  """ Return the bounding vertices of the texture square.

  """
  m = 1.0 / n
  dx = x * m
  dy = y * m
  return dx, dy, dx + m, dy, dx + m, dy + m, dx, dy + m


def tex_coords(top, bottom, side):
  """ Return a list of the texture squares for the top, bottom and side.

  """
  top = tex_coord(*top)
  bottom = tex_coord(*bottom)
  side = tex_coord(*side)
  result = []
  result.extend(top)
  result.extend(bottom)
  result.extend(side * 4)
  return result


TEXTURE_PATH = 'texture.png'

GRASS = tex_coords((1, 0), (0, 1), (0, 0))
SAND = tex_coords((1, 1), (1, 1), (1, 1))
BRICK = tex_coords((2, 0), (2, 0), (2, 0))
STONE = tex_coords((2, 1), (2, 1), (2, 1))

FACES = [
  ( 0, 1, 0),
  ( 0,-1, 0),
  (-1, 0, 0),
  ( 1, 0, 0),
  ( 0, 0, 1),
  ( 0, 0,-1),
]


def normalize(position):
  """ Accepts `position` of arbitrary precision and returns the block
  containing that position.

  Parameters
  ----------
  position : tuple of len 3

  Returns
  -------
  block_position : tuple of ints of len 3

  """
  x, y, z = position
  x, y, z = (int(round(x)), int(round(y)), int(round(z)))
  return (x, y, z)


def sectorize(position):
  """ Returns a tuple representing the sector for the given `position`.

  Parameters
  ----------
  position : tuple of len 3

  Returns
  -------
  sector : tuple of len 3

  """
  x, y, z = normalize(position)
  x, y, z = x // SECTOR_SIZE, y // SECTOR_SIZE, z // SECTOR_SIZE
  return (x, 0, z)


class Model(object):

  def __init__(self):

    # A Batch is a collection of vertex lists for batched rendering.
    self.batch = pyglet.graphics.Batch()

    # A TextureGroup manages an OpenGL texture.
    self.group = TextureGroup(image.load(TEXTURE_PATH).get_texture())

    # A mapping from position to the texture of the block at that position.
    # This defines all the blocks that are currently in the world.
    self.world = {}

    # Same mapping as `world` but only contains blocks that are shown.
    self.shown = {}

    # Mapping from position to a pyglet `VertextList` for all shown blocks.
    self._shown = {}

    # Mapping from sector to a list of positions inside that sector.
    self.sectors = {}

    # Simple function queue implementation. The queue is populated with
    # _show_block() and _hide_block() calls
    self.queue = deque()

    self._initialize()

  def _initialize(self):
    """ Initialize the world by placing all the blocks.

    """
    n = 80 # 1/2 width and height of world
    s = 1 # step size
    y = 0 # initial y height
    for x in xrange(-n, n + 1, s):
      for z in xrange(-n, n + 1, s):
        # create a layer stone an grass everywhere.
        self.add_block((x, y - 2, z), GRASS, immediate=False)
        self.add_block((x, y - 3, z), STONE, immediate=False)
        if x in (-n, n) or z in (-n, n):
          # create outer walls.
          for dy in xrange(-2, 3):
            self.add_block((x, y + dy, z), STONE, immediate=False)

    # generate the hills randomly
    o = n - 10
    for _ in xrange(120):
      a = random.randint(-o, o) # x position of the hill
      b = random.randint(-o, o) # z position of the hill
      c = -1 # base of the hill
      h = random.randint(1, 6) # height of the hill
      s = random.randint(4, 8) # 2 * s is the side length of the hill
      d = 1 # how quickly to taper off the hills
      t = random.choice([GRASS, SAND, BRICK])
      for y in xrange(c, c + h):
        for x in xrange(a - s, a + s + 1):
          for z in xrange(b - s, b + s + 1):
            if (x - a) ** 2 + (z - b) ** 2 > (s + 1) ** 2:
              continue
            if (x - 0) ** 2 + (z - 0) ** 2 < 5 ** 2:
              continue
            self.add_block((x, y, z), t, immediate=False)
        s -= d # decrement side lenth so hills taper off

  def hit_test(self, position, vector, max_distance=8):
    """ Line of sight search from current position. If a block is
    intersected it is returned, along with the block previously in the line
    of sight. If no block is found, return None, None.

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position to check visibility from.
    vector : tuple of len 3
      The line of sight vector.
    max_distance : int
      How many blocks away to search for a hit.

    """
    m = 8
    x, y, z = position
    dx, dy, dz = vector
    previous = None
    for _ in xrange(max_distance * m):
      key = normalize((x, y, z))
      if key != previous and key in self.world:
        return key, previous
      previous = key
      x, y, z = x + dx / m, y + dy / m, z + dz / m
    return None, None

  def exposed(self, position):
    """ Returns False is given `position` is surrounded on all 6 sides by
    blocks, True otherwise.

    """
    x, y, z = position
    for dx, dy, dz in FACES:
      if (x + dx, y + dy, z + dz) not in self.world:
        return True
    return False

  def add_block(self, position, texture, immediate=True):
    """ Add a block with the given `texture` and `position` to the world.

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position of the block to add.
    texture : list of len 3
      The coordinates of the texture squares. Use `tex_coords()` to
      generate.
    immediate : bool
      Whether or not to draw the block immediately.

    """
    if position in self.world:
      self.remove_block(position, immediate)
    self.world[position] = texture
    self.sectors.setdefault(sectorize(position), []).append(position)
    if immediate:
      if self.exposed(position):
        self.show_block(position)
      self.check_neighbors(position)

  def remove_block(self, position, immediate=True):
    """ Remove the block at the given `position`.

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position of the block to remove.
    immediate : bool
      Whether or not to immediately remove block from canvas.

    """
    del self.world[position]
    self.sectors[sectorize(position)].remove(position)
    if immediate:
      if position in self.shown:
        self.hide_block(position)
      self.check_neighbors(position)

  def check_neighbors(self, position):
    """ Check all blocks surrounding `position` and ensure their visual
    state is current. This means hiding blocks that are not exposed and
    ensuring that all exposed blocks are shown. Usually used after a block
    is added or removed.

    """
    x, y, z = position
    for dx, dy, dz in FACES:
      key = (x + dx, y + dy, z + dz)
      if key not in self.world:
        continue
      if self.exposed(key):
        if key not in self.shown:
          self.show_block(key)
      else:
        if key in self.shown:
          self.hide_block(key)

  def show_block(self, position, immediate=True):
    """ Show the block at the given `position`. This method assumes the
    block has already been added with add_block()

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position of the block to show.
    immediate : bool
      Whether or not to show the block immediately.

    """
    texture = self.world[position]
    self.shown[position] = texture
    if immediate:
      self._show_block(position, texture)
    else:
      self._enqueue(self._show_block, position, texture)

  def _show_block(self, position, texture):
    """ Private implementation of the `show_block()` method.

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position of the block to show.
    texture : list of len 3
      The coordinates of the texture squares. Use `tex_coords()` to
      generate.

    """
    x, y, z = position
    vertex_data = cube_vertices(x, y, z, 0.5)
    texture_data = list(texture)
    # create vertex list
    # FIXME Maybe `add_indexed()` should be used instead
    self._shown[position] = self.batch.add(24, GL_QUADS, self.group,
      ('v3f/static', vertex_data),
      ('t2f/static', texture_data))

  def hide_block(self, position, immediate=True):
    """ Hide the block at the given `position`. Hiding does not remove the
    block from the world.

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position of the block to hide.
    immediate : bool
      Whether or not to immediately remove the block from the canvas.

    """
    self.shown.pop(position)
    if immediate:
      self._hide_block(position)
    else:
      self._enqueue(self._hide_block, position)

  def _hide_block(self, position):
    """ Private implementation of the 'hide_block()` method.

    """
    self._shown.pop(position).delete()

  def show_sector(self, sector):
    """ Ensure all blocks in the given sector that should be shown are
    drawn to the canvas.

    """
    for position in self.sectors.get(sector, []):
      if position not in self.shown and self.exposed(position):
        self.show_block(position, False)

  def hide_sector(self, sector):
    """ Ensure all blocks in the given sector that should be hidden are
    removed from the canvas.

    """
    for position in self.sectors.get(sector, []):
      if position in self.shown:
        self.hide_block(position, False)

  def change_sectors(self, before, after):
    """ Move from sector `before` to sector `after`. A sector is a
    contiguous x, y sub-region of world. Sectors are used to speed up
    world rendering.

    """
    before_set = set()
    after_set = set()
    pad = 4
    for dx in xrange(-pad, pad + 1):
      for dy in [0]: # xrange(-pad, pad + 1):
        for dz in xrange(-pad, pad + 1):
          if dx ** 2 + dy ** 2 + dz ** 2 > (pad + 1) ** 2:
            continue
          if before:
            x, y, z = before
            before_set.add((x + dx, y + dy, z + dz))
          if after:
            x, y, z = after
            after_set.add((x + dx, y + dy, z + dz))
    show = after_set - before_set
    hide = before_set - after_set
    for sector in show:
      self.show_sector(sector)
    for sector in hide:
      self.hide_sector(sector)

  def _enqueue(self, func, *args):
    """ Add `func` to the internal queue.

    """
    self.queue.append((func, args))

  def _dequeue(self):
    """ Pop the top function from the internal queue and call it.

    """
    func, args = self.queue.popleft()
    func(*args)

  def process_queue(self):
    """ Process the entire queue while taking periodic breaks. This allows
    the game loop to run smoothly. The queue contains calls to
    _show_block() and _hide_block() so this method should be called if
    add_block() or remove_block() was called with immediate=False

    """
    start = time.perf_counter()
    while self.queue and time.time()- start < 1.0 / TICKS_PER_SEC:
      self._dequeue()

  def process_entire_queue(self):
    """ Process the entire queue with no breaks.

    """
    while self.queue:
      self._dequeue()


class Window(pyglet.window.Window):

  def __init__(self, *args, **kwargs):
    super(Window, self).__init__(*args, **kwargs)

    # Whether or not the window exclusively captures the mouse.
    self.exclusive = False

    # When flying gravity has no effect and speed is increased.
    self.flying = False

    # Strafing is moving lateral to the direction you are facing,
    # e.g. moving to the left or right while continuing to face forward.
    #
    # First element is -1 when moving forward, 1 when moving back, and 0
    # otherwise. The second element is -1 when moving left, 1 when moving
    # right, and 0 otherwise.
    self.strafe = [0, 0]

    # Current (x, y, z) position in the world, specified with floats. Note
    # that, perhaps unlike in math class, the y-axis is the vertical axis.
    self.position = (0, 0, 0)

    # First element is rotation of the player in the x-z plane (ground
    # plane) measured from the z-axis down. The second is the rotation
    # angle from the ground plane up. Rotation is in degrees.
    #
    # The vertical plane rotation ranges from -90 (looking straight down) to
    # 90 (looking straight up). The horizontal rotation range is unbounded.
    self.rotation = (0, 0)

    # Which sector the player is currently in.
    self.sector = None

    # The crosshairs at the center of the screen.
    self.reticle = None

    # Velocity in the y (upward) direction.
    self.dy = 0

    # A list of blocks the player can place. Hit num keys to cycle.
    self.inventory = [BRICK, GRASS, SAND]

    # The current block the user can place. Hit num keys to cycle.
    self.block = self.inventory[0]

    # Convenience list of num keys.
    self.num_keys = [
      key._1, key._2, key._3, key._4, key._5,
      key._6, key._7, key._8, key._9, key._0]

    # Instance of the model that handles the world.
    self.model = Model()

    # The label that is displayed in the top left of the canvas.
    self.label = pyglet.text.Label('', font_name='Arial', font_size=18,
      x=10, y=self.height - 10, anchor_x='left', anchor_y='top',
      color=(0, 0, 0, 255))

    # This call schedules the `update()` method to be called
    # TICKS_PER_SEC. This is the main game event loop.
    pyglet.clock.schedule_interval(self.update, 1.0 / TICKS_PER_SEC)

  def set_exclusive_mouse(self, exclusive):
    """ If `exclusive` is True, the game will capture the mouse, if False
    the game will ignore the mouse.

    """
    super(Window, self).set_exclusive_mouse(exclusive)
    self.exclusive = exclusive

  def get_sight_vector(self):
    """ Returns the current line of sight vector indicating the direction
    the player is looking.

    """
    x, y = self.rotation
    # y ranges from -90 to 90, or -pi/2 to pi/2, so m ranges from 0 to 1 and
    # is 1 when looking ahead parallel to the ground and 0 when looking
    # straight up or down.
    m = math.cos(math.radians(y))
    # dy ranges from -1 to 1 and is -1 when looking straight down and 1 when
    # looking straight up.
    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 get_motion_vector(self):
    """ Returns the current motion vector indicating the velocity of the
    player.

    Returns
    -------
    vector : tuple of len 3
      Tuple containing the velocity in x, y, and z respectively.

    """
    if any(self.strafe):
      x, y = self.rotation
      strafe = math.degrees(math.atan2(*self.strafe))
      y_angle = math.radians(y)
      x_angle = math.radians(x + strafe)
      if self.flying:
        m = math.cos(y_angle)
        dy = math.sin(y_angle)
        if self.strafe[1]:
          # Moving left or right.
          dy = 0.0
          m = 1
        if self.strafe[0] > 0:
          # Moving backwards.
          dy *= -1
        # When you are flying up or down, you have less left and right
        # motion.
        dx = math.cos(x_angle) * m
        dz = math.sin(x_angle) * m
      else:
        dy = 0.0
        dx = math.cos(x_angle)
        dz = math.sin(x_angle)
    else:
      dy = 0.0
      dx = 0.0
      dz = 0.0
    return (dx, dy, dz)

  def update(self, dt):
    """ This method is scheduled to be called repeatedly by the pyglet
    clock.

    Parameters
    ----------
    dt : float
      The change in time since the last call.

    """
    self.model.process_queue()
    sector = sectorize(self.position)
    if sector != self.sector:
      self.model.change_sectors(self.sector, sector)
      if self.sector is None:
        self.model.process_entire_queue()
      self.sector = sector
    m = 8
    dt = min(dt, 0.2)
    for _ in xrange(m):
      self._update(dt / m)

  def _update(self, dt):
    """ Private implementation of the `update()` method. This is where most
    of the motion logic lives, along with gravity and collision detection.

    Parameters
    ----------
    dt : float
      The change in time since the last call.

    """
    # walking
    speed = FLYING_SPEED if self.flying else WALKING_SPEED
    d = dt * speed # distance covered this tick.
    dx, dy, dz = self.get_motion_vector()
    # New position in space, before accounting for gravity.
    dx, dy, dz = dx * d, dy * d, dz * d
    # gravity
    if not self.flying:
      # Update your vertical speed: if you are falling, speed up until you
      # hit terminal velocity; if you are jumping, slow down until you
      # start falling.
      self.dy -= dt * GRAVITY
      self.dy = max(self.dy, -TERMINAL_VELOCITY)
      dy += self.dy * dt
    # collisions
    x, y, z = self.position
    x, y, z = self.collide((x + dx, y + dy, z + dz), PLAYER_HEIGHT)
    self.position = (x, y, z)

  def collide(self, position, height):
    """ Checks to see if the player at the given `position` and `height`
    is colliding with any blocks in the world.

    Parameters
    ----------
    position : tuple of len 3
      The (x, y, z) position to check for collisions at.
    height : int or float
      The height of the player.

    Returns
    -------
    position : tuple of len 3
      The new position of the player taking into account collisions.

    """
    # How much overlap with a dimension of a surrounding block you need to
    # have to count as a collision. If 0, touching terrain at all counts as
    # a collision. If .49, you sink into the ground, as if walking through
    # tall grass. If >= .5, you'll fall through the ground.
    pad = 0.25
    p = list(position)
    np = normalize(position)
    for face in FACES: # check all surrounding blocks
      for i in xrange(3): # check each dimension independently
        if not face[i]:
          continue
        # How much overlap you have with this dimension.
        d = (p[i] - np[i]) * face[i]
        if d < pad:
          continue
        for dy in xrange(height): # check each height
          op = list(np)
          op[1] -= dy
          op[i] += face[i]
          if tuple(op) not in self.model.world:
            continue
          p[i] -= (d - pad) * face[i]
          if face == (0, -1, 0) or face == (0, 1, 0):
            # You are colliding with the ground or ceiling, so stop
            # falling / rising.
            self.dy = 0
          break
    return tuple(p)

  def on_mouse_press(self, x, y, button, modifiers):
    """ Called when a mouse button is pressed. See pyglet docs for button
    amd modifier mappings.

    Parameters
    ----------
    x, y : int
      The coordinates of the mouse click. Always center of the screen if
      the mouse is captured.
    button : int
      Number representing mouse button that was clicked. 1 = left button,
      4 = right button.
    modifiers : int
      Number representing any modifying keys that were pressed when the
      mouse button was clicked.

    """
    if self.exclusive:
      vector = self.get_sight_vector()
      block, previous = self.model.hit_test(self.position, vector)
      if (button == mouse.RIGHT) or \
          ((button == mouse.LEFT) and (modifiers & key.MOD_CTRL)):
        # ON OSX, control + left click = right click.
        if previous:
          self.model.add_block(previous, self.block)
      elif button == pyglet.window.mouse.LEFT and block:
        texture = self.model.world[block]
        if texture != STONE:
          self.model.remove_block(block)
    else:
      self.set_exclusive_mouse(True)

  def on_mouse_motion(self, x, y, dx, dy):
    """ Called when the player moves the mouse.

    Parameters
    ----------
    x, y : int
      The coordinates of the mouse click. Always center of the screen if
      the mouse is captured.
    dx, dy : float
      The movement of the mouse.

    """
    if self.exclusive:
      m = 0.15
      x, y = self.rotation
      x, y = x + dx * m, y + dy * m
      y = max(-90, min(90, y))
      self.rotation = (x, y)

  def on_key_press(self, symbol, modifiers):
    """ Called when the player presses a key. See pyglet docs for key
    mappings.

    Parameters
    ----------
    symbol : int
      Number representing the key that was pressed.
    modifiers : int
      Number representing any modifying keys that were pressed.

    """
    if symbol == key.W:
      self.strafe[0] -= 1
    elif symbol == key.S:
      self.strafe[0] += 1
    elif symbol == key.A:
      self.strafe[1] -= 1
    elif symbol == key.D:
      self.strafe[1] += 1
    elif symbol == key.SPACE:
      if self.dy == 0:
        self.dy = JUMP_SPEED
    elif symbol == key.ESCAPE:
      self.set_exclusive_mouse(False)
    elif symbol == key.TAB:
      self.flying = not self.flying
    elif symbol in self.num_keys:
      index = (symbol - self.num_keys[0]) % len(self.inventory)
      self.block = self.inventory[index]

  def on_key_release(self, symbol, modifiers):
    """ Called when the player releases a key. See pyglet docs for key
    mappings.

    Parameters
    ----------
    symbol : int
      Number representing the key that was pressed.
    modifiers : int
      Number representing any modifying keys that were pressed.

    """
    if symbol == key.W:
      self.strafe[0] += 1
    elif symbol == key.S:
      self.strafe[0] -= 1
    elif symbol == key.A:
      self.strafe[1] += 1
    elif symbol == key.D:
      self.strafe[1] -= 1

  def on_resize(self, width, height):
    """ Called when the window is resized to a new `width` and `height`.

    """
    # label
    self.label.y = height - 10
    # reticle
    if self.reticle:
      self.reticle.delete()
    x, y = self.width // 2, self.height // 2
    n = 10
    self.reticle = pyglet.graphics.vertex_list(4,
      ('v2i', (x - n, y, x + n, y, x, y - n, x, y + n))
    )

  def set_2d(self):
    """ Configure OpenGL to draw in 2d.

    """
    width, height = self.get_size()
    glDisable(GL_DEPTH_TEST)
    viewport = self.get_viewport_size()
    glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(0, max(1, width), 0, max(1, height), -1, 1)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()

  def set_3d(self):
    """ Configure OpenGL to draw in 3d.

    """
    width, height = self.get_size()
    glEnable(GL_DEPTH_TEST)
    viewport = self.get_viewport_size()
    glViewport(0, 0, max(1, viewport[0]), max(1, viewport[1]))
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(65.0, width / float(height), 0.1, 60.0)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    x, y = self.rotation
    glRotatef(x, 0, 1, 0)
    glRotatef(-y, math.cos(math.radians(x)), 0, math.sin(math.radians(x)))
    x, y, z = self.position
    glTranslatef(-x, -y, -z)

  def on_draw(self):
    """ Called by pyglet to draw the canvas.

    """
    self.clear()
    self.set_3d()
    glColor3d(1, 1, 1)
    self.model.batch.draw()
    self.draw_focused_block()
    self.set_2d()
    self.draw_label()
    self.draw_reticle()

  def draw_focused_block(self):
    """ Draw black edges around the block that is currently under the
    crosshairs.

    """
    vector = self.get_sight_vector()
    block = self.model.hit_test(self.position, vector)[0]
    if block:
      x, y, z = block
      vertex_data = cube_vertices(x, y, z, 0.51)
      glColor3d(0, 0, 0)
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
      pyglet.graphics.draw(24, GL_QUADS, ('v3f/static', vertex_data))
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

  def draw_label(self):
    """ Draw the label in the top left of the screen.

    """
    x, y, z = self.position
    self.label.text = '%02d (%.2f, %.2f, %.2f) %d / %d' % (
      pyglet.clock.get_fps(), x, y, z,
      len(self.model._shown), len(self.model.world))
    self.label.draw()

  def draw_reticle(self):
    """ Draw the crosshairs in the center of the screen.

    """
    glColor3d(0, 0, 0)
    self.reticle.draw(GL_LINES)


def setup_fog():
  """ Configure the OpenGL fog properties.

  """
  # Enable fog. Fog "blends a fog color with each rasterized pixel fragment's
  # post-texturing color."
  glEnable(GL_FOG)
  # Set the fog color.
  glFogfv(GL_FOG_COLOR, (GLfloat * 4)(0.5, 0.69, 1.0, 1))
  # Say we have no preference between rendering speed and quality.
  glHint(GL_FOG_HINT, GL_DONT_CARE)
  # Specify the equation used to compute the blending factor.
  glFogi(GL_FOG_MODE, GL_LINEAR)
  # How close and far away fog starts and ends. The closer the start and end,
  # the denser the fog in the fog range.
  glFogf(GL_FOG_START, 20.0)
  glFogf(GL_FOG_END, 60.0)


def setup():
  """ Basic OpenGL configuration.

  """
  # Set the color of "clear", i.e. the sky, in rgba.
  glClearColor(0.5, 0.69, 1.0, 1)
  # Enable culling (not rendering) of back-facing facets -- facets that aren't
  # visible to you.
  glEnable(GL_CULL_FACE)
  # Set the texture minification/magnification function to GL_NEAREST (nearest
  # in Manhattan distance) to the specified texture coordinates. GL_NEAREST
  # "is generally faster than GL_LINEAR, but it can produce textured 图片
  # with sharper edges because the transition between texture elements is not
  # as smooth."
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
  setup_fog()


def main():
  window = Window(width=1800, height=1600, caption='Pyglet', resizable=True)
  # Hide the mouse cursor and prevent the mouse from leaving the window.
  window.set_exclusive_mouse(True)
  setup()
  pyglet.app.run()


if __name__ == '__main__':
  main()

我的世界小游戏python源代码包下载地址:

链接: https://pan.baidu.com/s/1gKAheRzAeNmRXgSU-A4PPg

提取码: rya9

到此这篇关于Python实现我的世界小游戏源代码的文章就介绍到这了,更多相关Python小游戏源代码内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python执行子进程实现进程间通信的方法
Jun 02 Python
Python使用ftplib实现简易FTP客户端的方法
Jun 03 Python
python利用正则表达式提取字符串
Dec 08 Python
python爬虫系列Selenium定向爬取虎扑篮球图片详解
Nov 15 Python
python调用API实现智能回复机器人
Apr 10 Python
python实现简单登陆流程的方法
Apr 22 Python
python 字典修改键(key)的几种方法
Aug 10 Python
python 提取key 为中文的json 串方法
Dec 31 Python
Python标准库使用OrderedDict类的实例讲解
Feb 14 Python
Django stark组件使用及原理详解
Aug 22 Python
pyCharm 实现关闭代码检查
Jun 09 Python
Python常用base64 md5 aes des crc32加密解密方法汇总
Nov 06 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
Mar 02 #Python
python 基于pygame实现俄罗斯方块
Mar 02 #Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
Mar 02 #Python
Autopep8的使用(python自动编排工具)
Mar 02 #Python
python 将Excel转Word的示例
Mar 02 #Python
Python字节单位转换(将字节转换为K M G T)
Mar 02 #Python
Python使用cn2an实现中文数字与阿拉伯数字的相互转换
Mar 02 #Python
You might like
浅析PHP水印技术
2007/02/14 PHP
php 求质素(素数) 的实现代码
2011/04/12 PHP
解析centos中Apache、php、mysql 默认安装路径
2013/06/25 PHP
php通过获取头信息判断图片类型的方法
2015/06/26 PHP
php获取excel文件数据
2017/04/21 PHP
PHP自定义递归函数实现数组转JSON功能【支持GBK编码】
2018/07/17 PHP
javascript GUID生成器实现代码
2009/10/31 Javascript
关于文本框的一些限制控制总结~~
2010/04/15 Javascript
获取3个数组不重复的值的具体实现
2013/12/30 Javascript
jquery数组封装使用方法分享(jquery数组遍历)
2014/03/25 Javascript
浅谈document.write()输出样式
2015/05/07 Javascript
在JavaScript中用getMinutes()方法返回指定的分时刻
2015/06/10 Javascript
IE7浏览器窗口大小改变事件执行多次bug及IE6/IE7/IE8下resize问题
2015/08/21 Javascript
JavaScript事件学习小结(五)js中事件类型之鼠标事件
2016/06/09 Javascript
jQuery实现页面顶部下拉广告
2016/12/30 Javascript
微信小程序 sha1 实现密码加密实例详解
2017/07/06 Javascript
基于javascript中的typeof和类型判断(详解)
2017/10/27 Javascript
vue2.x+webpack快速搭建前端项目框架详解
2017/11/30 Javascript
JS+canvas画一个圆锥实例代码
2017/12/13 Javascript
微信小程序实现一张或多张图片上传(云开发)
2019/09/25 Javascript
[01:54]TI珍贵瞬间系列(三):翻盘
2020/08/28 DOTA
Python入门篇之对象类型
2014/10/17 Python
python中常用的九种预处理方法分享
2016/09/11 Python
python读取图片的几种方式及图像宽和高的存储顺序
2020/02/11 Python
Django 自定义404 500等错误页面的实现
2020/03/08 Python
使用Python matplotlib作图时,设置横纵坐标轴数值以百分比(%)显示
2020/05/16 Python
python用tkinter实现一个简易能进行随机点名的界面
2020/09/27 Python
HTML5上传文件显示进度的实现代码
2012/08/30 HTML / CSS
HTML5 video 上传预览图片视频如何设置、预览视频某秒的海报帧
2018/08/28 HTML / CSS
h5页面唤起app如果没安装就跳转下载(iOS和Android)
2020/06/03 HTML / CSS
vue项目实现分页效果
2021/03/24 Vue.js
采购经理岗位职责
2014/02/16 职场文书
观看信仰心得体会
2014/09/04 职场文书
2015年消防工作总结
2015/04/24 职场文书
消费者理赔投诉书
2015/07/02 职场文书
教师节表彰会主持词
2015/07/06 职场文书