Wednesday, July 31, 2013

Cross Platform Media in games

Cross platform media is a way of selling the same product or series on different platforms.  It can be used to add extra content to a product (as in a behind the scenes video), to cross platform boundaries with a single story (if a tv episode finishes quickly and invites you to go to a website to finish the story) or multiple protects can share a universe or story but approach it from different angles or ways.

Defiance is a great example of this third kind of Crossmedia.  A SciFi TV series and  an MMO both set in the same universe but largely independent.  The amount of connectivity developers have with Online games allowed Trion to update the game based on the weekly episodes of the TV show.  Some characters would leave the show and travel to the area of the world the game is set and vice versa.

The key point here though, is that the game and the show are both fully enjoyable on their own.  This is an example of Two products enhancing each other, neither relying on the other, in the way a 'behind the scenes' does.

This is an important point to remember.  You shouldn't just take all the cut scenes out of your game and put them on YouTube.  You will only inconvenience the players who would have enjoyed your story in game, and given the action oriented players no more convenience than a skip button would have.

Then look at this from the point of view of a YouTube viewer.  Even if your cut scenes are complete enough to get a feel for your game without any of the atmosphere and back story gained from game play, why would I now want to play it when I know what happens?

To make this work, learn a lesson from Trion, tell a parallel story.  One that complements and sells your universe and ideas without giving away the game.  That way people will seek out your game, looking for another hit of the wonderful story and universe they just experienced..

To apply this to my game idea:

YouTube:  A series of animated shorts (each approx 5 -10 min) following Rex Marksly, the best pilot ace in the sky.  The series would run like the old 50's action comics come to life, over the top, cheesy humor and bright colors.  The Series would be set 100 years before the game.

Game:  The game allows the player to hunt for Rexs' hidden treasure, all the loot from his bold and amazing life.  Following clues from Rexs diary (which you won in a poker match) you travel the archipelago, finding more diary pages and clues to hunt down your fortune (While fighting pirates and taking bounties and generally being at least as awesome as Rex was anyway).

 So you don't need either to enjoy the other.  But besides the setting, how are they connected?  Well, each episode would contain enough information to track down an artifact or weapon otherwise hidden from the player.  Rex might get knocked out in the episode and drop his revolver.  The player then has the clues needed to go and find it.  These missions would not be core story missions but would enhance the overall fiction.

But we can do better than just two platforms.

Mobile App:  Small 2D arcade plane shooter.  Play as Rex Marksly and rule the skies.  Pay 1.99 for all levels or play for free and unlock extra levels by finding certain diary pages in the main game.  Once your saves are linked, earning points or treasure in the mobile game will provide main game advantages as well.

So the Animation, Game and Mobile game are all fun on their own, but enjoying all of them will create a richer experience both in terms of story and game play.

If the Animation was on YouTube, the game was chrome browser based and the mobile app was on android, Google might even pay for it.


Tuesday, July 16, 2013

How to fly a plane

http://forum.unity3d.com/threads/43984-Unity-testproject-a-little-flightsim

So, I want to make a movement script for unity to control a plane.  I want a nice simple control system, so I'm not going to use physics.  I'm going to use variable to control the required movement.  So, question one, how does a plane move?

How a plane moves

A plane has 4 axis of movement, Thrust, Pitch, Yaw and Roll.  Thrust is the forward velocity of the plane, in unity this would be the local Z position.  Pitch is the vertical angle of the nose, if you increase pitch it moves the nose up, making the plane climb higher, in Unity this would be the local X Rotation.  Yaw controls the horizontal angle of the plane, or the  global Y rotation (we'll get to why this is global).  and roll is local Z rotation.

While in flight, if the player removes all hands from the controls, I want the plane to move back towards a cruising speed Thrust value, the pitch and roll to move back to zero so the plane is level, and the yaw to stay constant.

if the player wants to adjust the thrust they should be able to accelerate to a maximum value, and decelerate to a minimum (not too slow).  Roll, can complicate the yaw and pitch calculations, as it rotates them (if the plane is Rolled 45 degrees (on the Z rotation) then the Pitch (X rotation) is no longer strait up and down but at 45 degrees.  This allows players to make sharp banking turns in some flight simulators, but this does not match the simple, arcade feel I'm going for, so I'm going to simulate the Roll axis by rotating the model When the player adjust the Yaw (So the plane looks like its banking), While applying the rest of my motion to a dummy game object containing my plane model.  This means that no matter how the plane looks like its banking, the X rotation is always perfectly vertical.

The Yaw is set to global rotation both to avoid being altered by the roll and pitch and so that later, its easier to get the global direction the plane is pointing to build a compass into the HUD.

Enough theory, lets code

So, lets start with a fresh scene in Unity.  Create an empty gameobject and place the plane model (or box) and your Main camera underneath it in the hierarchy.  Throw in some terrain and a light so you have some reference to fly over.
.








The other option is to use a follow cam.

Create a New CSharp script on your plane model, and lets get stated.

We'll being with Thrust. We'll need 4 variables. speed, cruiseSpeed, minSpeed and maxSpeed.  Set the min and max to whatever values you like (I used 10 and 60) and the speed and cruise to a value in the middle of the two (30).
float speed = 30.00f;
float cruiseSpeed = 30.00f;
float minSpeed = 10.00f;
float maxSpeed = 60.00f;
Within the update function we need 4 basic calculations.  A calculation to alter the move speed if the button is pressed.  A calculation to move the speed towards cruising if no button is pressed, code to prevent the speed from exceeding the maximum or dropping below the minimum and finally, code to translate the speed value to the objects transform.
Step 1.
//If the button is pressed, alter speed value
if(Input.GetButton("Thrust"))
{
speed += (Input.GetAxis("Thrust") * Time.deltaTime)* 25;
}

Input.GetButton is a boolean value so its false at zero and true at any other value.  Since the axis controls in unity move between values of - 1 to 1 this means that the statement is true as soon as the button is pressed. The 25 in there is the Acceleration value.  This can be changed.  For a different acceleration and deceleration value use two if statements

if (Input.GetAxis("Thrust") > 0)
if (Input.GetAxis("Thrust") < 0)

Step 2.

// Return to cruising speed it button is not pressed
else if(!Input.GetButton("Thrust"))
{
if(speed > cruiseSpeed)
speed -= (Time.deltaTime * 20);

else if (speed < cruiseSpeed)
speed += (Time.deltaTime * 20);
}

If there is no input from Thrust and speed is greater than cruise speed slow down or if its less than, speed up.

Step 3.

//Prevent Speeding or Slowing too much
if(speed > maxSpeed)
speed = maxSpeed;

if (speed < minSpeed)
speed = minSpeed;

This will keep the speed within limits.

Step 4.

//Apply Speed value to object
transform.parent.transform.Translate (0,0,speed * Time.deltaTime);

Transform.parent allows an object to access its parent objects properties.  transform.Translate is the equivalent of a += to each position coord of and object.  So transform.translate (x, y, z) means
transform.position.x += x;
transform.position.y += y;
transform.position.z += z;
in our case, we are leaving the x and y axis where they are and adjusting the z axis according to our speed value and the frame rate.

So Far our script looks like this.  When we test the script the plane should start moving forward, and should speed up and slow down when the "Thrust" Axis is used, and reset its speed otherwise.

But I want to turn!

Let's add some yaw controls, this bits easy

//***********  Yaw  ***********//

transform.parent.transform.Rotate(0, Input.GetAxis("Yaw") *Time.deltaTime*30,0, Space.World);

Just like above we want to affect the PlaneGameObject so we use transform.parent.  transform.Rotate works it the same way as transform.Translate except it effects Rotation rather than position.  We multiply by 30 for the turn speed.

This isn't nested in an if statment because when the button isn't pressed Input.GetAxis("Yaw") = 0.

0 * Time.deltaTime = 0 and
0 * 30 = 0

meaning that the rotation isn't affected at all when the button isn't pressed.

I still can't go up and down....

Next we'll set up the pitch controls.

// Rotate Nose
transform.parent.transform.Rotate(Input.GetAxis("Pitch")*Time.deltaTime*40,0,0);

This is exactly how we set up the yaw, but we also want the pitch to return to zero if the button is not being pressed

//Rotate Nose to Middle
rotX = ((int)transform.parent.transform.eulerAngles.x);

if((!Input.GetButton("Pitch")) && rotX != 0)
{
if((rotX > 0) && (rotX < 180))
transform.parent.transform.Rotate(Time.deltaTime*-50,0,0);
if((rotX > 180) && (rotX < 360))
transform.parent.transform.Rotate(Time.deltaTime*50,0,0);
if((transform.parent.transform.eulerAngles.x > -1) && (transform.parent.transform.eulerAngles.x < 1))
{
rotXfloat = transform.parent.transform.eulerAngles.x;
transform.parent.transform.Rotate(-rotXfloat,0,0);
}
}
we need to declare a new int variable up the top of the script called rotX. every frame we set rotX to equal the rotation value of the PlaneGameObject converted to an integer. Similar to the code used to return the speed to its cruising value, we move the pitch up to zero if the angle is with a range, and down to zero for the other half of the possible circle.  We use an Int as the value because of delta time.  movement based on deltaTime often produces figures with many decimal places.  This can cause the game to 'bounce' the rotation value back and forth over the 0 mark, overshooting each time.  Run a trace on your speed value to see this happening.  The effect isn't noticeable on the plane with Thrust, but for the Pitch this will cause the whole plane to shake up and down.  By setting the value to an int once the value is between -1 and 1 the first two if statements won't be able to tell and will not 'bounce' the value back and forth.

Once the pitch is within this 'deadzone' the third if statement detects the value and sets it too exactly 0, preventing vertical drift.

Now you should have full control of the Speed, Pitch and Yaw of your plane.

Sure I can move, but it looks crap

Adding the roll will greatly improve the appearance of the flight.

rotZ = transform.eulerAngles.z;

if ((Input.GetAxis("Yaw") <= 0) && ((rotZ < 30) || (rotZ > 320)))
{
transform.Rotate (0,0, (-(Input.GetAxis("Yaw")*Time.deltaTime))*100);
}

if ((Input.GetAxis("Yaw") >= 0) && ((rotZ > 330) || (rotZ < 40)))
{
transform.Rotate (0,0, (-(Input.GetAxis("Yaw")*Time.deltaTime))*100);
}


if ((!Input.GetButton("Yaw"))&&(rotZ != 0))
{
rotZint = (int)transform.eulerAngles.z;

if((rotZint > 0) && (rotZint < 179))
transform.Rotate(0,0,Time.deltaTime*-100);
if((rotZint > 180) && (rotZint < 360))
transform.Rotate(0,0,Time.deltaTime*100);
}

The first two if statements define the maximum range for the rotation and rotate based on rotZ (go declare that by the way (: ).  the reason for the slight staggering of the positive and negative ranges is again to deal with deltatime making things imprecise.  if the rotation of both was set to 30 deltaTime would set the rotation too 30.001 meaning that you couldn't rotate in the other direction.

the final if statement rotates the plane back to zero when the key isn't being pressed using an int value for the same reasons as the Pitch.

Monday, July 15, 2013

Sky Pirates.

Blurb:  Play as a seaplane bounty hunter on the most dangerous ocean in the world.  Take jobs from pirate gangs hunting loot or work for the ports protecting people for profit.

influences/inspiration/copywrite infrigments.

  • Porko Russo (Setting) (Art)
  • Windwaker (dynamic arc and gameplay context)
  • Jak and Daxter (PSP) (Flight Controls) (Platforming)
  • Waterworld (Setting)
  • Ratchet and Clank 2 (the space combat bits) (Flight Controls)
  • Indiana Jones (for ancient temple, pure platforming levels)


Gameplay: 

Game has two main game play modes, Arial combat and a FPS/Action rpg hybrid.  Missions will generally involve flying to location (either in your own time or tailing somebody, or, etc)  With an ground based level in the middle, followed by flying to the final location (to return the stolen goods/ While fighting off your pursuers/ etc).

Arial combat will be very simple (more burnout than forza) with a focus on easy controls and interesting missions and situations.  Players will have control of Thrust, Pitch and Yaw with Roll simulated during Yaw control.  A minimum flight speed will be enforced, as planes wont be able to stall and should not be able to float mid air.   Weapons will primarily be forward facing guns with bombs and missiles possible extras.

Ground Combat will blend FPS and Platforming to create interesting levels with a flow between action and puzzle solving.  The camera can be toggled by the player between FP ( Much better shooting accuracy, slower move speed, turn speed and lower jump height) and 3rd person (Poor shooting accuracy, faster movement and turn speed and improved jump).  This relationship is similar to the difference between normal play and iron sights in FPSs.

Art Style:

Game will use a combination of toon shading and watercolor effects to emulate traditional anime movies.  People complain about how they can tell which rock will blow up next or which door will open because its the cartoon one, out of place on its watercolor background.  This effect will be used to inform player which objects they can interact with and which they can't.

Story :

Good Question.  You lost your dog or something.  Or your wife died and your searching for an ancient magic to bring her back or I don't know.

Example Mission:

The Governors Daughter has been kidnapped by Nasty Sea Plane Pirates and he's offering a large reward for her return.  You get a tip on where they're hiding her and make your way there.  The guards on the dock are easy to deal with but the warehouse is locked up tight.  You climb the sea cliffs nearby and find an open skylight in the roof to drop in.

After taking out the pirate gang inside you find the girl and make your way back to your plane.  As soon as you take off pirate reinforcements are hot on your tail and you destroy them all in a daring and bloody dogfight before taking the girl home.

1. Arrive from Port after reciving mission
2. Take out pirates guarding dock (Shooting)
3. Scale Cliff to find way in (Platforming)
4. Take out pirates inside (Shooting)
5. Find Girl
6. Take Girl Back to plane and leave
7. Dogfight with pirates in planes and






This Graph Show the balance between the two types of "fun" at each point in the mission.  Both swap between high impactful peaks early in the mission with a small lull (as you take the girl back to the plane) adding impact to the final dogfight.
Higher difficultly levels may give the pirates an air guard on your approach (adding a dog fight to the beginning of the level), a couple of pirates hiding in the cliff platforming section (keeping the combat pressure on and making the platforming harder to focus on) and pirate reinforcements when you return to your plane (removing any break from combat in the entire mission.

Longer missions can provide multiple paths, some with a lot of combat and very little platforming and some requiring a lot of very carefully timed jumps but with very few enemies allowing players to play their preferred way and change the difficulty of mission through in game choices.  A completionist. may decide to enter through one path and exit by the other to collect as much loot as possible, whereas leaving by the route you already cleared would be easier and faster (especially in the case of combat).

To encourage the player to engage in multiple game play types, platforming, combat and aerial combat will all provide a variety of loot.  Enemies will drop money, weapons and ammunition in combat, platforming areas will be littered with chests containing Money, clothing and plane parts and combat will net players money from bounties and scrap metal (for plane upgrades) grated as a share from scrap collecting ships.

Game arc and Progression:

As players progress through the game they will unlock new types of landing gear for their plane. Players begin with a sea plane that can only land on water.  Some islands will have areas only accessible if you can land on an inland runaway (due to sea cliffs or impassable terrain).  Partway through the game players gain access to hybrid landing gear which enables runway landings as well as ocean landings.  The final landing type will be a jump jet system relying on rotating engines.  This will allow players to land on almost any large flat piece of land and will enable late game players to complete missions in a variety of different ways. (in the above example a player may land above the cliffs skipping steps 2 and 3).