Basic Information

This page allows you to edit the existing project (Whack a Mole). The edited project will replace the existing entry in the IoT Projects page. If you want to add a new entry based on the project, please fork from it instead.

* Photo URLs that end with any one of .jpg, .jpeg, .png or that are uploaded to the Gyazo web service in the PNG format (e.g.https://gyazo.com/hogehoge) are supported.

* Node.js entry point main: index.js and dependencies to the npm module dependencies: { f3js: (略) } will be automatically added and thus do not need to be in this form.

Private Project

This project is already public and cannot be made private.

Source Code

Provide the source code of a microcontroller or tiny computer in JavaScript. Node.js-based computers are supported. Require f3js package and use its API to design the device enclosure.

var useJoystick = false; // ジョイスティックを使う var groveSensor = require('jsupm_grove'); var button = new groveSensor.GroveButton(2); var upmBuzzer = require("jsupm_buzzer"); var buzzer = new upmBuzzer.Buzzer(3); var buzzer_volume = 50; // ブザーのボリューム [0, 100] buzzer.setVolume(buzzer_volume / 100); buzzer.stopSound(); var jsupm_joystick = require('jsupm_joystick12'); var joystick = new jsupm_joystick.Joystick12(0, 1); var upm_grove = require('jsupm_grove'); var groveRotary = new upm_grove.GroveRotary(0); var LCD = require("jsupm_i2clcd"); var lcd = new LCD.Jhd1313m1(6, 0x3E, 0x62); var f3js = require('f3js') , c = f3js.createContainer() , x = 10 , y = 10 , width = 160 , height = 105 , thickness = 42 , jw = 7 /* かみ合わせ幅 [5, 10] */ , jh = 2 /* 板厚[mm] [1, 5] */; c.x = x; c.y = y; // 表の面を作る var p = c.jrc(0, 0, width, height, jw, jh); /* // 上記は次のコードと同じ //var p = c.drawJointRectangle(0, 0, width, height, jw, jh); // または次のコードと同じ var p = c.createPath(); p.moveTo(0, 0); p.jointTo(width, 0, jw, jh); p.jointTo(width, height, jw, jh); p.jointTo(0, height, jw, jh); p.jointTo(0, 0, jw, jh); p.close(); */ // 表面にいろいろ配置する c.add(lcd, { x: 81, y: 40 }); c.add(button, { x: 20, y: 85, rotation: 90 }); c.add(buzzer, { x: 140, y: 20, rotation: 90 }); if (useJoystick) { c.add(joystick, { x: 140, y: 80, rotation: 90 }); } else { c.add(groveRotary, { x: 140, y: 85 }); } // 配線用の穴を開ける // Buzzer c.drawRectangle(135, 35, 10, 6); c.drawRectangle(133, 13, 14, 14); // Button c.drawRectangle(15, 64, 10, 6); c.drawRectangle(13, 78, 14, 14); if (useJoystick) { // Joystick c.drawRectangle(135, 49, 10, 6); c.drawRectangle(133, 63, 14, 34); c.drawRectangle(130, 63, 20, 26); } else { // RotaryAngleSensor c.drawRectangle(135, 64, 10, 6); c.drawRectangle(133, 78, 14, 14); } // 側面と裏面を作る var ps = p.extrude(45); ps[0].x = width + 5; ps[0].y = jh; ps[1].x = width + 5; ps[1].y = (thickness + 5) * 2 + jh; ps[2].x = width + 5; ps[2].y = thickness + 5 + jh; ps[3].x = width + 5; ps[3].y = (thickness + 5) * 3 + jh; ps[4].x = 0; // 最後の要素が裏面 ps[4].y = height + 5; // 表の面の真下に配置する for (var i = 0; i < ps.length; i ++) { c.add(ps[i]); } // // 側面の一つに電源用の穴を開ける ps[1].drawRectangle(jh + 5, thickness - jh - 5, height - jh*2 - 10, -10); // 以降はゲームのソースコード var iv_idle = false; var iv_game = false; var iv_gameover = false; var timelimit_sec = 30; /* 制限時間 [10, 60] */ var count = 0; var prev_button_val = 0; var prev_prev_button_val = 0; var score = 0; function startIdle() { lcd.setColor(255, 255, 255); lcd.setCursor(0,0); lcd.write(' Mogura Tataki '); lcd.setCursor(1,0); lcd.write(' Push Button '); if (iv_gameover) { clearInterval(iv_gameover); iv_gameover = false; } iv_idle = setInterval(function() { if (count >= 16) { lcd.setCursor(0,0); lcd.write(' Mogura Tataki '); count = 0; } else if (count >= 8) { lcd.setCursor(0,0); lcd.write(' Whack a Mole '); count++; } else { count++; } if (prev_button_val == 0 && button.value() > 0) { buzzer.playSound(upmBuzzer.DO, 100000); buzzer.stopSound(); clearInterval(iv_idle); iv_idle = false; startGame(); } prev_button_val = button.value(); }, 100); } function stopGame() { console.log("time up"); console.log("score: " + score); buzzer.playSound(upmBuzzer.DO, 100000); buzzer.stopSound(); lcd.setColor(255, 255, 255); lcd.setCursor(0,0); lcd.write(' '); lcd.setCursor(0,0); lcd.write(' Score : ' + score); lcd.setCursor(1,0); lcd.write(' Time Up '); if (iv_game) { clearInterval(iv_game); iv_game = false; } setTimeout(function() { iv_gameover = setInterval(function() { if (count >= 16) { lcd.setCursor(1,0); lcd.write(' Push Button '); count = 0; } else if (count >= 8) { lcd.setCursor(1,0); lcd.write(' Game Over '); count++; } else { count++; } if (prev_button_val == 0 && button.value() > 0) { buzzer.playSound(upmBuzzer.DO, 100000); buzzer.stopSound(); clearInterval(iv_gameover); iv_gameover = false; startIdle(); } prev_button_val = button.value(); }, 100); }, 3000); } function startGame() { var arr_mole = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; var mole_count_max = 5; var mole_count = mole_count_max; var time_count_max = timelimit_sec * 10; var time_count = 0; prev_button_val = 0; prev_prev_button_val = 0; score = 0; var pos = 0; iv_game = setInterval(function() { if (useJoystick) { if (joystick.getYInput() + 0.685 < -0.05 && pos > 0) { pos--; } else if (joystick.getYInput() + 0.685 > 0.05 && pos < 15) { pos++; } } else { pos = 15 - Math.floor(groveRotary.abs_value() / (1024 / 16)); } if (time_count >= time_count_max) { // time over stopGame(); } else { time_count++; // add_mole if (mole_count >= mole_count_max) { var changes = Math.floor(Math.random() * 5 + 1); for (i = 0; i < changes; i++) { var place = Math.floor(Math.random() * 16); if (arr_mole[place] == 0) { arr_mole[place] = 1; } else { arr_mole[place] = 0; } } mole_count = 0; } else { mole_count++; } // whack if ((prev_prev_button_val == 0 || prev_button_val == 0) && button.value() > 0 && arr_mole[pos] == 1) { arr_mole[pos] = 2; score++; console.log("score = " + score); if (score % 10 == 0) { buzzer.playSound(upmBuzzer.DO, 100000); buzzer.playSound(upmBuzzer.MI, 100000); buzzer.stopSound(); if (mole_count_max > 1) { mole_count_max--; console.log("mole_count_max = " + mole_count_max); } } else { buzzer.playSound(upmBuzzer.DO, 100000); buzzer.stopSound(); } } // background color hoge = Math.floor(Math.pow(time_count/time_count_max, 2)*255); lcd.setColor(255, 255-hoge, 255-hoge); // disp for (i = 0; i < 16; i++) { lcd.setCursor(0,i); if (arr_mole[i] == 1) { lcd.write('O'); } else if (arr_mole[i] == 2) { lcd.write('X'); arr_mole[i] = 0; } else { lcd.write(' '); } lcd.setCursor(1,i); if (i == pos) { lcd.write('T'); } else { lcd.write(' '); } } } prev_prev_button_val = prev_button_val; prev_button_val = button.value(); }, 100); } startIdle(); process.on('SIGINT', function() { if (iv_idle) { clearInterval(iv_idle); } if (iv_game) { clearInterval(iv_game); } if (iv_gameover) { clearInterval(iv_gameover); } lcd.setColor(255, 255, 255); process.exit(0); });
Customization

This content does not allow any customization.

Layout view options
Adding comments to variable declarations in the source code populate various GUI widgets in the "Customization" section depending on their types.

Design Alternatives

Modules

No modules are required for this project.

Layout
Program

Login first to use this feature.