in , , , ,

[GameMaker Tutorial] How to setup a simple slot machine reward system

GameMakerBlog Tutorials

Simple Slot Machine Reward System


If you play Adventure Capitalist then you would have probably seen the slot machine reward system that gives you a spin after you unlock certain milestones. Black Desert Online also has a type of slot machine reward system that can give you some pretty incredible rewards: a GM Advanced Lucky Box could net you a Kzarka box (or if you are like me, you end up getting armor stones…always..). One thing that they both have in common, is giving the player that thrill of getting lucky and hitting the jackpot, it is a great way to keep players engaged and wanting more. As long as it is sprinkled into the gameplay, a slot machine reward can add value and possibly monetization strategies as well, provided you do not abuse the players trust; but before you can do any of that, you need to know how to code a slot machine and that is what this article intends to accomplish.

No whammies, no whammies! STOP!

Slot machines may have their origins steeped in gambling and casinos but the methods are seen everywhere from tv games shows to all genres of games and implementing them is fairly straightforward. Some important things to understand first though are how actual slot machines look and if you take some example layouts and even sprites (for testing only) from any online casino sites, for example, these mobile slots games we can see a few things right away.

  • Each “Slot” on the reel consists of a vertical strip of sprites that give the appearance of moving
  • The vertical strip can contain as many individual sprites as you want
    • You could use this to “weight” certain chances, say if you have 1 really great prize and 3 average prizes, you can put the average prize sprites twice throughout the vertical strip and thereby increasing the odds of a player getting the average prize
  • A key factor is to evenly space out each sprite on the strip, this is important for making the vertical movement appear smooth
  • You can have as many reels as you want, you do not need to have only 1 and can have more than the classic 3

Once you have acquired the assets you need to create a vertical strip, the next phase is to actually put the vertical strip together. While not overly complicated, it does require the following of certain rules:

First: Make sure you have an even amount of pixels between each sprite on the strip that you create. I used a 4 sprite vertical strip with each sprite being 32×32. I added some white space at the top and bottom of each sprite so it looked centered in the wheel. The numbers come out as follows:

  • Sprite: Width = 32, Height = 32
  • Canvas: Width = 64, Height = 256
    • Each Sprite gets 16px of white space on each side, with the sprite centered in the middle
      • 16px white space | 32px SPRITE | 16px white space
    • Each sprite gets 16px of white space above and 16px white space below
      • 16px white space | 32px SPRITE | 16px white space
    • Example using the great YoYo RPG assets
      • post

Now things get technical

Now that we have a sprite strip, we can begin with the actual coding. I want to point out that I watched a really good tutorial on youtube, though it was for GameMaker 8 Pro it was easily extended to GameMaker Studio 2. The video is from the channel: Arend Peter Teaches – “Slots” Game Maker Tutorial. The code is fairly straightforward and can be extended quite easily. We begin with the easiest first:

  • Create a parent object whose children will be the “slot reels”:
    • objSlotParent
      • Create Event
        • y1 = 0; //This will be used to determine which sprite we show
          run_speed = 0; //How fast the “reels” spin
          running = false; //If the reels are current in motion
          totalImages = 4; //How many sprites are on the slot sprite sheet
          finishedSpinning = false; //Did the reel finish spinning
      • Space bar event
        • if (objReward.showingReward || (!finishedSpinning and !running)) //If a reward is showing, this allows them        to spin again OR if the “reels” are not spinning AND not finished spinning this allows them to spin again.            This is to prevent spin spamming
          alarm[0]=2+random_range(20,45); //Setup an alarm that STOPS the “reel” at the end of the time interval.           This is what selects a sprite to stop on. We use a random range in order to keep each “reel” from being             uniform and gives the entire play a nice random feel
          running = true; //This sets that the “reels” are now spinning
          run_speed = 7+random(5); //We give a random speed to each “reel” to further increase the experience
          objReward.showingReward = false; //We make sure we reset if a reward was showing
          objReward.sprite_index = -1; //Further resetting the reward if it was showing
      • Alarm[0] Event
        • running = false; //This sets that the “reel” is no longer in motion
          y1 -= y1 mod (sprite_height/totalImages); //This code is slightly complicated, this rounds off to the nearest “sprite” location. This is why making all sprites equal in distance is important. A very simple example: sprBlueGem.y1 = 69.5 | y1 -= 69.5 mod (256/4) | y1 -= 69.5 mod 64 | y1 = 69.5 – 5.5 | y1 = 64 | 64 = the top pixel of our second sprite
          finishedSpinning = true; //This sets that the “reel” has completed spinning
      • Draw Event
        • draw_sprite_part(sprite_index,image_index,0,y1,sprite_width,sprite_height/totalImages,x,y);
          draw_sprite_part(sprite_index,image_index,0,y1-sprite_height,sprite_width,sprite_height/totalImages,x,y);   //These top 2 lines are complicated but if you read my tutorial on Drawing Health Bars with Sprite Parts it might seem more familiar. The first draw_sprite_part draws a portion of the sprite strip, which is equal to 1 sprite in the sprite strip. if y1 = 64, this will draw the portion of the sprite strip starting at Y=64, or the 64th pixel which happens to be our second sprite on the strip. It will continue drawing for exactly 64 pixels because our (sprite_height/totalImages) = 64. | The second draw_sprite_part is critical to getting a seamless “reel” effect by drawing the entire sprite sheet after the sprite that was just drawn. You can see the effect of not having this second draw_part by commenting it out.
        • draw_text(x,y+100,”Y=”+string(floor(y1))); //This is for display purposes so you can see current y1, we floor it (round down) when viewing this way it is clean on the screen without decimals
      • Step Event
        • if (running) //If the “reels” are spinning
          y1 += run_speed; //This moves the y1 for the vertical movement
          y1 = y1 mod sprite_height; //This is a little tricky but it keeps the y1 value from exceeding the sprite_height. Example: if y1 = 355 | y1 = 355 mod  256 | y1 = 99. Again this simply keeps y1 from exceeding the sprite_height
  • Now Create 3 “slot reel” objects that will be the actual slots
    • objSlot1, objSlot2, objSlot3
      • Parent = objSlotParent
      • Sprite = sprSlot
    • Since objSlotParent takes care of all the actions for children we do not need anything else in the objects
  • Next, we just need a Reward Object to show when the player wins
    • objReward
      • Create Event
        • randomize(); //Used for dev so random numbers are really random
          rewardMap = ds_map_create(); //This sets up our reward map, which maps the Y1 value to the winning sprite
          ds_map_add(rewardMap,0,sprGreenGem); //The mapping is equal to the beginning pixel for each sprite on the sprite slot sheet
          showingReward = false; //Setting that we are NOT currently showing a reward
      • Draw Event
        • if (sprite_index != -1) //We will only draw if the sprite_index is set to something
          draw_self(); //Draw the sprite that is set, which is the reward sprite
          draw_text(x-sprite_width/2-15,y-42,”You Win!”); //Drawing some text for the player
      • Step Event
        • if (objSlot1.finishedSpinning and objSlot2.finishedSpinning and objSlot3.finishedSpinning) //Only check for a winner when all “reels” have stopped
          if (objSlot1.y1 == objSlot2.y1 && objSlot1.y1 == objSlot3.y1) //this does a simple check to see if all 3 reels match, if they do match, they will all be on the same y1 value
          objReward.sprite_index = ds_map_find_value(rewardMap,objSlot1.y1); //This looks up the correct winning sprite in the rewardMap based on the y1 value
          showingReward = true; //This sets that we are currently showing a reward
          objSlot1.finishedSpinning = false; //Set all “reels” back to default so the player can spin again
          objSlot2.finishedSpinning = false;
          objSlot3.finishedSpinning = false;
          objSlot1.finishedSpinning = false; //The player did not win, set all “reels” back to default so the player can spin again
          objSlot2.finishedSpinning = false;
          objSlot3.finishedSpinning = false;
  • Lastly, just setup your room with the following objects where you want them
    • objSlot1
    • objSlot2
    • objSlot3
    • objReward

Go ahead and spin, one time won’t hurt

Time to see everything in action. Press the space bar (or left click/tap) to spin. And of course: Good Luck!

Leave any questions or comments below.

Good Luck in all things,
Hikati Games
Hikati Games LLC Logo



What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

GIPHY App Key not set. Please check settings

One Comment

  1. Good morning,

    Thanks for the guide, it is very helpful, although I am having a few problems.

    I am having trouble assembling the sprite sheet, using different sprites, not the YoYo ones. My reels run and stop, but they never align, so I presume it is because of my slot sprite as I have double checked the code.

    When you say each “Sprite gets 16px of white space on each side, with the sprite centered in the middle
    16px white space | 32px SPRITE | 16px white space” and “each sprite gets 16px of white space above and 16px white space below 16px white space | 32px SPRITE | 16px white space”, do you mean in the sprites themselves or these distances should be calculated when placing them on the sprite strip?

    If you mean each individual sprite, does this mean the canvas should just be 64*64?

    Then, what are the coordinates you place each of the four sprites on the strip?

    Any help would be appreciated.

[GameMaker Tutorial] Drawing custom health bars with sprite parts

[GameMaker Tutorial] Simple Embedded database using Grid Data Structure