#www.stuffaboutcode.com #Raspberry Pi, Minecraft Snake # mcpipy.com retrieved from URL below, written by stuffaboutcode # http://www.stuffaboutcode.com/2013/03/raspberry-pi-minecraft-snake.html # License: # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import the minecraft.py module from the minecraft directory import mcpi.minecraft as minecraft #import minecraft block module import mcpi.block as block #import time, so delays can be used import time #import random module to create random number import random import server #snake class which controls the whole game class Snake: def __init__(self, mc, startVec3, playingBottomLeft, playingTopRight): self.mc = mc self.direction = "up" self.lenght = 5 self.tail = [] self.tail.insert(0, startVec3) self.playingBottomLeft = playingBottomLeft self.playingTopRight = playingTopRight self.createApple() self.score = 0 #draw's the whole snake def draw(self): for segment in self.tail: self.mc.setBlock(segment.x, segment.y, segment.z, block.DIAMOND_BLOCK) #add's one segment to the snake def addSegment(self, segment): self.mc.setBlock(segment.x, segment.y, segment.z, block.DIAMOND_BLOCK) self.tail.insert(0, segment) #do I need to clear the last segment if (len(self.tail) > self.lenght): lastSegment = self.tail[len(self.tail)-1] self.mc.setBlock(lastSegment.x, lastSegment.y, lastSegment.z, block.AIR) #pop the last segment off the tail self.tail.pop() #moves the snake, if it cant it returns false (i.e. game over) def move(self): newSegment = minecraft.Vec3(self.tail[0].x, self.tail[0].y, self.tail[0].z) if self.direction == "up": newSegment.y = newSegment.y + 1 elif self.direction == "down": newSegment.y = newSegment.y - 1 elif self.direction == "left": newSegment.x = newSegment.x - 1 elif self.direction == "right": newSegment.x = newSegment.x + 1 if (self.checkCollision(newSegment) == False): self.addSegment(newSegment) #have I eaten the apple? if (matchVec3(newSegment, self.apple) == True): #increase my lenght self.lenght = self.lenght + 2 #increase my score self.score = self.score + 10 #create a new apple self.createApple() return True else: #game over #flash snake head mc.setBlock(self.tail[0].x, self.tail[0].y, self.tail[0].z, block.AIR) time.sleep(0.3) mc.setBlock(self.tail[0].x, self.tail[0].y, self.tail[0].z, block.DIAMOND_BLOCK) time.sleep(0.3) mc.setBlock(self.tail[0].x, self.tail[0].y, self.tail[0].z, block.AIR) time.sleep(0.3) mc.setBlock(self.tail[0].x, self.tail[0].y, self.tail[0].z, block.DIAMOND_BLOCK) time.sleep(0.3) #show score mc.postToChat("Game over - score = " + str(self.score)) time.sleep(5) mc.postToChat("www.stuffaboutcode.com") return False #function to check if a new segment (or apple) can go there def checkCollision(self, newSegment): #am I going the boundary if ((newSegment.x == playingBottomLeft.x) or (newSegment.y == playingBottomLeft.y) or (newSegment.x == playingTopRight.x) or (newSegment.y == playingTopRight.y)): return True else: #or my own tail hitTail = False for segment in self.tail: if (matchVec3(segment, newSegment) == True): hitTail = True return hitTail #function to change the snake's direction def changeDirection(self, newDirection): #code to make sure user doesnt try and make the snake move back on itself if (newDirection == "up"): if (self.direction != "down"): self.direction = newDirection elif (newDirection == "down"): if (self.direction != "up"): self.direction = newDirection elif (newDirection == "left"): if (self.direction != "right"): self.direction = newDirection elif (newDirection == "right"): if (self.direction != "left"): self.direction = newDirection #create the apple at a random position on the board def createApple(self): badApple = True #loop until an apple is created which doesnt collide with the boundary or the snake while (badApple == True): x = random.randrange(playingBottomLeft.x, playingTopRight.x) y = random.randrange(playingBottomLeft.y, playingTopRight.y) z = playingBottomLeft.z newApple = minecraft.Vec3(x, y, z) badApple = self.checkCollision(newApple) self.apple = newApple self.mc.setBlock(self.apple.x, self.apple.y, self.apple.z, block.GLOWING_OBSIDIAN) #Compares vec3 objects, if they are the same returns true def matchVec3(vec1, vec2): if ((vec1.x == vec2.x) and (vec1.y == vec2.y) and (vec1.z == vec2.z)): return True else: return False #draws a vertical outline def drawVerticalOutline(mc, x0, y0, x1, y1, z, blockType, blockData=0): mc.setBlocks(x0, y0, z, x0, y1, z, blockType, blockData) mc.setBlocks(x0, y1, z, x1, y1, z, blockType, blockData) mc.setBlocks(x1, y1, z, x1, y0, z, blockType, blockData) mc.setBlocks(x1, y0, z, x0, y0, z, blockType, blockData) #main program if __name__ == "__main__": #constants screenBottomLeft = minecraft.Vec3(-10,4,15) screenTopRight = minecraft.Vec3(10,24,15) playingBottomLeft = minecraft.Vec3(-10, 4, 14) playingTopRight = minecraft.Vec3(10, 24, 14) snakeStart = minecraft.Vec3(0, 5, 14) upControl = minecraft.Vec3(0, -1, 1) downControl = minecraft.Vec3(0, -1, -1) leftControl = minecraft.Vec3(-1, -1, 0) rightControl = minecraft.Vec3(1, -1, 0) middleControl = minecraft.Vec3(0, 0, 0) #Connect to minecraft by creating the minecraft object # - minecraft needs to be running and in a game mc = minecraft.Minecraft.create(server.address) #Post a message to the minecraft chat window mc.postToChat("Hi, Minecraft Snake, www.stuffaboutcode.com") #Build game board # clear a suitably large area mc.setBlocks(-10, 0, -5, 10, 25, 16, block.AIR) # create playing board mc.setBlocks(screenBottomLeft.x, screenBottomLeft.y, screenBottomLeft.z, screenTopRight.x, screenTopRight.y, screenTopRight.z, block.STONE) drawVerticalOutline(mc, playingBottomLeft.x, playingBottomLeft.y, playingTopRight.x, playingTopRight.y, playingTopRight.z, block.OBSIDIAN) # create control buttons mc.setBlock(upControl.x, upControl.y, upControl.z, block.DIAMOND_BLOCK) mc.setBlock(downControl.x, downControl.y, downControl.z, block.DIAMOND_BLOCK) mc.setBlock(leftControl.x, leftControl.y, leftControl.z, block.DIAMOND_BLOCK) mc.setBlock(rightControl.x, rightControl.y, rightControl.z, block.DIAMOND_BLOCK) # blocks around control buttons, to stop player moving off buttons mc.setBlock(middleControl.x + 2,middleControl.y + 1,middleControl.z, block.GLASS) mc.setBlock(middleControl.x - 2,middleControl.y + 1,middleControl.z, block.GLASS) mc.setBlock(middleControl.x,middleControl.y + 1,middleControl.z + 2, block.GLASS) mc.setBlock(middleControl.x,middleControl.y + 1,middleControl.z - 2, block.GLASS) mc.setBlock(middleControl.x - 1,middleControl.y + 1,middleControl.z - 1, block.GLASS) mc.setBlock(middleControl.x - 1,middleControl.y + 1,middleControl.z + 1, block.GLASS) mc.setBlock(middleControl.x + 1,middleControl.y + 1,middleControl.z + 1, block.GLASS) mc.setBlock(middleControl.x + 1,middleControl.y + 1,middleControl.z - 1, block.GLASS) mc.setBlock(middleControl.x,middleControl.y - 1,middleControl.z, block.STONE) # put player in the middle of the control mc.player.setPos(middleControl.x + 0.5,middleControl.y,middleControl.z + 0,5) #time for minecraft to catchup time.sleep(3) mc.postToChat("Walk forward, backward, left, right to control the snake") time.sleep(3) #create snake snake = Snake(mc, snakeStart, playingBottomLeft, playingTopRight) snake.draw() playing = True try: #loop until game over while playing == True: #sleep otherwise the snake moves WAY too fast time.sleep(0.3) #get players position - are they on a control tile, if so change snake's direction playerTilePos = mc.player.getTilePos() playerTilePos.y = playerTilePos.y - 1 if matchVec3(playerTilePos, upControl) == True: snake.changeDirection("up") elif matchVec3(playerTilePos, downControl) == True: snake.changeDirection("down") elif matchVec3(playerTilePos, leftControl) == True: snake.changeDirection("left") elif matchVec3(playerTilePos, rightControl) == True: snake.changeDirection("right") #move the snake playing = snake.move() except KeyboardInterrupt: print "stopped"