Blade – Havoc
Blade Havoc is the game I created, inspired by the early 2000s Japanese T.V series called ‘Beyblade’, which I grew up watching. For this project, I wanted to make use of ML5. Particularly hand tracking and voice detection. Due to limited dexterity with my left hand, I realized that an interactive design ins’t something limited to tangible means of input, but should be open to other ends as well. In my case, and of those who find it difficult or boring to play with the conventional design, this project is meant to be a step in a newer direction. A direction and approach made possible thanks to amazing libraries now available online.
About:
Game Link: Click on Me to play
Github link for the code (commented) : GitHub
Game-Play instructions : The game makes use of hand gestures and speech recognition. In order to able to play the game, click on the link above which will redirect you to another window. Zoom in using Command + or Ctrl + to zoom in and increase the size of the canvas for better viewing. Make sure to have adequate adequate lighting, sit about 70- 90 cm away from the laptop in order to be visible to your webcam’s field of vision. Controls are fairly simple. Pinch your Thumb and Index Finger together to click, and in order to move the on screen pointers, move your hand. You may use either left or right hand of yours, but make sure to use one at a time, as the program is designed to handle one hand at a time. Likewise, you cannot plug and play two peripheral devices of the same nature at the same time. Not that you cannot do it, but it isn’t practical! The game greats you with animations, sound, and interactive design. The pictures have been photoshopped together to create canvas for the background. Pictures and sounds such as the sound track are borrowed from the show, and I in no circumstance take credit for the ownership or production of these assets. However, I did happen to photoshop – remove background- and put them together in a specific manner alongside color scheming to meet the needs of the game.
How the game works: The game is based on the story of spinning tops which collide with one another and run out of spin. In Japanese culture, this form of play has been quite popular.
The show takes cultural and historical inspiration from this, and so does my project. You can toggle the instructions button on the ‘Menu’ to understand how the game works.
Upon clicking, the game first takes you to the game rules window, and by clicking on the arrow at the bottom, it takes you to the game controls window. You can exit by pressing on the ‘close window’ button on the top right of the window pane.
Order of Events: The user first has to toggle the play button in order to proceed with the game.
The game starts with the view of the stadium, and commentator announcing the match between team USA and Japan. The two main characters are Tyson and Daitchi. Each scene proceeds after one of the character is done with their dialogue.
The match then begins with countdown and audio markers.
The beyblades are loaded into the dish, and the window shows the spin status of both the opponent and your beyblade. It shows special attack status to let the user know wether its active or not. In order to activate it , say ” Dragoon Galaxy turbo”. Each of the events, be it impact with other beyblade or activating special move, each has separate audio to it, which makes it even more interactive.
Since I happened to move my beyblade out of the stadium, I lost the game. You can try again by heading to the menu. Upon doing so the window will reload and all of the variables and states will be set to default status to avoid any conflict.
Game Controls: Pinch your finger to move your beyblade around. Open them to attack. If thumb and index finger close, you will be able to move, but cannot attack. In that case, you will take hits, untill you either get thrown out of the stadium, or lose out on spin.

Proud moment: If there is something I am proud of, it is definitely making the sound-classifier and the image-classifier from the ML5 library to get to work. After spending three days trying my best to debug and make the conflict and errors go away, I was finally able to do so. Note that most of the tutorials on ML5.js are in conflict with newer versions of the sdk. Kindly make sure to go over the documentations to avoid any issues. Moreover, I managed to add physics to each blade as well. Upon impact, the opponent’s blade bounces off of the walls whilst yours upon impact either pushes the other one away or you get hit away. Moreover, if you leave the parameters of the stadium, you end up losing the game. This edge detection and getting it to work is another accomplishment of mine after the implementation of machine-trained classifiers.
The Code:
Reusability and ML5.js : The code is made with modularity and re-usability in mind. For ml5.js , all of the setup code and functions have been moved to common functions to call them inside draw and setup at an instance, without having to go through heaps of code, when choosing to turn off / on the ml5.js features.
function ml5_preload_function(){ //importing the hand pose image classifier from ml5.js library handPose = ml5.handPose({flipped:true}); //importing the sound classifier. Doesn't require additional argument. classifier = ml5.soundClassifier('https://teachablemachine.withgoogle.com/models/LHGCWnuCY/model.json', ()=>{ // callback function for testing if the sound model is loaded as it wasn't working before. console.log ("sound model loaded"); }); } // arranges the setup for ml5 function ml5_setup_logic(){ handPose.detectStart(video,gotHands); classifyAudio(); } //the logic for ml5 which goes into draw function function ml5_draw_logic(){ if(hands.length >0){ let hand = hands[0]; let index = hand.index_finger_tip; let thumb = hand.thumb_tip; fill(255,0,0); let d = dist(index.x,index.y,thumb.x,thumb.y); if (d <= 20){ fill (0,0,255); virtual_click = true; } else if ( d > 20) { virtual_click = false; } noStroke(); circle(index.x,index.y, 16); circle (thumb.x,thumb.y, 16); // virtual_click=false pointerX_pos = (index.x + thumb.x)/2; pointerY_pos = (index.y + thumb.y)/2; }
These functions are then conveniently called inside the draw and setup functions.
Object Oriented Code : The class ‘Beyblade’ was made use of, which is custom built. Has attributes like spin speed, coordinates, states which return true or false, and methods like checking for impact.
class Beyblade{ constructor (pos1 , pos2 ,size , player=true){ this.xpos = pos1; this.ypos = pos2; this.size = size; this.spin = 100; this.special_move = false; this.speedX = 2; this.speedY = 1; this.inside_stadium = true; this.stadium_centerX = 316; this.stadium_centerY = 200; this.centerx = (pos1+size)/2; this.centery = (pos2+size)/2; this.isPlayer = player; this.angle = 0; } draw_bey(){ if (mytitle === "Activated") { this.special_move = true ; } if (this.special_move ===true & this.isPlayer == true) { image (player_bey[0],this.xpos,this.ypos,this.size,this.size); // rotate (this.angle); this.angle = this.angle + this.speed; } else if (this.special_move ===false & this.isPlayer == true) { image (player_bey[1],this.xpos,this.ypos,this.size,this.size); // rotate (this.angle); this.angle = this.angle + this.speed; } else { image (opponent_bey,this.xpos,this.ypos,this.size,this.size); // rotate (this.angle); this.angle = this.angle - this.speed; } } move_bey(){ if (this.isPlayer === true){ if (virtual_click == true){ this.xpos = pointerX_pos; this.ypos = pointerY_pos; } } else if (this.isPlayer == false){ this.xpos = this.xpos + this.speedX; this.ypos = this.ypos + this.speedY; } this.centerx = this.xpos + this.size / 2; this.centery = this.ypos + this.size / 2; } check_impact(something) { if (dist (this.centerx, this.centery, something.centerx, something.centery) <= this.size) { if (virtual_click == false){ if (this.special_move == true) { play_song(9); this.xpos += 30; this.ypos +=30; something.spin = something.spin -10; something.speedX = -something.speedX; something.speedY = -something.speedY; } else { play_song(9); this.xpos += 30; this.ypos +=30; something.spin = something.spin - 5; something.speedX = -something.speedX; something.speedY = -something.speedY; } } else { this.xpos += 30; this.ypos +=30; this.spin = this.spin - 5; play_song(9); } } } check_insideStadium(){ if (dist (this.stadium_centerX, this.stadium_centerY, this.centerx, this.centery ) > 200){ this.inside_stadium = false; } else { this.inside_stadium = true; } } bounce_walls(){ let displ = dist(this.stadium_centerX, this.stadium_centerY, this.centerx, this.centery); if (displ >= 200) { // 214 is the stadium radius this.speedX = -this.speedX + random(-1.5, 1.5); this.speedY = -this.speedY + random(-1.5, 1.5); // Reverse speed direction console.log("Beyblade bounced!"); } }
Training the Model: There were series of steps taken to get both the classifiers to get to work. First, I followed some tutorials online and referred to the Ml5.js documentations to get the hand classifier to work. I set the distance between the two fingers to detect when to consider the click and when not to. Daniel Schiffman’s videos were helpful, but a bit outdated.
After setting up the Hand-classifier, I inverted the video and drew in the backside of the canvas. As for the sound classifier, I had to go to Teachable Machine by Google to train a model for detecting specific words for game-control. Due to time constraints, this was more convenient way of training the model, as opposed to me training my own.
I had to train it for background noise and the special phrase that triggers the special move and changes the color and image of the beyblade.
Finally, the trained model was exported, and was implemented inside the sketch.js and html file to make it able to run.
Areas of improvement:
I am proud of the game as of now. It is interactive, helps me to relive my childhood memories, and share this joy with others. However, I wanted to add more levels, ability to change the settings and select different beyblades. This I will add in the future. As far as the game logic goes, I would like to work on the collision physics for the objects. I would like to tumble, roll and push back them forth even more, to make it even more realist.
Overall, I am proud of my work, and how the game turned out to be!