Open Tag

The best game of laser tag you've never played. Choose your class - from a sniper to a pyro, and customize your own game of laser tag!

Similar projects worth following
Open Tag a video game in real life. Where normal laser tag gives everyone the same device that sends the same tag that does the same thing, this game gives everyone a unique power or skill. Want to fight aggressively and charge at your enemies? Pick the pyro class, who can decimate foes with a powerful, short range flamethrower. Want to stay in the back and pick off your foes at a distance? Pick the poison class that can send tags farther than any other class. Want to support your allies in the middle of a firefight? Pick a healer that can give your allies health.

This customizable game of laser tag is built on the arduino. I'm adding new classes, hardware, and software updates whenever I get around to it. Come build your own and let's play laser tag!

I made open tag for a few reasons. To share my love for electronics with other people, to teach other people something cool, to play a fun game with my friends, and to inspire a new generation of engineers, makers and programmers. And I hope you can get into the guts of this system, see how it works and make it your own. And with that, here's what this is. 

I'm building a class based game of laser tag, similar to the video games Team Fortress 2 or Overwatch. It's a game where each person can pick a unique ability and work together as a team to complete some objective. Each class has an ability that has different properties. Some are good at close combat, others are good at a distance. Some heal allies and others make it easier to damage foes. You get to decide what ability you want to use and how to best assemble your team to defeat your enemy. 

The purpose of this is to give the game both breadth and depth (for more on that, check out this video). Instead of a standard game of laser tag, where everyone has the same device that sends tags the same distance and does the same thing, you get to pick which type of tag you want to send based on how you want to play the game. You get to make meaningful choices about what ability you want to use based on how you want to play the game, and each one is experientially different. This makes the game more fun and adaptable to different play styles. 

In addition to making the core game fun, I want this to be simple to build and understand. The point is not only to make a fun game, but to make something that other people can build off of. I want you to be able to take what I've built, understand it, and make it your own. And if it inspires you to learn more about electronics, Engineering, programming, or any other science, awesome. 


Arduino laser tag game with soldier, healer, base, pyro and ice complete. Five more classes to go.

ino - 48.45 kB - 09/24/2020 at 05:00


Open Tag Code V 0.901.png

Visualization of the functions that allow an arduino to play laser tag. Version 0.901. With soldier, healer, base, pyro and ice complete.

Portable Network Graphics (PNG) - 792.85 kB - 09/24/2020 at 04:59


Arduino Compatible Laser Tag V0.89.png

Picture of the arduino compatible for laser tag. The full project files are on Upverter:

Portable Network Graphics (PNG) - 217.81 kB - 07/20/2020 at 14:37


Headband Sensor Package V0.89.png

Picture of the headband sensor PCB. The full project files are on Upverter:

Portable Network Graphics (PNG) - 49.09 kB - 07/08/2020 at 14:40



This is version 0.89 of the Open Tag Arduino code.

ino - 28.35 kB - 06/21/2020 at 23:57


View all 6 files

  • New OLED image code and Library

    opentag08/14/2021 at 05:52 0 comments

    Well, I ran out of RAM and programming space to use Adafruit's OLED library. Bummer. But, not to worry, there are other arduino libraries for graphics. Some of which use very little RAM. Like this one

    This library uses minimal RAM and is a small enough library that I can use it with all the other code I've written. Perfect.

    Well, except, the way that I made the images now no longer works. I have to convert all of the images to XBM, a different format from the ones that the adafruit library uses. And I couldn't get the images to be displayed on the bottom row. So they are on the top row now. Oh well. That's not a big deal.

    So, to convert the images to XBM, I first had to scale the png images that I had to the correct pixel size. I'm using 26x32 for most of the images (so I can fit Fire, Water, Ice, Poison, and Lightning in 128 pixels. Lightning is a little smaller, so the rest can be 26 pixels wide). Quick Googling found this tool to resize the png to the correct size. I then used to convert the file from a png to a XBM. You can then download the file and open it in notepad to see the bits (in hex). Copy that to arduino and store it into program memory, and we are good to go with new images. The water drop icon is shown below:


    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x00, 0xFF, 0x03, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x80, 0xFF, 0x07, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x0F, 0x00, 0xC0, 0xFF, 0x1F, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0xF0, 0xFF, 0x3F, 0x00, 0x30, 0xFF, 0x3F, 0x00, 0x20, 0xFF, 0x1F, 0x00, 0x60, 0xFF, 0x1F, 0x00, 0x60, 0xFE, 0x1F, 0x00, 0xE0, 0xFC, 0x1F, 0x00, 0xC0, 0xF0, 0x0F, 0x00, 0x80, 0xE3, 0x07, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0xFE, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, };

    Isn't it beautiful ;) ?

  • Testing Different IR Receiver Placement

    opentag07/27/2021 at 05:26 0 comments

    I tested out three different versions of IR receiver placement on your head. I'm sticking with placing these on top of the head for now instead of on the device, since you can get consistent 360 degree coverage on someone's head. When playing with friends, people tried to hide their device to not get tagged, thinking that would save them. So, instead of trusting that humans will change (and not try to cheat), I'm designing the system around them.

    From bottom left to top right in the picture below, there is the first version, with eight IR receivers in an octagon shape (to give 360 degree coverage), which sits on top of your head. When testing with this one, it was hard to consistently tag people, as they would tilt their head up (changing the angle, so you couldn't hit the IR receivers, as their forehead would block the beam), or their hair would get in the way. 

    The second version, the one in the middle, has a tighter pattern of IR receivers (still covering the 360 degree angles, just more compact), and it is sitting on top of a one inch tall stand to make it sit an inch up from the top of your head. This one was easier to hit, despite people's hair or head tilt. 

    In the third version, top right, I soldered the infrared receivers onto copper tape along the RGB LED strip. That way, there was an IR receiver on the person's forehead (making it very easy to see and hit). 

    Three types

    A closer image of the IR receivers soldered to copper tape I placed on the back of the RGB LED strip is shown below.

    Soldering IR Receivers

    After comparing these three setups for IR receivers, I found that the second one was more reliable. For some reason, the IR receivers attached to the RGB LED strip performed the worst. I would have thought it would do better, but when tagging it, the device consistently missed consecutive tags (fired within 1/3rd of a second. Slower than that, and it got all of them). I don't know if there is some capacitance in the copper tape or something that the device is picking up, but from the experiment, I should do the next series of tests with the second version. Hopefully, it will give me the reliability and ease of tagging that I'm looking for. 

  • Headband Improvement and new PCB

    opentag07/10/2021 at 01:25 0 comments

    Got a new white PCB and soldered it up. Looks pretty good, if I do say so myself. 

    V0.98 Case, PCB, and Headband

    I also made some changes to the headband to use elastic strips instead of only using velcro (hook and loop) strips. I used hot glue to attach the velcro to the elastic, and it works fine. The only thing that sometimes gets in the way is hair, so the headband is more reliable when you put it on over a hat (baseball hats seem to work pretty well for this). 

    For the next series of tests, I'm going to try adding the IR receivers onto the RGB LED strip, and compare that to raising the IR receivers one inch up off of the top of the player's head. There were a few occasions where I couldn't seem to tag someone, and it may be because the IR receivers were blocked by the other player's head. But, overall, the devices work and you can play a game of laser tag with them. Woohoo!

    Also made some minor code changes to make it easier to see when you've hit someone with a status effect (poison, fire, etc.). Their headband now stays that color while they have that effect active (red for fire, green for poison, etc.). This will make it easier for players to work together and combine their abilities. 

  • Case Improvements

    opentag05/12/2021 at 04:06 0 comments

    Built a couple devices, played, and overall, it works! One issue that came up was difficulty aiming. The IR LED and the lens were not aligned very well on some of the devices, and that got me thinking. I want the IR LED to be held firmly in the proper direction, and I want to do the same thing for the lens. In addition to that, if I can't get them to be precisely aligned, I can have the sights be adjustable. So, if the device actually sends tags a little to the left, you can adjust the sights a little to the left, and the device will be much easier to aim. 

    With the goal of making it easy to tag other people, I re-designed the front sight and the LED holder, as shown below.

    New IR LED holder and adjustable sight

    The IR LED is now clamped in place by the acrylic case. To do this, I cut a slot in the acrylic and undersized the hole that the LED slots into. This displaces the acrylic and turns it into a kind of spring to keep the IR LED aligned. The IR LED can then be soldered onto the board while held in the proper orientation. 

    For the front sight, it now has a slot in it and is secured by a screw, so it can adjust up, down, left or right to align with wherever the device is actually aiming at. While this might not be necessary with the improvements in holding the IR LED in the proper position, the lens can still be knocked around and may not be perfectly aligned. Even when doing my best to keep it straight, the device did tend to send tags slightly to the left (due to the lens being slightly tilted to the left, even after trying to get it to stay straight). With a little adjustment of the sight, I was able to consistently aim at and tag a target. 

  • Building a Case and new PCB version

    opentag04/12/2021 at 04:49 0 comments

    During the pandemic, I've had a bit of time to build laser tag. The last few weeks, I've been working on a case, new PCB's, and adding a lens to increase the range that the devices can send tags. At night, from a test just a moment ago, the normal range tags go over 200 feet, and the short range tags go about thirty feet. That's around where I want them to be. It's probably a bit shorter during the day, but I haven't done the daytime testing yet.

    Case V0.99_3

    This is quite a bit of an improvement over the prototype, shown below. I mean, they both work, but one of them is definitely a lot cleaner looking. And held together with more than tape and love. 


    Also, the screen, indicator LED's, and sights all seem to be working well. The indicator LED's are a pretty big improvement in my book, considering that some players gave me feedback that it was hard to tell whether or not they were actually tagging other players. Indicator LED's solve that. If you successfully tag a player, your green "Good Hit" LED will blink. If you hit them with an ability, but it hit their armor (and therefore, the ability was blocked), the yellow "Hit Armor" LED will blink. If you are tagged, the red "Hit You" LED will blink, and an on board vibration motor will vibrate to indicate that you have been tagged.

    Screen V0.99_2

    I have a couple more minor tweaks to the case and PCB that I want to make, but the system as a whole is working nicely. I think I've gotten it to a place where it meets the requirements for version 1.0. I'll make a few of them to test that the functionality is what I want, but if it's there, then this is ready to be promoted to version 1.0! (Which, for me, means that it's at a place where it has all of the core functionality that I want it to have. And, it's a revision or two from being there)

  • How to Program Class Selection

    opentag03/01/2021 at 05:30 0 comments

    This entry is going to be a little coding specific, but I think it may be helpful to someone to understand how I went about adding features to the code, in case people want to do something similar in the future. You can follow a similar process.

    The first thing that I needed to do was figure out what I wanted the code to do. I wanted to allow a player to change their class for a short period of time after they are revived. They shouldn't be able to change classes in the middle of the game, because every time you change class, your health is reset. It would be pretty unfair to get hit a few times, then change classes to get full health in the middle of the game. 

    After you are revived (or when you power up the device), you should have a short amount of time, say, 5 seconds, where you can change your class (1). During this time, players can press the "change class button" to change classes (2). You need to know what your class is every time you change it, so the OLED should display your class every time you change it (3). At the end of that time, the OLED should switch to showing your current health (4). When that happens, your class is set, and you can't change it anymore. Understanding and writing this out was the most important part of changing the code. Without an understanding of how I want the code to work, it would be nearly impossible to make the change and make everything work. 

    So, knowing what I want the code to do, I now have to make changes to the code.

    1. To keep track of when you can change your classes, I created a new variable. When you are revived (or start the game, which uses the same function), that function sets this variable to 5 seconds in the future. As long as the current time hasn't passed this stored time, you can change classes. Show your current class and team on the OLED (using an OLED controlling function, which I'd already written)
    2. I added a button (active low), and used some logic I use for other buttons to only change classes once when the button is pressed. (I check if the button's state changed from not pressed to pressed. If so, change class to another valid class).
    3. When the class changes, update the OLED. 
    4. Once I've passed the time where I can no longer change classes, change the OLED to show current health 

    After going of that, I went into the code and added a function that did those things. I had to change some of the original code, as the function that I had that changed classes had other stuff bundled in it. So I pulled those things out so that I could call on them in this new function. I know this is a little hand-wavy about how I actually implemented the change, but I don't think going over the line by line changes is as helpful as going over the high level thinking that went into the change. If you really want to know how I did that, I'd be happy to send you the two versions for you to do a code comparison. The diagram of the functional blocks of code is shown below.

    Respawn code Flow Diagram

  • Team and Class Selection Design

    opentag02/17/2021 at 06:36 0 comments

    I'm thinking through a re-design of how players can select their team and class. While I do have a base that players can use to change their class and team, I'd like players to be able to utilize as much of the game as possible without needing a base. And so that's the main requirement.

    In addition to that requirement, there is a constraint. Players should not be able to change their class while they have health, or in the first few seconds of starting up their device. This is primarily going to be controlled by the software, so that shouldn't be too difficult for any of the solutions below.

    From there, I have a couple of objectives that I'd like the design to optimize:

    • Ease of use - it should be easy to change classes
    • Ease of expansion - There should be the ability to expand classes (and teams) in the future without a hardware change
    • Cost - shouldn't add too much extra hardware (relative to the other options, none of this hardware is actually very expensive)

    Here are the options (at least, the ones I could think of for now) for how to let a user select their team and class, and how I rate them on how well they meet these objectives:

     OptionEase of UseEase of ExpansionCost
    Menu with button selectMediumHighLow
    Menu with Rotary EncoderMediumHighHigh
    Voltage DividerLowHighLow
    Menu with Shift RegisterHighHighHigh

    And now for a little explanation of each:


    I'm currently using a potentiometer with labels around it on the circuit board. Just point the potentiometer to the class you want to play, and when you reset your device, you start the game as that class and team. Because the labels are on the board, it's not easy for someone to add classes or teams to the game and have those classes or teams be selectable with the potentiometer.

    Menu with Button Select

    This would be similar to how a digital wrist watch works. On startup, you can push a button to change your class, or another to change your team. You have a few seconds to do so. This means that every time you reset your device, you will have to select your team and class again, as it doesn't save. Not having the selection carry over is a little more annoying than the potentiometer, but that may be fine. 

    This could also let players select the number of lives that they start with, which could be a fun addition to the game.

    Rotary Encoder

    Similar to the potentiometer, I can use a rotary encoder to allow users to select their team and class. This would also require a menu on the screen, since the rotary encoder can continuously rotate, so you'd have to have the encoder scroll through items on a screen, similarly to how the menu with button select would work. It's more expensive and takes more pins than buttons, and provides the same functionality as buttons. But it is cool. 

    Voltage Divider 

    Let people plug different resistors into the board and have the arduino read the voltage. This requires that players swap out resistors on their board whenever they want to change teams or classes. This can cause quite a headache to look up the resistor values you want, find the resistors, plug them in, realize you lost the ones you need, etc. 

    It's very expandable, but it isn't very easy for the user.

    Shift Register

    I can add more inputs and have someone select their class and/or team using a shift register, which is detailed here. Then I could add a button for each class and a button for each team. But, then again, you'd need space for new classes and teams that are introduced later, or this would just let you have a keypad or lots of buttons to control a menu screen where you can change your class and/or team at the same time. It would be cool, but it doesn't seem worth it when there are simpler options that do the same thing. 


    Voltage divider isn't easy to use, so that's out. Shift register, rotary encoder and buttons all need a menu, and the buttons are the simplest of that group....

    Read more »

  • New case and PCB Design - Prototypes

    opentag01/18/2021 at 05:34 0 comments

    I've been upgrading the case and PCB design into a new form factor, one that looks much more like a gun. Compared to the first prototypes, this has a number of advantages:

    1. Easier to aim
    2. Easier to see the OLED screen while aiming
    3. Has indicator LED's to indicate if you have tagged someone or have been tagged yourself, and these indicator LED's are also easy to see
    4. Uses three AA's instead of six, using a boost converter
    5. Easier to hold with one hand

    I made a quick prototype on a perforated breadboard, and it's starting to come together:

    Prototype Version 0.98_0

    Also, I've been adding more hardware since the last PCB's that I've made, like the OLED, indicator LED's, and the HC-12 wireless transceivers. So, I added the new hardware, changed the size to fit in the new case and uploaded the files to OSH park.

    $104 for three boards!

    I'm used to these being $20 to $50 depending on how big they are. So I tried PCBWay. $95 for 5 boards. If I was making a couple hundred, then the price per board would be lower, but that was more than I wanted to spend on the prototype. So, I redesigned the board a little bit so that it was a bit smaller. It came in at a more manageable $60 at OSH park. Plus, when I have more time, I can panelize it to make the boards more cost efficient, as there are now three boards per device. But, I'll do that later after I've tested the thing and determined if the design actually works. I ended up getting them a Seeed Studio, as they had the cheapest boards for these dimensions. 

  • Time Multiplexing with the HC-12 Wireless Transceiver Module

    opentag12/07/2020 at 01:00 0 comments

    I'm using the HC-12 wireless transceiver module to allow each laser tag device to communicate wirelessly. The idea is that when you are tagged by someone, you can communicate back to the device that tagged you. That way, when you tag someone, you can indicate on your device that you successfully tagged someone. I got some feedback from players that it was hard to tell if they were tagging other people. The LED's on your head blink when you tag someone, but adding an indicator on your device may help. Plus, it paves the way to adding all sorts of other features that I want to have in the future, like regaining health when you tag someone.

    I chose the HC-12 instead of the nRF24L01+ for a few reasons:

    1. I am using just about every single pin on the arduino UNO, and I don't have enough pins to support the nRF24L01+, and I have enough pins for the HC-12
    2. I am using 90% of the program memory on the arduino UNO, and I don't want to add another library and potentially run out of program space for other features I want to add later

    And yes, I could upgrade to a different microcontroller and get more pins, more program memory, etc. And, for the next version, I'm planning on using a Blue Pill, if it meets the requirements for version 2.0. But, if I want to release a completed version 1.0, then I need to stop giving in to feature creep. Plus, based on my experience, the arduino UNO is a much easier starting point for beginners. Getting the Blue Pill running was a minor headache, as the tutorials I followed did not spell out how to do everything, and I had to do a bit of Googling and talk to a friend who had used one before in order for me to get it running using the Arduino software. The ultimate goal for this project is to make this beginner friendly, so if I can use an UNO, which has a low barrier to entry, then I'm going to. 

    After getting the radio set up (with the help of this tutorial) and reading the data sheet, I decided to have each device set to a different frequency. That way, I wouldn't have to worry about devices trying to send data at the same time, which would cause the radios to collide and potentially not send the correct data. And, then, after implementing it, I realized that it takes 40 ms to enter programming mode, and 80 ms to leave it. If you get tagged, change channels, send a message, and then change channels back, that's 240 ms, or about a quarter of a second. Which means that mostly, you aren't going to be listening for whether or not you have tagged someone else. And, if you are tagged by two or more people (which, can happen every 350 ms), you won't have enough time to switch back and forth between the two radio channels to send the data to each person. In essence, with at 240 ms delay between sending each data packet, this system can't scale with multiple people sending and receiving tags at the same time.

    To fix this, I decided to use time multiplexing to keep the devices from sending radio transmissions at the same time. The way I set this up is as follows:

    1. A base, or "master" device, sends a command to enter time sync mode. In this mode, the arduino ignores everything except for sending and receiving radio commands
    2. The base, or "master" device, sends a command to synchronize all radios.
    3. Once synchronized (or, if it times out), each device picks a set time from the synchronize radio command to send any data that it needs to send.

    For example, if there are three radios, and I want them to send data one time a second, then the first radio will send the data in the first third of a second, the second radio will send data in the second third of a second, and then the third radio will send data in the last third of a second. Every second, all three radios can send data, and they will always send in the order, 1,2,3 (if they have any data to send). I've set up the system to send data every 250 ms, with a 3 ms window for each device to send, and 2 ms of silence (for 25 total transmitting...

    Read more »

  • Case Version 0.96

    opentag11/03/2020 at 05:43 0 comments

    Started making a case for the laser tag device. I want something that will hold the arduino, battery, and align the infrared LED with a sight and optic so that it is easy to tag someone from far away. I've landed on using iron sights, similar to a pistol, to make it easy to aim the device at other players. 

    This version is a re-make of an older version, with an attachable lens on the front. Below is a photo of one of the prototypes, with a device installed.

    Case 0.96

    Case 0.96

    It seems to work well, and if you aim through the two posts, you can see the screen pretty easily. When I tried using them, I didn't look down at the screen very much, but the devices did send tags a considerable distance. I didn't measure it, but it went at least 50 yards. That is an acceptable range to play in a park, so I think that this design is at least good enough for the first version of the device. I'm not interested in making a case that looks more like a gun with a traditional trigger, so I'm not going to. This meets the criteria I have for a functional device, and is incredibly simple to make. So there you have it. 

    I'll need to make another prototype to fix some small issues with hole sizes and how to more easily detach the lens, but overall it's a good prototype. Maybe one or two more versions and I'll say it's good enough to be promoted to version 1.0.  

View all 24 project logs

  • 1
    How to build your own game of laser tag

    I've put the instructions for assembling the first version of the device on my website. Click here to go to the instructions. 

View all instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates