Support - My First Game

Creating Your First Game

If you want to make your own game, but you don't feel like you have the programming experience to dive right in, you're in the right place. We're going to build a Western-style, on-rails shooter. To see the pocket in its completed form, click here. The steps to create the scene are listed below. It's best to go through this tutorial from beginning to end, since each step builds on the previous step. Each step can be done on its own, so feel free to go through them all at once or break it up for yourself. Click on "Setting Up the Scene" to get started!

Setting Up the Scene

Setting Up the Scene

We'll begin by starting a new pocket. Do that now by clicking here, or by clicking on the Build icon (screwdriver) above.

Once the game builder has started, we will be greeted with the default scene, containing two blue cubes, one stacked on top of the other. We won't be using these cubes in our scene, so let's delete them now:

We'll be using a custom skybox and ground plane as well, so we'll want to delete the default ones. However, these objects are currently "locked," so we can't delete them right away. In Wild Pockets, certain objects can be locked, which means that they cannot be selected by a simple left-click. This is generally used for background objects like a ground plane and a skybox, because these objects are usually placed once and then never modified again. Locked objects can still be right-clicked on, so let's delete these:

We now have a completely empty scene. We'll begin by adding in our custom art assets. Please note that we could choose to use any art for our new skybox and ground plane, but this walkthrough will mention specific assets the Wild Pockets Team has created for it. Feel free to choose any or create new ones!

The Builder does an excellent job of guessing where to place the objects we place in our scene. Unfortunately, we don't currently have any other objects it can use to guess the best position, so we need to position this model manually. Also, the "jasonn/western world" skybox was premade with lighting already in it, so we do not want it to use the built-in Wild Pockets lights. Finally, we will want to lock this background art, the way our previous skybox and ground plane were locked.

We now have a background for the game! We can take a little time to move around it and get a feel for how big it is. Right-clicking allows us to look around, and the arrow keys allow us to move. If the camera is going too slowly, we can use the scroll wheel to zoom out; the camera moves faster when it is zoomed out and slower when it is zoomed in.

Our pocket is now at a good starting place for creating a game, so let's pick a name for the pocket and save it just like any other computer document, and then let's make sure it reloads correctly.

When the pocket reloads, it should look the same. Congratulations, you've saved your first pocket! Next up: creating content for it.

Creating Content

Creating Content

Welcome back! If it's not already open, let's go ahead and reopen the MyFirstGame scene by opening the Builder, finding it in My Library, and dragging it into the scene. Now that we're back, we're going to move forward with creating an on-rails shooter, so let's get started by adding some rails to our scene.

We are going to use these track sections to design and lay out the track for our shooter. We can play around with this track segment and get a feel for moving it around. Currently, we can click and drag the object around and use the scroll wheel to move it as well. For more precise control, when an object is selected, axes will appear that will allow us to drag the object around. Also, to make the object fall to the ground from above, we can click the Drop button.

Once we have a feel for movement, we can also play around with rotation. If we click on the Rotate Tool at the bottom of the screen (blue cube with green arrows curving around it), we can use the mouse in the same way to rotate the object around. The blue ring that appears will be the best tool for rotation: it will rotate the track's direction, leaving it wherever it is on the other two axes of rotation. We can always switch back to the Move tool by selecting it at the bottom of the screen (blue cube with red arrows coming out of it).

Once we've laid out the whole track, let's save our scene as it is, by going to the File menu and selecting Save. Now that we have the track saved, the next step is writing the script so that we can ride it. Let's give it a try.

Riding the Rails

Riding the Rails

Welcome again! If your scene is not already open, again, reopen it now. Now that we have the tracks in place, let's have learn to ride along them!

To start, let's name the track sections we laid down earlier. Giving the tracks names will allow us to find them more easily later.

Now, let's dive in and create our first script! We'll create a main script for our game: this is the most important script of all, because it is the one that is responsible for the gameplay. For those familiar with programming, this script is the one that contains the equivalent of your "main" function.

Now we're ready to write some code! The first function we're going to create is called onSceneStart(). This function (a function is just a block of code that can do something) is always called by the Wild Pockets engine when the game is first started. Again, for programmers, we can thing of onSceneStart as our "main." This is the typical place to do all of our setup work and any preparation before the game starts. The function starts like this (copy and paste this code into the text file):

function onSceneStart()

Since this is a shooter on rails, we'll be controlling the camera to follow those rails ourselves, so let's disable the standard Wild Pockets camera. Add to the script:

Camera.setMode("Manual")

This will allow us full control over our camera. Next, we need to define a path for our camera to follow. We start by creating a new path:

myPath = Path.new()

This creates a new path and calls it myPath. Now, we need to fill this path with "waypoints," which are places the path will go. Each waypoint will be a position in space and a rotation that represents which way it is pointing. Fortunately, we have a series of tracks that will help us out. We will create one waypoint for each section of track that we laid when building the game. This is why we gave the tracks names, so that we can refer back to them. This sample code assumes that the first track segment in the path is named "Track 1" (if not, replace "Track 1" in the code below, both times, with the actual name of the first track segment).

myPath:setPosition(1, SceneManager.getObject("Track 1"):getPosition()+vec(0, 0, 3))
myPath:setRotation(1, SceneManager.getObject("Track 1"):getRotation())

This code creates a waypoint on the path. The first line sets the position of the waypoint, the second sets the rotation.

The first number in each line (1) indicates the waypoint number. The path is going to visit the waypoints in numerical order according to these numbers, so our first track section is assigned to waypoint 1. We then set the actual position of the waypoint, which will be 3 units above the position of the track segment (so that the camera does not slide along the ground). We retrieve the position of the track segment using getPosition(), and we add (0,0,3) to stay 3 units above the ground. We then set the rotation of the waypoint, which looks exactly like setting the position, only we use setRotation() and getRotation() instead of setPosition() and getPosition(). We also do not need to add (0,0,3), or anything at all, to the rotation: we simply want to be pointed in the same direction as the track is pointed. Note that we again refer to waypoint 1.

We now need to repeat this for each section of track. Repeat the same code, increasing the waypoint number, for each section of track you placed in your scene. Remember to increase the waypoint number and change the name of the track segment for both lines. For example, your next two lines of code will look something like:

myPath:setPosition(2, SceneManager.getObject("Track 2"):getPosition()+vec(0, 0, 3))
myPath:setRotation(2, SceneManager.getObject("Track 2"):getRotation())

Repeat this for every track segment in your scene, in order. Remember: the order that your track segments are travelled will be based on the numbers at the beginning of these lines of code. If you have lined everything up in the Builder, the camera will follow this path smoothly. If you are having trouble understanding this, look ahead to our completed sample pocket.

Now that our path is set up, we need to tell the path what will be following it. In this case, it is our camera that will be following the path, so that it will look like the player is riding the rails:

myPath:setTarget(SceneManager.getCamera())

Finally, having set up this path, we need to actually start it moving. To make the path start going, simply use:

myPath:go()

Now we finish up the onSceneStart function by closing it with the end statement.

end

That's it! Be sure to save this file, and then go back to the Game Builder. Now we just have to set this file to be our scene's script, and then we're done (if we have been following these instructions to the letter, the Global Properties window should already be open, and the Script Properties tab should already be selected).

Now we're ready to try out our changes. Save your scene (File menu, select Save). Then under the "Test" menu, select "Begin Test." A new window will open containing your pocket, and the onSceneStart function we just wrote will be run. If everything went well, the camera will follow the tracks we laid down earlier! If the camera goes off in a strange direction, double-check your script code and the names of the track segments to make sure they're all in the right order. We can also go back and redesign the course: move our track segments around or even add or remove segments, as long as we change the script to use the new list of tracks. If things still look weird, pay attention to the tracks - the side that looks like actual tracks should be face-up, and the camera will try to go in the direction of the arrows.

Congratulations! We now have a pocket with some action in it! In the next step, we'll add a little more challenge: some enemies to deal with.

Adding Enemies

Adding Enemies

Welcome to the enemy-adding section! As before, if it's not currently open, start by opening your scene in the builder. Now that we have the track-riding working, we should add some enemies to the scene. We'll start by adding one enemy, and then we'll make more later.

With the cowboy in place, let's begin writing the script for it. In addition to the generic scene script we wrote already, a script can be attached to an individual object to determine how that object behaves. As we will here, we can create a simple script and attach it to several different objects to make them all behave the same way.

Writing the Enemy Script

We will now start writing the code that will determine the enemy's behavior. We will put this code in the file we just created. The first line of this file should read:

Enemy = Class.new()

This declares a new class (think of a class as a set of behavior we can assign to an object) that we can apply to our enemies within the scene. We call this class Enemy. Next, we write the initialize function:

function Enemy:_init()
    self:every(function() self:onShoot() end, 1)
end

This function will be called when the enemy is created by the Wild Pockets engine. In it, we set up a timer that will do something every second. This particular timer will call the function onShoot(), in which we will make the enemy shoot a bullet (we are about to write this). The 1 at the end of this line of code represents 1 second, and we could make the enemy shoot more or less often by changing this. We use self:every as opposed to Timer.every because self:every will clean itself up - if the enemy is destroyed, this function will no longer be in our way. Timer.every, on the other hand, will keep running forever.

Next, we write the onShoot() function itself:

function Enemy:onShoot()
    local ammoObject = SceneManager.createObject("Wild Pockets Team/ACME bullet",
                                                 self:getPosition() + vec(0, 0, 3))
    ammoObject:setHeading(self:getHeading())
    Timer.every(function()
                ammoObject:setPosition(ammoObject:getPosition() + self:getForwardVector())
                end, 0)
    Timer.later(function() delete(ammoObject) end, 15)
end

The first line of this function creates a scene object, called ammoObject, which will be the bullet the enemy shoots. The model for this object is "Wild Pockets Team/ACME bullet" similarly to how the model for our enemy was "jasonn/cowboy." We also, when we create it, set the position of the object to (0,0,3), three units above the ground plane, so that our bullet will appear to fly from the enemy's gun instead of sliding along the ground.

The next line sets the heading of our ammoObject to the heading of the enemy. In other words, it makes the bullet model point in the same direction as our enemy is pointing, again to make it look like it is coming out of the enemy's gun.

Then, we start another timer. This timer will actually cause the bullet to fly forwards, by increasing the position of our ammoObject by a little bit, continuously over time. We set the position equal to its current position, plus the "forward vector" of our enemy (which means a small amount pointed in the direction the enemy is facing). Don't worry too much about this line - it all means that the bullet will fly in the direction that our enemy's gun is pointed.

Finally, we set up an additional timer, to delete the ammo in 15 seconds. This is just cleanup code - it makes sure that, long after the ammo has left our field of view, it doesn't keep hanging out in the game forever.

More Scene Editing

Save the file - that wraps it up for our enemy class. When an enemy is created, it will shoot a bullet forwards every second. Now we need to make the enemy in our scene obey this behavior. We'll go back to the Game Builder to add our new class to the cowboy, making it into an enemy (again, if we have been following these instructions to the letter, the cowboy's properties window is already open and on the Script Properties tab).

Once you've got the cowboy set up, we can add more enemies by right-clicking on the cowboy and selecting "Clone." The clones will have the same script and class as the cowboy. Now we can take the time to position these enemies around the scene - again, always point toward the track so they can shoot us!

Now, there's one more change we'll need in order to make the bullets fly correctly: we should disable gravity so the bullets don't fall towards the ground as they fly.

And that's it! Save the pocket, then select "Begin Test" from the Test menu again. As we move along the tracks, the enemies will shoot at us, but we can't shoot back! We'll get our revenge in the final section.

Shooting Back

Shooting Back

Welcome to the final step. We only have a little bit left to do: we need to be able to shoot those enemies before they shoot us! We'll add the code to do this in the scene script. One more time, if it's not currently open, reopen your scene in the builder. In your text editor, return to the scene script we created earlier (MyFirstGameScript.lua).

We will start by adding an "Event Map" to our script, which will allow users to interact with our game by using the mouse and keyboard. Add the following code to the script's onSceneStart function, above the line that says "end" at the bottom:

controlsKeymap = EventMap.new()
controlsKeymap:setEvent("keyPress-space", function() myPath:go() end)
controlsKeymap:setEvent("keyPress-leftMouse", function() shoot() end)
EventHandler.push(controlsKeymap)

This creates a new Event Map and sets it up to pay attention to two kinds of input: pressing the spacebar and clicking the left mouse button. We want the spacebar to restart our camera moving along the path from the beginning again, so we use the line myPath:go() again. Left-clicking the mouse will call a function called shoot(), which will make us shoot at the enemies.

Now, here is what our shoot() function looks like. Put this function all the way at the bottom of the script (after the "end" statement of the onSceneStart function):

function shoot()
    local bullet = SceneManager.createObject("jasonn/bullet",
                                             SceneManager.getCamera():getPosition())
    bullet:setCollisionHandler(handleCollisions)
    bullet:setVelocity(Mouse.getRay() / 2)
    Timer.later(function() delete(bullet) end, 15)
end

The lines "function shoot()" and "end" just define the function so that our EventMap code knows what code to run. Inside this function, the first line (SceneManager.createObject) should look a little familiar, from the Enemy class we wrote earlier. It creates a bullet object and places it at the camera's current position. The next line adds a "collision handler," which is a function that will be called when this bullet collides with something. Then, we set the velocity of the bullet, so that it will start flying forwards. We use Mouse.getRay() to shoot the bullet toward wherever the mouse is, so that it will go in the direction that the player clicked. Finally, like we did with the enemy's ammo, we set up a timer to delete the bullet 15 seconds after we shoot, so that we don't have bullets hanging out in the scene forever.

Almost done! For the last step, we will write the collision handler we added earlier (which we named handleCollisions). This function will be be called when the bullet hits something, and it will be responsible for determining what to do about it (in this case, killing the enemy). Here is what the function looks like (add this to the bottom of the script file):

function handleCollisions(self, other, mode)
    if other:hasKeyword("enemy") then
        delete(other)
        delete(self)
    end
end

When this function is called, it will be given three pieces of information: self, which represents the object that hit something, other, which represents the object that it hit, and mode, which we can ignore. self will always be our bullet, because the bullet is what we called setCollisionHandler() on back in the shoot() function.

The first line of the collision handler checks to see if the thing that the bullet hit is an enemy, by checking for the keyword "enemy," which we will soon go back and add to the enemies in our scene. If it is, we delete both the enemy and the bullet, removing them from the scene.

Know Your Enemies

Save the scene script and return to the builder. Now we just need to identify the things in the scene that are considered enemies.

Now your enemies are properly identified for the collision handler to find them.

Our First Game

Now it's time to test our game! Save the scene, then test the pocket one more time ("Begin Test" in the "Test" menu). Shoot the enemies before they shoot you! Press the spacebar to go back to the beginning and get them all!

Congratulations on your first game! When you're done testing it, close the test window that popped up. Feel free to make more changes in the Game Builder. Play around. This is a good time to add background scenery to enhance the experience. Try searching the Global Library for "cactus" or "shack" and dragging them in. We can add any model we find in the library to the scene. As you add them, be sure to right-click on them and select "Anchor" from the menu; if the objects aren't anchored, they might float away when hit by a bullet.

For reference, here is a link to the Wild Pockets Team's completed version of the pocket.

One more thing you can do, in the builder, is go up to the "Test" menu and select "Play Pocket in View Page." This brings up the page where you can play your game. Share it with your friends (be sure to save any changes you make)! You can even use the embed code at the bottom of the page to embed it in any other page. Congratulations on writing your first game, and welcome to Wild Pockets!