Order now AGK Bitesize

Lesson One - The AGK World

by Steven Holding

AGK Basic is not a complicated language to learn for anyone with a 'basic' knowledge of programming but there are a number of new concepts we need to get our heads around to fully take advantage of this new tool.

"AGK Bitesize" is a set of tutorials which are designed to help you get used to these concepts a few at a time. We want you take a bite, chew it for a while and then take another bite. Rather than trying to take too much in one go and end up spitting it out without even properly tasting it!

This first tutorial is an introduction to the "World" of AGK. It is essentially a 2D world but one that is not limited to the dimensions of your screen. There are commands such as "WorldToScreenX()" which may have grabbed your interest but do you fully understand the concept yet? If not then read on as this is one of the powerful parts of AGK that can be easily missed or misunderstood.

AGK gives us a "World" in which to position sprites. We can set the position of our sprites in terms of "World co-ordinates" or "Screen co-ordinates". If we don't want these sprites to move then we can fix them to their screen position, I will show an example of this in a little while but first let's jump in and create a world to explore! Start a new project; by default you will see this code.

rem
rem AGK Application
rem

rem Landscape App
SetDisplayAspect( 4.0/3.0 )

rem A Wizard Did It!
do
 Print("hello world")
 Sync()
loop

Let's quickly look at positioning a sprite. When the command "setDisplayAspect()" is used we begin using a percentage based positioning system. This is another powerful part of AGK, it is also a slightly counter-intuitive one to get used to for those of us used to positioning things in DarkBASIC Professional which uses a "pixel" based system but positioning a sprite in a percentage based world is not so hard or different. Add this code into your new project just after "setDisplayAspect( 4.0/3.0 )".

rem create a sprite
spr = createSprite(0)
setSpriteSize(spr,4,-1)
setSpriteOffset(spr,2,getSpriteHeight(spr)/2)
setSpritePositionByOffset(spr,50,50)

This line creates a new sprite with no image (0) and assigns its spriteID to a variable called "spr".

spr = createSprite(0)

This next line sets the size of the sprite to 4% of the width of the screen.

setSpriteSize(spr,4,-1)

The "-1" tells AGK to set the height of the sprite for you. If you are using an image then the aspect ratio of the image will be transferred to the sprite. If we had written this as "setSpriteSize(spr,4,4)" our sprite would not be square as you might expect but it would be 4% of the screen width by 4% of the screen height (on a screen 640x480 this would be about 25x19 pixels).

setSpriteOffset(spr,2,getSpriteHeight(spr)/2)

Here I want to set the "offset" of the sprite to the centre, so I set the "X" offset at "2" and ask AGK to tell set the vertical offset of the sprite to the height of the sprite divided by 2. Setting a sprite offset changes the "centre of rotation" for the sprite and allows us to position sprites by a defined position on the sprite.

setSpritePositionByOffset(spr,50,50)

Bitesize Tutorial Step 1 Finally I set the sprite position based on its offset (in this case the centre of the sprite) to 50% across the screen and 50% down the screen. If we did not use the sprite's offset it would be positioned with the top left corner of the sprite in the centre of the screen rather than being completely central. Run the project and you should see something like the image opposite.

We now have a sprite in a world co-ordinate of 50, 50. Let's move the world around using the mouse. Add this code into the loop just after "Print("hello world")".


rem move the view with the pointer
 if getPointerPressed()=1
   viewX# = getViewOffsetX()
   viewY# = getViewOffsetY()
   startX# = getPointerX()
   startY# = getPointerY()
 else
  if getPointerState()=1
   dx# = startX# - getPointerX()
   dy# = startY# - getPointerY()
   setViewOffset(viewX# + dx#, viewY# + dy#)
  endif
 endif

Here we check for the mouse button (or finger on a touch screen device) to be pressed, then save the screen (view) offset and the position of the mouse. While the mouse / finger are still pressed we add the movement to the screen offset. Compile the project and try it!

Now let's fix a sprite to the screen. Copy this code into your project after the code for adding the first sprite.

rem create a fixed sprite
fix = createSprite(0)
setSpriteSize(fix,16,-1)
setSpriteOffset(fix,8,getSpriteHeight(fix)/2)
setSpritePositionByOffset(fix,10,50)
setSpriteColor(fix,255,0,0,128)
fixSpriteToScreen(fix,1)

Bitesize Tutorial Step 2 This will add a larger fixed sprite to the screen on the left side at 10% across and 90% down. I've made this one red in colour and semi-transparent so you can see your world sprite behind it. Sprites fixed to the screen will not always be in front of world sprites, this just happened because we made the screen sprite last and didn't set a depth for either sprite.

This brings us rather neatly to the subject of depth which is crucial to any 2D game and dealt with nicely by AGK. If we plan ahead we can make use of the Depth property of sprites to great effect. By adding the correct depth to a set of sprites we can quickly make a simple scene really come to life!

Adding Depth to your scene

Setting sprite depth is useful for making sure your sprites are drawn in the correct order. Setting your character's depth to 100 and the background to 200 (for example) makes sure that your character is always drawn in front of your background.

What about making that depth even more apparent by using a parallax scrolling system? This gives the illusion of depth by making objects in the foreground and background move at different rates and can be easily and quickly done using the sprite depth you've already set.

Here's a very quick example using a 'star field' as an example. Copy the following code into a new project before the loop.

rem first create an array to store the spriteID's in
dim spriteArray[100]

rem now create 100 sprites
for s=1 to 100
 rem create a sprite
 spr = createSprite(0)
 
 rem get a random depth between 1 and 100
 d = random(1,100)
 
 rem set the sprite size and depth
 setSpriteDepth(spr,d)
 setSpriteSize(spr,1.0-(d/100.0),-1)
 
 rem set it at a random position in our world
 setSpritePositionByOffset(spr,random(0,100),random(0,100))
 
 rem add to the array
 spriteArray[s] = spr
next

You should now have 100 random sprites on the screen which have a size based on their depth. Next in the game loop we want to look at every sprite and give it an offset based on its depth.

do
 rem get the view offset
 vx# = getViewOffsetX()
 vy# = getViewOffsetY()
 
 rem loop through 100 sprites
 for s=1 to 100
  spr = spriteArray[s]
  d# = getSpriteDepth(spr)
  
  `set the sprite offsets based on the view offset
  Xoff# = -(d#-100.0)*0.01*vx#
  Yoff# = -(d#-100.0)*0.01*vy#
  setSpriteOffset(spr,Xoff#,Yoff#)
  
  `check it's still on screen
  wx# = getSpriteX(spr)
  wy# = getSpriteY(spr)
  sx# = worldToScreenX(wx#)
  sy# = worldToScreenY(wy#)
  
  `if not then give it a new position
  if sx#<0 then setSpritePosition(spr,wx#+100,wy#)
  if sx#>100 then setSpritePosition(spr,wx#-100,wy#)
  if sy#<0 then setSpritePosition(spr,wx#,wy#+100)
  if sy#>100 then setSpritePosition(spr,wx#,wy#-100)
 next
 
rem move the view with the pointer (as in the previous example)
 if getPointerPressed()=1
        viewX# = getViewOffsetX()
        viewY# = getViewOffsetY()
   startX# = getPointerX()
   startY# = getPointerY()
 else
  if getPointerState()=1
   dx# = startX# - getPointerX()
   dy# = startY# - getPointerY()
   setViewOffset(viewX# + dx#, viewY# + dy#)
  endif
 endif
 
 sync()
loop

If you drag the scene with your mouse you'll see the smaller sprites in the background moving slower than the large sprites in the foreground. This is a simple parallax effect.

Download the code When you build your world either using code or a level editor it is worth considering the depth aspect of your scene early on so that you can use a simple effect like this to really add depth to your game world. Here is a downloadable version with a simple spaceship to fly around, I've added a little more code for adding some images and ship movement but the parallax effect code is exactly the same as before  (with graphics by Josh Mooney).

Bitesize Tutorial Step 3

Hopefully now you have a basic understanding of the AGK World. The next AGK Bitesize tutorial will introduce you to the AGK Physics system which is based on Box2D.