Automatically Generated ScriptCraft to Draw An Image

image_process

Having done tagger.js, I thought “wouldn’t it be nice not to have to specify the design by hand?”

I started thinking about how cool it would be to have a way to take an image file and use that to define the design that tagger.js was going to spray.

The first thing that I determined was that, as far as I can see, there isn’t any built-in support for the various image formats (GIF, JPEG, PNG, etc.) in ScriptCraft. OK, so what then? Well, web browsers are great at handling images in all kinds of different formats. The HTML5 canvas element is good for playing around with bitmaps and on top of all that, JavaScript is supported for the coding part!

So, with very little previous experience and plenty of Googling, I decided to make a web page which would allow the user to enter a file’s name, press a few buttons and a ScriptCraft script would appear, as if by magic. Development was pretty smooth, baring one significant road-bump which I’ll describe. I’m not going to go into details about how the HTML file was made, but it should be clear enough if you want to read it. I will however describe the process of colour mapping.

HTML5 and a Tale of Tainted Canvases

Say what? An odd problem I quickly hit was that I couldn’t just specify an image file from just anywhere (using HTTP:). In fact, even worse, when I directly loaded my HTML page in my browser (using FILE:), I couldn’t even load up an image file which was in the same directory as the HTML page.

More Googling followed. Turns out that the browser was trying to protect me from “cross-origin data”, which is a security risk. Luckily there was an easy solution. I downloaded a small web server application and used that to serve my HTML page, which eliminated the issue. The web-server I chose was Mongoose, because it’s a single application, light and fast, but you can use another web-server if you prefer.

Testing in Chrome

I used Google Chrome as my browser for developing and testing this webpage. Chrome has a JavaScript console, which greatly simplifies debugging scripts. It can be found from the menu to the right of the address bar, at More Tools > JavaScript Console. Among other features, It allows you to set breakpoints and watch the value of variables as the script executes. It will also show you errors in your code, where it finds them.

Colour Mapping

The most important part of this script is mapping the colour of each pixel in the original image to an equivalent block in MineCraft. For this example, I have restricted myself to the 16 wool colours. So, for every pixel in the original image, I have to choose the MineCraft wool block that’s the closest in colour.

MineCraft Wool Palette

MineCraft Wool Palette

The colours we are going to match against are above. If you’re curious, here’s how I generated this MineCraft palette, I laid all 16 MineCraft wool blocks in order, from white to black, and then took a screenshot. This screenshot was, of course, influenced by the lighting in MineCraft at the time I took the screenshot and each block had the wool texture applied to (i.e. they weren’t just one flat colour). I did some further image manipulation to improve the palette. I applied a strong blur effect to downplay the effect of the texture and then I used my image editors Histogram Stretch functionality to make sure that the whitest and blackest colours were pushed towards true white and true black. Finally I sampled one point on each block and that became my representative colour.

These colours, in RGB format, became an array in the JavaScript inside my webpage:

var paletteRGB = [[255, 255, 255], 
                  [222, 146, 79],
                  [177, 98, 186],
                  [115, 152, 197],
                  [178, 185, 60],
                  [76, 179, 67],
                  [213, 151, 159],
                  [51, 51, 51],
                  [164, 180, 170],
                  [44, 109, 122],
                  [116, 68, 167],
                  [30, 50, 113],
                  [59, 43, 14],
                  [35, 62, 15],
                  [132, 53, 40],
                  [0, 0, 0]];

RGB (Red/Green/Blue) is a common way to represent colour. Its three numerical values, each of which can range between 0 and 255, represent the relative strengths of the Red, Green and Blue channels. We can think of this as a co-ordinate system, with the R, G and B values as axes.

RGB Colour Space Imagined as a Cube

Description: RGB Colour Space Imagined as a Cube. Author: SharkD. Source: http://commons.wikimedia.org/wiki/File:RGB_color_solid_cube.png

The image above shows what this looks like. Pure white is on the corner nearest to us. The opposite corner, which we can’t see, is pure black. Colours aren’t just on the surface of this cube either, If we were to cut through it at any plane, we would see all the colours on the inside as well.

Therefore, the difference between two colours can be thought of as the distance between two points in RGB space. It’s Pythagoras’ Theorem again, as we saw in the rainbowk.js project, but in 3D. All we have to do is take the colour of each pixel in the input image, calculate how far is is from each MineCraft wool colour and pick the wool colour which is the closest in distance; that will be the most similar.

Easy right? Well, almost. Turns out, our eyes don’t quite work that way. We’re not as sensitive to changes in some colours as we are in others. We’re most sensitive to changes in shades of blue, and least sensitive to changes in shades of green. If asked to pick by eye, we might make a different choice for the “closest” colour than then one given by mathematics alone. Luckily, scientists have worked out factors which account for this. If you look in the final script you’ll see that there are factors which are used to weight (make more important) the difference in some colours than others. You don’t need to understand how these numbers were arrived at, just understand why they are there.

// It's Pythagoras' theorem again, but weighted.
function weightedDistanceSquaredRgb(r0, g0, b0, r1, g1, b1)
{
  // These weights are used to convert RGB -> YUV and are useful here
  // to enhance the perceived closeness of two colours
  var weightR = 0.299;
  var weightG = 0.587;
  var weightB = 0.114;
  
  // Distance between two points in space: sqrt(x^2 + y^2 + z^2)
  return distanceSquared(r0 * weightR, g0 * weightG, b0 * weightB,
                         r1 * weightR, g1 * weightG, b1 * weightB);
}

By the way, notice that we’re returning the distance squared here. It’s a common programming shortcut if we’re just checking for the nearest thing. If something has the closest distance, it will also have the smallest distance squared. Doing the square root calculation isn’t worth it – so we don’t.

Downloading and Running

The ZIP file containing this HTML file (image_process.html) and a few sample images can be downloaded from here. Remember, you’ll have to use a web-server to view this webpage and have it be able to process the images. Feel free to try your own images, just copy them into the same directory as the HTML file first, and remember to keep them small as every pixel becomes a MineCraft block. My sample images are all around 40px wide.

What’s Next?

Next week we’ll extend this little application to add optional transparency to the output and merge it with tagger.js so our image is sprayed onto the environment.

PiDojo : Connecting to the Raspberry Pi from your laptop

As it would be awkward to bring televisions and keyboards and all the other equipment required to operate the Raspberry Pi into CoderDojo we will connect to them from our laptops. We had a go at this today and we made some progress but we had problems with a couple of computers hopefully, I may have found a fix for them.

We were able to connect most of the laptops using Internet Connection Sharing but on the ones we couldn’t connect to, I think creating a Network Bridge might work. Instructions are available here. Here are my slides from today Raspberry Pi Headless Operation.pptx

Scriptcraft – A Little Friendly Vandalism

For this week’s sample script, building on the ideas developed the week before, I decided to pander to the crowd a little and show a script called tagger.js which allows you to ‘spray’ a design, in a block type of your choice onto the environment. It can be downloaded from here.

Description: Graffiti near Moganshan Road in Shanghai. Photographer: Jakub Hałun. Artist: Unknown. Source: Wikimedia Commons

Defining Our Design

The script contains an array of strings used to defined our design. In the array each string represents a row. Each character in those strings represents a block. Spaces are treated as blanks, anything else is a part of our design. Take a look at this specification which represents a peace sign:

var tag = ["   ***   ",
           " ** * ** ",
           " *  *  * ",
           "*   *   *",
           "*  ***  *",
           "* * * * *",
           " *  *  * ",
           " ** * ** ",
           "   ***   "];

It may be a little hard to make out at first, because characters are much narrower than lines are tall and the whole thing is stretched. Comparing to this drawing should help:

Peace Sign

Peace sign design for tagger.js

I’ve used asterisks in my strings just because it fills the space, but any non-space character will work just as well.

Spraying Onto What’s Already There

The fun thing about tagger.js is that it places the design on whatever is already in the world. It’s not restricted to flat surfaces!

The script looks at the area the player is facing and moves forwards, within a sensible limit, until it encounters a solid block (not air). If it finds one, it changes the block to the requested type. These diagrams show the operation.

Tagger_before

Tagger_after

If no block is found within the search depth, as has happened several times in the diagram above, that part of the design is left out.

In Action

Below is a screenshot of tagger in action: a big stone sphere with a love heart, made of red wool, and a partial smiley, made of gold blocks, sprayed onto it (partial because I was too far away when I called the script and some blocks were beyond the default depth).

tagger

Not Only … But Also

The script also has a few other little interesting features. In common with many of the standard Scriptcraft functions, this one shows how to check for parameters being left out and how to provide default values when that happens. It also shows how to retrieve a part of an existing string, used here to get a single character at a time. Take a look at the script yourself to see how this happens.

Week 5 – 2015 – Scratch Beginners

Hello everyone.

Good to see everyone there on Saturday. We made a game called Wipeout similar to on old game called Breakout.

wipeout

We used a number of important coding concepts again this week, loops and decisions, Variables, broadcasting, etc.

concepts

Yesterday during class, we didn’t have time to add the Lives and the Scores but I am hoping everyone will try it themselves at home. We have done it many times now and I am sure you are well able to do it. Try it first on your own but I have put my game up on the scratch website so you can take a look at it if you get stuck. Here is a link Wipeout Game

No Coderdojo Athenry for the next two weeks but I hope to see you all back on the 7th of March.

Enjoy the break

Martha

PiDojo -week 1 : Getting started with the Raspberry Pi

Today we had our first PiDojo session. We had a short demo where we looked at what is possible with the Raspberry Pi.

We then had a search for projects where we saw loads of interesting ideas. We also set up one of our five new RPis.

We will continue working with the Raspberry Pi after the break so anybody who is interested can come along. All you need to bring is your laptop and an idea for a Raspberry Pi project.

Here are my slides from today Raspberry Pi presentation

Scriptcraft – Discovering the World

Introduction

Thus far, we have used Scriptcraft to build cool structures in our Minecraft worlds, but the interaction has been a little one-sided. We’ve placed objects into the world, but we’ve never stopped to ask: “What’s already there?”.

papapishu-Boys-running

That’s a powerful question to ask, because once we know what’s already in the world, our interaction with it becomes richer and opens up many new possibilities.

Objects in JavaScript

Objects in JavaScript have Properties and Methods. Properties are what they sound like; a value associated with object that we can get or set. Methods are actions, in the form of a function, that we can ask the object to perform.

If you thought of me as a Person object then you could imagine some of the Properties and Methods I might have. For Properties I might have things like NameAge, Height, Weight, etc. An example of a Method I might have could be SayHi() [notice the round brackets after the name marking this as a method]. That would make me say “Hi!”. A method might have arguments, so it could be SayHiTo(“Dave”) which would make me say “Hi Dave!”. A method could equally calculate a value. An example might be CalculateBMI() which would calculate my Body Mass Index (BMI) value based on my Height and Weight properties. On second thoughts… scratch that idea. SampleObject Exploring Existing Objects

How do we explore the objects in the ScriptCraft world? One way is to read the API documentation:

Another way is to look at the Scriptcraft code files themselves, especially drone.js.

Another handy, lazy, way to explore an object you already have a reference to in ScriptCraft is just to treat it like a string and pass it to self.sendMessage(). You’ll usually get a representation which shows some of the properties of the object and those properties’ values. It’s incomplete, but very quick and might show what you’re looking for.

Getting the Block Type

All of this was building to finding out, from Scriptcraft, what the block at a particular location is. Using a combination of the techniques listed above, I determined that I needed to call a method on the Bukkit World object called getBlockAt(). In Scriptcraft the server object has an array called worlds and the normal world is worlds[0]. For the curious; worlds[1] is the nether and worlds[2] is the end.

That’s everything we need to create a simple script to examine the block that we’re currently looking at. We can create a Drone, which is created at the block we are looking at by default, to get the location. Here is the main part of the code:

// Create a drone (will be placed at the block the player's looking at)
var d = new Drone();

// Gather information about the world, the drone's location
// and the block at the drone's location
var world = server.worlds[0];
var loc = d.getLocation();
var chunk = loc.chunk;
var block_info = world.getBlockAt(loc.x, loc.y, loc.z);

The remainder of the code is just printing this information to the console in a tidy way. We called it whats_that.js and it can be downloaded from here. The screenshot below shows it being run.

whats_that2

This will form the basis for some future projects.

Quick Final Note on Block Metadata

One final note and something that wasn’t discussed at our session last week: to fully define a block we need to know both its type and its metadata. Two wool blocks of different colours have the same type but different metadata values to distinguish them from one-and-other. Similarly steps use the metadata value to distinguish between the different possible orientations. You can use the whats_that() function to explore this.

Week 2 – 2015 Scratch Beginneers

Hi everyone,

This week we took a look at the open source graphics program called Paint.net

It’s a very useful piece of software for editing and working with photos and clip art. Over the next couple of weeks we will use it to clean up our photos of our 3D playdoh models or Lego figures.

PAINTNET

Here are the PDF version of the notes: CDA-S4-Challenge09-LearnAboutPainting.pdf

See you all next week

Python Games – Week 10: Ping Pong game

As we have covered most of the concepts required to make games using Pygame I won’t be doing any more slideshows instead we will spend all of our time writing games from now on. Today we started to make a very simple Ping Pong game and we will spend another session or two finishing it.

tennis

Anybody who has missed a few sessions is always welcome back, but now would be a great time to return as we will be explaining everything from the beginning again.