Intro: How to Make a Soccer Simulator
My son Ben was turning 6 in July of 2011. Ben is playing a lot of soccer with his friends, and always striving to become better. So for his 6th birthday party, I created a soccer simulator.
Based on past experience, a birthday party game needs to fit the following guideline:
3. Fast - so you can rotate a lot of players through in a short time
4. Neat to watch- you'll have an audience behind you.
In this instructable, I'll walk you through the entire process from concept to creation, show you a video of the completed project, and provide a download link to where you can get the source code for this game.
I've decided to submit this instructable to the Make it Real challenge, since this is a video game concept made into a real soccer experience for rainy days!
Step 1: The Concept
Every game needs a concept even before you get started. This one popped into my head one day on the way to work. We were going to have a sports-themed birthday party for my son Ben, complete with home-made carnival games to let you win the items in your take home goodie-bag. But we wanted to have something extra- enter the 'Soccer Simulator'.
The object was to build a soccer goal inside with a set tee position (so you can't miss the goal and send a soccer ball careening all over my basement into breakable stuff, and other players). You're set up for a free kick at the goal, and on the other side of the goal is a live action video of a goal and a goalie that reacts to your kick!
The game needs to last a few minutes, so a single kick won't do. Also, since I coach youth soccer, I really wanted to stress some skills- like shoot at the side net! Therefore, I wanted to implement the following features:
1. Plot a ball that is speed and directionally accurate.
2. The game is levelled, each level is harder, and the goalie becomes faster.
3. The game CAN NOT progress beyond level 8 (that's enough for any one player)
4. Level 1 is pretty easy, but even there a kick right down the middle will get blocked.
5. Subsequent levels require you to kick further to either side, and a fast kick will give you more wiggle room.
Step 2: Game Content Part 1
First thing I needed was a video of a goalie jumping around after an imaginary soccer ball. Fortunately, my friend Mark Macdonald is a former Northridge NCAA goalie. Mark is also CEO of Venice Nutrition, and he's managed to keep quite fit at 40.
So Mark and I scheduled a day at the park, and I filmed him for about 10 minutes with a 720p flip camcorder. We imagined soccer balls from every angle, and even did a few jeers at an imaginary audience, and a few walks of shame. We shot a few times, and eventually I edited the whole thing down to about 3 minutes of video, taking note of the exact position in the video that I wanted to branch to when necessary.
Next thing I needed was sounds. I spent a decent amount of time looking through freesound.org, as well as any free versions of sounds that I could find, that would be friendly to my game. What I needed was:
1. A referee whistle blowing
2. A crowd cheering
3. A crowd's disappointed sound (you know the one- AWwww)
4. Vuvuzelas. yes, I know- why would I BE so annoying? But anyone who watched any of the last World Cup knows that these things were ALWAYS playing. So I put them in a loop on the game too.
Step 3: Game Content Part II - the Ball
I spent about 2 days modeling and skinning an Adidas Jabulani (the official world cup ball) in Blender, when my son Ben told me "Daddy, that's neat, but can we use my camp ball instead?" Since Ben is the creative consultant, and the final word in these matters, of course I complied. I took a bunch of pictures of the ball, and pasted onto a model that I made following THIS tutorial. This worked out pretty well, as we put the actual ball that I had modeled on the tee whenever we played the game.
You'll notice in this picture that the ball is plenty far from perfect. Turns out it doesn't matter. Once you import it intot he game and introduce some directional light (I did an ambient light plus a directional sun), most of the mistakes just hide in the creases between the panels.
And those red spots? That was Ben's method of personalizing the ball while he was at camp- EVERYONE had one of these balls, and he wanted an easy way to identify his.
Step 4: The Goal (Part I)
Here's where the bulk of work went into this project- the goal. The first picture is a fritzing representation of the soccer goal. There's a few things missing- like the inductor, cap, and mosfet actually show up on an Arduino shield, then are plugged into the Arduino Mega, but you get the idea. The emitter/sensor pairs are actually set up so that they are optically isolated. By this I mean that there are holes drilled into each side of the goal, and if you were a sensor, the only emitter you could see is the one directly across from you. The emitters are your standard high output IR LEDs (much like you'd find on any IR remote control). The sensors are the Vishay TSOP58038 which is an infrared beam break sensor. This means it does not have AGC (automatic gain control) or constant signal rejection like most of your IR code sensors.
I built a wooden goal out of 2x4 studs, but cut a 1/2" square channel on the outside all the way around. This is my wiring channel. As you can imagine, there are a LOT of wires running through there. Then, I drilled the emitter and sensor holes- 11 horizontal beams and 7 vertical beams. These are drilled the exact size of each sensor or emitter, and then each is glued in place with liquid nails polyurethane adhesive. This is probably overkill, but it's what I had on hand. I think I then spent 3 straight nights wiring all this stuff together on the floor of the basement.
First test? Failure. This is when I found out that 38khz noise was coupling onto the sensor power lines, fooling the filter into thinking that it was seeing 38KHz all the time. I added the inductor and cap (present in the fritzing diagram) to filter out that unwanted noise. Second test? Better, but the sensors were now picking up the emitters to either side of the one directly across. This wouldn't work. I cut a few more 2x4's, drilled through with a smaller bit (1/8") and put them in place. Success! I could now report (with my test utility) exactly what beams were broken, and I had an 11 x 7 grid array of sensors.
The second picture below is from drilling the sensor/emitter holes on the drill press. The third pic is a rough test I did- I put a flashlight up behind the board about 3' away from this door (the cleanest white surface I could find in my shop) to test the width and dispersion of the collimated beam. The last picture is of the control box open, showcasing the arduino mounted to the side of the finished goal- LOTS of wires! Notice how I've got each of them numbered for attachment to the correct pin.
Step 5: The Goal (Part I Continued)
This picture is interesting, and gets its own step. Here's why: most cameras (including my phone camera) will pick up infrared light as white light. If you have the goal on, and line up your camera just right, you can see a white light inside the emitter hole, blasting out 38kHz in a nice square wave. Move the camera a few inches to either side, and you can't see the light anymore. It's a great way to spot check to see if your emitter array is fully functional.
Step 6: The Goal (Part II)
No point in a physical game without a physical goal! The next stage was to create a soccer goal. Since I obviously don't have enough room for a full sized goal, I settled on a goal that is 4' tall and 6' wide (1.2m x 1.8m). I chose the size based on how wide you could kick a soccer ball from about 3' (0.9m) away from the front, and not send it careening all over the basement. I constructed the goal out of simple 2x4 studs, and then drilled 1/4" holes to hold the sensors in one side, and 1/8" holes to hold the IR emitters on the other side. During initial testing, it worked great. I could block a single beam from anywhere and detect it. Unfortunately, when I populated all of the emitters and sensors, the adjacent emitters would bleed over and be seen my the detectors. I needed deeper holes to collimate the beams! THAT is why there is a second layer of 2x4s- to make deeper holes for IR beams! I cut a 1/2" wiring channel in the outside of the goal which you can see in picture 3. I don't have a dado blade, so that's 8-10 table saw blade widths.
Step 7: The Goal (Part III - Netting and Hinges)
It's not really a goal if it can't stop a soccer ball! I obtained sports netting from ebay- look for black soccer net. I purchased a 7' x 10' section for less than $20, and cut it to size. I then attached it with cable staples to the front face of the goal. I used wire ties to attach it everywhere else. I knew I would want to store the goal at some point, so I hinged the supports and the top. This way it folds up when not in use, and I latch the side supports to the back support when deployed with an eye ring and dull hook. It sets up pretty stable, and it's durable. I thought about putting the hook side of velcro onto the bottom of the goal to prevent it from sliding all over the place, but it turned out not to be necessary. The goal is heavy enough to stay put.
Step 8: The Tee
- Known starting position, for accurate determination of ball flight.
- Known starting time for ball flight, so you can determine ball speed
- Tee switch, so you know when to progress to the next state in the game.
The Tee itself is just a piece of 1/2" thick plywood with a 2x4 fit to the end to give it a little slope. I've attached a microswitch like this one: http://www.sparkfun.com/products/9414 under the middle (where the tee goes) so we can sense the ball, and then the whole thing goes in the middle of a piece of cheap astroturf carpet. The particular carpet I chose is this one. (Home Depot Link). Since it comes in 12' width, I cut it in half and joined the pieces to make a 4' x 6' tee surface, with my tee about in the middle, and then lined the edges with black duct tape. But how to hold the ball in place? There was a slight slope, but still enough to let the ball roll off without anything to attach it. I tried a lot of things here- even a cut up toilet plunger end! Eventually, I settled on a bit of foam rod taped in a circle (available at any home maintenance store.) Usually this stuff is used for stuffing sidewalk cracks before you fill them in, but it fit my application just fine. it often flies off with the ball, but the kids quickly figured out they needed to run and get it with each kick.
Step 9: The Software
I had some experience with, and knew I could create an accurate ball flight in Irrlicht. Irrlicht is a cross platform open source 3D engine, and the people on the forum are absolutely wonderful at helping users from newbies to gurus. Irrlicht fit my needs because:
- It's open source and cross platform, and I need to develop for Linux (my downstairs media center is Mythbuntu)
- The folks on the forum are incredibly patient and helpful
- I had experience with it
So I went on the Irrlicht forums in search of a solution. What I found was perfect: Irrlicht VideoMaster. Turns out Bate, from the Irrlicht forums, had written an Irrlicht implementation of the Theora Playback Library. This is a nice stable way to play back Ogg Theora video. This meant that all I had to do was convert my video (h.264) to ogg, and I could play it back full screen or any size that I choose- even as a texture! Even better, I can instantly jump to any time period (within 0.1 seconds) on the video, as well as play, pause, rewind, etc.
As you can see from the Irrlicht VideoMaster Thread, I had very little trouble porting it to Linux. I then used ffmpeg to convert my video to OGG. From there it was easy to put in the soccer ball I had modeled in step 3, play some custom game sounds (referee whistles, Vuvuzelas, a 'boot' sound, and crowd noise) and some standard text on the screen to instruct and inform the player.
All I needed besides that was a method for the arduino and my application to talk. So I had the goal (ardiuno) send a signal when the ball was teed up for 1/2 second, and a different signal if the ball was unteed without getting through the goal. When there is a successful kick, the arduino sends 3 bytes- x coordinate, y coordinate, and time of flight.
For ball flight, I basically used the Irrlicht coordinate system (cartesian) to simulate ball flight. I knew the direction the ball was travelling, and I knew the speed. All I had to do was implement gravity, simulate some spin based on where the ball was kicked, and provide a coefficient of bounce when it hit the ground. It worked great! All source code is available on the last step.
I did discover one bug- if a player was kicking the ball, and someone was standing IN the goal (a likely event at the birthday party) the ball would travel at nearly infinite speed, and disappear from the universe. Everything still worked, just the ball on screen was invisible until you restart the game. The ball wasn't really necessary for play, but it did add a cool factor. The kids didn't mind. I have a video of this on the next step.
Step 10: The Results!
Step 11: Extras- the Source!
- Created a code::blocks project (based on the irrlicht sample projects) for the Irrlicht Videomaster project and ported it to linux.
- Once that worked, I just removed the sample content and code that came with that project, and put my own code in there (soccer simulator code!)
- That's it. so 95% of this is the demo that I downloaded from Bate and ported to Linux. The other 5% is the soccer sim code that I wrote to support the game.
I'm also including the ardiuno sketch used to drive the hardware from step 4. At least that was from scratch!
Here it is.
If you like this, or want to make your own, I'll keep an eye on the comments. Happy building!