python简单小游戏代码200行,用python写小游戏源代码

本篇文章给大家谈谈python简单小游戏代码200行,以及用python写小游戏源代码,希望对各位有所帮助,不要忘了收藏本站喔。

这篇文章主要介绍了Python实现我的世界小游戏源代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

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

移动

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

选择建筑材料

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

ESC退出程序。

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

在这里插入图片描述

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

882

883

884

885

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902

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源代码包下载地址:

链接: 百度网盘 请输入提取码

提取码: rya9

到此这篇关于Python实现我的世界小游戏源代码的文章就介绍到这了.

点击拿去50G+学习视频教程
100+Python初阶、中阶、高阶电子书籍

     

  • 26
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值