Minecraft Skeleton

Minecraft Skeleton figure.

Minecraft Skeleton drawn using the Symbol program written in Python.

Experimenting with the symbol drawing routine can give interesting results. I’m not a great artist, so hopefully this will give some inspiration. I found it easiest to put each of the lines in the list one after the other and then fill in with # symbols. They then need joining together again to create a proper Python list.

While I remember, it also seems easier to create the programs using nano running over SSH from another computer to save having to minimise Minecraft and switch over to IDLE. Just a thought.

 

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")

line = "  #####  "," ####### ","#########","#  ###  #","#########","#### ####","#########"," # # # # "," #######","  #####  ","   ###   ","#########","#   #   #","# ##### #","#   #   #","# ##### #","#   #   #","# ##### #","# #   # #","  #   #  ","  #   #  ","  #   #  "," ##   ## ","###   ###"

print line

startx,starty,startz = mc.player.getPos() #get the player's position

starty=starty+24 #lift the starty so that it's not written under your feet!

for row in line: # one row at a time from list_line (the result from figlet)
    starty=starty-1 # work down from the top
    column=0
    for letter in row: # work along each row - check each character. If it's a "#" then print a block else leave it as air
        column = column+1
        if letter =="#":
            mc.setBlock(startx-column,starty,startz,1)
        else:
            mc.setBlock(startx-column,starty,startz,0)

Advertisements

Minecraft aircraft

 

Minecraft passenger plane.

Passenger plane generated by a Python Program

I was set the challenge of creating a Python program that automatically creates an aircraft at the player’s position. I used the symbol generating routine as a starting position for the fuselage and then added a few loops to create the wings and tail fin. I’d like to play with the textures and various block ids to see what can be achieved, but at the moment I feel that they’d make an interesting addition to many Minecraft scenes.

#Airplane program... IPRoulson 2015
from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")

fuselage_mtl = 42
wing_mtl = 57
fin_mtl = 57
tailfin_mtl = 49
seat_mtl=41

startx,starty,startz = mc.player.getPos() #get the player's position

#start in the same place each time:
#startx=0
#starty=2
#startz=0

#create fuselage from pattern
line = "  ###  "," #   # ","#     #","#     #","#     #"," ##### ","  ###  "

for fuselage in range(1,45):
    yplot=starty+10 #lift the starty so that it's not written under your feet!  
    
    for row in line: # one row at a time from list line
        yplot=yplot-1 # work down from the top
        column=0
        for letter in row: # work along each row - check each character. If it's a "#" then print a block else leave it as air
            column = column+1
            if letter =="#":
                mc.setBlock(startx-column,yplot,startz+fuselage,fuselage_mtl)
            else:
                mc.setBlock(startx-column,yplot,startz+fuselage,0)

#create nose cone
xoffset=4

#MAIN SOLID
mc.setBlocks(startx-(xoffset+2),(starty+5),(startz),(startx-xoffset)+2,starty+6,(startz-6),fuselage_mtl)
mc.setBlocks(startx-(xoffset+1),(starty+5),(startz-6),(startx-xoffset)+1,starty+6,(startz-7),fuselage_mtl)

#clear cockpit area
mc.setBlocks(startx-(xoffset+1),(starty+5),(startz),(startx-xoffset)+1,starty+6,(startz-4),0)

#floor cockpit
mc.setBlocks(startx-(xoffset+1),(starty+4),(startz),(startx-xoffset)+1,starty+4,(startz-4),fuselage_mtl)

#MAIN WINDOW BLOCK
mc.setBlocks(startx-(xoffset+1),(starty+7),(startz),(startx-xoffset)+1,starty+8,(startz-4),20)
#FRONT TAPER OF WINDOW
mc.setBlocks(startx-(xoffset+1),(starty+7),(startz-5),(startx-xoffset)+1,starty+7,(startz-5),20)    
#clear cockpit glass
mc.setBlocks(startx-xoffset,starty+7,startz,startx-xoffset,starty+7,startz-4,0)

#punch out windows
for window in range(5,42,3):
    xoffset=4
    mc.setBlock(startx-(xoffset+3),starty+6,startz+window,20)
    mc.setBlock((startx-xoffset)+3,starty+6,startz+window,20)

#fit the seats
for window in range(6,45,3):
    xoffset=4
    mc.setBlock(startx-(xoffset+2),starty+5,startz+window,seat_mtl)
    mc.setBlock((startx-xoffset)+2,starty+5,startz+window,seat_mtl)
    mc.setBlock(startx-(xoffset+1),starty+5,startz+window,seat_mtl)
    mc.setBlock((startx-xoffset)+1,starty+5,startz+window,seat_mtl)

#draw wing
for wing in range(1, 15):
    xoffset=4
    zoffset=11
    length=13
    mc.setBlocks(startx-(xoffset+wing+length),starty+3,startz+zoffset+wing,(startx-xoffset)+wing+length,starty+3,startz+zoffset+wing,wing_mtl)

#draw tailplane
for fin in range(1, 10):
    xoffset=4
    zoffset=35
    length=2
    mc.setBlocks(startx-(xoffset+fin+length),starty+9,startz+zoffset+fin,(startx-xoffset)+fin+length,starty+9,startz+zoffset+fin,fin_mtl)

#draw tailfin
for fin in range(2,10):
    xoffset=4
    zoffset=44
    mc.setBlocks(startx-xoffset,starty+19-fin,startz+zoffset,(startx-xoffset),starty+19-fin,startz+zoffset-fin,tailfin_mtl)
fighter

Eurofighter Typhoon generated by a Python program

 

The second image is loosely based on the Eurofighter Typhoon. There are no air intakes and the engines are not set to afterburner – perhaps someone would like to try adding these.

One addition I’m considering is to use the half-steps to create smoother edges. I am sure it’s possible and it would really improve the look of many of these objects. Maybe sometime later…

#Eurofighter Typhoon program... IPRoulson 2015
from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")


#block ids used? 42 - iron block, 49 - obsidian, 41 - gold block
fuselage_mtl = 42
wing_mtl = 42
fin_mtl = 42
tailfin_mtl = 42
seat_mtl=41

mc.setBlocks(-30,0,-30,40,30,45,0)

startx,starty,startz = mc.player.getPos() #get the player's position

#start in the same place each time:
#startx=0
#starty=2
#startz=0

#create fuselage from pattern
line = "   #   "," ##### ","#     #","#     #"," ##### ","  ###  "

for fuselage in range(1,25):
    yplot=starty+10 #lift the starty so that it's not written under your feet!  
    
    for row in line: # one row at a time from list line
        yplot=yplot-1 # work down from the top
        column=0
        for letter in row: # work along each row - check each character. If it's a "#" then print a block else leave it as air
            column = column+1
            if letter =="#":
                mc.setBlock(startx-column,yplot,startz+fuselage,fuselage_mtl)
            else:
                mc.setBlock(startx-column,yplot,startz+fuselage,0)
#create engine                
xoffset=4

mc.setBlocks(startx-(xoffset+3),(starty+5),(startz+23),(startx-xoffset)-1,starty+7,(startz+24),49)
mc.setBlocks(startx-(xoffset-1),(starty+5),(startz+23),(startx-xoffset)+3,starty+7,(startz+24),49)
mc.setBlock(startx-(xoffset+2),starty+6,startz+24,35,14)
mc.setBlock(startx-(xoffset-2),starty+6,startz+24,35,14)
#create nose cone
xoffset=4

#MAIN SOLID
mc.setBlocks(startx-(xoffset+2),(starty+5),(startz),(startx-xoffset)+2,starty+6,(startz-6),fuselage_mtl)
mc.setBlocks(startx-(xoffset+1),(starty+5),(startz-6),(startx-xoffset)+1,starty+6,(startz-7),fuselage_mtl)
mc.setBlock(startx-xoffset,starty+6,startz-8,fuselage_mtl)

#draw canard
for fin in range(1, 4):
    xoffset=4
    zoffset=-3
    length=5
    mc.setBlocks(startx-(xoffset+fin+length),starty+6,startz+zoffset+fin,(startx-xoffset)+fin+length,starty+6,startz+zoffset+fin,fin_mtl)

#clear cockpit area
mc.setBlocks(startx-(xoffset+1),(starty+5),(startz),(startx-xoffset)+1,starty+6,(startz-4),0)

#floor cockpit
mc.setBlocks(startx-(xoffset+1),(starty+4),(startz),(startx-xoffset)+1,starty+4,(startz-4),fuselage_mtl)

#MAIN WINDOW BLOCK
mc.setBlocks(startx-(xoffset+1),(starty+7),(startz),(startx-xoffset)+1,starty+8,(startz-4),20)
#FRONT TAPER OF WINDOW
mc.setBlocks(startx-(xoffset+1),(starty+7),(startz-5),(startx-xoffset)+1,starty+7,(startz-5),20)    
#clear cockpit glass
mc.setBlocks(startx-xoffset,starty+7,startz,startx-xoffset,starty+7,startz-4,0)

#draw wing
for wing in range(1, 18):
    xoffset=4
    zoffset=7
    length=3
    mc.setBlocks(startx-(xoffset+wing+length),starty+4,startz+zoffset+wing,(startx-xoffset)+wing+length,starty+4,startz+zoffset+wing,wing_mtl)
#draw wingtips
xoffset=4
zoffset=17
length=6
mc.setBlocks(startx-(xoffset+20),starty+4,startz+zoffset,startx-(xoffset+20),starty+4,startz+zoffset+length,wing_mtl)
mc.setBlocks((startx-xoffset)+20,starty+4,startz+zoffset,(startx-xoffset)+20,starty+4,startz+zoffset+length,wing_mtl)

#draw tailfin
for fin in range(2,10):
    xoffset=4
    zoffset=24
    mc.setBlocks(startx-xoffset,starty+15-fin,startz+zoffset,(startx-xoffset),starty+15-fin,startz+zoffset-fin,tailfin_mtl)

Minecraft – Python experiments

Here’s a few little Python files that illustrate control of Minecraft. It starts with connecting to the Minecraft API and writing to the screen and then develops it using loops to create towers, stairs, stacks of TNT and beyond. Note that most of the blocks will be drawn at coordinates (0,0,0) so you’ll have to navigate around to find them. Occasionally Minecraft draws a mountain in the way, so the drawing might be underground.

Sending text to the screen:

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")

Creating a stack of ten blocks:

This little code snippet uses a loop to count from 0 to 9. (It’s a feature of Python that the loop starts at zero and finishes one before the last number asked for). The setblock function then places a block at each of the Y locations from 0 up to 9.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")
for stack in range(10):
    mc.setBlock(0,stack,0,1)

Creating a stack of one hundred blocks:
Here the range of values being created is much larger. This extends a long way up into the sky.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")
for stack in range(100):
    mc.setBlock(0,stack,0,1)

Creating a huge stack of TNT ready to explode:
This version of the previous program uses setBlock but with the TNT block type (46). This is then followed with a 1 to ensure that the TNT can be triggered.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")
tnt=46
for stack in range(100):
    mc.setBlock(0,stack,0,tnt,1)

Creating a staircase which extends into the sky:
This snippet moves the blocks along the X and Y axis at the same time to ensure that the blocks move up and forward at the same time. This creates a staircase effect.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")
tnt=46
for stack in range(100):
    mc.setBlock(stack,stack,0,1)

Creating a wide staircase:
This modification of the staircase duplicates the stacking, making sure that the blocks are placed at Z=0, Z=1, Z=2 and Z=3. The staircase is much wider and more interesting.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")
tnt=46
for stack in range(100):
    mc.setBlock(stack,stack,0,1)
    mc.setBlock(stack,stack,1,1)
    mc.setBlock(stack,stack,2,1)
    mc.setBlock(stack,stack,3,1)

Using a nested loop to create a row of stacks:
Python allows one loop inside another. This means that a stack can then be placed multiple times. The output of this looks like a row of fence posts, although it could equally be a set of bridge supports over a wide gap.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
#mc.postToChat("Python is now in control!")
for row in range(0,50,5):
    for stack in range(10):
        print("Row ",row," : stack ",stack)
        mc.setBlock(row,stack,0,1)

Creating a grid of stacks:
This is another nested loop which creates a grid of stacked cubes. This might be ideal for the columns supporting the roof of a temple.

from mcpi import minecraft
mc = minecraft.Minecraft.create()
#mc.postToChat("Python is now in control!")
for columns in range(0,50,5):
    for row in range(0,50,5):
        for stack in range(10):
        print("Row ",row," : stack ",stack)
        mc.setBlock(row,stack,columns,1)

Raspberry Pi Arcade Machine

Overall view of the Arcade Machine.

Overall view of the Arcade Machine.

Something I’ve been wanting to do for a while… and something that seemed to interest the students – A Raspberry Pi Arcade Machine!

It’s pretty straightforward but the end result could prove to be rather good. We needed the following:

  • Case – some Melamine-faced chipboard left over from a lab refit
  • Push-to-make switches – the more the merrier
  • Some switch bezels – cut on the CNC router
  • An audio amplifier (built from a kit) with two 8Ω loudspeakers
  • Speaker bezels – converted from the Raspberry Pi logo and cut on the router
  • Raspberry Pi, second-hand LCD monitor, HDMI-VGA adapter.
  • Software: Stella Atari Emulator, Scratch, Python and PyGame.
  • Python and uinput to handle switches and turn them into keypresses.

Continue reading

i2c LCD and Digital Temperature Sensor

DS18B20 temperature sensor on breadboard

DS18B20 digital temperature sensor – only three wires and a resistor needed!

These DS18B20 devices are pretty nifty. I remember all of the hassle connecting an LM35 to a computer, sorting out the changes in current into something a BBC analogue port can handle, calibrating and scaling. And now… One little device, a 4k7 resistor and a few lines of code.

Here I’ve combined the sensor and the i2c display together to give me the Pi temperature and the room temperature. It’s been quite mild this autumn even without the central heating on!

There are a number of tutorials on the internet (such as this one)showing how these devices are used. I’m more familiar with using them with a PICAXE but they’re just as simple with the Raspberry Pi. It’s important to note that each of the sensors has their own address, so make sure you check carefully.

The code is straightforward:

import os
import commands
import time
import pylcdlib
import datetime

lcd = pylcdlib.lcd(0x27,0)
lcd.lcd_write(0x01);
lcd.lcd_puts("                 ",1) #display on line 1
lcd.lcd_puts("                 ",2) #display on line 2


def get_cpu_temp():
	tempFile = open( "/sys/class/thermal/thermal_zone0/temp" )
	cpu_temp = tempFile.read()
	tempFile.close()
	return float(cpu_temp)/1000

while True:
	tfile = open("/sys/bus/w1/devices/28-0000011628bf/w1_slave")
	text = tfile.read()
	tfile.close()
	secondline = text.split("\n")[1]
	temperaturedata = secondline.split(" ")[9]
	floattemperature = (float(secondline[29: ])/1000)
	lcd.lcd_puts("Temp: "+str(floattemperature),2) #display on line 2

	lcd.lcd_puts("CPU :"+str(get_cpu_temp())+"       ",1) #display on line 1
	time.sleep(1)

The LCD is really hard to photograph. I’ve tried a whole number of settings on the point’n’squirt camera at home, as well as my phone, but neither really shows up how well these LCDs show text.

Having used the LCDs with the PICAXE, I’m sure it’s possible to access the degrees symbol! Another challenge is using i2c with Python3. It seems that the libraries are unavailable, although trawling the ‘net has shown some leads that I’ll follow up.

Display showing the temperature.

LCD showing processor temperature and the temperature returned by the DS18B20.

Where next? My earliest experiments involved using the sensor with a PICAXE, which then sent the data to the Raspberry Pi as a serial data stream. These results were then uploaded to COSM (now known as Xively, having had a brief spell as Pachube). It was interesting to watch COSM plot the graphs over a period of time. It wouldn’t take much imagination to see how this could easily become an environmental monitoring and control platform – and many have succeeded!

Raspberry Pi with a Glockenspiel

Raspberry Pi and Glockenspiel

This glockenspiel has been converted to play automatically.

I found a glockenspiel in the local recycling centre and decided to have a go at automating it after seeing details on the Raspberry Pi forum and also on the PICAXE website.

It’s quite a straightforward design, using motors to rotate the hammers downwards and then using a rubber band to lift the hammer upwards one the chime has been struck.

Programming this in Python is relatively straightforward – just allocate most of the GPIO outputs to controlling the motors and then trigger them sequentially. The motors are connected to the GPIO outputs using a pair of ULN2803 darlington driver IC’s. It’s quick but as we’ll see, not the best solution.

I haven’t yet found out how to make the software do a clean exit when CTRL-C is pressed – something to do with creating an exception and then using this to shut down the GPIO outputs. Without this, it’s possible to exit while the motors are energised meaning that the peak stall current is passed through the darlington drivers. I’ve had to replace a couple already.

When I design a PCB for this, I think I’ll use a bunch of discrete darlington transistors (BCX38C) along with a current limiting device.

Overall, the sound is pleasant to listen to. I’d like to refine the software and also include the possibility of using RTTTL ringtones. I’ll probably need to filter out sharps/flats and add some kind of a transpose function. Probably a challenge for later!