Gw Temp

Menu

Tutorial - 'Cursors' by rjt

An item about Sphere posted on

Blurb

This tutorial explains how to program cursors (and some systems that use cursors), which can be used for things like menus.

Body

This tutorial explains how to program cursors (and various systems that use cursors), which can be used for things like menus. I wrote this tutorial for people familiar with basic JavaScript coding. If you aren’t, look at the docs folder in the directory where you have installed Sphere, or look for tutorials here at Gaming World.
It’s fairly simple to use cursors, and the functions GetMouseX() and GetMouseY() return the x and y values of the mouse, respectively. Using this, you could do something like this, to show the cursor at its current position:

var MouseX = GetMouseX();
var MouseY = GetMouseY();
image = LoadImage(“Cursor.jpg”);
image.blit(MouseX, MouseY);
FlipScreen();
GetKey();

However, this only shows the current coordinates of the cursor; to show a cursor moving, this would be used:

image = LoadImage(“Cursor.jpg”);
while(true)
{
MouseX = GetMouseX();
MouseY = GetMouseY();
image.blit(MouseX, MouseY);
FlipScreen();
if(IsKeyPressed(KEY_ESCAPE) == true)
{
break;
}
}

This loops, sowing the cursor, until the enter key is pressed. You may notice that if you exclude the if statement, the cursor lags. This is because the IsKeyPressed() function updates the mouse’s x an y coordinates.
Say you wanted a cursor menu? That can be done easily enough, like so:
function Intro()
{
StartGame = LoadImage(“start.jpg”);
LoadGame = LoadImage(“load.jpg”);
ExitGame = LoadImage(“exit.jpg”);
Cursor = LoadImage(“cursor.jpg”);
while(true)
{
StartGame.blit(20, 80);
LoadGame.blit(80, 80);
ExitGame.blit(140, 80);
MouseX = GetMouseX();
MouseY = GetMouseY();
Cursor.blit(MouseX, MouseY);
if(MouseX > 20 && MouseX < 60 && MouseY < 80 && MouseY > 120 && IsMouseButtonPressed(MOUSE_LEFT))
{
NewGame();
}
if(MouseX > 80 && MouseX < 120 && MouseY < 80 && MouseY > 120 && IsMouseButtonPressed(MOUSE_LEFT))
{
LoadGame();
}
if(MouseX > 140 && MouseX < 180 && MouseY < 80 && MouseY > 120 && IsMouseButtonPressed(MOUSE_LEFT))
{
Exit();
}
if(IsKeyPressed(KEY_ESCAPE))
{
Exit();
}
}
}

The lines 9 to 14 onwards show the New Game, Load Game and Exit Game images and show the cursor. However, the important lines to note are from line 15 onwards. These lines use an if command to check if the user is clicking the left mouse button (IsMouseButtonPressed(MOUSE_LEFT)) and they also check if the mouse is over any of the buttons (It checks if the mouse x and y values are greater than the x and y values of where each image starts, and then it checks if the x and y values of the mouse are less than the x and y values of where each image ends). This effectively checks if the user is clicking on a button, and if they are, either NewGame(), LoadGame() or Exit() is run, depending on which button was clicked.
What if you wanted to be able to preview maps in the engine? You’d need to have some form of scrolling system for maps larger than the screen, and for this you could use a cursor (so you’d end up with a system for viewing maps like in an RTS game). To accomplish this, you could use:

while(true)
{
MouseX = GetMouseX();
MouseY = GetMouseY();
RenderMap();
if((GetScreenWidth() == (MouseX + 1)) && ((GetLayerWidth(0) * GetTileWidth()) > (GetCameraX() + (GetScreenWidth()/2))))
{
SetCameraX(GetCameraX()+8);
}
if(0 == (MouseX))
{
SetCameraX(GetCameraX()-8);
}
if((GetScreenHeight() == (MouseY + 1)) && ((GetLayerHeight(0) * GetTileHeight()) > (GetCameraY() + (GetScreenHeight()/2))))
{
SetCameraY(GetCameraY()+8);
}
if(0 == (MouseY))
{
SetCameraY(GetCameraY()-8);
}
if(GetCameraY() < (GetScreenWidth()/2))
{
SetCameraY((GetScreenWidth()/2));
}
if(GetCameraX() < (GetScreenHeight()/2))
{
SetCameraX((GetScreenHeight()/2));
}
FlipScreen();
}

This code checks if the cursor is on the edge of the screen, and if it is, it scrolls the map the relevant direction. To scroll the map, it uses the functions SetCameraX() and SetCameraY(), which set the coordinates of where the camera is looking on the map. The first if function consists of two parts. The first simply checks if the cursor is on the right edge of the map, but the second isn’t so simple: first of all, it multiplies GetLayerWidth(0) (which returns the layer width in tiles) by the width of the tiles in the maps tileset, then it checks if this is bigger than the camera’s current x value plus half of the screen’s width. Let me explain why it does all of this: some functions (like GetLayerWidth()) measure in tiles, whereas other (like GetScreenWidth()) measure in pixels. We want to measure everything in pixels, so when we use GetLayerWidth(), we have to multiply it by GetTileWidth() to find the width of the layer in pixels. As I have said, on the other side of the greater than symbol, it adds half of the screen’s width to the camera’s current x value. Remember that the camera always tries to position itself in the center of the screen (you’ll notice this when you control a character that has the camera attached to him, walking around). Unfortunately this can cause some problems when scrolling, and without getting into long explanations that don’t matter (if you really want to know, email me ;D) just know that if half of the screen’s width plus the camera’s current x value is larger than the map’s width in pixels, and the script is still scrolling, it’ll cause problems. This is a bit confusing, but it’s not vital that you understand it, so just remember that the second part of the first if statement is there as a precaution against problems occurring when you try to scroll.

Anyway, if both of the two conditions in this if statement are true, then it increase the camera’s x value, thus scrolling the map right.

The second if command checks if the cursor is on the left edge of the screen, and if it is, it scrolls the map left. The third has the same function as the first, except instead of checking if the cursor is on the right edge, it checks if it’s on the bottom edge. Again it has a second part to act as a precaution against scrolling problems. The fourth checks if the cursor is along the top edge of the screen, and it scrolls the map upwards if it is. The next two if statements are again precautions against problems with scrolling. What I mean by problems with scrolling (and I called them bugs with scrolling above) is that if you exclude these precautions, when you scroll to the edge of the map, the camera’s x/y values will keep being increased, because there is no more map to show, there will be no visible change, yet if you try to scroll the opposite way, it’ll wait until the camera’s x/y value has returned to normal before scrolling (so you would have to wait several seconds before it started to scroll). Again, this is irrelevant information: once you leave the precautions in, there will be no problems.

That’s it for this tutorial. Any feedback, contact me at rjt@gamingw.net.