Learning to program with Minecraft

Let's Get Fracking!

"Hello World!" programs are dumb, so you're going to dive right in and make a game within Minecraft – call it Treasure Hunt. The aim of the game is to find (and demolish!) a diamond block that has been hidden (buried) somewhere in the Minecraft world. Every 10 seconds, the program will post "Colder!" or "Warmer!" to the chat screen, depending on whether you are farther from or closer to the hidden block than the last time you checked (see the game program in Listing 1).

Listing 1

treasureHunt.py

01 import random, math, time
02
03 import mcpi.block as block
04 import mcpi.minecraft as minecraft
05 mc=minecraft.Minecraft.create()
06
07 v_height=0
08
09 while v_height <= 0:
10     (tx, tz)=(random.randint(-125,125), random.randint(-125,125))
11     v_height=mc.getHeight(tx, tz)
12
13 mc.setBlock(tx, v_height-2, tz, block.DIAMOND_BLOCK)
14
15 vdistance = math.sqrt(math.pow(mc.player.getTilePos().x-tx, 2) + math.pow(mc.player.getTilePos().z-tz, 2))
16
17 while mc.getBlock(tx, v_height-2, tz)!=0:
18
19     vnewdistance=math.sqrt(math.pow(mc.player.getTilePos().x-tx,2)+ math.pow(mc.player.getTilePos().z-tz, 2))
20
21     if vnewdistance == 0: mc.postToChat("Dig!")
22     elif vdistance > vnewdistance: mc.postToChat("Warmer!")
23     elif vdistance < vnewdistance: mc.postToChat("Colder!")
24     else: mc.postToChat("Move!")
25
26     vdistance=vnewdistance
27
28     time.sleep(10)
29
30 mc.postToChat("Treasure found... And destroyed!")
31 mc.postToChat("Congratulations!")

Line 1 loads several standard Python modules you'll need later on. With the random module, you'll pick a place to hide the treasure; math comes with methods like sqrt (square root) and pow (power) that you'll need to calculate the distance from the player to the treasure. Finally, you'll need time to post messages every 10 seconds.

Lines 3 and 4 import Minecraft-specific modules. The block module allows you to manipulate blocks, and the minecraft module allows you to know the player's position, to print messages to the chat window, and so forth.

Line 5 creates a connection to the running Minecraft server. Lines 3 to 5 will be pretty standard in all the Minecraft programs you write.

After loading all the necessary modules, the first thing you have to do is hide the treasure. The Pi version of Minecraft is 256 blocks wide on the x axis and 256 blocks deep on the z axis. Position (0,0) is the center of the grid. The y axis is up/down. I haven't been able to find the upper limit for the y axis, but 0 is sea level, which will be important later.

To keep things safe, the program will place the treasure within a square area that has 251 squares on a side (line 10). Even though you're avoiding the extreme edges (Minecraft Pi sometimes crashes when you play too close to the limits of the world), you still have a playing field of 63,001 blocks, and the treasure can be anywhere  … or almost. To avoid burying the treasure under the sea (because that would be evil), you check to make sure the highest point of the chosen location is above sea level (lines 9 to 11) with getHeight(), which is part of the Minecraft API.

So that the diamond is not immediately visible, you push it two layers under the surface (line 13). The setBlock method used in this instruction is part of the Minecraft API (Table 2) and takes the x, y, z position of the block you want to modify, plus the type of block you want to transform it into. For a full list of the types of blocks you can use, check out the Minecraft: Pi Edition wiki [5].

Tabelle 2

Minecraft API Methods

Method

Arguments

Returns

Description

Minecraft Class: mc.[method]

getBlock

x, y, z

blockId: int

Get the block ID at the named coordinates

getBlockWithData

x, y, z

vec3: obj

Get a block object at named coordinates

getBlocks

x0, y0, z0, x1, y1, z1

[int]

Get block IDs in cuboid between two coordinates

setBlock

x, y, z, id, [state]

 

Sets a block at coordinates; optional argument state is between 0 and 15

setBlocks

x0, y0, z0, x1, y1, z1, id, [state]

 

Sets blocks between two sets of coordinates; optional argument state is between 0 and 15

getHeight

x,z

int

Returns the highest block at a point

getPlayerEntityIds

 

[int]

Returns the IDs of all players connected to the game

saveCheckpoint

 

 

Saves the current state of the game

restoreCheckpoint

 

 

Restores the game to the latest saved state

postToChat

message: str

 

Posts a message to the chat

setting

key, stat: bol

 

Changes the settings of the world; key values: world_immutable, nametags_visible

Player Class: mc.player.[method]

getPos

x, y, z

vec3: obj

Returns the player's position as an object with floats

setPos

x, y, z

 

Sets the player's position using floats

getTilePos

x, y, z

vec3: obj

Returns the player's position as an object with integers

setTilePos

x, y, z

 

Sets the player's position using integers

setting

key, stat: bol

 

Changes the player's settings; key value: autojump

Events Class: mc.events.[method]

clearAll

 

 

Clears all events from buffer

pollBlockHits

 

[vec3: obj]

Returns an array of block hits; block hits created with sword right-click

Camera Class: mc.camera.[method]

setNormal

[entityID]

 

Sets the camera to normal for a list of player entities

setFixed

 

 

Sets the camera to fixed

setFollow

[entityId]

 

Sets the camera to follow for a list of player entities

setPos

x, y, z

 

Sets the camera position to coordinates

Entity Class: mc.entity.[method]

getPos

id: int

vec3: obj

Gets the position of the entity as floats

setPos

entityId:int, x, y, z

 

Sets the position of the entity

getTilePos

entityId: int

vec3: obj

Returns the position of an entity as a vector with integers

setTilePos

entityId:int, x, y, z

 

Sets the position of an entity with integers

setting

entityId: int, key, stat: bol

 

Changes the entity's settings; key value: autojump

An unexpected effect of the code as described is that the diamond is not only underground but can also be hidden under a tree. Because this adds a little more challenge to the game, I decided to leave it as is.

Minesweep

Before entering the main loop of the game, you first measure the distance from the point at which the player starts to the diamond stash (line 15). Note that the distance to the treasure is as the crow flies. Vertical distance is not taken into account. The coordinates of the treasure are stored in tx and ty, and you can determine player position by using the player.getTilePos() Minecraft method. This method returns a vector with three attributes: x, y and z. So, you can find out the x component of your player's coordinates by calling:

mc.player.getTilePos().x

Just change the trailing x, for y or z to get the corresponding components of the player's coordinates. This, by the way, is called dot notation.

You will have learned from geometry that the way to calculate a distance between two points (your player and the diamond) on a grid is by using the Pythagorean theorem (Figure 2). The difference between mc.player.getTilePos().x and tx is the length of one of the legs of a right triangle and the difference between mc.player.getTilePos().z and tz is the length of the other leg. The hypotenuse of your imaginary triangle is the distance between the two points: In Python, that calculation looks like line 15.

Figure 2: Using the Pythagorean theorem, you can calculate the distance from the player to the diamond.

The aim of the game is to locate and destroy the diamond, so now you create a loop that uses the Minecraft method getBlock() to check the content of the diamond's location (line 17). As soon as the location contains air (i.e., 0, which is the numeric value for a block of type AIR [5]), the diamond has been destroyed and the loop will exit. Meanwhile, you must check the player position every 10 seconds to see if it is any closer to or farther from the treasure (lines 21-24).

If the distance is 0 (i.e., the player has arrived at the correct location), the program uses the postToChat() Minecraft method to show a Dig! message in the chat window. If the distance has decreased since the last time you checked, you post Warmer! (Figure 3); if it has increased (i.e., the player has moved farther away from the goal), you'll post Colder!. If the distance hasn't changed, you can assume the player hasn't moved and you post the incentive Move!.

Figure 3: Messages in the chat window guide the player toward the treasure.

The new distance becomes the old distance (line 26), then the program waits for 10 seconds (line 28) for the player to move, and the cycle starts again.

As soon as the player locates (Figure 4) and destroys the diamond, the loop exits, and the program congratulates the player (Figure 5) and ends.

Figure 4: You found the treasure. Now smash it to bits!
Figure 5: The program congratulates you on your successful quest.

Buy this article as PDF

Express-Checkout as PDF

Pages: 6

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Using the Raspberry Pi as a Minecraft server

    Minecraft has millions of devoted fans worldwide, and players who organize a communal game with friends and acquaintances achieve an entirely new gaming experience. The Raspberry Pi is an excellent replacement for the Minecraft server.

  • Don't Use a Hammer

    When you first start building, you probably learn how to use one device and one programming language. Then comes the day you design a project that your toolset either can't solve or forces you to jump through too many hoops to get the outcome you desire. That's the day you start looking at new devices and languages to solve your problem. Having an arsenal of tools at your disposal makes solving problems easier.

  • Synchronizing with broadcasts

    This article draws inspiration from the popular Pokémon Go app to recreate a sprite hunting game in Scratch. The project explores synchronization and randomness as the player explores various backdrops in search of sprites.

  • Exploring the Kano Kit Pi pack and learning environment

    The Kano Kit learning platform puts the Pi in easy reach for even the youngest users.

  • Event Report: Pi and More 3

    From all over Germany, Raspberry Pi fans went to Trier in mid-June for "Pi and More 3." For a whole day, visitors of all ages enjoyed lectures and participated in hands-on workshops.