Wild Tiger's Sphere Tutorial Part 2

From Spheriki

Jump to: navigation, search

Part 2 of Wild Tiger's tutorial assumes that you have finished the first part and understand the baics.

Contents

Demo Game

Phew. We made it through the basics! Well I hope you did. If you didn't you may find everything else hard. Anyway, let's make things happen. Oh and by the way, don't expect to make that perfect game you've been dreaming up in two days. It takes a lot of practice and knowledge of Sphere and JavaScript to get you that far! Let's make a map and do stuff!! Wooo!

Basics

Well, before we start you need to have a map and a spriteset ready. Now I’m not going to give you so just scout around other games and see what you can use, or if you want, play around with "import" under the file menu.

Just make sure your spriteset is in the spriteset folder, and your map is in the map folder.

Okay, make our map work shall we? How? Like this:

function game()
{
    CreatePerson ("Player", "guy.rss", false);     // The false part just means that the player wont be destroyed after every time
    AttachCamera ("Player");                       // the map's changed.
    AttachInput ("Player");
    SetTalkActivationKey (KEY_ENTER);              // When you talk to a person, you have to press enter!
    MapEngine ("Map.rmp", 80);                     // Starts up your map.
}

Just change the above how you like. If you want to change the main player's name from "Player" (Though this really has nothing to do with the actually hero, it's just what you call if you want the spriteset you're controlling to do something, like move in a scene for instance. Guy.rss should be changed to your spriteset's name, and Map.rmp should be changed to the name of your map.

From here you can probably walk around like an idiot! Woohoo!


Talking to NPC's

Okay, let's make a player that you can talk to. Open up the map, right-click where you want to put this person and then Insert Entity | Person...

Okay, now, type in a name for this person... let's call him Bob. (Don't put "" on either side of Bob's name) Now click the little box with "..." in it and find your spriteset. Once found, press okay. Now, click okay again, then close the map after saving it.

Now we need to make a text box function.

Okay, go to your main script (In my case, game.js) Make sure you keep the above game function there. Underneath it, make a new function, like so:

var main_font = GetSystemFont();
var main_window = GetSystemWindowStyle();
 
function game()
{
    CreatePerson ("Player", "guy.rss", false);  
    AttachCamera ("Player");
    AttachInput ("Player");
    SetTalkActivationKey (KEY_ENTER);
    MapEngine ("Map.rmp", 80);
}
 
function Text_Box (txt)
{
  main_window.drawWindow(16, 16,GetScreenWidth()-32,GetScreenHeight()-192);
  main_font.drawTextBox(20, 22,GetScreenWidth()-34,GetScreenHeight()-202, 0, txt);    
  FlipScreen();  
  RenderMap();
 
  while (GetKey() != KEY_ENTER);    
}

Some new stuff! Okay, I’ll explain them.

  • GetSystemWindowStyle() : Well, this gets the system's window style. If you like, you can use LoadWindowStyle ("name.rws");

name.rws being the name of your window style.

  • RenderMap() : Alright, this'll make the map show while the text box is on, as FlipScreen() pretty much just makes the whole thing black. Try taking out RenderMap() and see what happens.
  • while (GetKey() != KEY_ENTER) : All this means, is while GetKey (any key) isn't pressed, then wait until GetKey() is pressed.
  • .drawWindow (x, y, width, height) : Basically makes a box at x, y, with the size of width and height. GetScreenWidth() and GetScreenHeight() basically just return the size of the game screen. So, if we minus something it'll shrink.
  • .drawTextBox (x, y, width, height, offset, text) : Makes a text box, so that it continues until it hits the side of the box with writing, then it'll go down to the next line, so that it doesn't go off the screen.

Hope that made sense. Okay, save that, and go back to the map. Right click on the player and click edit entity. Now, goto "On Activate Talk" in the little selection bar. Underneath that, type Text_Box ("Hello world!"); Now click okay. Save the map and run the game. Now all you have to do is walk up to the guy, talk to him (usually enter or space bar) and he'll say "Hello world". Simple.


Menu System

Let's add a menu!

Okay, before we start I’ll get you acquainted with EvaluateSystemScript() and EvaluateScript(). Well basically, if you had a game with just one -huge- script files there'd be utter chaos. Trying to find a certain piece of code would take ages. That's why we split them up, and call them. EvaluateSystemScript () Calls a certain script from the System folder of sphere. Use it like: EvaluateSystemScript ("menu.js"); To call a script that's -in- your game, use EvaluateScript ("name.js");

Okay, let's make a menu! Add this in to your game:

EvaluateSystemScript ("menu.js");   // This has to be called to use a menu!!!
 
function Game_Menu()
{  
  RenderMap();
 
  var menu = new Menu();
  menu.addItem ("Items", Items_Menu); 
  menu.execute (10, 40, 110, 64);     // x, y, width, height
}
 
function Items_Menu()
{
  // This is empty!
}
 
function t() { }   // This does nothing, it's just so you can put something in the menu item so it makes more sense.

Woah! menu.addItem? menu is now defined, and anything with menu.addItem will add onto that list (as long as it's in the function, remember var menu = new Menu() isn't a global. Execute makes a box for all the menu items to go into.

Okay, so how do we get this to open when we press a key? Simple. BindKey(). Go up to the game function, and change...

function game()
{
    CreatePerson ("Player", "guy.rss", false);  
    AttachCamera ("Player");
    AttachInput ("Player");
    SetTalkActivationKey (KEY_ENTER);
    MapEngine ("Map.rmp", 80);
}

to this:

function game()
{
    BindKey (KEY_ESCAPE, 'Game_Menu()', 't()');
    CreatePerson ("Player", "guy.rss", false);  
    AttachCamera ("Player");
    AttachInput ("Player");
    SetTalkActivationKey (KEY_ENTER);
    MapEngine ("Map.rmp", 80);
    UnbindKey (KEY_ESCAPE);
}

How does bind key work? Well basically you have the open key.... KEY ESCAPE, what it opens... our Game_Menu() and when you press escape again what does it do? t(), which does nothing. So it just closes. Okay, save and try that. Usually pressing escape quits the game, but not anymore! How do you quit now? Well until you make an Exit (just do menu.addItem ("Exit", Exit); ) item in the menu, just press Alt + F4. Even with the exit item, Alt + F4 is faster.


Learning Objects

Phew, hope I haven't confused you so far? Well, now that we've figure out how to make a menu...how about we'll make some items for it, hey? Just to make sure, before you can rush into a game you have to make every little bit in it, items..equipment...etc...sphere is much more complex than RPG Maker 2k, if you use that and will require a lot more work. It'll need teams of people and months of work (Well, depends what your making) and if your by yourself, you'll need a lot more time ;) Duh. Anyway, I suppose you should learn about Objects first!

I must admit, I really have no idea how to explain them, because hey, I’m quite new to Sphere myself...well sorta. I know enough to use it. :) How about I’ll give you an example?

function Item (name, amount)
{
  this.name = name;
  this.amount = amount;
}

So what does this mean? Well first you're making an object, called "Item". Secondly, Item has two parameters, name and amount. Thirdly, the name and amount property are direct links to the function parameter. That'll mean this.name = the name you give it. Eg, new Item ("Potion", 10); which would mean this.name = "Potion" and this.amount = 10. To call "this" outside of the function, you'd have to have an Object name. You could do this:

var potion = new Item ("Potion", 10);

And to call "Potion" or 10 you'd do this:

potion.name   or   potion.amount

And to draw it to the screen you would do this:

main_font.drawText (0, 0, potion.name);

There are other ways other than "var potion" for the Object name, but before showing you that, just incase you don't understand and want a working Item Object, I’ll write it out for you all together, just so you can look it over and try to understand it:

var main_font = GetSystemFont();
 
function Item (name, amount)
{
  this.name = name;
  this.amount = amount;
}
 
var Potion = new Item ("Potion", 10);
 
function game()
{
  main_font.drawText (0, 0, "Name: " + Potion.name);   // Would come out as "Name: Potion" 
  main_font.drawText (0, 10, "Amount: " + Potion.amount);    // Would come out as "Amount: 10"
  FlipScreen();
  GetKey(); 
}


Menu Items

Well, now I’ll show you how -I'd- make the items. Rather than making a variable for -each- item, i'd put it in an Array. This way, you can list them using the numbers in the square brackets [ and ]. Okay, first off, let's call the array.

var Items = new Array();

Now, let's add in our Item function:

function Item ()   // This should be blank, rather than this.name = name.
{
  this.name = "";    // See how I made these blank? That's so I can set them inside our array, rather than list them on one line.
  this.amount = 0;  
}

Okay, now let's make the first part of our array...number 0.

Items[0] = new Item ()     // First, let's declare the first Item in our array a new Item.
Items[0].name = "Potion";  // Next, let's make the empty "this.name" become "Potion".
Items[0].amount = 10;      // And now for the empty amount...

See how this is working? Basically it's making a new "this.name" for each variable..array or whatever you want to call it. This basically means you can make many more items, with the same function. Let's make some more items!

Items[1] = new Item ()    // Second in the array..
Items[1].name = "Ether"; 
Items[1].amount = 5; 
 
Items[2] = new Item ()    // Third in the array..
Items[2].name = "High Potion"; 
Items[2].amount = 2;

This means you can call the names like this main_font.drawText (0, 0, Items[0].name); or if you want to change them after you've created them (Why you would want to change the name of an item is beyond me...so let's just change the amount, because it'll have to increase and decrease as you buy and sell items in your game):

Items[0].amount ++;  // This'll make Items[0].amount increase by one!

Okay...now...let's make this into a menu, so that it will list all the items. I’m not sure if I’ll get a fully working items menu in this tutorial...we'll see how I feel. Let's just make it say "Item used" without doing anything else other than that when you press it, okay? Let's make this open up on your map, because it looks better there. Make sure you have a map ready. I’ll call my map just "Map.rmp".

EvaluateSystemScript ("menu.js");
var main_font = GetSystemFont();
 
function Item ()   
{
  this.name = ""; 
  this.amount = 0;  
}
 
var Items = new Array();
Items[0] = new Item ()
Items[0].name = "Potion"; 
Items[0].amount = 10;
 
Items[1] = new Item ()
Items[1].name = "Ether"; 
Items[1].amount = 5; 
 
Items[2] = new Item ()
Items[2].name = "High Potion"; 
Items[2].amount = 2; 
 
function game()
{
    BindKey (KEY_ESCAPE, 'Game_Menu()', 't()');              // If you want to try it out without a map, just remove everything
    CreatePerson ("Player", "guy.rss", false);                        // inside this function, and replace it with Game_Menu();
    AttachCamera ("Player");
    AttachInput ("Player");
    SetTalkActivationKey (KEY_ENTER);
    MapEngine ("Map.rmp", 80);
    UnbindKey (KEY_ESCAPE);
}
 
function Game_Menu()
{  
  RenderMap();                                                                               // Make sure to remove this if you're not using a map.
 
  var menu = new Menu();
  for (var i = 0; i < Items.length; i++)
  {
    if (Items[i].amount > 0)
    {
      menu.addItem (Items[i].name + ": " + Items[i].amount, useItem); 
    }
  }
  menu.execute (10, 40, 110, 64); 
}
 
function useItem()
{
  main_font.drawText (0, 10, "Item used");
  FlipScreen();
  GetKey(); 
}

Woah...what does:

for (var i = 0; i < Items.length; i++)
{
  if (Items[i].amount > 0)
  {
    menu.addItem (Items[i].name + ": " + Items[i].amount, useItem); 
  }
}

mean? Basically, it'll go through the length of Items (Items[0], Items[1], Items[2]....that's 3 items!) and then it'll check if the current item's amount is over 0 before adding it. If it does equal to 0, it won't show up in the menu, but if it does it'll show up with the name and amount of the item, and useItem will show "Item used". Try changing one of the amount for one of the items. Go on. It won't be there anymore if it's a 0!

I know.. let's make a stat's menu. This is easier to do, and I can make this work without too much coding. I'll actualy make this one work. :D First of, let's make an object, shall we?

function Stats (name, hp, mp)
{
  this.name = name;    // The name of your player 
  this.hp = hp;      // The health points
  this.maxhp = hp;  // The max health points (eg, 10 out of 50 hp. The 50 would be the max, and hp above would be current.
  this.mp = mp;   // Ditto for the above, except magic points
  this.maxmp = mp;  
  this.atk = 0;  // The player's attack 
  this.def = 0;  // The player's defence
  this.level = 0;  // The players current level
  this.alive = true;  // Is the player alive or not?
}

By the way, when I have this.maxhp = hp, it doesn't mean that it'll always be the same as hp all the time. It just sets it to the max at the start. So, basically it'll start off as 10 out of 10 hp, and if you minus PlayerObject.hp, it'd minus only the current hp, but max would be the same. (5/10 for example) Okay, this'll make our object. This is basically a mix of the two types we can make, one liner and seperate lines:

var main_font = GetSystemFont();  // Load the font
EvaluateSystemScript ("menu.js");  // For our menu
 
var Members = new Array();
Members[0] = new Stats ("Bob", 10, 0);          // Name is bob, hp is 10 and mp is 0.
Members[0].atk = 5;  // Sets player 0's attack to 5.
Members[0].def = 3;  // Sets player 0's defence to 3. 
Members[0].level = 1;  // Sets player 0's level to 1.
 
Members[1] = new Stats ("Fred", 5, 5);          
Members[1].atk = 2;  
Members[1].def = 9; 
Members[1].level = 1;
 
Members[2] = new Stats ("George", 5, 10);
Members[2].atk = 6;  
Members[2].def = 1; 
Members[2].level = 1;

Let's make a stats function!

function Show_Stats (who)
{
  main_font.drawText (0, 0,   "Name: " + Members[who].name);
  main_font.drawText (0, 10, "HP: " + Members[who].hp + " / " + Members[who].maxhp);
  main_font.drawText (0, 20, "MP: " + Members[who].mp + " / " + Members[who].maxmp);
  main_font.drawText (0, 30,  "Atk: " + Members[who].atk);
  main_font.drawText (0, 40, "Def: " + Members[who].def);
  main_font.drawText (0, 50, "Level: " + Members[who].level);
  FlipScreen();
  GetKey();
  Stats_Menu(); // Go back to the stats menu after you've looked at the player.
}

Now for the status menu!

function Stats_Menu()
{  
  RenderMap();  // Make sure to remove this if you're not using a map.
 
  var menu = new Menu();
  for (var i = 0; i < Members.length; i++)
  {
    if (Members[i].alive == true)  // Checks if the player is alive or not.
    {
      menu.addItem (Members[i].name, new Function("Show_Stats("+i+");") ); 
    }
  }
  menu.execute (10, 40, 110, 64); 
}

So what's "new Function ("");"  ? Well, it's another hard one to explain, I don't know it to well, but that's the only way I know how to make the menu open up "i" from the for loop. You could do new function() { ShowStats (i); } But that doesn't like to work for some reason... I suppose i'll just tell you it's the same thing, except what you write is in the "" of the Function, and to add the "i" you -have- to have the "+i+" bit. So it's like this: new Function(" ShowStats (" + i + "); ");

What that does is Show the stats of the current member it's up to. So if Member[0] is created, and you press Member[0] it has to open ShowStats(0); Which then in turn would open what it needs for that player.

Now, let's run it!

function game()
{
  Stats_Menu();
}


Credits

  • Wild Tiger for writing the tutorial.
  • matmunn14 for creating the wiki page.
Personal tools