Saturday, February 20, 2016

A game using Node-RED and Freeboard

I wanted to play with some widgets in Freeboard, just for learning purposes. Not having any serious application in mind I came up with the idea of doing something to combine learning + fun. This is a good way to learn, by having fun, isn't?

I have created a Node-RED flow for a computer game.

How the game works: There will be two virtual players "throwing" a virtual dice whose values can range from 0 to 100. The player with the higher number will score one point in each run. The game stops when both players hit the same random number. When this event occurs the player with the higher score is declared the winner.

Freeboard panes and widgets:
One pane for each player with the following widgets. A gauge widget to display the random number. An indicator light widget to easily shows the winner of the run.A text widget that accumulates the score of each player. A separate pane will show how many runs were played at  a given time. An indicator light pane to signal when the game is over. A text widget to show who won the game.



See below a surprising result after running the game several times. It is quite unusual that one player can score much more than the other, but it can happen in the laws of statistics.



At the end of the day, I found that the game was indeed very useful for learning Node-RED since I had to come up with some more advanced functions as well as a logic to start and stop the game. Nothing too complex but also not trivial for a starter.

If you read this post, and the next one,  you will learn a few things:

- How to import flows (created by another people)  into Node-RED
- Use context variable inside your flow
- Use random math function inside a function node
- Use the delay node standard in Red-NODE
- Use three different kinds of widgets in Freeboard

How to import a flow
This is a very handy feature of  Node-RED. You can share your flow with someone else. The point is that the flows are treated as JSON data and can be easily exported and imported.

Let's try. Copy below text.



[{"id":"49f89440.b6076c","type":"inject","z":"1cfb43bd.e304bc","name":"Fire","topic":"none","payload":"fire","payloadType":"string","repeat":"","crontab":"","once":false,"x":80,"y":333,"wires":[["5676f3d1.a9890c"]]},{"id":"43c02113.bc3fe","type":"freeboard","z":"1cfb43bd.e304bc","name":"FREEBOARD-01","x":559,"y":60,"wires":[]},{"id":"db8c93d2.24737","type":"function","z":"1cfb43bd.e304bc","name":"Random","func":"var value1=Math.floor(Math.random()*100);\nvar value2=Math.floor(Math.random()*100);\nvar light1=0;\nvar light2=0;\nvar light3=0;\n\ncontext.global.runs +=1;\nif (value1>value2) {\n context.global.win1+=1\n light1=1;\n light2=0;\n}else if (value2>value1) {\n context.global.win2+=1;\n light1=0;\n light2=1;\n}else {\n light1=1;\n light2=1;\n light3=1;\n context.global.stop = true;\n if (context.global.win1 > context.global.win2) {\n context.global.winner = \"Player 1\";\n } else if (context.global.win2 > context.global.win1) {\n context.global.winner = \"Player 2\";\n } else {\n context.global.winner = \"It is a draw ! !\";\n }\n }\n\nmsg.payload={value1:value1, value2:value2, runs: context.global.runs, win1:context.global.win1, win2:context.global.win2, light1:light1, light2:light2 , light3:light3 , winner:context.global.winner }\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":60,"wires":[["2e899306.d1766c","43c02113.bc3fe"]]},{"id":"2e899306.d1766c","type":"function","z":"1cfb43bd.e304bc","name":"Test Stop","func":"\nif (!context.global.stop) {\n msg.payload = context.global.stop;\n return msg; \n}\n","outputs":1,"noerr":0,"x":362,"y":332,"wires":[["4b15678b.b4ea98"]]},{"id":"4b15678b.b4ea98","type":"delay","z":"1cfb43bd.e304bc","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":179,"y":62,"wires":[["db8c93d2.24737"]]},{"id":"5676f3d1.a9890c","type":"function","z":"1cfb43bd.e304bc","name":"Start","func":"context.global.start = true;\ncontext.global.stop = false;\n\nif (context.global.start) {\n context.global.win1=0;\n context.global.win2=0;\n context.global.runs=0;\n context.global.winner=\"open game\";\n context.global.start=false;\n}\nreturn msg;","outputs":1,"noerr":0,"x":216,"y":333,"wires":[["2e899306.d1766c"]]}]



Now open your FRED environment, click on the menu icon in the right upper corner of your browser (those 3 stacked lines), select import and then Clipboard.





A dialogue box will open. Paste the text into it.



If all is done correctly the following flow will show up in your canvas.




We are done with the Node-RED part. As for the Freeboard, the process is also very simple but I would rather make a video that shows the process to create the widgets and show the game in action.

I will work on that now.

Take care.