-
Notifications
You must be signed in to change notification settings - Fork 3
Tutorials
Welcome to RedWire, a new game engine dedicated to remixing and mashing up games. RedWire gives you the power to take games apart and put them together again in different ways. RedWire is pretty different than other game engines you may have used, so we made this tutorial to take you through how to use it.
If you know some JavaScript that will help, but it's not absolutely necessary.
- Step 1: Load Redwire
- Step 2: Draw a circle
- Step 3: Follow the mouse
- Step 4: React to the mouse button
- Step 5: Images
- Step 6: Memory
- Step 7: Sequences
- Step 8: Splitting it up
- Step 9: Transform and roll out!
- Step 10: Circuits
- Step 11: Mashup with Drag and Drop
- Step 12: Sound
- Last step: Share!
First off, RedWire is tested on Google Chrome and Mozilla Firefox. It may work fine in other browsers, but for best results we recommend you use one of these two.
In another browser window, goto http://redwire.io. You'll see a list of games displayed there. Look for one called "Blank" by "micouz", and click the "remix" link. That will take you to a window where you can see the entire interface.
Since this game is completely blank, it's a bit hard to see what each panel represents. In the picture below, they are all labeled.
At this point, you need to login. Hit the "Login" button in the upper-right, and then click "Register". Type in a username, email, and password and press "OK".
Now the "Fork" button will become available. Press it and you will see that the top now says "Blank (version 1) by [username]".
While we're at it, let's make this game our by changing it's name. Click on the name "Blank" and type in something else, like "Super Circle Game", and click the checkbox.
Although we've made changes on our own computer, no one else can see them yet. Now go ahead and show the world your forked game by pressing the "Publish" button on the upper-right. You'll see that we're now on version 2.
So far, so good... now let's make the game actually do something.
In RedWire, every bit of functionality, every line of code, is contained within a chip. Like chips in electronics, each has pins that can take values in and send them out. One of these chips is called the IO buffer. The IO buffer lets the game interact with the outside world, including the player. For example, mouse movement, keyboard presses, graphics and sound all go through the IO buffer.
Let's do something very simple: draw a circle on the screen. In order to do this, we need to put in a chip that sends the circle to the canvas pin on the IO buffer. We'll use the "Draw Circle" chip to do exactly that.
You'll find the "Draw Circle" chip under the "Processors" tab in the Toolbox panel in the upper-left. Click it and drag it over to the board, where you can drop it on top of the "Main" chip. Once it's there, you can click the edit button .
This button will bring up a big dialog box where you can fill out what the chip does. You can start by giving it a name on the top, like "Draw a circle".
For the time being, we don't actually see anything on the screen. That's because we didn't yet tell the chip what layer to draw the circle on. Click on the drop down box in the middle near the bottom, next to "canvas", and pick "simple". A text box will appear to the right. Now enter io.canvas.fg
into the box.
Once you hit the Done button, you should see a blue circle drawn in the middle.
The window should like the picture below:
What if we don't want the circle to be blue? Well, just click the edit button next to the "Draw Circle" chip again, and enter a value like "red"
into the first big text box. Press Done again and the circle should have changed colors. In fact, pretty much all CSS colors should do.
We can also change the position of the circle by providing a position for the "position" pin. Positions in RedWire are provided as 2-element arrays, in the [x, y]
format. So we can give a position like [200, 100]
, which will draw the a circle that's centered 200 pixels to the right, and 100 pixels down.
Changing the size of the circle is even easier- just provide a number to the "radius" pin.
Finally, let's talk about layers. We set the "canvas" pin to a layer called "fg". If you look at the layers panel on the bottom right, you'll see that this game has two layers by default: "bg" and "fg". By clicking the plus button beneath these two, you can add more layers.
Next, let's make this interactive!
We can't get very far with a circle that doesn't move. In in order to do that, we can wire up our "Draw circle" chip to use current mouse position that's provided by the "mouse" pin on the IO buffer, like in the diagram below:
All we need to do it edit the chip, and change that static position to io.mouse.position
. In the end, your "Draw Circle" chip should look like this:
In order to see what this does, hit the blue "play" button in the upper left of the screen. As you move the mouse around the game screen, the circle should follow you.
You can keep the game playing as you edit the code, to change the color of the circle, for example. But an even more powerful approach is to record the game and then play it back again. To do this, stop the game and then hit the red "record" button that's right next to the play button. Now when you hit play again, RedWire is recording all the input that the player is giving. When you hit stop, the scroll bar will fill up with all the recorded frames.
You can go back and see what happened by pulling the scroll bar, or by using the buttons to the right of the scroll bar. There's even a play back button that plays it back for you.
What's powerful about the recording feature is that when you change the code, RedWire will recalculate the recorded frames, starting with the current one, based on the the recorded input. To try this out, first move the frame back to the beginning. Then change the color or the size of the circle being drawn. When you play back again, you will see that the new shape follows the same path that you took before. This feature saves you time when you need to see "what would have happened" with your new code.
Recording is great, but it does take RedWire longer to recalculate after each change. So press the orange "X" button to erase the recording when you're done.
Let's say we want to have the circle change color when we press it. We can do this easily be editing the chip and setting the color
to something like io.mouse.down && "green" || "red"
or io.mouse.down ? "green" : "red"
. This is JavaScript syntax for picking the color "green" when the mouse is down (the pin io.mouse.down
is true when the mouse is down, and false when it is up).
But what if we only want to draw the circle when the mouse button is pressed? This is a bit different. To return to the electronics metaphor, we want to either power up or power down our chip depending on what the user is doing. This is where switches come in.
A switch is another type of chip, with input and output pins like the others. But a switch can have "children", and control which of those children are turned on at each frame. It makes this decision based on its input. So in our case, we can use a switch that activates its children only when the mouse is down.
RedWire comes with a switch called "On Mouse Down". You can drag it over to your board, and then drag the "Draw Circle" chip under it, like in the following image:
Play the game, and now you should should only see the circle shown when you click.
But what if we want to do something more complicated, like drawing a circle when the mouse is down, but writing text when the mouse is up? To do that, we can use a switch that turns on one chip when the mouse is down, and another when the mouse is up.
The easiest way in RedWire is to use the "If" switch, that you'll find in the Switches tab of the toolbox. You can drag it over to the board just like you did for the first chip.
Click edit and give the switch a name, like "If the mouse is down". Here, the switch already has a pin, called "value". In the box on the right, provide it the value io.mouse.down
.
Now drag the "Draw Circle" chip and drop it on the "If" switch. This means that the "Draw Circle" will only be turned on when the mouse is down. You can then delete the previous "On Mouse Down" chip.
Like an "if-else" expression in many programming languages, you can give it a second child that is turned on when the value is false. To do so, drag a "Draw Text" chip from the toolbox onto the if switch.
Click edit, set the "canvas" pin to io.canvas.fg
, and change the text to "Click somewhere"
.
When you hit play, you should see the text except when you click, when it will change into a circle.
You can do a lot more with switches than what we show in this example. You can put more than 2 chips inside a switch, including other switches. Switches can also use their output pins as well as their input pins.
This circle is beautiful, of course. But let's use some professional artwork for a change...
Why not a background image? Grab the wallpapers from the awesome A MAZE game festival: day and night. Then you can drag them onto the assets panel.
Each asset has a name. By default the name is equal to the filename used to import it, but you can click on the name to change it. In this case, let's change the name to "amaze".
Drag a "Draw Image" processor onto the board to draw the picture. You can call it something like "Draw the background" and set the canvas pin to draw to "io.canvas.bg" (the default background layer).
You might want to edit the draw chip to scale the picture so that it fits nicely into the canvas (which is 960x540). You can do so by setting the "scale" pin to 1/2
or 0.5
.
If all goes well, the image will set behind the circle . That's because the "bg" layer is in back of the "fg" layer used for the circle. You can drag the layers around in the layer panel to change the order.
You can do a lot more stuff with the IO buffer, including handling the keyboard, changing the mouse cursor, displaying HTML and getting values back from forms, adding fonts, measuring time, and sending HTTP requests. For more information on the possibilities of IO, check out the IO Buffer Interface wiki page.
Let's put IO aside to talk about another kind of buffer: memory.
Let's say that we want to have a shape move on its own, instead of following the mouse. To do this, we need to remember what the current position of a shape is, and then modify this position at each frame. But by design, chips can't keep any state on their own. Instead, they use another kind of buffer, the memory buffer.
Like the IO buffer, the memory buffer has input and output pins. But instead of generating output like the IO buffer does, the memory buffer only outputs the values that are currently in memory. You can give it values at the start, and it will keep these until they are overwritten by other chips.
Here's an example: Let's imagine that we have a chip called "Move" that has two pins: speed and position. At each frame, it adds the speed to the position and outputs the new position. You could hook it up to memory, like in the diagram below. On the first frame, speed is 10 in memory, and the position is 50. Because of this, the chip will spit out 60 at the new position.
Because the chip is hooked up to the position pin in memory, 60 will be written in the position pin in memory. So at the next frame, the move chip will have 60 in the input pin, and so it will calculate 70.
In our game, we want to have our circle grow over time. To do this, we'll add another chip in parallel to our draw chip, that just increases the radius of the circle. The diagram would look something like this:
As you can see, the "Draw Circle" chip now takes the radius of the circle from memory instead of having it hard-coded in. Changing the radius is done on another chip that modifies the radius value in memory.
To get this to work, we'll create a pin in memory called "radius". First, make sure that you are on the first frame. The easiest way to do this is to press the orange X button to erase any recording. Next, click on the box below "memory" and click "Append".
Type in radius
in the text box on the left, and 100
in the text box on the right. This means that we want to create a memory pin called "radius" with an initial value of 100.
Now edit the "Draw circle" chip so that the radius is equal to memory.radius
. You can play around with changing the radius in memory, and see how it draws something different on the screen.
Once again, once you start modifying the memory, make sure that you do it on the first frame if you want it to be saved with the game!
Now we want to radius to change over time. We're going to use a new type of chip do do this, called an emitter. An emitter is a chip that doesn't do anything by itself, but let's manipulate memory and IO values as we'd like.
Drag an emitter chip from under the "Basic" tab on to the board. Click on its edit button. Call it "Increase the radius".
Emitters work by calculating a value and then sending that value to a pin. Press the plus button in the middle of the dialog box. In the big box in the middle is where we do the calculating. In our case, we want to put memory.radius + 1
. On the right, we say where we want to send that value. Since we want to overwrite the previous radius, we'll set the box on the right to memory.radius
:
When you hit play, you should see your circle growing over time.
Once the circle gets too big, though, you can't see much anymore. Stop the game and drop a new emitter that decreases the radius (memory.radius - 1
). If you try to run both at once RedWire will stop and show an error, something like:
FRAME 1:
ERROR: patchMemory Memory patches conflict: [{"path":"/radius","patches":[{"replace":"/radius","value":99,"path":["0"]},{"replace":"/radius","value":101,"path":["1"]}]}]
This means that two chips were both writing to memory at the same time, and their changes conflicted. You can get around this problem by hitting the "Mute" button on one of the two chips. This temporarily deactivates the chip, which is also useful when you want to better understand what part of your program is causing a problem.
But what if we wanted these chips to turn on and off by themselves?
Let's say we wanted to have the radius increase for a while, and then decrease when it gets to a certain size. You can probably guess that we will use a switch to do it, just like we used the "If" switch to draw text or a circle earlier.
The switch we'll use this time is called "Do One at a Time". At each frame, only one child will be active. When that child reports having finished, the switch will activate the next child on the following frame. It uses an input/output pin to know which child is active at the current frame.
We're going to setup the board like in the diagram below. You can see that the "Increase radius" chip is at the bottom left, controlled by a "Do While" switch.
At first, we will set the "active child" pin to 0 in memory, so that the first part of the sequence (increasing the radius) is active, and the second part is off.
A "Do While" chip will run its child as long as the condition provided to it is true. In this case, we set the condition to be size < 200
. Once the radius reaches this size, the "Do While" chip shuts off its child, and sends a DONE
signal to its parent to inform it that it has completed.
Now the second part of the sequence will run, decreasing the radius. This too is controlled by a "Do While" that checks for a minimum size. Once it is reached, it will also signal DONE, and the sequence will repeat.
Getting this working is just a matter of a few drag and drops. First, create the memory pin "activeChild" and set to 0 (make sure you are on the first frame when you manipulate the memory!). Next, drop in the "Do One at a Time" switch and wire it to both read and write to memory.activeChild
.
To do that, click on the drop-down box and change it from "custom" to "simple", and then type memory.activeChild
in the source or destination boxes. In simple mode, the chip will both read and write to the same destination.
Finally, setup the two "Do While" chips with the conditions memory.radius < 200
(for growing) and memory.radius > 10
(for shrinking). The result should look something like this:
Try it out, and you should see your circle increasing, then decreasing, and increasing again.
The principle applies to any kind of sequence you can think of. For example, first showing a title screen before playing the game, moving from one level to another, etc.
Now we know how to run one chip after another. But what about running the same chip multiple times in a frame?
Let's say we want to draw a bunch of these animated circles. Every time we click, we want another circle to appear at that place. From what we've seen so far, we know that we could write a chip that uses a JavaScript loop to draw a bunch of shapes. But there's a better way: Splitters.
Spitters are chips that have children, a bit like switches. But instead of picking which of their children are active on a frame, they run all of their children multiple times, one for each piece of data in a collection. This is like a for-each
loop in imperative programming languages, or a map
operation in functional ones.
First, let's record the clicks. Create a memory pin called clicks
and make sure that it is an array (once again, make sure you're on the first frame to do this).
Then, place an "If" switch that checks for the condition io.mouse.justDown
. The difference between "down" and "justDown" is that "justDown" is only true on the first frame with the mouse button down (there's also "justUp" to find when the player releases the button).
Underneath the "If", put an emitter that writes to memory.clicks
. Since we don't want to overwrite the previous values written in the array, you can use the function RW.appendToArray(array, value)
that returns a new array with the value added to it. In our case, the complete expression is thus RW.appendToArray(memory.clicks, io.mouse.position)
.
Now onto the splitter part. We want to set it up so that the splitter loops over all the clicks in the array memory.clicks
, and calls our "Draw Circle" emitter for each one. If you diagram it, it looks like this:
Now we'll examine the execution step by step. Imagine that there are 3 positions in the memory.clicks
array. The splitter will first run "Draw Circle" with the first position, and "Draw Circle" will generate a corresponding circle shape.
Then, the splitter will run "Draw Circle" with a second position, generating a second shape.
And finally the 3rd position and the 3rd shape.
We're already storing the click positions in memory, but now we need to setup the splitter. First, drag a splitter from the "Basic" tab of the toolbox over to the board. Edit it, and give it a name like "For each click position". Have it split the array memory.clicks
, and bind each click value to click
. Children of the splitter will have access to this binding.
Now, move "Draw Circle" under the splitter. Edit "Draw Circle" to use bindings.click
instead of io.mouse.position
.
Finally, you can remove the "If" switch that doesn't serve a purpose anymore, or reverse the condition so that it says "Click somewhere" only when the mouse is up (the condition would be something like !io.mouse.down
). The board will look like this:
By now, we've taken a tour of most of the RedWire functionality. Only two building blocks remain: transformers and circuits.
Transformers are basically just JavaScript functions, but they have a special role within RedWire. They must be "pure", meaning that they cannot modify their arguments. Instead they can only return new information. Transformers can call other transformers, but can't access IO or memory buffers directly. Instead, you can call them from chips like emitters and switches.
Generally, transformers are useful to avoid typing long blocks of code in an emitter, and to centralize code that you use multiple times.
Let's create our own transformer to see how it's done. Let's make a transformer that helps us draw stars!
In the toolbox, open the "Transformers" tab and hit the plus button at the bottom. Give the transformer the name "makeStarPoints" (because we'll be calling it from JavaScript, it's more practical to use names without spaces).
Transformers can take arguments just like functions in other languages. You can add an argument by pressing the plus button under "Arguments", and putting the name in the box. In our case, our transformer will take 3 arguments: nPoints
, innerRadius
, and outerRadius
.
Creating the star shape itself requires a bit of geometry, but we'll steal an algorithm from off the internet - thanks, Larry Spencer! Copy the following code into the big text box:
var points = [];
for (var ixVertex = 0; ixVertex <= 2 * nPoints; ++ixVertex) {
var angle = ixVertex * Math.PI / nPoints - Math.PI / 2;
var radius = ixVertex % 2 == 0 ? outerRadius : innerRadius;
points.push([radius * Math.cos(angle), radius * Math.sin(angle)]);
}
return points;
Notice that like classic JavaScript functions, the transformer can have local variables, and must return
a value at the end to do anything useful.
The result should look like:
To use it, drag a "Draw Path" processor onto the board, call it "Draw a star", and send the shape to following to io.canvas.fg
. Set the position to something like [300, 300]
, and set the "points" pin to transformers.makeStarPoints(5, 50, 100)
.
When you hit Done, you'll see your pretty star!
You may have noticed that the top accordion in the toolbox panel mentions "circuits". Circuits are a way to package up game behavior in a block that's more easily reusable. A circuit has its own memory, and its own access to IO. A circuit can be embedded into another circuit just like any other chip, and it can have its own pins to communicate with the containing circuit.
So far, our game only has the "main" circuit. Let's create a new one by pressing the plus button in the Circuits box.
Now give this circuit a name, "star". For the time being, we'll leave the pins alone.
Hit the "done" button and you should see the circuit in the list. Now press the button with the extending arrows to switch to that circuit
When you do this, you'll see that the board, memory, and layers panels will lose their contents. That's because this new circuit can store its own information here. Above the board, you'll also see "Circuit: star" written, to remind us that we are no longer looking at the main circuit.
Let's create a new canvas layer, called "fg". Since this is a new circuit, the name won't conflict with the existing one.
We want to have the star drawing happen inside this circuit. Go back to the main circuit and look for the arrow button next to the "Draw a star" chip you made in the last step. Pressing the button will open a menu where you can tell RedWire to move the chip to the "star" circuit.
Once you click Done, you'll see... nothing. Because we haven't included the star circuit into the main circuit yet. To do that, click the "home" button at the top of the board to switch back to the main board. Then drag the star circuit into the board right at the top. You'll see a new layer created for the main board, also called "star". This layer contains all the visual output of the star circuit. We can move them around just like the other layers.
Now switch back to the star circuit by clicking the gray button right next to the circuit chip in the board . Let's give the star some animation.
Add a new variable to memory- frameCount
, and give an initial value, like 100. Then modify the "Draw Star" chip to rotate the star by this number of degrees, by assigning the expression memory.frameCount % 360
to the "rotate" pin.
Next, add an emitter that simply increments the frame count in memory. When you hit play, you should see a rotating star.
Let's imagine that we want two of these stars, but in different positions. To do that, we'll add a pin to the circuit itself that will specify the center. Expand the "Circuits" list in the toolbox and click the edit button. Now add an input pin called position
. You can give it a default value if you wish.
Alter the "Draw star" emitter to use this circuit pin for its position attribute (circuit.position
).
Finally, we can go back to the main chip by pressing the "home" button. Drag and drop another circuit chip besides the first one. Click the edit button on each, and give a different value for the position pin, like [200, 200]
for one and [700, 400]
for the other. When you click play, you should see two different stars spinning at the same speed.
What's great about circuits is that we can inspect them in the same way as the rest of the system, by recording a session and seeing how their memory changes.
One of the central goals of RedWire is to make it easy to remix and mashup games. We've shown how easy it is to fork any game on the site, but what about mixing parts of one game with another?
In RedWire, this is done through drag and drop. Using the same browser, open up a new window for the game that you want to steal from. then simply drag the parts over. This works for everything that's in the toolbox, assets, and even chips within a board. Best of all, RedWire will find the dependencies for you, copying over chips, assets, and transformers, that might be needed.
Drag and drop is most powerful with circuits, because they contain their own memory and behavior. Let's take a quick example.
In a second browser window, load up the "Stupendous Space Shooter" game. The first chip in the main board is a circuit called "starfield". Take it and drag it over onto the board of your own game. It will copy over other data with it, such as an asset of the star.
When you hit play, you'll just see stars. That's because the layer of the new circuit is on the top. Move the layer just in front of the "bg" layer so we can our other shapes.
Congratulations, you just got yourself a brand star background.
Warning: Audio support is still not well standardized across browsers and platforms. In particular, different browsers support different file types.
RedWire can play music and sound for your game. It can even play cool 8-bit sound effects generated by the jsfx library. Let's spice up our game with a few sounds.
To play recorded sounds, we need to drag over a short audio file onto our assets. Unfortunately, different browsers support different audio formats. We'll use OGG files here, which are generally well supported. Download crash.ogg to your computer for this example.
Next, we need to create an audio channel to play our sound clip. Channels work like graphics layers: you add them to your circuit, and they have different types depending on their use. Press the plus button under "Channels" in the layers panel. Let's call this channel "clips". Since this is a short clip, like for a sound effect, will use the clip type of channel.
The next step is to wire up an emitter to send this sound to the channel. Drop a "Play Sound" processor under the root of your board, call it "Play crash", wire it to io.sound.clips
and give it the asset "crash.ogg"
.
When you hit OK, you won't hear the sound right away. To preserve developer sanity, RedWire only plays sounds when you click the "play" button on the top. When you do, you should hear the sound repeated over and over again.
That's probably not what we want. Let's put this emitter under a "Limit Rate" switch that will only play it every once in a while. To do this, we'll need to create a new memory pin (make sure you are at the first frame!). Call it timeOfLastSound
and give it a value of 0
. Then drag over a "Limit Rate" switch and put our emitter under it. Call the switch "Only play once in a while". Set the pin "currentTime" to io.time
, "minTime" to 5000
and lastTime to simply bind to memory.timeOfLastSound
.
When you hit play this time, there will be a little break between the sounds.
Now let's add some music to it. The difference between music and clips in RedWire is that only one piece of music can play at a time. Also, the music will automatically loop when it finishes.
Download techno.mp3 to your computer, and then over to the assets. Create a new channel called "music", with the type music. Drag a "Play Music" processor under the root that simply sends to io.sound.music
, with the asset "techno.mp3"
.
That's all it takes! If you want to change the music currently playing, you just send a different asset, and the music will change on the fly.
With recorded music we can do whatever we like, but for sound effects it's actually a lot more fun to play with the old-school game sounds that JSFX generates. To do this, first go to to the jsfx site and come up with some sounds that you like. The effects are described as JavaScript arrays, for example: ["square",0.0000,0.4000,0.0000,0.3200,0.0000,0.2780,20.0000,496.0000,2400.0000,0.4640,0.0000,0.0000,0.0100,0.0003,0.0000,0.0000,0.0000,0.0235,0.0000,0.0000,0.0000,0.0000,1.0000,0.0000,0.0000,0.0000,0.0000]
The easiest way to store these sound descriptions is in memory. Add a memory pin called "clickSound". Then switch the memory panel over to the "Code" view.
This will let us copy and paste easily. Paste the sound clip you want in the place of the ""
that was created by default.
Next, create a channel called "fx", with the type fx. Drop a new "When" switch under the board root. Call it "When mouse just down", and set it to track the condition io.mouse.justDown
. Drag a "Play FX" processor under the switch. Set the channel to io.sound.fx
and the "fx" pin to memory.clickSound
.
Now each time you click you should hear the cool sound that you made with jsfx!
Publish one last time, and then "Play" button under the "Tools" dropdown on the upper-right: . You'll leave editing mode, and come to a page where you can play the game. You can share this link to show people what you created.
You can also embed the finished game on another website within an iframe. Just change the end of the URL from "play" to "embed", like in this JSFiddle.
The best way to learn about making games on RedWire is by editing games on the site. You can go on http://redwire.io and pick some games to edit, like Asteroids, Pong, or the SpaceShooter.
For a description of the standard chips and functions that RedWire provides, check out Standard Toolbox Reference. For more information on input/output, including drawing, HTML, charts, mouse and keyboard, check out our IO Buffer Interface. For a more theoretical brief, look at our Manifesto.
Finally, you can find our blog on http://redwireio.tumblr.com or follow us @RedWireIO.
Good luck and good remixing!
Tutorials:
Reference:
Development:
Problems: